Skip to content

Commit

Permalink
50001: Added old notes ready for merging
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverKillane committed Dec 17, 2023
1 parent d008f42 commit 6afaef8
Show file tree
Hide file tree
Showing 147 changed files with 6,053 additions and 1 deletion.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
\documentclass{report}
\title{50001 - Algorithm Analysis and Design - Lecture 1}
\author{Oliver Killane}
\date{12/11/21}

\input{../50001 common.tex}

\begin{document}
\maketitle
\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=d281ea45-d9df-4f23-8578-adbf00d38370}

\section*{Introduction}
An algorithm is a method of computing a result for a given problem, at its core in a systematic/mathematical means.
\\
\\ This course extensively uses haskell instead of pesudocode to express problems, though its lessons still apply to other languages.

\section*{Fundamentals}
\sidenote{Insertion Problem}{
Given an integer $x$ and a sorted list $ys$, produce a list containing $x:ys$ that is ordered.
\\
\\ Note that this can be solved by simply using $sort(x:ys)$ however this is considered wasteful as it does not exploit the fact that $ys$ is already sorted.
}
An example algorithm would be to traverse $ys$ until we find a suitable place for $x$
\codelist{Haskell}{insert.hs}
\subsubsection*{Call Steps}
In order to determine the complexity of the function, we use a \keyword{cost model} and determine what steps must be taken.
\\
\\ For example for $insert \ 4 \ [1,3,6,7]$
\\ \begin{steps}
\start{insert \ 4 \ [1,3,6,7]}
\step{1 : insert \ 4 \ [3,6,7]}{definition of $insert$}
\step{1 : 3 : insert \ 4 \ [6,7]}{definition of $insert$}
\step{1 : 3 : : 4 : [6,7]}{definition of $insert$}
\end{steps}
Hence this requires $3$ call steps.
\\
\\ We can use recurrence relations to get a generalised formula for the worst case (maximum number of calls):
\[\begin{matrix}
T_{insert} 0 & = 1 \\
T_{insert} 1 & = 1 + T_{insert}(n-1) \\
\end{matrix}\]
We can solve the recurrence:
\[\begin{matrix}
T_{insert} (n) & = 1 + T_{insert}(n-1) \\
T_{insert} (n) & = 1 + 1 + T_{insert}(n-2) \\
T_{insert} (n) & = 1 + 1 + \dots + 1 + T_{insert}(n-n) \\
T_{insert} (n) & = n + T_{insert}(0) \\
T_{insert} (n) & = n + 1 \\
\end{matrix}\]

\subsubsection*{More complex algorithms}
\codelist{Haskell}{isort.hs}
\[\begin{matrix}
T_{isort} 0 & = 1 \\
T_{isort} n & = 1 + T_{insert}(n-1) + T_{isort}(n-1) \\
\end{matrix}\]
Hence by using our previous formula for $insert$
\[\begin{matrix}
T_{isort} n & = 1 + n + T_{isort}(n-1) \\
\end{matrix}\]
And by recurrence:
\[\begin{matrix}
T_{isort} (n) & = 1 + n + (1 + n - 1) + T_{isort}(n-2) \\
T_{isort} (n) & = 1 + n + (1 + n - 1) + (1 + n - 2) + \dots + T_{isort}(n-n) \\
T_{isort} (n) & = 1 + n + (1 + n - 1) + (1 + n - 2) + \dots + T_{isort}(0) \\
T_{isort} (n) & = n + n + (n - 1) + (n - 2) + \dots + (n-n) + 1 \\
T_{isort} (n) & = 1 + n + \sum_{i = 0}^n{i} \\
T_{isort} (n) & = \sum_{i = 0}^{n+1}{i} \\
T_{isort} (n) & = \cfrac{(n+1)\times(n+1)}{2} \\
\end{matrix}\]
\end{document}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
insert :: Int -> [Int] -> [Int]
insert x [] = [x]
insert x yss@(y:ys)
| x <= y = x:yss
| otherwise = y : insert x ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
isort :: [Int] -> [Int]
isort [] = []
isort (x:xs) = insert x (isort xs)
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
\documentclass{report}
\title{50001 - Algorithm Analysis and Design - Lecture 10}
\author{Oliver Killane}
\date{18/11/21}

