diff --git a/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/Lecture 1.pdf b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/Lecture 1.pdf new file mode 100644 index 0000000..a0cfa65 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/Lecture 1.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/Lecture 1.tex b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/Lecture 1.tex new file mode 100644 index 0000000..9fedee3 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/Lecture 1.tex @@ -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} diff --git a/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/code/insert.hs b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/code/insert.hs new file mode 100644 index 0000000..a656541 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/code/insert.hs @@ -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 \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/code/isort.hs b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/code/isort.hs new file mode 100644 index 0000000..71e21bc --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 1 - (Introduction)/code/isort.hs @@ -0,0 +1,3 @@ +isort :: [Int] -> [Int] +isort [] = [] +isort (x:xs) = insert x (isort xs) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/Lecture 10.pdf b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/Lecture 10.pdf new file mode 100644 index 0000000..86eaafd Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/Lecture 10.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/Lecture 10.tex b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/Lecture 10.tex new file mode 100644 index 0000000..64b7096 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/Lecture 10.tex @@ -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} diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/RAList.hs b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/RAList.hs new file mode 100644 index 0000000..9d910eb --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/RAList.hs @@ -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 diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/list lookup.hs b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/list lookup.hs new file mode 100644 index 0000000..65d03c2 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/list lookup.hs @@ -0,0 +1,3 @@ +(!!) :: [a] -> Int -> a +(x:xs) !! 0 = x +(_:xs) !! k = xs !! (k-1) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/list tree.hs b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/list tree.hs new file mode 100644 index 0000000..473f1e4 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/code/list tree.hs @@ -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" diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/diagram/RAList.drawio b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/diagram/RAList.drawio new file mode 100644 index 0000000..ed11669 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/diagram/RAList.drawio @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/image/RAList.png b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/image/RAList.png new file mode 100644 index 0000000..9428fb1 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 10 - (Random Access Lists)/image/RAList.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/Lecture 11.pdf b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/Lecture 11.pdf new file mode 100644 index 0000000..2e277b2 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/Lecture 11.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/Lecture 11.tex b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/Lecture 11.tex new file mode 100644 index 0000000..2a12ea4 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/Lecture 11.tex @@ -0,0 +1,68 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 11} + \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=678e8f17-9eb3-4469-96d0-adde00d597c2} + +\section*{Equality} +\codelist{Haskell}{equality.hs} +Eq is the typeclass for equality, any instance of this class should ensure the equality satisfied the laws: +\begin{center} + \begin{tabular}{r l} + reflexivity & $x == x$ \\ + transitivity & $x == y \land y == z \Rightarrow x == z$ \\ + symmetry & $x == y \Rightarrow y == x$ \\ + \end{tabular} +\end{center} +We also expect the idescernability of identicals (Leibniz Law): +\[x == y \Rightarrow f \ x == f \ y\] +For a set-like interface we have a member function: +\codelist{Haskell}{member.hs} +If we assume only that Eq holds, the complexity is $O(n)$ as we must potentially check all members of the set. To get around this, we use ordering. + +\section*{Orderings} +The Ord typeclass allows us to check for inequalities: +\codelist{Haskell}{order.hs} +We must try to ensure certain properties hold, for example for to have a partial order we require: +\begin{center} + \begin{tabular}{r l} + reflexivity & $x \leq x$ \\ + transitivity & $x \leq y \land y \leq z \Rightarrow x \leq z$ \\ + antisymmetry & $x \leq y \land y \leq x \Rightarrow x == y$ \\ + \end{tabular} +\end{center} +There are also total orders (all elements in the set are ordered compared to all others), for which we add the constraint: +\begin{center} + \begin{tabular}{r l} + connexity & $x \leq y \lor y \leq x$ \\ + \end{tabular} +\end{center} + +\section*{Ordered Sets} +\codelist{Haskell}{ordset.hs} +We can implement this class for Trees: +\codelist{Haskell}{search tree.hs} +However the worst case here is still $O(n)$ as we do not balance the tree as more members are inserted. If the members are added in order, the tree devolves to a linked list. +\\ +\\ We need a way to create a tree that self balances. + +\section*{Binary Search Trees (AVL Trees)} +\codelist{Haskell}{avl tree.hs} +When inserting into the tree we must keep the tree balanced such that no subtree's left is more than one higher than its' right. +\codelist{Haskell}{avl tree insert.hs} +We must rebalance the tree after insertion, this must consider the following cases: +\centerimage{width=\textwidth}{htree balanced.png} +When the tree's balanced invariant has been broken, we must follow these cases: +\centerimage{width=\textwidth}{htree rotate right.png} +\codelist{Haskell}{avl rotate right.hs} +When the right subtree's right subtree is higher: +\centerimage{width=\textwidth}{htree rotate left.png} +\codelist{Haskell}{avl rotate left.hs} +We can use rotate left and rotate right to for the two cases where the right subtree is 2 or more higher than the left. +\codelist{Haskell}{avl balance.hs} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl balance.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl balance.hs new file mode 100644 index 0000000..1906726 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl balance.hs @@ -0,0 +1,10 @@ +balance :: Ord a => HTree a -> a -> HTree a -> HTree +balance l x r + | lh == lr || abs (lr - lr) == 1 = t + | lh > lr = rotr(hnode (if height ll < height lr then rotl l else l) x r) + | otherwise = rotl(hnode l x (if height rl > height rr then rotr r else r)) + where + lh = height l + rl = height r + (HNode _ ll _ lr) = l + (HNode _ rl _ rr) = r \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl rotate left.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl rotate left.hs new file mode 100644 index 0000000..bbc4105 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl rotate left.hs @@ -0,0 +1,5 @@ +rotl :: HTree a -> HTree a +rotl (HNode _ ll w (HNode _ lrl x lrr)) + = hnode (hnode ll w lrl) x lrr + +-- so for the example: HNode _ wt y r -> rotr ( hnode (rotl wt) y r) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl rotate right.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl rotate right.hs new file mode 100644 index 0000000..a2acb2a --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl rotate right.hs @@ -0,0 +1,2 @@ +rotr :: HTree a -> HTree a +rotr (HNode _ (HNode _ ll x lr) y r) = hnode ll x (hnode lr y r) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl tree insert.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl tree insert.hs new file mode 100644 index 0000000..216e509 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl tree insert.hs @@ -0,0 +1,6 @@ +insert :: Ord a => a -> HTree a -> HTree a +insert x HTip = hnode Tip x Tip +insert x t@(HNode _ l y r) + | x == y = t + | x < y = balance (insert x l) y r + | otherwise = balance l y (insert x r) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl tree.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl tree.hs new file mode 100644 index 0000000..d2a1c8e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/avl tree.hs @@ -0,0 +1,10 @@ +-- H for height! The int stored at a node is the height of that tree. +data HTree a = HTip | HNode Int (HTree a) a (HTree a) + +height :: HTree a -> Int +height HTip = 0 +height (HNode h _ _ _) = h + +hnode :: HTree a -> a -> HTree a -> HTree a +hnode l x r = HNode h l x r + where h = max (height l) (height r) + 1 diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/equality.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/equality.hs new file mode 100644 index 0000000..638d826 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/equality.hs @@ -0,0 +1,2 @@ +class Eq a where + (==) :: a -> a -> Bool diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/member.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/member.hs new file mode 100644 index 0000000..799fa2e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/member.hs @@ -0,0 +1 @@ +(in) :: Eq a => a -> Set a -> Bool \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/order.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/order.hs new file mode 100644 index 0000000..c52b022 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/order.hs @@ -0,0 +1,5 @@ +class Eq a => Ord a where + (<=) :: a -> a -> Bool + (<) :: a -> a -> Bool + (>=) :: a -> a -> Bool + (>) :: a -> a -> Bool \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/ordset.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/ordset.hs new file mode 100644 index 0000000..55c514f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/ordset.hs @@ -0,0 +1,6 @@ +class OrdSet ordset where + empty :: ordset n + insert :: Ord a => a -> ordset a -> ordset a + member :: Ord a => a -> ordset a -> Bool + fromList :: Ord a => [a] -> ordset a + toList :: Ord a => ordset a -> [a] \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/search tree.hs b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/search tree.hs new file mode 100644 index 0000000..6b6255e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/code/search tree.hs @@ -0,0 +1,26 @@ +data Tree a = Tip | Node (Tree a) a (Tree a) + +instance OrdSet Tree where + empty :: Tree n + empty = Tip + + insert :: Ord a => a -> Tree a -> Tree a + insert x Tip = Node Tip x Tip + insert x (Node l y r) + | x == y = t + | x < y = Node (insert x l) y r + | otherwise = Node l y (insert x r) + + member :: Ord a => a -> Tree a -> Bool + member x Tip = False + member x (Node l y r) + | x == y = True + | x < y = member x l + | otherwise = member x r + + fromList :: Ord a => [a] -> Tree a + fromList = foldr insert empty + + toList :: Ord a => Tree a -> [a] + toList Tip = [] + toList (Node l y r) = toList l ++ y:toList r \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree balanced.drawio b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree balanced.drawio new file mode 100644 index 0000000..5a5a029 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree balanced.drawio @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree rotate left.drawio b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree rotate left.drawio new file mode 100644 index 0000000..f16b25d --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree rotate left.drawio @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree rotate right.drawio b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree rotate right.drawio new file mode 100644 index 0000000..0ff101e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/diagram/htree rotate right.drawio @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree balanced.png b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree balanced.png new file mode 100644 index 0000000..833bdca Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree balanced.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree rotate left.png b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree rotate left.png new file mode 100644 index 0000000..63c04f0 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree rotate left.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree rotate right.png b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree rotate right.png new file mode 100644 index 0000000..6bd4261 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 11 - (Search Trees)/image/htree rotate right.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/Lecture 12.pdf b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/Lecture 12.pdf new file mode 100644 index 0000000..fa95f6e Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/Lecture 12.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/Lecture 12.tex b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/Lecture 12.tex new file mode 100644 index 0000000..291115b --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/Lecture 12.tex @@ -0,0 +1,41 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 12} + \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=abdb5a60-fd1c-44bb-afbe-ade100fb80eb} + +\section*{Red-Black Trees} +\keyword{AVL trees} worked by storing an extra integer (height) to use in rebalancing, \keyword{red-black trees} use an extra bit to determine if a node is red or black. +\\ +\\ In practice they are less balanced than \keyword{AVL trees} however the insertion is faster and the data structure is a little bit smaller. +\codelist{Haskell}{red-black tree.hs} +The structure relies on two invariances: +\begin{enumerate} + \item Every Red node must have a Black parent node. + \item Every path from the root to leaf must have the same number of black nodes. +\end{enumerate} +\subsubsection*{Valid Red Black Trees} +\centerimage{width=\textwidth}{red-black trees.png} +\subsubsection*{Invalid Red Black Trees} +\centerimage{width=\textwidth}{not red-black trees.png} +We have an insert function that needs to rebalance the tree: +\codelist{Haskell}{red-black insert.hs} +\centerimage{width=\textwidth}{balance cases.png} + +\section*{Counting} +We can exploit the analogy we used with counting and trees for \keyword{RALists} here, with a difference. +\\ +\\ Imagine a counting system that lacks zeros. We can count to 10 as: +\begin{center} + \begin{tabular}{l l l l l l l l l l l l l l l l l l} + Normal: & 1 & 2 & \dots & 9 & 10 & \dots & 11 & 12 & \dots & 19 & 20 & \dots & 101 & 102 & \dots & 110 & 111 \\ + Special: & 1 & 2 & \dots & 9 & X & \dots & 11 & 12 & \dots & 19 & 1X & \dots & X1 & X2 & \dots & XX & 111 \\ + \end{tabular} +\end{center} +We can use this with the pattern of inserting elements into a red black tree (in order) to map red black trees to an incrementing number. +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/rbtree functions.hs b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/rbtree functions.hs new file mode 100644 index 0000000..e2749bf --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/rbtree functions.hs @@ -0,0 +1,2 @@ +fromOrdList :: Ord a => [a] -> RBTree a +fromOrdList = foldr insert Empty \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/red-black insert.hs b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/red-black insert.hs new file mode 100644 index 0000000..0696e5e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/red-black insert.hs @@ -0,0 +1,23 @@ +blacken :: Ord a => RBTree a -> RBTree a +blacken (Node Red l x r) = Node Black l x r +blacken t = t + +balance :: Ord a => Colour -> RBTree a -> a -> RBTree a -> RBTree a +balance c l v r = case Node c l v r of + Node Black (Node Red (Node Red a x b) y c) z d -> bal x y z a b c d + Node Black (Node Red a x (Node Red b y c)) z d -> bal x y z a b c d + Node Black a x (Node Red (Node Red b y c) z d) -> bal x y z a b c d + Node Black a x (Node Red b y (Node Red c z d)) -> bal x y z a b c d + t -> t + where + bal x y z a b c d = Node Red (Node Black a x b) y (Node Black c z d) + +insert :: Ord a => a -> RBTree a -> RBTree a +insert = (blacken .) . ins + where + ins :: Ord a => a -> RBTree a -> RBTree a + ins x Empty = Node Red Empty x Empty + ins x t@(Node c l y r) + | x < y = balance c (ins x l) y r + | x == y = t + | otherwise = balance c l y (ins x r) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/red-black tree.hs b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/red-black tree.hs new file mode 100644 index 0000000..2a365dc --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/code/red-black tree.hs @@ -0,0 +1,3 @@ +data Colour = Red | Black + +data RBTree a = Empty | Node Colour (RBTree a) a (RBTree a) diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/balance cases.drawio b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/balance cases.drawio new file mode 100644 index 0000000..9169354 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/balance cases.drawio @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/not red-black trees.drawio b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/not red-black trees.drawio new file mode 100644 index 0000000..5bf4aef --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/not red-black trees.drawio @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/red-black trees.drawio b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/red-black trees.drawio new file mode 100644 index 0000000..ddea936 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/diagram/red-black trees.drawio @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/balance cases.png b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/balance cases.png new file mode 100644 index 0000000..bca4c18 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/balance cases.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/not red-black trees.png b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/not red-black trees.png new file mode 100644 index 0000000..f14c04a Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/not red-black trees.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/red-black trees.png b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/red-black trees.png new file mode 100644 index 0000000..4c15ca4 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 12 - (Red Black Trees 1)/image/red-black trees.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/Lecture 13.pdf b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/Lecture 13.pdf new file mode 100644 index 0000000..3771366 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/Lecture 13.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/Lecture 13.tex b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/Lecture 13.tex new file mode 100644 index 0000000..aa0f2d7 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/Lecture 13.tex @@ -0,0 +1,21 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 13} + \author{Oliver Killane} + \date{22/11/21} + +\input{../50001 common.tex} + +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=ce3f2216-40e2-4203-9898-ade70160bbb1} + +\section*{Red Black Trees Continued} +We have a pattern with inserting elements from an ordered list into the tree. +\centerimage{width=\textwidth}{red black insert pattern.png} +We can encode this as a special binary number system, using $1$ and $2$ such that the least significant bit is a the number of trees of $2^0$ nodes, and the nth is $2^n$. +\centerimage{width=\textwidth}{red black counting pattern.png} +We can increment this by: +\codelist{Haskell}{treenary.hs} +We can convert a list of digits back to a red black tree by: +\codelist{Haskell}{to RBTree.hs} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/code/to RBTree.hs b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/code/to RBTree.hs new file mode 100644 index 0000000..2a8d233 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/code/to RBTree.hs @@ -0,0 +1,7 @@ +-- fold left to combine the digits together into a tree +fromList :: [a] -> RBTree a +fromList xs = foldl link Empty (foldr add xs) + +link :: RBTree a -> Digit a -> RBTree a +link l (One x t) = Node Black l x t +link l (Two x t y u) = Node Black (Node Red l x t) y u \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/code/treenary.hs b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/code/treenary.hs new file mode 100644 index 0000000..15b9ace --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/code/treenary.hs @@ -0,0 +1,7 @@ +-- each element is a red black tree (+ an extra root element (a)) +data Digit a = One a (RBTree a) | Two a (RBTree a) a (RBTree a) + +incr :: a -> RBTree a -> [Digit a] -> [Digit a] +incr x t [] = [One x t] +incr x t ((One y u) : ds) = Two x t y u : ds +incr x t ((Two y u z v) : ds) = One x t : incr y (Node Black u z v) ds \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/diagram/red black counting pattern.drawio b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/diagram/red black counting pattern.drawio new file mode 100644 index 0000000..38a17b6 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/diagram/red black counting pattern.drawio @@ -0,0 +1,717 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/diagram/red black insert pattern.drawio b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/diagram/red black insert pattern.drawio new file mode 100644 index 0000000..afe5973 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/diagram/red black insert pattern.drawio @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/image/red black counting pattern.png b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/image/red black counting pattern.png new file mode 100644 index 0000000..f86bfec Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/image/red black counting pattern.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/image/red black insert pattern.png b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/image/red black insert pattern.png new file mode 100644 index 0000000..1b45806 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 13 - (Red Black Trees 2)/image/red black insert pattern.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/Lecture 14.pdf b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/Lecture 14.pdf new file mode 100644 index 0000000..1a0ad2d Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/Lecture 14.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/Lecture 14.tex b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/Lecture 14.tex new file mode 100644 index 0000000..f8c50e3 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/Lecture 14.tex @@ -0,0 +1,62 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 14} + \author{Oliver Killane} + \date{28/11/21} +\input{../50001 common.tex} +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=a562661f-da77-4d28-85a6-ade80168e6e5} + +\section*{Randomized Algorithms} +An algorithm that uses random values to produce a result. +\begin{center} + \begin{tabular}{l l l} + \textbf{Algorithm Type} & \textbf{Running time} & \textbf{Correct Result} \\ + Monte Carlo & Predicatable & Unpredictably \\ + Las Vegas & Unpredictable & Predictably \\ + \end{tabular} +\end{center} + +\section*{Random Generation} + +Functions are deterministic (always map same inputs to same outputs), this is known as \keyword{Leibniz's law} or the \keyword{Law of indiscernibles}: +\[x = y \Rightarrow f x = f y\] +We can exhibit pesudo random behaviour using an input that varies \begin{tabular}{l l} + explicitly & (e.g Random numbers through seeds) \\ + implicitly & (e.g Microphone or camera noise) \\ +\end{tabular} + +\subsection*{Inside IO Monad} +We can use basic random through the IO monad like this: +\codelist{Haskell}{simple random.hs} +However using the \struct{IO monad} is too specific, we may want to use random numbers in other contexts. + +\subsection*{StdGen} +In haskell we can use \struct{Stdgen}. +\codelist{Haskell}{stdgen.hs} +By passing the newly generated \struct{StdGen} we can generate new values based on the original seed. +\centerimage{width=\textwidth}{random seeds.png} + +\subsection*{With Random Monad} +Rather than passing \struct{StdGen} seeds through the program, we can use the \struct{MonadRandom} monad which internally uses this value. + + +\section*{Randomized $\pi$} +\centerimage{width=0.6\textwidth}{randomized pi.png} +(Monte Carlo Algorithm - known number of samples, known running time per sample) To estimate $\pi$, find the proportion of randomly selected spots that are within the circle. +\begin{center} + \begin{tabular}{l l} + Area of square & $2 \times 2 = 4$ \\ + Area of circle & $\pi \times 1^2 = \pi$ \\ + Probability in circle & $\cfrac{\pi}{4}$ \\ + \end{tabular} +\end{center} +Once we have the proportion, we can multiply by 4 to get an estimate of $\pi$. +\codelist{Haskell}{montePi.hs} + +\section*{Treaps} +Simultaneously a \keyword{Tree} and a \keyword{Heap}. Stores values in order, while promoting higher priority nodes to the top of the tree. +\centerimage{width=0.8\textwidth}{treap.png} +\codelist{Haskell}{treap.hs} +\centerimage{width=0.8\textwidth}{lnode and rnode.png} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/MonadRandom.hs b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/MonadRandom.hs new file mode 100644 index 0000000..b9bab25 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/MonadRandom.hs @@ -0,0 +1,5 @@ +class Monad m => MonadRandom m where + getRandom :: Random a => m a + getRandoms :: Random a => m [a] + getRandomR :: Random a => (a, a) -> m a + getRandomRs :: Random a => (a, a) -> m [a] \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/montePi.hs b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/montePi.hs new file mode 100644 index 0000000..4a07e8f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/montePi.hs @@ -0,0 +1,40 @@ +import Control.Monad.Random (getRandomR, randomRs, MonadRandom) +import System.Random (mkStdGen, StdGen) + +-- Here we can use one quarter of the circle, hence if the distance from the +-- bottom left (0,0) to the point is within 1 then it is in the circle. +inside :: Double -> Double -> Bool +inside x y = 1 >= x * x + y * y + +-- Take 1000 samples and return 4 * the proportion. +montePi :: MonadRandom m => m Double +montePi = loop samples 0 + where + samples = 10000 + loop 0 m = return (4 * fromIntegral m / fromIntegral samples) + loop n m = do + x <- getRandomR (0,1) + y <- getRandomR (0,1) + loop (n-1) (if inside x y then m + 1 else m) + + + + +-- Using a stream of random numbers (RandomRs) + +-- Get pairs of random numbers from the stream +pairs :: [a] -> [(a,a)] +pairs (x:y:ls) = (x,y):pairs ls + +-- From the pairs of random numbers, get the proportion of points inside the +-- circle and use to get pi. +montePi' :: Double +montePi' = 4 * hits src / fromIntegral samples + where + samples = 10000 + hits = fromIntegral . + length . + filter (uncurry inside) . + take samples . + pairs + src = randomRs (0, 1) (mkStdGen 42) :: [Double] \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/simple random.hs b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/simple random.hs new file mode 100644 index 0000000..f2311b3 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/simple random.hs @@ -0,0 +1,6 @@ +import Control.Monad.Random (getRandom) + +main :: IO () +main = do + x <- getRandom :: IO Int + print (42 + x) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/stdgen.hs b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/stdgen.hs new file mode 100644 index 0000000..11ed27f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/stdgen.hs @@ -0,0 +1,21 @@ +import System.Random (StdGen) + +-- Create a source of randomness from an integer seed +mkStdGen :: Int -> StdGen + +-- Generate a random interger, and a new source of randomness +random :: StdGen -> (Int, StdGen) + +-- Generate an infinite list of random numbers using an initial seed +-- (source of random). +randoms :: StdGen -> [Int] +randoms seed = x:randoms seed' where (x, seed') = random seed + +-- In order to generate random value for any type, a typeclass is used +class Random a where + random :: StdGen -> (a, StdGen) + randoms :: StdGen -> [a] + + -- Random over a (R)ange + randomR :: (a,a) -> StdGen -> (a, StdGen) + randomRs:: (a,a) -> StdGen -> [a] \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/treap.hs b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/treap.hs new file mode 100644 index 0000000..3bc2578 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/code/treap.hs @@ -0,0 +1,47 @@ +-- Node contains child treaps, as well as value (a) and the priority (Int) +data Treap a = Empty | Node (Treap a) a Int (Treap a) + +-- Normal tree search using values +member :: Ord a => a -> Treap a -> Bool +member x (Node l y _ r) + | x == y = True + | x < y = member x l + | otherwise = member x r +member _ Empty = False + +-- Priority based insert +pinsert :: Ord a => a -> Int -> Treap a -> Treap a +pinsert x p Empty = Node Empty x p Empty +pinsert x p t@(Node l y q r) + | x == y = t + | x < y = lnode (pinsert x p l) y q r + | otherwise = rnode l y q (pinsert x p r) + +-- rotate right (check left node) +lnode :: Treap a -> a -> Int -> Treap a -> Treap a +lnode Empty y q r = Node Empty y q r +lnode l@(Node a x p b) y q c + | q > p = Node a x p (Node b y q c) + | otherwise = Node l y q c + +-- rotate left (check right node) +rnode :: Treap a -> a -> Int -> Treap a -> Treap a +rnode l y q Empty = Node l y q Empty +rnode a x p r@(Node b y q c) + | q < p = Node (Node a x p b) y q c + | otherwise = Node a x p r + +-- delete node by recursively searching, then delete and merge subtrees +delete :: Ord a => a -> Treap a -> Treap a +delete x Empty = Empty +delete x (Node a y q b) + | x == y = merge a b + | x < y = Node (delete x a) y q b + | otherwise = Node a y q (delete x b) + +merge :: Treap a -> Treap a -> Treap a +merge Empty r = r +merge l Empty = l +merge l@(Node a x p b) r@(Node c y q d) + | p < q = Node a x p (merge b r) + | otherwise = Node (merge l c) y q d \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/lnode and rnode.drawio b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/lnode and rnode.drawio new file mode 100644 index 0000000..0383451 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/lnode and rnode.drawio @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/random seeds.drawio b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/random seeds.drawio new file mode 100644 index 0000000..eab1e1d --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/random seeds.drawio @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/randomized pi.drawio b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/randomized pi.drawio new file mode 100644 index 0000000..c873702 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/randomized pi.drawio @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/treap.drawio b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/treap.drawio new file mode 100644 index 0000000..ea16802 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/diagram/treap.drawio @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/lnode and rnode.png b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/lnode and rnode.png new file mode 100644 index 0000000..d2bf31f Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/lnode and rnode.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/random seeds.png b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/random seeds.png new file mode 100644 index 0000000..a504856 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/random seeds.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/randomized pi.png b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/randomized pi.png new file mode 100644 index 0000000..aa9e33b Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/randomized pi.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/treap.png b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/treap.png new file mode 100644 index 0000000..d21c575 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 14 - (Randomized Algorithms)/image/treap.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/Lecture 15.pdf b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/Lecture 15.pdf new file mode 100644 index 0000000..da17d9d Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/Lecture 15.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/Lecture 15.tex b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/Lecture 15.tex new file mode 100644 index 0000000..357098f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/Lecture 15.tex @@ -0,0 +1,23 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 15} + \author{Oliver Killane} + \date{29/11/21} +\input{../50001 common.tex} +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=e7c5b433-e2eb-4762-9a09-adee01382a82} + +\section*{Randomized Treaps} +By using a random value for priority when inserting values into the treap, we can ensure a high likelihood of balancing, without complex balancing being required. +\\ +\\ We can use this to create a randomized quicksort. +\codelist{Haskell}{randomized treap.hs} + +\section*{Randomized Binary Trees} +We can balance a binary tree without using a treap, by inserting at the root (and rotating the tree to ensure it is ordered) with a certain probability. +\codelist{Haskell}{Randomized Binary Tree.hs} +For every insert we have chance $\cfrac{1}{n+1}$ of inserting at the root of the tree. Then this occurs, the contents are rotated to ensure the tree's ordering is maintained. +\\ +\\ This means that there is a very high probability of balance being maintained, however correct results are only returned when distinct elements are inserted at most once. + +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/code/Randomized Binary Tree.hs b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/code/Randomized Binary Tree.hs new file mode 100644 index 0000000..9ebbf78 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/code/Randomized Binary Tree.hs @@ -0,0 +1,43 @@ +import System.Random (StdGen, mkStdGen, randomR) + +data BTree a = Empty | Node (BTree a) a (BTree a) + +insert :: Ord a => a -> BTree a -> BTree a +insert x Empty = Node Empty x Empty +insert x t@(Node l y r) + | x == y = t + | x < y = Node (insert x l) y r + | otherwise = Node l y (insert x r) + +-- basic lefty/right rotations +rotr :: BTree a -> a -> BTree a -> BTree a +rotr (Node a x b) y c = Node a x (Node b y c) +rotr _ _ _= error "(rotr): left was empty" + +rotl :: BTree a -> a -> BTree a -> BTree a +rotl a x (Node b y c) = Node (Node a x b) y c +rotl _ _ _= error "(rtol): right was empty" + + +-- Insert to the root of the tree (maintaining order) +insertRoot :: Ord a => a -> BTree a -> BTree a +insertRoot x Empty = Node Empty x Empty +insertRoot x t@(Node l y r) + | x == y = t + | x < y = rotr (insertRoot x l) y r + | otherwise = rotl l y (insertRoot x r) + +-- Randomized binary tree +data RBTree a = RBTree StdGen Int (BTree a) + +empty :: RBTree a +empty = RBTree (mkStdGen 42) 0 Empty + +-- chance of 1 / n+1 of inserting at root. +insert' :: Ord a => a -> RBTree a -> RBTree a +insert' x (RBTree seed n t) = RBTree seed' (n+1) (f x t) + where + f = case p of + 0 -> insertRoot + _ -> insert + (p, seed') = randomR (0,n) seed \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/code/randomized treap.hs b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/code/randomized treap.hs new file mode 100644 index 0000000..2a785d6 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 15 - (Treaps)/code/randomized treap.hs @@ -0,0 +1,26 @@ +import System.Random (StdGen, mkStdGen, random) +-- node random :: StdGen -> (Int, StdGen) + +data RTreap a = RTreap StdGen (Treap a) + +insert :: Ord a => a -> RTreap a -> RTreap a +insert x (RTreap seed t) = RTreap seed' (pinsert x p t) + where (p, seed') = random seed + +-- note 42 is used for +empty :: RTreap a +empty = RTreap (mkStdGen 42) Empty + +-- Build up tree, requires O(n log n) +fromList :: Ord a => [a] -> RTreap a +fromList xs = foldr insert empty xs + +-- Linear time conversion (use treap tolist) +toList :: RTreap a -> [a] +toList (RTreap _ t) = tolist t + +-- Randomiozed Quicksort O(n log n) +-- Effectively the random priorities are the partitions, first pivot is the +-- highest priority. +rquicksort :: Ord a => [a] -> [a] +rquicksort = toList . fromList \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/Lecture 16.pdf b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/Lecture 16.pdf new file mode 100644 index 0000000..68fcaa1 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/Lecture 16.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/Lecture 16.tex b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/Lecture 16.tex new file mode 100644 index 0000000..0376ac1 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/Lecture 16.tex @@ -0,0 +1,34 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 16} + \author{Oliver Killane} + \date{18/12/21} +\input{../50001 common.tex} +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=940579d0-4ab4-41d0-a3a9-adf8008866f0} + +\section*{Mutable Algorithms} +We can use \struct{STRef} \var{s} \var{a} to hold a mutable reference to +\var{a} that can be created, read and modified. +\codelist{Haskell}{st.hs} + +We can use this to create a mutable version of fibonacci. +\codelist{Haskell}{fib.hs} + +\section*{Mutable Datastructures} +\subsection*{Array} +\codelist{Haskell}{array.hs} +Each operation is assumed to take constant time. +\\ +\\ For example, an algorithm to find the smallest natural number not in a list. +\codelist{Haskell}{minfree.hs} + +\subsection*{Hash} +\codelist{Haskell}{hash.hs} +A hash generates an integer from some data. Typically range restricted +(e.g hashmap can hold a finite number of entries), and the hash function +should be designed to reduce collisions (two distinct data having the same hash). +\\ +\\ Below is an example of a bucket based hash map, using linked list buckets. +\centerimage{width=0.6\textwidth}{hash diagram.png} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/array.hs b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/array.hs new file mode 100644 index 0000000..02541bb --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/array.hs @@ -0,0 +1,13 @@ +import Control.Monad.ST +import Data.Array.ST + +-- Use indexable i, range, default to get a mutable array in some state +newArray :: Ix i => (i,i) -> a -> ST s (STArray s i a) + +-- Use indexable i, a mutable array and return the value a with state s +readArray :: Ix i -> STArray s i a -> i -> ST s a + +-- Use indexable i, a mutable array, and the value to place, return a +-- computation that updates the array (new state) but returns no value. +-- note: +writeArray :: Ix i => STArray s i a -> i -> a -> ST s () \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/fib.hs b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/fib.hs new file mode 100644 index 0000000..7e41d49 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/fib.hs @@ -0,0 +1,24 @@ +import Data.STRef (newSTRef, readSTRef, writeSTRef) +import Control.Monad.ST (runST) + +-- immutable looping fibonacci +fib :: Int -> Integer +fib n = loop n 0 1 + where + loop :: Int -> Integer -> Integer -> Integer + loop 0 x y = x + loop n x y = loop (n-1) y (x+y) + +-- mutable looping fibonacci +fib0 :: Int -> Integer +fib0 n = runST $ do + rx <- newSTRef 0 + ry <- newSTRef 1 + let loop 0 = do readSTRef rx + loop n = do { + x <- readSTRef rx; + y <- readSTRef ry; + writeSTRef rx y; + writeSTRef ry (x + y); + loop (n - 1);} + loop n \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/hash.hs b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/hash.hs new file mode 100644 index 0000000..c73ba37 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/hash.hs @@ -0,0 +1,2 @@ +class Hashable a where + hash :: a -> Int \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/minfree.hs b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/minfree.hs new file mode 100644 index 0000000..570e46e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/minfree.hs @@ -0,0 +1,36 @@ +import Data.Array.MArray (MArray(newArray)) +import Data.Array.ST +import Control.Monad.ST +import Data.List ((\\)) + +-- immutable +minfree :: [Int] -> Int +minfree xs = head ( [0..] \\ xs ) + +-- effectively the same as minfree +minfree' :: [Int] -> Int +minfree' xs = head . filter(not . (`elem` xs)) $ [0..] + + +-- Builds up an array of which are present, +minfreeMut :: [Int] -> Int +minfreeMut = length . takeWhile id . checklist + +{- +Build an array, at each index True/False for if the index is in xs +We only need to use an array of size (length xs) as we do not care about +natural numbers larger than this (if they are in the list, then a smaller +natural number was missed). + +xs [0,1,2,3,6,7,8] +ys [T,T,T,T,F,F,T] ... (don't care about 7 or 8) + +-} +checklist :: [Int] -> [Bool] +checklist xs = runST $ do { + ys <- newArray (0,l - 1) False :: ST s (STArray s Int Bool); + sequence [writeArray ys x True | x <- xs, x < l]; + getElems ys; + } + where + l = length xs diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/st.hs b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/st.hs new file mode 100644 index 0000000..db1ff55 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/code/st.hs @@ -0,0 +1,19 @@ + +-- State Transformer (ST) takes a state s and return value a. +-- "Give me any program with any state s, and if it returns an a, so will I". +runST :: (forall s . ST s a) -> a + +-- Take a value a, produces a program with some state s, that returns a +-- reference with that state and the value stored. +newSTRef :: a -> ST s (STRef s a) + +-- Takes in a reference in some state s, performs a computation to get a +readSTRef :: STRef s a -> ST s a + +-- Take in a reference, and a new value a, performing a computation to update +-- the referenced value (update does not return anything itself, hence ()). +writeSTRef :: STRef s a -> a -> ST s () + +-- Takes a value, returns a computation that executes in any state s to return +-- an a. +return :: a -> ST s a \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/diagram/hash diagram.drawio b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/diagram/hash diagram.drawio new file mode 100644 index 0000000..0532bf5 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/diagram/hash diagram.drawio @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/image/hash diagram.png b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/image/hash diagram.png new file mode 100644 index 0000000..e5b59f5 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 16 - (Mutable Algorithms)/image/hash diagram.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/Lecture 17.pdf b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/Lecture 17.pdf new file mode 100644 index 0000000..15b8c94 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/Lecture 17.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/Lecture 17.tex b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/Lecture 17.tex new file mode 100644 index 0000000..3002f97 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/Lecture 17.tex @@ -0,0 +1,21 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 17} + \author{Oliver Killane} + \date{18/12/21} +\input{../50001 common.tex} +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=78ea6bc7-9ac6-47ae-8bc9-adf8008866b4} + +\section*{Mutable Nub} +This can be useful for the \fun{nub} function (removes duplicates from a list) by using a bucket based hashmap of items from the list to determine duplication. +\codelist{Haskell}{nub.hs} + +\section*{Quicksort} +We can also implement quicksort, which can be done in place in an array +(saved memory and time as accesses are constant time). +\\ +\\ By using mutable data structures we can swap elements when reordering by reading and writing from the array. +\codelist{Haskell}{quicksort.hs} + +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/code/nub.hs b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/code/nub.hs new file mode 100644 index 0000000..ff38566 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/code/nub.hs @@ -0,0 +1,29 @@ +import Control.Monad (when) +import Data.Array.ST + ( getElems, newListArray, readArray, writeArray, STArray ) +import Control.Monad.ST ( ST, runST ) + + +-- immutable version: +nub :: Eq a => [a] -> [a] +nub = reverse . foldl nubHelper [] + where + nubHelper :: Eq a => [a] -> a -> [a] + nubHelper ns c + | c `elem` ns = ns + | otherwise = c:ns + +-- mutable version, create a hash table of characters to track which have +-- already been seen. +nubMut :: (Hashable a, Eq a) => [a] -> [a] +nubMut xs = concat $ runST $ do + axss <- newListArray (0, n - 1) (replicate 256 [ ]) :: ST s (STArray s Int [a]) + sequence [do { + let hx = hash x `mod` (n - 1) + ys <- readArray axss hx + unless (x `elem` ys) $ do writeArray axss hx (x : ys)} + | x <- xs] + getElems axss + where + -- number of buckets in the hash table + n = 256 \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/code/quicksort.hs b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/code/quicksort.hs new file mode 100644 index 0000000..4c3e218 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 17 - (Mutable Algorithms II)/code/quicksort.hs @@ -0,0 +1,47 @@ +import Data.Array.ST ( readArray, writeArray, STArray, getElems ) +import Control.Monad.ST ( ST ) + +-- swap elements over (classic store in temp & swap over other before writeback) +swap :: STArray s Int a -> Int -> Int -> ST s () +swap axs i j = do + temp <- readArray axs i + readArray axs j >>= writeArray axs i + writeArray axs j temp + +qsort :: Ord a => [a] -> [a] +qsort xs = runST $ do + axs <- newListArray (0,n) xs + aqsort axs 0 n + getElems axs + where + n = length xs - 1 + +{- +Partition around a pivot (k) (all smaller to left, larger to right +(unsorted)), then recur on these partitions +Index: 0 (k-1) k (k+1) n +Contents: [ ..<= x .. ][x][ .. >x ..] +-} +aqsort :: Ord a => STArray s Int a -> Int -> Int -> ST s () +aqsort axs i j + | i >= j = return () + | otherwise = do + k <- apartition axs i j + aqsort axs i (k - 1) + aqsort axs (k + 1) j + +apartition :: Ord a => STArray s Int a -> Int -> Int -> ST s Int +apartition asx p q = do + x <- readArray axs p + let loop i j + | i > j = do + swap axs p j + return j + | otherwise = do + u <- readArray axs i + if u < x + then do loop (i + 1) j + else do + swap axs i j + loop i (j - 1) + loop (p+1) q \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/Lecture 2.pdf b/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/Lecture 2.pdf new file mode 100644 index 0000000..bece841 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/Lecture 2.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/Lecture 2.tex b/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/Lecture 2.tex new file mode 100644 index 0000000..bda38bb --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/Lecture 2.tex @@ -0,0 +1,139 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 2} + \author{Oliver Killane} + \date{12/11/21} + +\input{../50001 common.tex} + +\newcommand{\cond}[3]{\text{if } #1 \text{ then } #2 \text{ else } #3} + +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=c8abc020-d7c8-44ad-b1df-adc100991181} + +\section*{Evaluation \& Cost Models} +\codelist{Haskell}{minimum.hs} +When analysing the cost of \fun{minimum} we must consider how the function is evaluated. +\\ +\\ For example we could shortcut the once \fun{isort} has determined the first element (the minimum) of the list. +\\ +\sidenote{Cost Model}{ + A model to determine the time taken to execute a program. + \\ + \\ The model assigns cost to different operations (e.g comparisons, calls, memory reads/writes) + \\ + \\ A very generalised cost model assigns cost based on the number of \keyword{reductions} required to evaluate a program. +} + +\section*{Small While Language} +We can define a small language of expressions as follows: +\[e ::= x \ | \ k \ | \ f \ e_1 \dots e_n \ | \ \cond{e}{e_1}{e_2}\] +where $k$ means constant and $x$ is the variable form. +\\ Infix functions such as $+, -, \times$ are written normally, and are also expressions as they can be used in the form $(+) \ e_1 \ e_2$. +\\ +\\ There are also several primitive constants: $True, False, 0, 1, 2, \dots$ +\\ List constants and operations are also primitive: $[], (:), null, head, tail$ + +\section*{Evaluation Order} +\begin{itemize} + \bullpara{Applicative Order}{ Strict evaluation + \\The leftmost, innermost reducible expression is evaluated first. + \\ e.g for $fst (3 \times 2, 1 + 2)$ + \\ \begin{steps} + \start{fst (3 \times 2, 1 + 2)} + \step{ fst (6, 1 + 2)}{Definition of $\times$} + \step{fst (6, 3)}{ Definition of $+$} + \step{6}{Definition of $fst$} + \end{steps} + } + \bullpara{Normal Order}{ Lazy evaluation + \\ The leftmost outer reducible is evaluated first. Efectively evaluating the function before its arguments. + \\ e.g for $fst (0, 1 + 2)$ + \\ \begin{steps} + \start{fst (3 \times 2, 1 + 2)} + \step{3 \times 2}{ Definition of $fst$} + \step{6}{ Definition of $\times$} + \end{steps} + } +\end{itemize} +For a given program, if \keyword{applicative} and \keyword{normal} terminate, then they produce the same value in normal form. +\\ +\\ However there are some programs where \keyword{normal} evaluation terminates, but \keyword{applicative} will not. +\begin{minipage}[t]{0.4\textwidth} + \centerline{\textbf{Applicative}} + \begin{steps} + \start{fst (0, \text{crazy nonesense})} + \step{CRASH!}{ By lack of definition for crazy nonesense} + \end{steps} +\end{minipage} +\hfill +\begin{minipage}[t]{0.4\textwidth} + \centerline{\textbf{Normal}} + \begin{steps} + \start{fst (0, \text{crazy nonesense})} + \step{0}{ Definition of $fst$} + \end{steps} +\end{minipage} +The program may by syntactically correct, but have an error such as zero-division which will not be evaluated and hence not result in improper termination under \keyword{normal} order. +\begin{large} \[\text{Applicative Terminates} \Rightarrow \text{Normal Terminates}\] \end{large} + +\section*{Cost Model for Small While} +We can evaluate a cost model for the small while language by creating a function $T$ to assign cost to expressions. +\\\begin{tabular}{p{0.25\textwidth} p{0.35\textwidth} p{0.4\textwidth}} + \textbf{Type} & \textbf{Function} & \textbf{Explanation} \\ + \hline + non-primitive function & $\begin{matrix} + f \ a_1 \ \dots \ a_n = e \\ + T(f) \ a_1 \ \dots \ a_n = T(e) + 1 \\ + \end{matrix}$ & Given we have already computed all argument, the cost of the function is the cost of the expression it produces, and a single call. \\ + \hline + primitive function & $T(f) \ x \dots \ x_n = 0$ & Primitive functions are assumed to be free. \\ + \hline + Variable & $T(x) = 0$ & accessing variables is free. \\ + \hline + Application & $T(f \ e_1 \ \dots \ e_n) = T(f) \ e_1 \ \dots \ e_n + T(e_1) + \dots + T(e_n)$ & When applying a function we must consider both its cost, and the cost of all argument expressions. \\ + \hline + Conditional & $T(\cond{p}{e_1}{e_2}) = T(p) + \cond{p}{T(e_1)}{T(e_2)}$ & Cost of condition and of the resulting expression. \\ +\end{tabular} + +\section*{Cost Model Example} +Given the function: +\[mul \ m \ n = \cond{m=0}{0}{n + mul \ (m-1) \ n}\] +Evaluate $T(mul \ 3 \ 100)$ +\\ +\begin{proof} + \proofstep{1}{$mul \ 3 \ 100$}{} + \proofstep{2}{$T(\cond{3=0}{0}{100 + mul \ (3-1) \ 100}) + 1$}{By Rule for non-primitive functions} + \proofstep{3}{$T(3=0) + T(100 + mul \ (3-1) \ 100) + 1$}{By rule for conditionals} + \proofstep{4}{$0 + T(100 + mul \ (3-1) \ 100) + 1$}{By primitive functions} + \proofstep{5}{$T(+) (100 \ mul \ (3-1) \ 100) + T(100) + T(mul \ (3-1) \ 100) + 1$}{By application rule} + \proofstep{6}{$0 + T(100) + T(mul \ (3-1) \ 100) + 1$}{By rule for primitive functions} + \proofstep{7}{$0 + T(mul \ (3-1) \ 100) + 1$}{By rule for constants} + \proofstep{8}{$T(mul) \ (3-1) \ 100 + T(3 - 1) + T(100) + 1$}{By application rule} + \proofstep{9}{$T(mul) \ (3-1) \ 100 + T(-) 3 \ 1 + T(100) + 1$}{By application rule} + \proofstep{10}{$T(mul) \ 2 \ 100 + 1$}{By application rule} + \proofstep{11}{$T(\cond{2=0}{0}{100 + mul \ (2-1) \ 100}) + 1 + 1$}{By Rule for non-primitive functions} + \proofstep{12}{$T(2=0) + T(100 + mul \ (2-1) \ 100) + 2$}{By rule for conditionals} + \proofstep{13}{$0 + T(100 + mul \ (2-1) \ 100) + 2$}{By primitive functions} + \proofstep{14}{$T(+) (100 \ mul \ (2-1) \ 100) + T(100) + T(mul \ (2-1) \ 100) + 2$}{By application rule} + \proofstep{15}{$0 + T(100) + T(mul \ (2-1) \ 100) + 2$}{By rule for primitive functions} + \proofstep{16}{$0 + T(mul \ (2-1) \ 100) + 2$}{By rule for constants} + \proofstep{17}{$T(mul) \ (2-1) \ 100 + T(2 - 1) + T(100) + 2$}{By application rule} + \proofstep{18}{$T(mul) \ (2-1) \ 100 + T(-) 2 \ 1 + T(100) + 2$}{By application rule} + \proofstep{19}{$T(mul) \ 1 \ 100 + 2$}{By application rule} + \proofstep{20}{$T(\cond{1=0}{0}{100 + mul \ (1-1) \ 100}) + 2 + 1$}{By Rule for non-primitive functions} + \proofstep{21}{$T(2=0) + T(100 + mul \ (1-1) \ 100) + 3$}{By rule for conditionals} + \proofstep{22}{$0 + T(100 + mul \ (1-1) \ 100) + 3$}{By primitive functions} + \proofstep{23}{$T(+) (100 \ mul \ (1-1) \ 100) + T(100) + T(mul \ (1-1) \ 100) + 3$}{By application rule} + \proofstep{24}{$0 + T(100) + T(mul \ (1-1) \ 100) + 3$}{By rule for primitive functions} + \proofstep{25}{$0 + T(mul \ (1-1) \ 100) + 3$}{By rule for constants} + \proofstep{26}{$T(mul) \ (1-1) \ 100 + T(1 - 1) + T(100) + 3$}{By application rule} + \proofstep{27}{$T(mul) \ (1-1) \ 100 + T(-) 2 \ 1 + T(100) + 3$}{By application rule} + \proofstep{28}{$T(mul) \ 0 \ 100 + 3$}{By application rule} + \proofstep{29}{$T(\cond{0=0}{0}{100 + mul \ (1-1) \ 100}) + 3 + 1$}{By Rule for non-primitive functions} + \proofstep{30}{$T(0=0) + T(0) + 4$}{By rule for conditionals} + \proofstep{31}{$0 + T(0) + 4$}{By rule for primitive functions} + \proofstep{32}{$0 + 4$}{By rule for variables} + \proofstep{33}{$4$}{} +\end{proof} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/code/minimum.hs b/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/code/minimum.hs new file mode 100644 index 0000000..c22cf23 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 2 - (Evaluation)/code/minimum.hs @@ -0,0 +1,2 @@ +minimum :: [Int] -> Int +minimum = head . isort \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/Lecture 3.pdf b/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/Lecture 3.pdf new file mode 100644 index 0000000..e9cef54 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/Lecture 3.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/Lecture 3.tex b/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/Lecture 3.tex new file mode 100644 index 0000000..147a248 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/Lecture 3.tex @@ -0,0 +1,67 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 3} + \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=5df30741-34e2-4e90-adcd-adc2013d7aaf} + +\section*{Asymptotics} +\sidenote{L-Function}{ + A \keyword{Logarithmico-exponential} function $f$ is: + \compitem{ + \item real: $f \in X \to Y$ where $X,Y \subset \mathbb{R}$ + \item positive: $\forall x \in X . [f(x) \leq 0]$ + \item monotonic: $\forall x_1, x_2 \in X . [x_1 < x_2 \Leftrightarrow f(x_1) < f(x_2)]$ (positive monotonic) or $\forall x_1, x_2 \in X . [x_1 < x_2 \Leftrightarrow f(x_1) > f(x_2)]$ (negative monotonic) + \item one valued: $\forall x\in X, y_1, y_2 \in Y . [f(x) = y_1 \land f(x) = y_2 \Rightarrow y_1 = y_2]$ + \item on a real variable defined for all values greater than some definite value: $X \equiv \{x | x > \text{definite limit} \land x \in \mathbb{R}\}$ + } + + \keyword{L-Functions} are continuous, of constant sign and as $n \to \infty$ the value $f(n)$ tends to $0, \infty$ or some other positive definite limit. + \\ + \\ Functions that aren't \keyword{L-Functions} are called \keyword{Wild Functions}. +} + +In asymptotics we use \keyword{L-Functions} to describe the growth of time used by algorithms as the size of the input to an algorithm grows. +\\ +\\ Common functions are shown below: +\centerimage{width=\textwidth}{L-Function plots.png} + +\section*{Du Bois-Reymond Theorem} +Defines inequalities for the rate of increase of functions. +\\ +\\ Where $lim = \lim_{n \to \infty}{\cfrac{f(n)}{g(n)}}$ +\begin{proof} + \proofstep{$<$}{$f \prec g \Leftrightarrow lim = 0$}{$g$ grows much faster than $f$} + \proofstep{$\leq$}{$f \preccurlyeq g \Leftrightarrow lim < \infty$}{$g$ grows much faster than $f$ or some multiple of $f$} + \proofstep{$=$}{$f \asymp g \Leftrightarrow 0 < lim < \infty$}{$g(n)$ grows towards some constant times $f(n)$} + \proofstep{$\geq$}{$f \succcurlyeq g \Leftrightarrow lim > 0$}{$f$ grows much faster than $g$ or some multiple of $g$} + \proofstep{$>$}{$f \succ g \Leftrightarrow lim = \infty$}{$f$ grows much faster than $g$} +\end{proof} +These operators form a trichotomy such that one of the below will always hold: +\[\begin{matrix} + f \prec g & f \asymp g & f \succ g + \end{matrix}\] +Further the operators $\succ$ and $\prec$ are converse: +\[f \succ g \Leftrightarrow g \prec f\] +And transitive: +\[\begin{matrix} + f \prec g \land g \prec h \Rightarrow f \prec h \\ + f \preccurlyeq g \land g \preccurlyeq h \Rightarrow f \preccurlyeq h \\ + \end{matrix}\] +We can place the common \keyword{L-Functions} in order: +\[1 \prec \log{n} \prec \sqrt{n} \prec n \prec n \log{n} \prec n^2 \prec n^3 \prec n! \prec n^n\] + +\section*{Bachman-Landau Notation} +\[\begin{matrix} + \text{Comparison with Bois-Reymond} & \text{Set definition} \\ + f \in o(g(n)) \Leftrightarrow f \prec g & o(g(n)) = \{f | \forall \delta > 0. \exists n_0 > 0.\forall n > n_0 [f(n) < \delta g(n)]\} \\ + f \in O(g(n)) \Leftrightarrow f \preccurlyeq g & O(g(n)) = \{f | \exists \delta > 0. \exists n_0 > 0.\forall n > n_0 [f(n) \leq \delta g(n)]\} \\ + f \in \Theta (g(n)) \Leftrightarrow f \asymp g & \Theta (g(n)) = O(g(n)) \cap \Omega(g(n)) \\ + f \in \Omega (g(n)) \Leftrightarrow f \succcurlyeq g & \Omega (g(n)) = \{f | \exists \delta > 0. \exists n_0 > 0.\forall n > n_0 [f(n) \geq \delta g(n)]\} \\ + f \in \omega (g(n)) \Leftrightarrow f \succ g & \omega (g(n)) = \{f | \forall \delta > 0. \exists n_0 > 0.\forall n > n_0 [f(n) > \delta g(n)]\} \\ + \end{matrix}\] +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/image/L-Function plots.png b/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/image/L-Function plots.png new file mode 100644 index 0000000..df28ff7 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 3 - (Asymptotics)/image/L-Function plots.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/Lecture 4.pdf b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/Lecture 4.pdf new file mode 100644 index 0000000..ff5888a Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/Lecture 4.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/Lecture 4.tex b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/Lecture 4.tex new file mode 100644 index 0000000..9ee7f36 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/Lecture 4.tex @@ -0,0 +1,99 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 4} + \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=8ddef027-50cb-4256-9115-adc50139006e} + +\section*{Lists} +\codelist{Haskell}{list.hs} +\centerimage{width=0.6\textwidth}{list anatomy.png} +Lists in \keyword{Haskell} are a persistent data structure, meaning that when operations are applied to lists the original list is maintained (not mutated). + +\subsubsection*{Append} +We can append lists, by traversing over the first list, copying values (this ensures both argument lists are preserved). +\codelist{Haskell}{append.hs} +\centerimage{width=\textwidth}{list structure.png} +As the entire first list must be traversed, the cost of $xs ++ ys$ is $T_{(++)}(n) \in O(n)$ where $n = length \ xs$ + +\subsubsection*{Foldr} +\codelist{Haskell}{foldr.hs} +\centerimage{width=0.8\textwidth}{foldr.png} +As you can see, $foldr \ (:) \ [] \equiv id$. +\\ Foldr can also be expressed through bracketing +\[foldr \ f \ k \ [x_1, x_2, \dots, x_n] \equiv f \ x_1 \ (f \ x_2 \ ( \dots (f \ x_n \ k) \dots))\] + +\sidenote{Associativity}{ + \keyword{Associativity} determines how operations are grouped in the absence of brackets. + \[\begin{matrix} + a \spadesuit b \spadesuit c & \text{unbracketed statement} \\ + ((a) \spadesuit b) \spadesuit c & \spadesuit \text{ is left associative} \\ + a \spadesuit (b \spadesuit (c)) & \spadesuit \text{ is right associative} \\ + \end{matrix}\] + If $\spadesuit$ is associative, then the right \& left associative versions are equivalent. +} +\fun{foldr} applies functions in a right-associative scheme. + +\subsubsection*{Foldl} +\codelist{Haskell}{foldl.hs} +\centerimage{width=0.8\textwidth}{foldl.png} +As you can see $foldl \ (snoc) \ [] \equiv id$. +\\ Foldl can be expressed through bracketing +\[foldl \ f \ k \ [x_1, x_2, \dots, x_n] \equiv f \ (\dots (f \ (f \ k \ x_1) x_2) \dots x_n)\] + +\section*{Monoids} +Consider the case when for some $\bigstar $ and $\epsilon$: $foldr \ \bigstar \ \epsilon \equiv foldl \ \bigstar \ \epsilon$. +For this to be possible for $\bigstar \ :: \ a \to a \to a$ and $\epsilon \ :: \ a$. +\begin{center} + \begin{tabular}{r l} + $\bigstar$ must be associative & $x \ \bigstar \ (y \ \bigstar \ z) \equiv (x \ \bigstar \ y) \ \bigstar z$ \\ + $\epsilon$ must have no effect & $\epsilon \ \bigstar \ n = n$ \\ + \end{tabular} +\end{center} +These properties for a \keyword{monoid} $(a, \bigstar, \epsilon)$. +\\ Other example include: +\[\begin{matrix} + (lists, ++, []) & (\mathbb{N}, +, 0) & (\mathbb{N}, \times, 1) & (bool, \land, true) \\ + (bool, \lor, false) & (\mathbb{R}, max, \infty) & (\mathbb{R}, min, -\infty) & (Universal \ set, \cup, \emptyset) \\ + \end{matrix}\] +We can also find monoids of functions: +\[(a \to a, (.), id)\] +as $(id \ . \ g) x \equiv id (g \ x)$ and $((f \ . \ g) \ . h) x = f(g(h \ x))$ + +\section*{Concat} +We can easily define concat recursively as: +\codelist{Haskell}{concat.hs} +We can also notice that $([[a]], (++), [])$ is a monoid, so we can use \fun{foldr} or \fun{foldl} +\\\begin{minipage}[t]{0.45\textwidth} + \codelist{Haskell}{concatr.hs} +\end{minipage} +\hfill +\begin{minipage}[t]{0.45\textwidth} + \codelist{Haskell}{concatl.hs} +\end{minipage} +as \fun{(++)} makes a copy of the first argument (to ensure persistent data), if we apply is in a left associative bracketing scheme we will have to make larger \& larger copies. +\[( \dots (((( [ \ ] \text{++}_{0} \ xs_1) \text{++}_{m} \ xs_2) \text{++}_{2m} \ xs_3) \text{++}_{3m} \ xs_4 \dots) \text{++}_{mn} \ xs_n\] +Hence where $n = length \ xss$ and $m = length \ xs_1 = length \ xs_2 = \dots = length \ xs_n$. +\[\begin{matrix} + T_{concatl}(m,n) \in O(n^2m) \\ + T_{concatr}(m,n) \in O(nm) \\ + \end{matrix}\] + +\section*{DLists} +Instead of storing a list, we store a composition of functions that build up a list. + +\[ \begin{matrix} + xs_1 \text{++} xs_2 \text{++} xs_3 \text{++} \dots \text{++} xs_n \\ + \Downarrow \\ + f \ xs_1 \bullet f \ xs_2 \bullet f \ xs_3 \bullet \dots \bullet f \ xs_n \\ + \Downarrow \\ + (xs_1 \ \text{++}) \bullet (xs_2 \ \text{++}) \bullet (xs_3 \ \text{++}) \bullet \dots \bullet (xs_n \ \text{++}) \\ + \end{matrix}\] +We can then apply this function on the empty list $[ \ ]$ to get the resulting list. +\codelist{haskell}{DList.hs} +We can form a \keyword{monoid} of ($DList$,++,$DList \ id$). +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/DList.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/DList.hs new file mode 100644 index 0000000..e85a2db --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/DList.hs @@ -0,0 +1,11 @@ +newtype DList a = DList ([a] -> [a]) + +instance List DList where + toList :: DList a -> [a] + toList (DList fxs) = fxs [] + + fromList :: [a] -> DList a + fromList xs = DList (xs++) + + (++) :: DList a -> DList a -> DList a + DList fxs ++ DList fys = DList(fxs . fys) diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/append.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/append.hs new file mode 100644 index 0000000..14dd30e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/append.hs @@ -0,0 +1,3 @@ +(++) :: [a] -> [a] -> [a] +[] ++ ys = ys +(x:xs) ++ ys = x:(xs ++ ys) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concat.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concat.hs new file mode 100644 index 0000000..25b694d --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concat.hs @@ -0,0 +1,3 @@ +concat :: [[a]] -> [a] +concat [] = [] +concat (xs:xss) = xs ++ concat xss diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concatl.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concatl.hs new file mode 100644 index 0000000..06a7d2b --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concatl.hs @@ -0,0 +1,2 @@ +concatr :: [[a]] -> [a] +concatr = foldl (++) [] diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concatr.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concatr.hs new file mode 100644 index 0000000..1398aec --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/concatr.hs @@ -0,0 +1,2 @@ +concatr :: [[a]] -> [a] +concatr = foldr (++) [] diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/foldl.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/foldl.hs new file mode 100644 index 0000000..f2ccc41 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/foldl.hs @@ -0,0 +1,3 @@ +foldl :: (b -> a -> b) -> b -> [a] -> b +foldl f k [] = k +foldl f k (x:xs) = foldl f (f k x) xs \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/foldr.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/foldr.hs new file mode 100644 index 0000000..cd19896 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/foldr.hs @@ -0,0 +1,3 @@ +foldr :: (a -> b -> b) -> b -> [a] -> b +foldr f k [] = k +foldr f k (x:xs) = f x (foldr f k xs) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/list.hs b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/list.hs new file mode 100644 index 0000000..693a595 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/code/list.hs @@ -0,0 +1,6 @@ +data List [a] = [] | (:) a [a] + +-- or... +data List a where + Empty :: List a + Cons :: a -> List a -> List a \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/foldl.drawio b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/foldl.drawio new file mode 100644 index 0000000..4cba94a --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/foldl.drawio @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/foldr.drawio b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/foldr.drawio new file mode 100644 index 0000000..738f8e0 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/foldr.drawio @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/list anatomy.drawio b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/list anatomy.drawio new file mode 100644 index 0000000..e289d84 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/list anatomy.drawio @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/list structure.drawio b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/list structure.drawio new file mode 100644 index 0000000..dcee5c9 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/diagram/list structure.drawio @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/foldl.png b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/foldl.png new file mode 100644 index 0000000..88865e1 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/foldl.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/foldr.png b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/foldr.png new file mode 100644 index 0000000..24e115b Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/foldr.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/list anatomy.png b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/list anatomy.png new file mode 100644 index 0000000..3494171 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/list anatomy.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/list structure.png b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/list structure.png new file mode 100644 index 0000000..c907c5a Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 4 - (Lists)/image/list structure.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/Lecture 5.pdf b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/Lecture 5.pdf new file mode 100644 index 0000000..d502a59 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/Lecture 5.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/Lecture 5.tex b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/Lecture 5.tex new file mode 100644 index 0000000..fe343b7 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/Lecture 5.tex @@ -0,0 +1,39 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 5} + \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=7cfe76ce-2e38-465f-a1d0-adc800b8a764} + +\section*{DLists Continued\dots} +\subsubsection*{Monoids (again)} +A \keyword{monoid} is a triple $(M, \diamond, \epsilon)$ where $\diamond$ is associative and of type $M \to M \to M$, and $x \diamond \epsilon \equiv x$. +\codelist{Haskell}{monoid.hs} +A haskell typeclass can then be instantiated for many other data types. For example the \keyword{monoid} $(\mathbb{Z}, +, 0)$ (note that we cannot enforce \keyword{monoid} properties through haskell, unlike languages such as \keyword{agda}). +\codelist{Haskell}{integer monoid.hs} +Likewise we can abstract Lists to a class (which we can instantiate for DLists). + +\subsubsection*{List Class} +\codelist{Haskell}{list class.hs} +$[a]$ is out abstract list type, and $list a$ is our concrete type. +\\ +\\ It is critical to ensure that $toList \ \bullet \ fromList \equiv id$ +\\ But in general $fromList \ \bullet \ toList \not\equiv id$ (this is as the internal representation may change +and much information about the internal representaion cannot be preserved by toList, for example an unbalanced tree +changed to a list maybe be balanced when converted back to a tree). +\\ +\\ We also included $normalise \ :: \ fromList \ \bullet \ toList$ as a useful tool to reset the internal structure (for example to rebalanced the tree representation of a list) + +\section*{Haskell Implementation} +To prevent conflicts due to Prelude functions already being defined we can use: +\codelist{Haskell}{import prelude.hs} +To help ensure correctness we can use \keyword{Quickcheck} to check properties +\codelist{Bash}{get quickcheck.sh} +Then can use quickcheck to define properties we want to test: +\codelist{Haskell}{use quickcheck.hs} +\codelist{Bash}{run quickcheck.sh} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/get quickcheck.sh b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/get quickcheck.sh new file mode 100644 index 0000000..6954d71 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/get quickcheck.sh @@ -0,0 +1 @@ +cabal install --lib QuickCheck \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/import prelude.hs b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/import prelude.hs new file mode 100644 index 0000000..325b16e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/import prelude.hs @@ -0,0 +1,2 @@ +import Prelude hiding(head, tail, (++), etc...) +import qualified Prelude diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/integer monoid.hs b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/integer monoid.hs new file mode 100644 index 0000000..08fad52 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/integer monoid.hs @@ -0,0 +1,9 @@ +-- declaring newtype so that many monoid instance on Int do not conflict +newtype PlusInt = PlusInt Int + +instance Monoid PlusInt where + (<>) :: PlusInt -> PlusInt -> PlusInt + (<>) = (+) + + mempty :: PlusInt + mempty = 0 diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/list class.hs b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/list class.hs new file mode 100644 index 0000000..965ea7f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/list class.hs @@ -0,0 +1,19 @@ +class List list where + empty :: list a + single :: a -> list a + + (:) :: a -> list a -> list a + snoc :: list a -> list a -> list a + + head :: list a -> a + tail :: list a -> list a + + last :: list a -> a + init :: list a -> list a + + (++) :: list a -> list a -> list a + + length :: list a -> Int + + fromList :: [a] -> list a + toList :: list a -> [a] \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/monoid.hs b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/monoid.hs new file mode 100644 index 0000000..27da2b1 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/monoid.hs @@ -0,0 +1,3 @@ +class Monoid m where + (<>) :: m -> m -> m + mempty :: m diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/run quickcheck.sh b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/run quickcheck.sh new file mode 100644 index 0000000..b6b872b --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/run quickcheck.sh @@ -0,0 +1,15 @@ +ghci file_to_check.hs +*file_to_check> quickCheck (prop_normalise :: [Int] -> Bool) ++++ OK, passed 100 tests. +*file_to_check> quickCheck (prop_normalise :: [Bool] -> Bool) ++++ OK, passed 100 tests. +*file_to_check> verboseCheck (prop_normalise :: [Bool] -> Bool) +Passed: +... + +Passed: +... + +etc... + ++++ OK, passed 100 tests. \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/use quickcheck.hs b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/use quickcheck.hs new file mode 100644 index 0000000..1416492 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 5 - (Abstraction)/code/use quickcheck.hs @@ -0,0 +1,15 @@ +import Test.QuickCheck + +-- code to test written here ... + +prop_propertyname :: InputTypes -> Bool +prop_propertyname = test code + +-- example for normalise (takes a list type, that has equality defined for it) +prop_normalise (Eq a, Eq (list a), List list) => list a -> Bool +prop_normalise xs = (toList . fromList) xs == xs + +-- Can return properties (requires show) using the triple-equals +prop_assoc :: (Eq (list a), Show (list a), List list) + => list a -> list a -> list a -> Property +prop_assoc xs ys zs = (xs ++ ys) ++ zs === xs ++ (ys ++ zs) diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/Lecture 6.pdf b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/Lecture 6.pdf new file mode 100644 index 0000000..af3c235 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/Lecture 6.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/Lecture 6.tex b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/Lecture 6.tex new file mode 100644 index 0000000..40c2455 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/Lecture 6.tex @@ -0,0 +1,72 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 6} + \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=0cc4b21b-9502-4919-8602-adcc00d14ece} + +\section*{Divide \& Conquer} +\begin{enumerate} + \item Divide a problem into subproblems + \item Divide and conquer subproblems into subsolutions + \item Conquer subsolutions into a solution +\end{enumerate} +\centerimage{width=0.35\textwidth}{divide and conquer.png} + +\section*{Merge Sort} +\codelist{Haskell}{merge sort.hs} +\fun{SplitAt} divides, and \fun{merge} Conquers. We can calculate the time complexity for the recurrence relations below (based on recursive structure of \fun{msort}): +\\ \begin{tabular}{l l } + $T_{msort}(0) $ & $= 1 $ \\ + $T_{msort}(1) $ & $= 1 $ \\ + $T_{msort}(n) $ & $= T_{length}(n) + T_{splitAt}(\cfrac{n}{2}) + T_{merge}(\cfrac{n}{2}) + 2 \times T_{msort}(\cfrac{n}{2}) $ \\ +\end{tabular} + +We can simplify the complexity of \fun{msort} +\\ \begin{tabular}{l l } + $T_{msort}(n) $ & $= T_{length}(n) + T_{splitAt}(\cfrac{n}{2}) + T_{merge}(\cfrac{n}{2}) + 2 \times T_{msort}(\cfrac{n}{2}) $ \\ + & $= n + \cfrac{n}{2} + \cfrac{n}{2} + \cfrac{n}{2} + 2\times T_{msort}(\cfrac{n}{2})$ \\ + & $= \cfrac{5}{2} \times n + 2\times T_{msort}(\cfrac{n}{2})$ \\ +\end{tabular} +\sidenote{Master Theorem}{ + For an algorithm $algo$ such that: + \[T_{algo}(n) = a \times T_{algo}(\cfrac{n}{b}) + f(n) + \text{base cases}\] + The work at recursion level $\log_bn$ is $\Theta(a^{\log_bn})$ + To calculate the order of the time complexity: + \begin{enumerate} + \item Get the recurrence relation in the form above. + \item Get the critical exponent $E$ by formula: $E = \log_ba = \cfrac{\log a}{\log b}$. + \item Given $f(n) = n^c$ we can express the work as a geometric sum $\sum_{i=0}^{\log n}ar^i$ where $r = \cfrac{a}{b^c}$. + \end{enumerate} + \[r > 1 \Leftrightarrow a > b^c \Leftrightarrow \log_b a > c \Leftrightarrow E > c\] + \[\begin{matrix} + E < c & T_{algo}(n) \in \Theta(f(n)) \\ + E = c & T_{algo}(n) \in \Theta(f(n)\log_bn) = \Theta(f(n) \log n) \\ + E > c & T_{algo}(n) \in \Theta(a^{\log_bn}) = \Theta(n^{\log_ba}) = \Theta(n^E) \\ + \end{matrix}\] +} +By master theorem we can easily see $T_{msort}(n) \in \Theta(n \log n)$. +We can also calculate it using a graph: +\centerimage{width=0.4\textwidth}{mergesort.png} + +\section*{Quicksort} +\codelist{Haskell}{quick sort.hs} +Note for simplicity, we assume the lists are split into equal parts. +\\ \begin{tabular}{l l } + $T_{qsort}(0) $ & $= 1$ \\ + $T_{qsort}(1) $ & $= 1$ \\ + $T_{qsort}(n) $ & $= T_{partition}(n-1) + T_{++}(\cfrac{n}{2}) + 2 \times T_{qsort}(\cfrac{n}{2})$ \\ +\end{tabular} +\\In the worst case, the partition splits $xs$ into $(xs, [])$, we have complexity: +\\ \begin{tabular}{l l } + $T_{qsort}(n) $ & $= T_{partition}(n-1) + T_{++}(n-1) + T_{qsort}(0) + T_{qsort}(n-1)$ \\ + & $= 2(n-1) + n + 1 + T_{qsort}(n-1)$ \\ +\end{tabular} +\centerimage{width=0.4\textwidth}{quicksort.png} +We can once again use master theorem, or a diagram such as below to see the complexity: +Hence in the worst case $T_{qsort}(n) \in O(n^2)$ (same as insertion sort). +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/code/merge sort.hs b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/code/merge sort.hs new file mode 100644 index 0000000..61bc5cf --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/code/merge sort.hs @@ -0,0 +1,12 @@ +msort :: Ord a => [a] -> [a] +msort [] = [] +msort [x] = [x] +msort xs = merge (msort us) (msort vs) + where (us,vs) = splitAt (length xs `div` 2) xs + +merge :: Ord a => [a] -> [a] -> [a] +merge [] ys = ys +merge xs [] = xs +merge xss@(x:xs) yss@(y:ys) + | x <= y = x : merge xs yss + | otherwise = y : merge xss ys \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/code/quick sort.hs b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/code/quick sort.hs new file mode 100644 index 0000000..2674123 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/code/quick sort.hs @@ -0,0 +1,10 @@ +qsort :: Ord a => [a] -> [a] +qsort [] = [] +qsort [x] = [x] +qsort (x:xs) = qsort us ++ x:qsort vs + where (us, vs) = partition ( Bool) -> [a] -> ([a],[a]) +partition p xs = (filter p xs, filter (not . p) xs) + +dxgfdg \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/divide and conquer.drawio b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/divide and conquer.drawio new file mode 100644 index 0000000..61e52b8 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/divide and conquer.drawio @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/mergesort.drawio b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/mergesort.drawio new file mode 100644 index 0000000..1f77c8f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/mergesort.drawio @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/quicksort.drawio b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/quicksort.drawio new file mode 100644 index 0000000..32f5cde --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/diagram/quicksort.drawio @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/divide and conquer.png b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/divide and conquer.png new file mode 100644 index 0000000..ec8bda1 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/divide and conquer.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/mergesort.png b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/mergesort.png new file mode 100644 index 0000000..54736cd Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/mergesort.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/quicksort.png b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/quicksort.png new file mode 100644 index 0000000..5532725 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 6 - (Divide and Conquer)/image/quicksort.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/Lecture 7.pdf b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/Lecture 7.pdf new file mode 100644 index 0000000..4d9d6cf Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/Lecture 7.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/Lecture 7.tex b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/Lecture 7.tex new file mode 100644 index 0000000..44c1e11 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/Lecture 7.tex @@ -0,0 +1,66 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 7} + \author{Oliver Killane} + \date{13/11/21} + +\input{../50001 common.tex} + +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=6348fa64-2119-481e-b96b-adcf00dfa196} + +\section*{Dynamic Programming} +A technique to efficiently calculate solutions to certain recursive problems. +\begin{enumerate} + \item Describe an inefficient recursive algorithm. + \item Reduce inefficiency by storing intermediate shared results. +\end{enumerate} + +\section*{Fibonacci Sequence} +\subsubsection*{Fully Recursive} +\codelist{Haskell}{recursive fib.hs} +\begin{tabular}{l l} + $T_{fib}(0)$ & $= 1$ \\ + $T_{fib}(1)$ & $= 1$ \\ + $T_{fib}(n)$ & $= 1 + T_{fib}(n-2) + T_{fib}(n-1)$ \\ +\end{tabular} +\\ The complexity of this algorithm is $T_{fib}(n) \in O(2^n)$. +\subsubsection*{Saving Intermediate Results} +We can use a helper function which takes the remaining number of additions, and the two previous values. +\codelist{Haskell}{more parameter fib.hs} +\begin{tabular}{l l} + $T_{fib}(0)$ & $= 1$ \\ + $T_{fib}(1)$ & $= 1$ \\ + $T_{fib}(n)$ & $= 1 + T_{fib}(n-1)$ \\ +\end{tabular} +\\The complexity of this algorithm is $T_{fib}(n) \in O(n)$. +\\ +\\ This way every value is calculated only once for each call. However values are not saved between calls. +\subsubsection*{Memoisation} +\codelist{Haskell}{memoising fib.hs} +This creates a large list, we must only index on the list to get the value. +By using an array we can reduce the time taken to get to the $n$th element. +\subsubsection*{Array Based Memoisation} +\codelist{Haskell}{memoisation functions.hs} +Hence we can make our algorithm: +\codelist{Haskell}{array memoised fib.hs} +Here we can do constant time lookups for values in the table. If a value is not present, it is lazily evaluated using other elements in the table. +\\ +\\ In this way we only calculate each fibonacci number once, and only when we need it. Further it is saved for any subsequent calls to fib. + +\section*{Edit-Distance} +The \keyword{Edit-Distance} Problem is concered with calculating the \keyword{Levenshtein} distance between two strings. +\sidenote{Levenshtein Distance}{ + The number of insertions, deletions \& updates required to convert one string into another. + \[toil \to_{+1} oil \to_{+1} il \to_{+1} ill\] +} + +\codelist{Haskell}{dist recursive.hs} +This problem becomes of order $O(3^n)$ as it recurs 3 ways for each call. +\\ +\\ We can reuse results for two substrings through memoisation, first we make a new recursive version that uses the index we are checking in each string: +\codelist{Haskell}{dist indexed.hs} +We can then use \fun{tabulate} to create a memoised version. +\codelist{Haskell}{dist memoised.hs} +As there are at most $m \times n$ entires in the table, and each are calculated at most once, and the lookup time is constant (using arrays), the complexity is $O(mn)$. +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/array memoised fib.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/array memoised fib.hs new file mode 100644 index 0000000..321ffac --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/array memoised fib.hs @@ -0,0 +1,12 @@ +import Data.Array ( Array, (!) ) + +fib :: Int -> Integer +fib n = table ! n + where + table :: Array Int Integer + table = tabulate (0,n) memo + + memo :: Int -> Integer + memo 0 = 0 + memo 1 = 1 + memo n = table ! (n-2) + table ! (n-1) diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist indexed.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist indexed.hs new file mode 100644 index 0000000..8fea69f --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist indexed.hs @@ -0,0 +1,15 @@ +dist :: String -> String -> Int +dist xs ys = dist' xs ys (length xs) (length ys) + +dist' :: String -> String -> Int -> Int -> Int +dist' xs ys i 0 = i +dist' xs ys 0 j = j +dist' xs ys i j + = minimum [dist' xs ys i (j-1) + 1, + dist' xs ys (i-1) j + 1, + dist' xs ys (i-1) (j-1) + if x == y then 0 else 1] + where + m = length xs + n = length ys + x = xs !! (m-i) + y = ys !! (n-j) \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist memoised.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist memoised.hs new file mode 100644 index 0000000..f9282bb --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist memoised.hs @@ -0,0 +1,23 @@ +import Data.Array ( Array, (!) ) + +dist :: String -> String -> Int +dist xs ys = table ! (m,n) + where + table = tabulate ((0,0),(m,n)) (uncurry memo) + + memo :: Int -> Int -> Int + memo i 0 = i + memo 0 j = j + memo i j + = minimum [table ! (i, j - 1) + 1, + table ! (i-1,j) + 1, + table ! (i - 1,j - 1) + if x == y then 0 else 1] + where + x = ays ! (m - i) + y = ays ! (n - j) + + m = length xs + n = length ys + axs,ays :: Array Int Char + axs = fromList xs + ays = fromList ys \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist recursive.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist recursive.hs new file mode 100644 index 0000000..f6b829e --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/dist recursive.hs @@ -0,0 +1,8 @@ +dist :: String -> String -> Int +dist xs [] = length xs +dist [] ys = length ys +dist xxs@(x:xs) yys@(y:ys) + = minimum + [dist xxs ys + 1, + dist xs yys + 1, + dist xs ys + if x == y then 0 else 1] diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/memoisation functions.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/memoisation functions.hs new file mode 100644 index 0000000..c54c776 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/memoisation functions.hs @@ -0,0 +1,17 @@ +-- Array Data Type +import Data.Array ( Ix(range), Array, array ) + +-- Tabulate function +tabulate :: Ix i => (i,i) -> (i -> e) -> Array i e +tabulate (a,b) f = array (a,b) [(i,f i) | i <- range (a,b)] + +-- Ix (class of all indexes) + +-- T(!) is in O(1) +(!) :: Ix i => Array i e -> i -> e + +-- Range creates a lits of indexes in a range +range :: Ix i => (i,i) -> [i] + +-- Array function creates an array from a range of indexes & values +array :: Ix i => (i,i) -> [(i,e)] -> Array i e \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/memoising fib.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/memoising fib.hs new file mode 100644 index 0000000..da45e87 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/memoising fib.hs @@ -0,0 +1,5 @@ +fibs :: [Integer] +fibs = 0 : 1 : zipWith (+) fibs (tail fibs) + +fib :: Int -> Integer +fib n = fibs !! n \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/more parameter fib.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/more parameter fib.hs new file mode 100644 index 0000000..09b75fa --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/more parameter fib.hs @@ -0,0 +1,6 @@ +fib :: Int -> Integer +fib n = fibHelper n 0 1 + where + fibHelper :: Int -> Integer -> Integer -> Integer + fibHelper 0 x y = x + fibHelper n x y = fibHelper (n-1) y (x + y) diff --git a/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/recursive fib.hs b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/recursive fib.hs new file mode 100644 index 0000000..ab417eb --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 7 - (Dynamic Programming)/code/recursive fib.hs @@ -0,0 +1,4 @@ +fib :: Int -> Integer +fib 0 = 0 +fib 1 = 1 +fib n = fib (n-1) + fib (n-2) diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/Lecture 8.pdf b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/Lecture 8.pdf new file mode 100644 index 0000000..23b4310 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/Lecture 8.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/Lecture 8.tex b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/Lecture 8.tex new file mode 100644 index 0000000..21445e9 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/Lecture 8.tex @@ -0,0 +1,84 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 8} + \author{Oliver Killane} + \date{17/11/21} + +\input{../50001 common.tex} + +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=77a4fe23-79fb-4468-8f5c-add300eedc4d} + +\section*{Amortized Analysis} +So far we have studied complexity of a single, isolated run of an algorithm. \keyword{Amortizsed Analysis} is about understanding cost in a wider context (e.g averaged over many calls to a routine). + +\section*{Dequeues} +\sidenote{Dequeue}{ + A Dequeue is a double ended queue. An abstract datatype that generalises a queue. Elements can be added or removed from either end. + \\ + \\ Common associated funtions are: + \begin{center} + \begin{tabular}{l l} + \fun{snoc} & Insert element at the back of the queue. \\ + \fun{cons} & Insert element at the front of the queue. \\ + \fun{eject} & Remove last element. \\ + \fun{pop} & remove fist element. \\ + \fun{peek} & Examine but do not remove first element. \\ + \end{tabular} + \end{center} + Dequeues are also called head-tail linked lists or symmetric lists. +} +we use a dequeue when we want to reduce the time taken to perform certain operations. +\subsubsection*{List Operation Complexity} +\centerimage{width=0.4\textwidth}{list anatomy.png} +\begin{minipage}[t]{0.4\textwidth} + \begin{center} + \begin{tabular}{l l} + \fun{cons} & O(1) \\ + \fun{head} & O(1) \\ + \fun{tail} & O(1) \\ + \end{tabular} + \end{center} +\end{minipage} +\hfill +\begin{minipage}[t]{0.4\textwidth} + \begin{center} + \begin{tabular}{l l} + \fun{snoc} & O(1) \\ + \fun{last} & O(1) \\ + \fun{init} & O(1) \\ + \end{tabular} + \end{center} +\end{minipage} +\subsubsection*{Dequeue Structure} +To achieve $O(1)$ complexity in the \fun{snoc}, \fun{init} and \fun{last} we use two lists. +\centerimage{width=0.7\textwidth}{dequeue structure.png} +One list starts contains the start of the list, and the other the end (reversed). +\\ +\\ We keep two invariants for $Dequeue \ us \ sv$: +\[null \ us \Rightarrow null \ sv \lor single \ sv\] +\[null \ sv \Rightarrow null \ us \lor single \ us\] +In other words, if one list is empty, the other can contain at most 1 element. +\\ +\\ An example implementation in haskell is below: +\codelist{Haskell}{dequeue declaration.hs} + +When considering the cost of \fun{tail} and \fun{init} we must consider that there are two possibilities: +\begin{center} + \begin{tabular}{l l p{7cm}} + High Cost & $\begin{matrix} + init (Dequeue \ us \ [s]) \\ + tail (Dequeue \ [u] \ sv) \\ + \end{matrix}$ + & This operation is $O(n)$ complexity due to the \fun{spitAt} and \fun{reverse} operation done on half of a list. \\ + Low Cost & $\begin{matrix} + init (Dequeue \ us \ (s:sv)) \\ + tail (Dequeue \ (u:us) \ sv) \\ + \end{matrix}$ & Low cost $O(1)$ operation as it requires only a pattern match on the first element. \\ + \end{tabular} +\end{center} +As both of these operations rebalance the \keyword{Dequeue} to to be balanced (half the queue on each list), we these operations can have an amortized cost of $O(1)$. +\\ +\\ We know this as the average cost is of order $O(1)$. The $O(n)$ cost is incurred every $n/2$ calls to \fun{tail}/\fun{init}. +\centerimage{width=0.6\textwidth}{dequeue tail.png} +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/code/dequeue declaration.hs b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/code/dequeue declaration.hs new file mode 100644 index 0000000..47d87ed --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/code/dequeue declaration.hs @@ -0,0 +1,65 @@ +-- can ignore certain patterns due to invariant +{-# OPTIONS_GHC -Wno-incomplete-patterns #-} + +data Dequeue a = Dequeue [a] [a] + +instance List Dequeue where + toList :: Dequeue a -> [a] + toList (Dequeue us sv) = us ++ reverse sv + + fromList :: [a] -> Dequeue a + fromList xs = Dequeue us (reverse vs) + where (us,vs) = splitAt (length xs `div` 2) xs + + -- use the invariant, if [] sv then sv = [x] or [] + + -- O(1) + cons :: a -> Dequeue a -> Dequeue a + cons x (Dequeue us []) = Dequeue [x] us + cons x (Dequeue us sv) = Dequeue (x:us) sv + + -- O(1) + snoc :: Dequeue a -> a -> Dequeue a + snoc (Dequeue [] sv) x = Dequeue sv [x] + snoc (Dequeue us sv) x = Dequeue us (x:sv) + + -- O(1) + last :: Dequeue a -> a + last (Dequeue _ (s:_)) = s + last (Dequeue [u] _) = u + last (Dequeue [] []) = error "Nothing in the dequeue" + + -- O(1) + head :: Dequeue a -> a + head (Dequeue (u:_) _) = u + head (Dequeue [] [v]) = v + head (Dequeue [] []) = error "Nothing in the dequeue" + + -- O(1) + tail :: Dequeue a -> Dequeue a + tail (Dequeue [] []) = error "Nothing in the dequeue" + tail (Dequeue [] _) = empty + tail (Dequeue _ []) = empty + tail (Dequeue [u] sv) = Dequeue (reverse su) + where + n = length sv + (su, sv') = splitAt (n `div` 2) sv + -- note: could also do a fromList (reverse sv) but less efficient + + tail (Dequeue (u:us) sv) = Dequeue us sv + + -- O(1) + init :: Dequeue a -> Dequeue a + init (Dequeue [] []) = error "Nothing in the dequeue" + init (Dequeue [] _) = empty + init (Dequeue _ []) = empty + init (Dequeue us [s]) = fromList us + init (Dequeue us (s:sv)) = Dequeue us sv + + isEmpty :: Dequeue a -> Bool + isEmpty (Dequeue [] []) = True + isEmpty _ = False + + empty :: Dequeue a + empty = Dequeue [] [] + diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/dequeue structure.drawio b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/dequeue structure.drawio new file mode 100644 index 0000000..6df0526 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/dequeue structure.drawio @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/dequeue tail.drawio b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/dequeue tail.drawio new file mode 100644 index 0000000..b0ec1e6 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/dequeue tail.drawio @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/list anatomy.drawio b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/list anatomy.drawio new file mode 100644 index 0000000..e289d84 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/diagram/list anatomy.drawio @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/dequeue structure.png b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/dequeue structure.png new file mode 100644 index 0000000..4bc231e Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/dequeue structure.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/dequeue tail.png b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/dequeue tail.png new file mode 100644 index 0000000..630d1a0 Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/dequeue tail.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/list anatomy.png b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/list anatomy.png new file mode 100644 index 0000000..6f507df Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 8 - (Amortized Analysis)/image/list anatomy.png differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/Lecture 9.pdf b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/Lecture 9.pdf new file mode 100644 index 0000000..f8ab5ed Binary files /dev/null and b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/Lecture 9.pdf differ diff --git a/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/Lecture 9.tex b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/Lecture 9.tex new file mode 100644 index 0000000..fc54ca4 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/Lecture 9.tex @@ -0,0 +1,82 @@ +\documentclass{report} + \title{50001 - Algorithm Analysis and Design - Lecture 9} + \author{Oliver Killane} + \date{17/11/21} + +\input{../50001 common.tex} + +\begin{document} +\maketitle +\lectlink{https://imperial.cloud.panopto.eu/Panopto/Pages/Viewer.aspx?id=83376d33-8332-4d64-abce-add60165e432} +\section*{Amortization} +The complexity of \fun{tail} is an example of \keyword{Amortized analysis}, where operation's wider context are considered when calculating the complexity. +\[xs_0 \overset{op_0}{\leadsto} xs_1 \overset{op_1}{\leadsto} xs_2 \overset{op_2}{\leadsto} xs_3 \overset{op_3}{\leadsto} \dots \overset{op_{n-1}}{\leadsto} xs_n\] +We defined 3 parts: +\begin{enumerate} + \bullpara{Cost Function}{ + \\ $C_{op_i}(xs_i)$ determines the cost of operation $op_i$ on data $xs_i$. Estimating how many steps it takes for each operation to execute. + } + \bullpara{Amortized Cost Function}{ + \\ $A_{op_i}(xs_i)$ for each operation $op_i$ on data $xs_i$. + } + \bullpara{Size Function}{ + \\ $S(xs)$ that calculates the size of data $xs$ + } +\end{enumerate} +We define these functions with the goal to show that: +\[C_{op_i}(xs_i) \leq A_{op_i} (xs_i) + S(xs_i) - S(xs_{i+1})\] +The cost of the operation is smaller than the amortized cost, plus the difference in size of the data structure before and after the operation. +\\ +\\ Once this is shown, we can infer that: +\[\sum^{n-1}_{i=0}C_{op_i}(xs_i) \leq \sum^{n-1}_{i=0}A_{op_i}(xs_i) + S(xs_0) - S(xs_n)\] +Furthermore when $S(xs_0) = 0$ this implies: +\[\sum^{n-1}_{i=0}C_{op_i}(xs_i) \leq \sum^{n-1}_{i=0}A_{op_i}(xs_i) - S(xs_n) \Rightarrow \sum^{n-1}_{i=0}C_{op_i}(xs_i) \leq \sum^{n-1}_{i=0}A_{op_i}(xs_i)\] +This means the cost of the operations is less than the sum of the amortized costs. +\\ +\\ For example, if $A_{op_i}(xs) = 1$ then the total cost will be bounded by $O(n)$. + +\subsubsection*{Tail example} +\[\begin{matrix} + C_{cons}(xs) = 1 & C_{snoc}(xs) = 1 & C_{head}(xs) = 1 & C_{last}(xs) = 1 \\ + \end{matrix}\] +For tail we can do the following: +\\ \begin{proof} + \proofstep{1}{$C_{tail}(Dequeue \ us \ sv) = length \ sv$}{Create a cost function of \fun{tail}.} + \proofstep{2}{$A_{op}(xs) = 2$}{Create an arbitrary cost function.} + \proofstep{3}{$S(Dequeue \ us \ sv) = |length \ us - length \ sv|$}{Create a size function for \keyword{dequeue}.} + \proofstep{4}{$Dequeue \ us \ sv \text{ where } length \ sv = k$}{Worst case where $us$ is a singleton} + \proofstep{5}{$\begin{matrix} + S(Dequeue \ us \ sv) = k - 1 \\ + S(Dequeue \ us' \ sv') = 1 \\ + \end{matrix}$}{Size of the next data structure can be at most $1$.} + \proofstep{6}{$C_{tail}(Dequeue \ us \ sv) = k$}{Calculate the worst case cost of \fun{tail}.} + \proofstep{7}{$k \leq 2 + (k-1) - 1 = k + 2$}{As this inequality holds, the time complexity of all $n$ instructions is $O(n)$.} +\end{proof} +As the time complexity of all $n$ instructions together is $O(n)$, the amortized cost of a single instruction is $O(1)$. + +\subsubsection*{About the size function} +We want to balance the size function such that: +\compitem{ + \item The size function is $0$ to start with. + \item The size between operations is large enough to prove the inequality. +} +The size function is arbitrary, if you cannot choose a size function that satisfied the goal inequality, then you're probably making a mistake + +\subsubsection*{Peano Numbers} +\codelist{Haskell}{peano.hs} +This shows how similar operations of similarly structured data can be. + +\section*{Binary Numbers} +\codelist{Haskell}{binary.hs} +we can do amortized analysis on incr: +\begin{proof} + \proofstep{1}{$C_{incr}(bs) = t + 1$ where $t = length \ (takeWhile \ (==I) \ bs)$}{Create a cost function.} + \proofstep{2}{$A_{incr}(bs) = 2$}{Create Amortized Cost} + \proofstep{3}{$S(bs) = length . filter \ (==I) \ \$ \ bs $}{Create size function.} + \proofstep{4}{Given $bs' = incr \ bs$ we show $C_{incr}(bs) \leq A_{incr}{bs} + S(bs) - S(bs')$}{Setup inequality} + \proofstep{5}{$t + 1 \leq 2 + S(bs) - (S(bs) - t + 1)$}{Subsitiute in inequality} + \proofstep{6}{$t + 1 \leq 1 + t$}{Hence inequality holds} + \proofstep{7}{$S(start) = 0$}{Start size is zero.} +\end{proof} +Hence The sum of $C$ is smaller than the sum of $A$, as this is over $n$ operations and $\sum A = 2n$, $C_{incr}(bs) \in O(1)$. +\end{document} diff --git a/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/code/binary.hs b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/code/binary.hs new file mode 100644 index 0000000..15e9f19 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/code/binary.hs @@ -0,0 +1,9 @@ +data Bit = I | O + +-- [LSB,...,MSB] +type Binary = [Bit] + +incr :: Binary -> Binary +incr [] = [I] +incr (O:bs) = I:bs +incr (I:bs) = O:incr bs diff --git a/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/code/peano.hs b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/code/peano.hs new file mode 100644 index 0000000..280c046 --- /dev/null +++ b/50001 - Algorithm Analysis and Design/Lecture 9 - (Amortized Incrementing)/code/peano.hs @@ -0,0 +1,18 @@ +data Peano = Zero | Succ Peano + +-- analogous to (:) Cons +incr :: Peano -> Peano +incr = Succ + +-- analogous to tail +decr :: Peano -> Peano +decr (Succ n) = n +decr Zero = error "Cannot decrement zero" + +-- analogous to (++) concatenate +add :: Peano -> Peano -> Peano +add a Zero = a +add a (Succ b) = Succ (add a b) + +-- tail recursive version for extra goodness! +add a b = add (incr a) (decr b) diff --git a/50001 - Algorithm Analysis and Design/README.md b/50001 - Algorithm Analysis and Design/README.md index 4ccbd91..46c8e8d 100644 --- a/50001 - Algorithm Analysis and Design/README.md +++ b/50001 - Algorithm Analysis and Design/README.md @@ -26,4 +26,6 @@ The module syllabus includes: ## Lecturer [Dr Nicolas Wu](https://zenzike.com/) -[Back to main notes](../README.md) \ No newline at end of file +[Back to main notes](../README.md) + +TODO: add extra credit for Yelun \ No newline at end of file