\input{../50001 common.tex}

\begin{document}
\maketitle
\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=62e2dbd5-4fba-4758-b2a6-addb016ec088}

\section*{List lookup}
\codelist{Haskell}{list lookup.hs}
As you ca see \fun{!!} costs $O(n)$ as it may traverse the entire list.
\\
\\ If we want this access to be faster, we can use trees:
\codelist{Haskell}{list tree.hs}
This costs $O(\log n)$ as each recursive call acts on half of the remaining list.
\\
\\ However we have difficulty with insertion:
\begin{center}
\begin{tabular}{l l l}
Insert Quickly & $n : t = node (Leaf n) t$ & Effectively becomes a linked list, $\log n$ search time ruined. \\
Insert Slowly & Rebalance tree (e.g \keyword{AVL} tree) & Complex and no longer $O(1)$ insert. \\
\end{tabular}
\end{center}

\section*{Random Access Lists}
A list containing elements that are either nothing, or a perfect tree with size the same as $2^{index}$.
\centerimage{width=\textwidth}{RAList.png}
The empty tree can be represented by a $Tip$ value (from the notes), or using type $Maybe(Tree)$ (from the lecture) where $Tree \ a = Leaf \ x \ | \ Node \ n \ l \ r$.
\\
\\ When we add to a tree, we add to the first element of the \struct{RAList}, if the invariant is breached (no longer perfect tree of size $2^0$) it can be combined with the next list over (if empty, place, else combine and repeat).
\\
\\ This way while the worst case insert is $O(n)$, our amortized complexity is $O(1)$ much as with increment.
\codelist{Haskell}{RAList.hs}
\end{document}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
data Tree a = Tip | Leaf a | Node Int (Tree a) (Tree a)

type RAList a = [Tree a]

instance List RAList where
toList :: RAList a -> [a]
toList (RaList ls) = concatMap toList ls

fromList :: [a] -> RAList a
fromList = foldr (:) empty

empty :: RAList a
empty = []

(:) :: a -> RAList a -> RAList a
n : [] = [Leaf n]
n : (RAList ls) = RAList (insertTree (Leaf n) ls)
where
insertTree :: Tree a -> [Tree a] -> [Tree a]
insertTree t ([]) = [t]
insertTree t (Tip:ls) = t:ls
insertTree t (t':ts) = Tip: insertTree (node t t') ts

length :: RAList a -> Int
length (RAList ls) = foldr ((+) . length) 0 ls

(!!) :: RAList a -> Int -> a
(RAList []) !! _ = error "(!!): empty list"
(RAList (x:xs)) !! n
| isEmpty x = (RAList ts) !! k
| n < m = x !! n
| otherwise = (RAList xs) !! (n-m)
where m = length x
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
(!!) :: [a] -> Int -> a
(x:xs) !! 0 = x
(_:xs) !! k = xs !! (k-1)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
data Tree a = Tip | Leaf a | Node Int (Tree a) (Tree a)

node :: Tree a -> Tree a -> Tree a
node l r = Node (size l + size r) l r

instance List Tree where
toList :: Tree a -> [a]
toList Tip = []
toList (Leaf n) = [n]
toList (Fork n l r) = toList l ++ toList r

-- Invariant: size Node n a b = n = size a + size b
length :: Tree a -> Int
length Tip = 0
length (Leaf _) = 1;
length (Node n _ _) = n;

(!!) :: Tree a -> Int -> a
(Leaf x) !! 0 = x
(Node n l r) !! k
| k < m = l!!k
| otherwise = r!! (k-m)
where m = length l

-- case for Tip !! n or Leaf !! >0
_ !! _ = error "(!!): Cannot get list index"
Loading

0 comments on commit 6afaef8

Please sign in to comment.