\lab{Data Structures I: Linked Lists}{Linked Lists}
\label{lab:Python_DataStructures}

\objective{Analyzing and manipulating data are essential skills in scientific computing.
Storing, retrieving, and rearranging data take time.
As a dataset grows, so does the amount of time it takes to access and analyze it.
To write effecient algorithms involving large data sets, it is therefore essential to be able to design or choose the data structures that are most optimal for a particular problem.
In this lab we begin our study of data structures by constructing a generic linked list, then using it to implement a few common data structures.}

\section*{Introduction} % =====================================================

\emph{Data structures} are specialized objects for organizing data efficiently.
There are many kinds, each with specific strengths and weaknesses, and different applications require different structures for optimal performance.
For example, some data structures take a long time to build, but once built their data are quickly accessible.
Others are built quickly, but are not as efficiently accessible.
These strengths and weaknesses are determined by how the structure is implemented.

Python has several built-in data structure classes, namely \li{list}, \li{set}, \li{dict}, and \li{tuple}.
Being able to use these structures is important, but selecting the correct data structure to begin with is often what makes or breaks a good program.
In this lab we create a structure that mimics the built-in list class, but that has a different underlying implementation.
Thus our class will be better than a plain Python list for some tasks, but worse for others.

\subsection*{Nodes} % ---------------------------------------------------------

Think of data as several types of objects that need to be stored in a warehouse.
A \emph{node} is like a standard size box that can hold all the different types of objects.
For example, suppose a particular warehouse stores lamps of various sizes.
Rather than trying to carefully stack lamps of different shapes on top of each other, it is preferable to first put them in boxes of standard size.
Then adding new boxes and retrieving stored ones becomes much easier.
A \emph{data structure} is like the warehouse, which specifies where and how the different boxes are stored.

A node class is usually simple.
The data in the node is stored as an attribute.
Other attributes may be added (or inherited) specific to a particular data structure.

\begin{problem} % Restricting data types of the Node class.
Consider the following generic node class.
\begin{lstlisting}
class Node(object):
    """A basic node class for storing data."""
    def __init__(self, data):
        """Store 'data' in the 'value' attribute."""
        self.value = data
\end{lstlisting}

Modify the constructor so that it only accepts data of type \li{int}, \li{long}, \li{float}, or \li{str} (comparable types).
If another type of data is given, raise a \li{TypeError} with an appropriate error message.
Modify the constructor docstring to document these restrictions.
\end{problem}

\begin{info}
Often the data stored in a node is actually a \emph{key} value.
The key might be a memory address, a dictionary key, or the index of an array where the true desired information resides.
For simplicity, in this and the following lab we store actual data in node objects, not references to data located elsewhere.
\end{info}

\section*{Linked Lists} % =====================================================

A \emph{linked list} is a data structure that chains nodes together.
Every linked list needs a reference to the first node in the chain, called the \li{head}.
A reference to the last node in the chain, called the \li{tail}, is also often included.
Each node instance in the list stores a piece of data, plus at least one reference to another node in the list.

The nodes of a \emph{singly linked list} have a single reference to the next node in the list (see Figure \ref{fig:singly_linked}), while the nodes of a \emph{doubly linked list} have two references: one for the previous node, and one for the next node in the list (see Figure \ref{fig:doubly_linked}).
This allows for a doubly linked list to be traversed in both directions, whereas a singly linked list can only be traversed in one direction.

\begin{lstlisting}
class LinkedListNode(Node):
    """A node class for doubly linked lists. Inherits from the 'Node' class.
    Contains references to the next and previous nodes in the linked list.
    """
    def __init__(self, data):
        """Store 'data' in the 'value' attribute and initialize
        attributes for the next and previous nodes in the list.
        """
        Node.__init__(self, data)       # Use inheritance to set self.value.
        self.<<next>> = None
        self.prev = None
\end{lstlisting}

\begin{figure} % Singly linked list.
\centering
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto, node distance=1.5cm,thick,main node/.style={rectangle,draw}, minimum size=.5cm]
\tikzset{rect node/.style={rectangle, draw, minimum height = .5cm, minimum width=.2cm}}
    \node[main node] (1) {A};
    \node[main node] (2) [right of=1] {B};
    \node[main node] (3) [right of=2] {C};
    \node[main node] (4) [right of=3] {D};
    \node[draw = none, black!20!blue, node distance=1.5cm] [above left of=1](H) {Head};
\foreach \r in {1, 2, 3, 4}{
    \node[rect node][right of=\r, node distance = .36cm]{};}
\node[draw = none, node distance = 1.5cm] [right of=4]{};
\foreach \s/\t  in {1/2, 2/3, 3/4}{\path[draw](\s) edge[shorten <=.1cm](\t);}
    \draw[black!20!blue] (H) edge (1.north);
\end{tikzpicture}
\caption{A singly linked list. Each node has a reference to the next node in the list. The head attribute is always assigned to the first node.}
\label{fig:singly_linked}
\end{figure}

\begin{figure} % Doubly linked list.
\centering
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto, node distance=1.5cm, thick,main node/.style={rectangle,draw}, minimum size=.5cm]
\tikzset{rect node/.style={rectangle, draw, minimum height = .5cm, minimum width=.9cm}}
    \node[main node] (1) {A};
    \node[main node] (2) [right of=1] {B};
    \node[main node] (3) [right of=2] {C};
    \node[main node] (4) [right of=3] {D};
    \node[draw=none, node distance=.07cm] (1up) [above of=1] {};
    \node[draw=none, node distance=.07cm] (1dn) [below of=1] {};
    \node[draw=none, node distance=.07cm] (2up) [above of=2] {};
    \node[draw=none, node distance=.07cm] (2dn) [below of=2] {};
    \node[draw=none, node distance=.07cm] (3up) [above of=3] {};
    \node[draw=none, node distance=.07cm] (3dn) [below of=3] {};
    \node[draw=none, node distance=.07cm] (4up) [above of=4] {};
    \node[draw=none, node distance=.07cm] (4dn) [below of=4] {};
    \node[draw = none, black!20!blue, node distance = 1.5cm] [above right of=4] (T) {Tail};
    \node[draw = none, black!20!blue, node distance = 1.5cm] [above left of=1] (H) {Head};
    \node[rect node](1.5)[]{};
    \node[rect node](2.5)[right of=1.5]{};
    \node[rect node](3.5)[right of=2.5]{};
    \node[rect node](4.5)[right of=3.5]{};
\foreach \s/\t  in {1up/2up, 2dn/1dn, 2up/3up, 3dn/2dn, 3up/4up, 4dn/3dn}{
        \path[draw](\s) edge[shorten <=.1cm, shorten >=.1cm](\t);}
    \draw[black!20!blue] (H) edge (1.north);
    \draw[black!20!blue] (T) edge (4.north);
\end{tikzpicture}
\caption{A doubly linked list. Each node has a reference to the node before it and a reference to the node after it. In addition to the head attribute, this list has a tail attribute that is always assigned to the last node.}
\label{fig:doubly_linked}
\end{figure}

Now we create a new class, \li{LinkedList}, that will link \li{LinkedListNode} instances together by modifying each node's \li{<<next>>} and \li{prev} attributes.
The list is empty initially, so we assign the \li{head} and \li{tail} attributes the placeholder value \li{None}.

%\subsection*{append()}

We also need a method for adding data to the list.
The \li{append()} makes a new node and adds it to the very end of the list.
There are two cases to consider: appending to an empty list, and appending to a nonempty list.
See Figure \ref{fig:append}.

\begin{lstlisting}
class LinkedList(object):
    """Doubly linked list data structure class.

    Attributes:
        head (LinkedListNode): the first node in the list.
        tail (LinkedListNode): the last node in the list.
    """
    def __init__(self):
        """Initialize the 'head' and 'tail' attributes by setting
        them to 'None', since the list is empty initially.
        """
        self.head = None
        self.tail = None

    def append(self, data):
        """Append a new node containing 'data' to the end of the list."""
        # Create a new node to store the input data.
        new_node = LinkedListNode(data)
        if self.head is None:
            # If the list is empty, assign the head and tail attributes to
            # new_node, since it becomes the first and last node in the list.
            self.head = new_node
            self.tail = new_node
        else:
            # If the list is not empty, place new_node after the tail.
            self.tail.<<next>> = new_node               # tail --> new_node
            new_node.prev = self.tail               # tail <-- new_node
            # Now the last node in the list is new_node, so reassign the tail.
            self.tail = new_node
\end{lstlisting}

\begin{figure} % append().
\centering
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto, node distance=1.6cm,thick,main node/.style={rectangle,draw}, minimum size=.5cm]
\tikzset{rect node/.style={rectangle, draw, minimum height = .5cm, minimum width=.2cm}}
    \node[main node] (1) {A};
    \node[main node] (2) [right of=1] {B};
    \node[main node] (3) [right of=2] {C};
    \node[main node] (5) [right of=3, node distance=3.5cm] {A};
    \node[main node] (6) [right of=5] {B};
    \node[main node] (7) [right of=6] {C};
    \node[draw=none, node distance=.07cm] (1up) [above of=1] {};
    \node[draw=none, node distance=.07cm] (1dn) [below of=1] {};
    \node[draw=none, node distance=.07cm] (2up) [above of=2] {};
    \node[draw=none, node distance=.07cm] (2dn) [below of=2] {};
    \node[draw=none, node distance=.07cm] (3up) [above of=3] {};
    \node[draw=none, node distance=.07cm] (3dn) [below of=3] {};
    \node[draw=none, node distance=.07cm] (5up) [above of=5] {};
    \node[draw=none, node distance=.07cm] (5dn) [below of=5] {};
    \node[draw=none, node distance=.07cm] (6up) [above of=6] {};
    \node[draw=none, node distance=.07cm] (6dn) [below of=6] {};
    \node[draw=none, node distance=.07cm] (7up) [above of=7] {};
    \node[draw=none, node distance=.07cm] (7dn) [below of=7] {};
    \node[draw=none, black!20!blue, node distance=1.5cm] [above left of=1](H1) {Head};
    \node[draw = none, black!20!blue, node distance=1.5cm] [above right of=2](T1) {Tail};
    \node[draw=none, black!20!blue, node distance=1.5cm] [above left of=5](H2) {Head};
    \node[draw = none, black!20!blue, node distance=1.5cm] [above right of=7](T2) {Tail};
\foreach \r in {1, 2, 3, 5, 6, 7}{
        \node[rect node][right of=\r, node distance = .36cm]{};
        \node[rect node][left  of=\r, node distance = .36cm]{};}
\foreach \s/\t in {1up/2up, 2dn/1dn, 5up/6up, 6dn/5dn}{
        \path[draw](\s) edge[shorten <=.1cm, shorten >=.1cm](\t);}
\foreach \s/\t in {6up/7up, 7dn/6dn}{
        \path[draw](\s) edge[red, shorten <=.1cm, shorten >=.1cm](\t);}
    \draw[black!20!blue, shorten >=.1cm] (H1) edge (1.north);
    \draw[black!20!blue, shorten >=.1cm] (T1) edge (2.north);
    \draw[black!20!blue, shorten >=.1cm] (H2) edge (5.north);
    \draw[black!20!blue, shorten >=.1cm] (T2) edge (7.north);
\end{tikzpicture}
\caption{Appending a new node to the end of a nonempty doubly linked list. The red arrows are the new connections. Note that the \li{tail} attribute is adjusted.}
\label{fig:append}
\end{figure}

\begin{warn} % Warning about 'is' vs '=='.
The \li{is} comparison operator is \textbf{not} the same as the \li{==} comparison operator.
While \li{==} checks for numerical equality, \li{is} evaluates whether or not two objects are at the same location in memory.

\begin{lstlisting}
# This comparison evaluates to True since the numerical values are the same.
>>> 7 == 7.0
True

# 7 is an int and 7.0 is a float, so they cannot be stored at the same
# location in memory. Therefore 7 'is not' 7.0.
>>> 7 is 7.0
False
\end{lstlisting}

For numerical comparisons, always use \li{==}.
When comparing to built-in Python constants such as \li{None}, \li{True}, \li{False}, or \li{NotImplemented}, use \li{is} instead.
\end{warn}

\subsection*{find()} % --------------------------------------------------------

The \li{LinkedList} class only explicitly keeps track of the first and last nodes in the list via the \li{head} and \li{tail} attributes.
To access any other node, we must use each successive node's \li{<<next>>} and \li{prev} attributes.

\begin{lstlisting}
>>> my_list = LinkedList()
>>> my_list.append(2)
>>> my_list.append(4)
>>> my_list.append(6)

# To access each value, we use the 'head' attribute of the LinkedList
# and the 'next' and 'value' attributes of each node in the list.
>>> my_list.head.value
2
>>> my_list.head.<<next>>.value
4
>>> my_list.head.<<next.next>>.value
6
>>> my_list.head.<<next.next>> is my_list.tail
True
>>> my_list.tail.prev.prev is my_list.head
True
\end{lstlisting}

% Problem 2: LinkedList.find()
\begin{problem}
Add a method called \li{find(self, data)} to the \li{LinkedList} class that
returns the first node in the list containing \li{data} (return the actual \li{LinkedListNode} object, not its \li{value}).
If no such node exists, or if the list is empty, raise a \li{ValueError} with an appropriate error message.
\\
(Hint: if \li{current} is assigned to one of the nodes the list, what does the following line do?)
\begin{lstlisting}
current = current.<<next>>
\end{lstlisting}
\end{problem}

\subsection*{Magic Methods} % -------------------------------------------------

Endowing data structures with magic methods makes it much easier to use it intuitively.
Consider, for example, how a Python list responds to built-in functions like \li{len()}. % and \li{print()}. % TODO: Add this in for Python 3.
At the bare minimum, we should give our linked list the same functionality.

\begin{problem} % __len__() and __str__() for the LinkedList class.
Add magic methods to the \li{LinkedList} class so it behaves more like the built-in Python list.
\begin{enumerate}
\item Write the \li{__len__()} method so that the length of a \li{LinkedList} instance is equal to the number of nodes in the list.
To accomplish this, consider adding an attribute that tracks the current size of the list.
It should be updated every time a node is successfully added or removed.

\item Write the \li{__str__()} method so that when a \li{LinkedList} instance is printed, its output matches that of a Python list.
Entries are separated by a comma and one space, and strings are surrounded by single quotes.
Note the difference between the string representations of the following lists:

\begin{lstlisting}
>>> num_list = [1, 2, 3]
>>> str_list = ['1', '2', '3']
>>> print(num_list)
[1, 2, 3]
>>> print(str_list)
<<['1', '2', '3']>>
\end{lstlisting}
\end{enumerate}
\end{problem}

\subsection*{remove()} % ------------------------------------------------------

In addition to adding new nodes to the end of a list, it is also useful to remove nodes and insert new nodes at specified locations.
To delete a node, all references to the node must be removed.
Then Python will automatically delete the object, since there is no way for the user to access it.
Na{\"i}vely, this might be done by finding the previous node to the one being removed, and setting its \li{<<next>>} attribute to \li{None}.

\begin{lstlisting}
class LinkedList(object):
    # ...
    def remove(self, data):
        """Attempt to remove the first node containing 'data'.
        This method incorrectly removes additional nodes.
        """
        # Find the target node and sever the links pointing to it.
        target = self.find(data)
        target.prev.<<next>> = None                     # -/-> target
        target.<<next>>.prev = None                     # target <-/-
\end{lstlisting}

Removing all references to the target node will delete the node (see Figure \ref{fig:remove_bad}).
However, the nodes before and after the target node are no longer linked.

\begin{lstlisting}
>>> my_list = LinkedList()
>>> for i in xrange(10):
...     my_list.append(i)
...
>>> print(my_list)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> my_list.remove(4)               # Removing a node improperly results in
>>> print(my_list)                  # the rest of the chain being lost.
[0, 1, 2, 3]                        # Should be [0, 1, 2, 3, 5, 6, 7, 8, 9].
\end{lstlisting}

\begin{figure}[H] % Incorrect remove().
\centering
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto, node distance=1.5cm,thick,main node/.style={rectangle,draw}, minimum size=.5cm]
\tikzset{rect node/.style={rectangle, draw, minimum height = .5cm, minimum width=.2cm}}
    \node[main node] (1) {A};
    \node[main node] (2) [right of=1] {B};
    \node[main node] (3) [right of=2] {C};
    \node[main node] (4) [right of=3] {D};
    \node[main node] (5) [right of=4, node distance=2.6cm] {A};
    \node[main node] (6) [right of=5] {B};
    \node[main node] (7) [right of=6] {C};
    \node[main node] (8) [right of=7] {D};
    \node[draw=none, node distance=.07cm] (1up) [above of=1] {};
    \node[draw=none, node distance=.07cm] (1dn) [below of=1] {};
    \node[draw=none, node distance=.07cm] (2up) [above of=2] {};
    \node[draw=none, node distance=.07cm] (2dn) [below of=2] {};
    \node[draw=none, node distance=.07cm] (3up) [above of=3] {};
    \node[draw=none, node distance=.07cm] (3dn) [below of=3] {};
    \node[draw=none, node distance=.07cm] (4up) [above of=4] {};
    \node[draw=none, node distance=.07cm] (4dn) [below of=4] {};
    \node[draw=none, node distance=.07cm] (5up) [above of=5] {};
    \node[draw=none, node distance=.07cm] (5dn) [below of=5] {};
    \node[draw=none, node distance=.07cm] (6up) [above of=6] {};
    \node[draw=none, node distance=.07cm] (6dn) [below of=6] {};
    \node[draw=none, node distance=.07cm] (7up) [above of=7] {};
    \node[draw=none, node distance=.07cm] (7dn) [below of=7] {};
    \node[draw=none, node distance=.07cm] (8up) [above of=8] {};
    \node[draw=none, node distance=.07cm] (8dn) [below of=8] {};
\foreach \r in {1, 2, 3, 4, 5, 6, 7, 8}{
    \node[rect node][right of=\r, node distance = .36cm]{};
    \node[rect node][left of=\r, node distance = .36cm]{};}
\foreach \s/\t in {1up/2up, 2dn/1dn, 2up/3up, 3dn/2dn, 3up/4up, 4dn/3dn, 5up/6up, 6dn/5dn, 7dn/6dn, 7up/8up}{
        \path[draw](\s) edge[shorten <=.1cm, shorten >=.1cm](\t);}
    \node[draw=none, node distance=1.5cm] [right of=8]{};  % Centralize
\end{tikzpicture}
\caption{Na{\"i}ve Removal for Doubly linked Lists. Deleting all references pointing to $C$ deletes the node, but it also separates nodes $A$ and $B$ from node $D$.}
\label{fig:remove_bad}
\end{figure}

This can be remedied by pointing the previous node's \li{<<next>>} attribute to the node after the deleted node, and similarly changing that node's \li{prev} attribute.
Then there will be no reference to the removed node and it will be deleted, but the chain will still be connected.

\begin{figure}[H] % Correct remove().
\centering
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto, node distance=1.5cm,thick,main node/.style={rectangle,draw}, minimum size=.5cm]
\tikzset{rect node/.style={rectangle, draw, minimum height = .5cm, minimum width=.2cm}}
    \node[main node] (1) {A};
    \node[main node] (2) [right of=1] {B};
    \node[main node] (3) [right of=2] {C};
    \node[main node] (4) [right of=3] {D};
    \node[main node] (5) [right of=4, node distance=2.6cm] {A};
    \node[main node] (6) [right of=5] {B};
    \node[main node] (7) [right of=6] {C};
    \node[main node] (8) [right of=7] {D};
    \node[draw=none, node distance=.07cm] (1up) [above of=1] {};
    \node[draw=none, node distance=.07cm] (1dn) [below of=1] {};
    \node[draw=none, node distance=.07cm] (2up) [above of=2] {};
    \node[draw=none, node distance=.07cm] (2dn) [below of=2] {};
    \node[draw=none, node distance=.07cm] (3up) [above of=3] {};
    \node[draw=none, node distance=.07cm] (3dn) [below of=3] {};
    \node[draw=none, node distance=.07cm] (4up) [above of=4] {};
    \node[draw=none, node distance=.07cm] (4dn) [below of=4] {};
    \node[draw=none, node distance=.07cm] (5up) [above of=5] {};
    \node[draw=none, node distance=.07cm] (5dn) [below of=5] {};
    \node[draw=none, node distance=.07cm] (6up) [above of=6] {};
    \node[draw=none, node distance=.07cm] (6dn) [below of=6] {};
    \node[draw=none, node distance=.07cm] (7up) [above of=7] {};
    \node[draw=none, node distance=.07cm] (7dn) [below of=7] {};
    \node[draw=none, node distance=.07cm] (8up) [above of=8] {};
    \node[draw=none, node distance=.07cm] (8dn) [below of=8] {};
\foreach \r in {1, 2, 3, 4, 5, 6, 7, 8}{
    \node[rect node][right of=\r, node distance = .36cm]{};
    \node[rect node][left of=\r, node distance = .36cm]{};}
\foreach \s/\t in {1up/2up, 2dn/1dn, 2up/3up, 3dn/2dn, 3up/4up, 4dn/3dn, 5up/6up, 6dn/5dn, 7dn/6dn, 7up/8up}{
        \path[draw](\s) edge[shorten <=.1cm, shorten >=.1cm](\t);}
    \path[draw, shorten <=.2cm](6) edge[red, bend left] (8);
    \path[draw, shorten <=.2cm](8) edge[red, bend left] (6);
    \node[draw=none, node distance=1.5cm] [right of=8]{};  % Centralize
\end{tikzpicture}
\caption{Correct Removal for Doubly linked Lists. To avoid gaps in the chain, nodes $B$ and $D$ must be linked together.}
\label{fig:remove_good}
\end{figure}

\begin{problem} % LinkedList.remove().
Modify the \li{remove()} method given above so that it correctly removes the first node in the list containing the specified data.
Account for the special cases of removing the first, last, or only node.
\end{problem}

\begin{warn} % Garbage collection warning.
Python keeps track of the variables in use and automatically deletes a variable if there is no access to it.
In many other languages, leaving a reference to an object without explicitly deleting it could cause a serious memory leak.
See \url{https://docs.python.org/2/library/gc.html} for more information on Python's auto-cleanup system.
\end{warn}

\subsection*{insert()} % ------------------------------------------------------

\begin{problem} % LinkedList.insert()
Add a method called \li{insert(self, data, place)} to the \li{LinkedList} class that inserts a new node containing \li{data} immediately before the first node in the list containing \li{place}.
Account for the special case of inserting before the first node.

See Figure \ref{fig:insert} for an illustration.
Note that since \li{insert()} places a new node before an existing node, it is not possible to use \li{insert()} to put a new node at the end of the list or in an empty list (use \li{append()} instead).
\end{problem}

\begin{figure}[H] % insert().
\centering
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto, node distance=1.6cm,thick,main node/.style={rectangle,draw}, minimum size=.5cm]
\tikzset{rect node/.style={rectangle, draw, minimum height = .5cm, minimum width=.2cm}}
    \node[main node] (1) {A};
    \node[main node] (2) [right of=1] {B};
    \node[main node] (3) [right of=2] {D};
    \node[main node] (4) [below right of=2] {C};
    \node[main node] (5) [right of=3, node distance=3.5cm] {A};
    \node[main node] (6) [right of=5] {B};
    \node[main node] (7) [right of=6, node distance=2.2cm] {D};
    \node[main node] (8) [below right of=6] {C};
    \node[draw=none, node distance=.07cm] (1up) [above of=1] {};
    \node[draw=none, node distance=.07cm] (1dn) [below of=1] {};
    \node[draw=none, node distance=.07cm] (2up) [above of=2] {};
    \node[draw=none, node distance=.07cm] (2dn) [below of=2] {};
    \node[draw=none, node distance=.07cm] (3up) [above of=3] {};
    \node[draw=none, node distance=.07cm] (3dn) [below of=3] {};
    \node[draw=none, node distance=.07cm] (4up) [above of=4] {};
    \node[draw=none, node distance=.07cm] (4dn) [below of=4] {};
    \node[draw=none, node distance=.07cm] (5up) [above of=5] {};
    \node[draw=none, node distance=.07cm] (5dn) [below of=5] {};
    \node[draw=none, node distance=.07cm] (6up) [above of=6] {};
    \node[draw=none, node distance=.07cm] (6dn) [below of=6] {};
    \node[draw=none, node distance=.07cm] (7up) [above of=7] {};
    \node[draw=none, node distance=.07cm] (7dn) [below of=7] {};
    \node[draw=none, node distance=.07cm] (8up) [above of=8] {};
    \node[draw=none, node distance=.07cm] (8dn) [below of=8] {};
    \node[draw=none, black!20!blue, node distance=1.5cm] [above left of=1](H1) {Head};
    \node[draw = none, black!20!blue, node distance=1.5cm] [above right of=3](T1) {Tail};
    \node[draw=none, black!20!blue, node distance=1.5cm] [above left of=5](H2) {Head};
    \node[draw = none, black!20!blue, node distance=1.5cm] [above right of=7](T2) {Tail};
\foreach \r in {1, 2, 3, 4, 5, 6, 7, 8}{
        \node[rect node][right of=\r, node distance = .36cm]{};
        \node[rect node][left  of=\r, node distance = .36cm]{};}
\foreach \s/\t in {1up/2up, 2dn/1dn, 2up/3up, 3dn/2dn, 5up/6up, 6dn/5dn}{
        \path[draw](\s) edge[shorten <=.1cm, shorten >=.1cm](\t);}
\foreach \s/\t in {6up/8up, 8dn/6dn, 8up/7up, 7dn/8dn}{
        \path[draw](\s) edge[red, shorten <=.1cm, shorten >=.1cm](\t);}
    \draw[black!20!blue, shorten >=.1cm] (H1) edge (1.north);
    \draw[black!20!blue, shorten >=.1cm] (T1) edge (3.north);
    \draw[black!20!blue, shorten >=.1cm] (H2) edge (5.north);
    \draw[black!20!blue, shorten >=.1cm] (T2) edge (7.north);
    \node[draw = none, node distance = 1.5cm] [right of=8]{};  % Centralize
\end{tikzpicture}
\caption{Insertion for Doubly linked Lists.}
\label{fig:insert}
\end{figure}

\begin{info} % Big-O rates for linked lists.
The temporal complexity for inserting to the beginning or end of a linked list is $O(1)$, but inserting anywhere else is $O(n)$, where $n$ is the number of nodes in the list.
This is quite slow compared other data structures.
In the next lab we turn our attention to \emph{trees}, special kinds of linked lists that allow for much quicker sorting and data retrieval.
\end{info}

\section*{Restricted-Access Lists} % ==========================================

It is sometimes wise to restrict the user's access to the some of the data within a structure.
The three most common and basic restricted-access structures are \emph{stacks}, \emph{queues}, and \emph{deques}.
Each structure restricts the user's access differently, making them ideal for different situations.

\begin{itemize}
\item \textbf{Stack}: \emph{Last In, First Out} (LIFO).
Only the last item that was inserted can be accessed.
A stack is like a pile of plates: the last plate put on the pile is (or should be) the first one to be taken off.
Stacks usually have two main methods: \li{push()}, to insert new data, and \li{pop()}, to remove and return the last piece of data inserted.

\item \textbf{Queue} (pronounced ``cue''): \emph{First In, First Out} (FIFO).
New nodes are added to the end of the queue, but an existing node can only be removed or accessed if it is at the front of the queue.
A queue is like a line at the bank: the person at the front of the line is served next, while newcomers add themselves to the back of the line.
Queues also usually have a \li{push()} and a \li{pop()} method, but \li{push()} inserts data to the end of the queue while \li{pop()} removes and returns the data at the front of the queue.\footnote{\li{push()} and \li{pop()} for queues are sometimes called \li{enqueue()} and \li{dequeue()}, respectively)}

\item \textbf{Deque} (pronounced ``deck''): a double-ended queue.
Data can be inserted or removed from either end, but data in the middle is inaccessible.
A deque is like a deck of cards, where only the top and bottom cards are readily accessible.
A deque has two methods for insertion and two for removal, usually called \li{append()}, \li{appendleft()}, \li{pop()}, and \li{popleft()}.
\end{itemize}

\begin{problem} % Deque class.
Write a \li{Deque} class that inherits from the \li{LinkedList} class.
%
\begin{enumerate}
\item Use inheritance to implement the following methods:
%
\begin{itemize}
    \item \li{pop(self)}: Remove the last node in the list and return its data.
    \item \li{popleft(self)}: Remove the first node in the list and return its data.
    \item \li{appendleft(self, data)}: Insert a new node containing \li{data} at the beginning of the list.
\end{itemize}
The \li{LinkedList} class already implements the \li{append()} method.

\item Override the \li{remove()} method with the following:

\begin{lstlisting}
def remove(*args, **kwargs):
    raise NotImplementedError("Use pop() or popleft() for removal")
\end{lstlisting}

This effectively disables \li{remove()} for the \li{Deque} class, preventing the user from removing a node from the middle of the list.

\item Disable the \li{insert()} method as well.
\end{enumerate}
\end{problem}

\newpage

\begin{info}
The \li{*args} argument allows the \li{remove()} method to receive any number of positional arguments without raising a \li{TypeError}, and the \li{**kwargs} argument allows it to receive any number of keyword arguments.
This is the most general form of a function signature.
\end{info}

Python lists have \li{append()} and \li{pop()} methods, so they can be used as stacks.
However, data access and removal from the front is much slower, as Python lists are not implemented as linked lists.

The \li{collections} module in the standard library has a \li{deque} object, implemented as a doubly linked list.
This is an excellent object to use in practice instead of a Python list when speed is of the essence and data only needs to be accessed from the ends of the list.

\begin{problem} % Reverse a file using a stack/deque.
Write a function that accepts the name of a file to be read and a file to write to.
Read the first file, adding each line to the end of a deque.
After reading the entire file, pop each entry off of the end of the deque one at a time, writing the result to a line of the second file.

For example, if the file to be read has the list of words on the left, the resulting file should have the list of words on the right.

\begin{lstlisting}
<<My homework is too hard for me.         I am a mathematician.
I do not believe that                   Programming is hard, but
I can solve these problems              I can solve these problems
Programming is hard, but                I do not believe that
I am a mathematician.                   My homework is too hard for me.
\end{lstlisting}

You may use a Python list, your \li{Deque} class, or \li{collections.deque} for the deque.
Test your function on the file \texttt{english.txt}, which contains a list of over 58,000 English words in alphabetical order.
\end{problem}

\newpage

\section*{Additional Material} % ==============================================

\subsection*{Improvements to the Linked List Class} % -------------------------

\begin{enumerate}
\item Add a keyword argument to the constructor so that if an iterable is input, each element of the iterable is immediately added to the list.
This makes it possible to cast an iterable as a \li{LinkedList} the same way that an iterable can be cast as one of Python's standard data structures.

\begin{lstlisting}
>>> my_list = [1, 2, 3, 4, 5]
>>> my_linked_list = LinkedList(my_list)    # Cast my_list as a LinkedList.
>>> print(my_linked_list)
[1, 2, 3, 4, 5]
\end{lstlisting}

\item Add new methods:
\begin{itemize}
\item \li{count()}: return the number of occurrences of a specified value.
\item \li{reverse()}: reverse the ordering of the nodes (in place).
\item \li{rotate()}: rotate the nodes a given number of steps to the right (in place).
\item \li{sort()}: sort the nodes by their data (in place).
\end{itemize}

\item Implement more magic methods:
\begin{itemize}
\item \li{__max__()}: return the greatest element.
\item \li{__min__()}: return the least element.
\item \li{__getitem__()} and \li{__setitem__()}: enable standard bracket indexing.
\item \li{__iter__()}: support \li{for} loop iteration, the \li{iter()} built-in function, and the \li{in} statement.
\end{itemize}
\end{enumerate}

\subsection*{Other Linked List} % ---------------------------------------------

The \li{LinkedList} class can also be used as the backbone for other data structures.
%
\begin{enumerate}
\item A \emph{sorted list} adds new nodes strategically so that the data is always kept in order.
A \li{SortedLinkedList} class that inherits from the \li{LinkedList} class should have a method called \li{add(self, data)} that inserts a new node containing \li{data} before the first node in the list that has a \li{value} that is greater or equal to \li{data} (thereby preserving the ordering).
Other methods for adding nodes should be disabled.

A linked list is \textbf{not} an ideal implementation for a sorted list (try sorting \texttt{english.txt}).

\item In a \emph{circular linked list}, the ``last'' node connects back to the ``first'' node.
Thus a reference to the tail is unnecessary.
\end{enumerate}


\documentclass[letterpaper,10pt]{article}
\usepackage[margin=2cm]{geometry}

\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage[colorlinks]{hyperref}

\setlength{\parindent}{0em}
\setlength{\parskip}{0.3em}

\newcommand{\panhline}{\begin{center}\rule{\textwidth}{1pt}\end{center}}

\title{\textbf{Parametric Models: Prior Information, From Models to Answers}}
\author{Praddep Ravikumar (Instructor), HMW-Alexander (Noter)}

\begin{document}

\maketitle

\panhline
\href{../index.html}{Back to Index}

\panhline
\tableofcontents

\section*{Resources}

\begin{itemize}
	\item \href{../../Lectures/03_ParametricModels.pdf}{Lecture}
\end{itemize}

\panhline

\section{Bayesian Learning}

Given a prior knowledge to estimate the model.

Bayesian Learning:
$$P(\theta|\mathcal{D}) = \frac{P(\mathcal{D}|\theta)P(\theta)}{P(\mathcal{D})}$$
or equivalently
$$P(\theta|\mathcal{D}) \propto P(\mathcal{D}|\theta)P(\theta)$$
Likelihood measures the fitness between data and parameters, Prior is the knowledge how possible the parameters to be.

\begin{itemize}
	\item Prior information encoded as a distribution over possible values of parameter.
	\item Using the Bayes rule to get an updated posterior distribution over parameters.
\end{itemize}

\subsection{Prior Distribution}

\subsubsection{Where to get}

\begin{itemize}
	\item Represents expert knowledge (philosophical approach)
	\item Simple posterior form (engineer's approach)
\end{itemize}

\subsubsection{Uniformative priors}

Simple distribution.
\begin{figure}[!h]
	\centering
	\includegraphics[width=4cm]{./img/uniform.png}
\end{figure}

\subsubsection{Conjugate Priors}

\begin{itemize}
	\item Closed-form representation of posterior
	\item prior and posterior have the same algebraic form as a function of parameters
\end{itemize}

Bernoulli Example: (Binomial's conjugate prior is Beta distribution)
\begin{itemize}
	\item Likelihood in Bernoulli model: $P(D|\theta)=\theta^{\alpha_1}(1-\theta)^{\alpha_2}$
	\item Prior is Beta distribution: $P(\theta)=\frac{\theta^{\beta_1-1}(1-\theta)^{\beta_2-1}}{B(\beta_1,\beta_2)} \sim Beta(\beta_1,\beta_2)$
	\item Posterior is also Beta distribution: $P(\theta|D)\sim Beta(\beta_1+\alpha_1,\beta_2+\alpha_2)$
\end{itemize}

Multinomial example: (Multinomial's conjugate prior is Dirichelet distribution)
\begin{itemize}
	\item Likelihood is Multinomial($\theta=\{\theta_1,\dots,\theta_k\}$), $P(D|\theta)=\prod_{i=1}^{k}\theta_i^{\alpha_i}$, $\alpha_i\in\{0,1\}$ is the data $D$, $\sum_{i=1}^{k}\theta_i =1$.
	\item Prior is Dirichlet distribution: $P(\theta)=\frac{\prod_{i=1}^{k}\theta_i^{\beta_i-1}}{B(\beta_1,\dots,\beta_k)} \sim Dirichlet(\beta_1,\dots,\beta_k)$
	\item Posterior is also dirichlet distribution: $P(\theta|D) \sim Dirichlet(\beta_1+\alpha_1,\dots,\beta_k+\alpha_k)$
\end{itemize}

As we get more samples, effect of prior is "washed out"

\section{Maximum A Posteriori Estimation}

Choose $\theta$ that maximizes a posterior probability:
$\hat{\theta}_{MAP}=\arg\max_\theta{P(\theta|D)}$

\begin{equation}
\begin{array}{rcl}
\hat{\theta}_{MAP} & = & \arg\max_\theta{P(\theta|D)} \\
				   & = & \arg\max_\theta{P(D|\theta)P(\theta)}
\end{array}
\end{equation}

Bernoulli example:

\begin{equation}
\begin{array}{rcl}
P(\theta|D) & \sim & Beta(\beta_1+\alpha_1,\beta_2+\beta_2) \\
\hat{\theta}_{MAP} & = & \frac{\alpha_1+\beta_1-1}{\alpha_1+\beta_1+\alpha_2+\beta_2-2}
\end{array}
\end{equation}

\subsection{MLE vs. MAP}

\begin{itemize}
	\item MLE: Choose value that maximizes the probability of observed data
	\item MAP: Choose value that is mot probable given observed data and prior belief
	\item When prior is a uniform distribution, MLE=MAP.
\end{itemize}

\subsection{MAP for Gaussian mean and variance}

Conjugate priors
\begin{itemize}
	\item Gaussian prior: $$P(\mu|\eta,\lambda)=\frac{1}{\lambda\sqrt{2\pi}}\exp(-\frac{(\mu-\eta)^2}{2\lambda^2})=\mathcal{N}(\eta,\lambda)$$
	\item Variance: Wishart Distribution\footnote{\url{https://en.wikipedia.org/wiki/Wishart_distribution}}
\end{itemize}

MAP for Gasussian Mean:
\begin{itemize}
	\item $\hat{\mu}_{MLE}=\frac{1}{n}\sum_{i=1}^{n}x_i$
	\item $\hat{\mu}_{MAP}=\frac{\frac{1}{\sigma^2}\sum_{i=1}^{n}x_i+\frac{\eta}{\lambda^2}}{\frac{n}{\sigma^2}+\frac{1}{\lambda^2}}$
\end{itemize}

\section{Non-Bayesian Prior Information via Constraints}

\begin{itemize}
	\item MLE: $$\max_\theta\log P(D|\theta)$$
	\item Constrained MLE: $$\max _\theta\log P(D|\theta)~~s.t.~\mathcal{R}(\theta)\leq C$$
	\item When $\mathcal{R}$ is convex, constrained MLE is equivalent to regularized MLE (lagrange multiplier\footnote{\url{http://www1.maths.leeds.ac.uk/~cajones/math2640/notes4.pdf}}): $$\max_\theta\{\log P(D|\theta)+\lambda\mathcal{R}(\theta)\}$$
	\item The MAP estimator can be seen to be a special case by simply setting: $$\lambda\mathcal{R}(\theta)=\log P(\theta)$$
\end{itemize}

\end{document}


%
% @author   Shmish  "shmish90@gmail.com"
% @legal    MIT     "(c) Christopher Schmitt"
%

\documentclass{article}

%
% Document Imports
%

\usepackage{fancyhdr}
\usepackage{extramarks}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{amsfonts}
\usepackage{color}

%
% Document Configuation
%

\newcommand{\hwAuthor}{Christopher Schmitt}
\newcommand{\hwSubject}{Math 218}
\newcommand{\hwSection}{Section 81}
\newcommand{\hwSemester}{Summer 2019}
\newcommand{\hwAssignment}{Assignment 3}

%
% Document Enviornments
%

\setlength{\headheight}{65pt}
\pagestyle{fancy}
\lhead{\hwAuthor}
\rhead{
  \hwSubject \\
  \hwSection \\
  \hwSemester \\
  \hwAssignment
}

\newenvironment{problem}[1]{
  \nobreak\section*{Problem #1}
}{}

%
% Document Start
%

\begin{document}
  \begin{problem}{1}
    Let $R$ be the relation on the set $Q$ defined by:
    \begin{center}
      $(a, b) \in R \text{ if and only if } |a - b| \le 4$
    \end{center}

    $R$ is Reflexive.
    \begin{proof}
      Let $a \in Q$
      \begin{equation*}
        \begin{split}
          |a - a| & \le 4\\
          |0| & \le 4\\
          0 & \le 4\\
          (a, a) & \in R
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is Symmetric.
    \begin{proof}
      Let $a, b \in Q$, Suppose $(a, b) \in R$
      \begin{equation*}
        \begin{split}
          |a - b| & \le 4\\
          |b - a| & \le 4 \text{ [Absolute value]}\\
          (b, a) & \in Q
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is not Transitive.
    \begin{proof}
      \begin{equation*}
        \begin{split}
          |10 - 6| \le 4 & \wedge |6 - 2| \le 4\\
          |10 - 2| & > 4
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is not Antisymmetric.
    \begin{proof}
      \begin{equation*}
        \begin{split}
          |10 - 6| & \le 4 \\
          |6 - 10| & \le 4
        \end{split}
      \end{equation*}
    \end{proof}
  \end{problem}

  \begin{problem}{2}
    Let $R$ be the relation on the set $R$ defined by:
    \begin{center}
      $(a, b) \in R \text{ if and only if } 5a = b$
    \end{center}

    $R$ is not Reflexive.
    \begin{proof}
      Let $a \in R$
      \begin{equation*}
        5a \neq a \text{ [In General]}
      \end{equation*}
    \end{proof}

    $R$ is not Symmetric.
    \begin{proof}
      Let $a, b \in R$
      \begin{equation*}
        \begin{split}
          5(5) & = 25\\
          5(25) & \neq 5
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is not Transitive.
    \begin{proof}
      Let $a, b, c \in R$, Suppose $(a, b), (b, c) \in R$
      \begin{equation*}
        \begin{split}
          5(1) & = 5\\
          5(5) & = 25\\
          5(1) & \neq 25
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is Antisymmetric.
    \begin{proof}
      Let $a, b \in R$, Suppose $(a, b), (b, a) \in R$
      \begin{equation*}
        \begin{split}
          5(a) = b & \wedge 5(b) = a\\
          5(5(b)) & = b\\
          25(b) & = b \text{ iff $b = 0$}\\
          5(5(a)) & = a\\
          25(a) & = a \text{ iff $a = 0$}\\
        \end{split}
      \end{equation*}
      $a$ and $b$ must both the same if $(a, b), (b, a) \in R$, so $R$ is Antisymmetric
    \end{proof}
  \end{problem}

  \begin{problem}{3}
    Let R be the relation on the set Z defined by:
    \begin{center}
      $(a, b) \in \text{ if and only if } ab \ge 1$
    \end{center}

    $R$ is not Reflexive.
    \begin{proof}
      \begin{equation*}
        0(0) < 1
      \end{equation*}
    \end{proof}

    $R$ is Symmetric.
    \begin{proof}
      Let $a, b \in Z$, Suppose $(a, b) \in R$
      \begin{equation*}
        \begin{split}
          a(b) & \ge 1\\
          b(a) & \ge 1
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is Transitive.
    \begin{proof}
      Let $a, b, c \in Z$, Suppose $(a, b), (b, c) \in  R$
      \begin{equation*}
        \begin{split}
          ab \ge 1 & \wedge bc \ge 1\\
          (ab)(bc) & \ge 1\\
          acb^2 & \ge 1\\
          ac & \ge b^{-2}
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is not Antisymmetric.
    \begin{proof}
      \begin{equation*}
        \begin{split}
          1(2) & \ge 1\\
          2(1) & \ge 1
        \end{split}
      \end{equation*}
    \end{proof}
  \end{problem}

  \begin{problem}{4}
    Let $R$ be the relation on the set $Z \times Z$ defined by:
    \begin{center}
      $((a, b),(c, d)) \in R \text{ if and only if } a + 2b \le c + 2d$
    \end{center}

    $R$ is Reflexive.
    \begin{proof}
      Let $(a, b) \in Z \times Z$
      \begin{equation*}
        \begin{split}
          a + 2(b) & \le a + 2(b)\\
          ((a, b), (a, b)) & \in R
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is not Symmetric.
    \begin{proof}
      Let $(a, b), (c, d) \in Z \times Z$, Suppose $((a, b), (c, d)) \in R$
      \begin{equation*}
        \begin{split}
          0 + 2(0) & \le 1 + 2(1)\\
          0 & \le 2\\
          1 + 2(1) & > 0 + 2(0)\\
          3 & > 0
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is Transitive.
    \begin{proof}
      Let $(a, b), (c, d), (e, f) \in Z \times Z$, Suppose $(a, b) R (c, d) \wedge (c, d) R (e, f)$
      \begin{equation*}
        \begin{split}
          a + 2(b) \le c + 2(d) & \wedge c + 2(d) \le e + 2(f)\\
          a + 2(b) & \le e + 2(f)
        \end{split}
      \end{equation*}
    \end{proof}

    $R$ is Antisymmetric.
    \begin{proof}
      Let $(a, b), (c, d) \in Z \times Z$, Suppose $(a, b) R (c, d)$
      \begin{equation*}
        \begin{split}
          a + 2(b) & \le c + 2(d)\\
          c + 2(d) & \le a + 2(b)\\
          a + 2(b) & = c + 2(b)
        \end{split}
      \end{equation*}
    \end{proof}
  \end{problem}

  \begin{problem}{5}
    Let $\sim$ be the relation on the set $Z$ defined by:
    \begin{center}
      $a \sim b \text{ if and only if } a = \pm b$.
    \end{center}

    $\sim$ is Reflexive.
    \begin{proof}
      Let $a \in Z$
      \begin{equation*}
        \begin{split}
          a & = \pm a\\
          a^2 & = (\pm a)^2\\
          a^2 & = a^2
        \end{split}
      \end{equation*}
    \end{proof}

    $\sim$ is Symmetric.
    \begin{proof}
      Let $a, b \in Z$, Suppose $a \sim b$
      \begin{equation*}
        \begin{split}
          a & = \pm b\\
          a = b & \vee a = -b\\
          a = b & \implies b = a\\
          a = -b \implies -b & = a \implies b = -a
        \end{split}
      \end{equation*}
    \end{proof}

    $\sim$ is Transitive.
    \begin{proof}
      Let $a, b, c \in Z$, Suppose $a \sim b, b \sim c$
      \begin{equation*}
        \begin{split}
          a & = \pm b\\
          a^2 & = (\pm b)^2\\
          a^2 & = b^2\\
          b & = \pm c\\
          b^2 & = (\pm c)^2\\
          b^2 & = c^2\\
          a^2 = & ~ b^2 = c^2\\
          a^2 & = b^2
        \end{split}
      \end{equation*}
    \end{proof}

    Find all the elements in the class $\bar{7}$
    \begin{center}
      $\bar{7} = \{7, -7\}$
    \end{center}
  \end{problem}

  \begin{problem}{6}
    Let $\sim$ be the relation on the set $Z$ defined by:
    \begin{center}
      $a \sim b \text{ if and only if } 8 \text{ is a divisor of } 7a + b$
    \end{center}

    $\sim$ is Reflexive.
    \begin{proof}
      Let $a \in Z$
      \begin{equation*}
        \begin{split}
          8 & | 7(a) + a\\
          8(k) = 7(a) & + a \text{ where $K \in \mathbb Z$ }\\
          8(k) & = 8(a)
        \end{split}
      \end{equation*}
    \end{proof}

    $\sim$ is Symmetric.
    \begin{proof}
      Let $a, b \in Z$
      \begin{equation*}
        \begin{split}
          8 & | 7(a) + b\\
          8(k) = 7(a) & + b \text{, where $k \in \mathbb Z$}\\
          -8(k) & = -7(a) - b\\
          -8(k) + 8(a) + 8(b) & = -7(a) + 8(a) - b + 8(b)\\
          8(-k + a + b) & = a + 7(b)\\
          8(-k + a + b) & = 7(b) + a
        \end{split}
      \end{equation*}
    \end{proof}

    $\sim$ is Transitive.
    \begin{proof}
      Let $a, b, c \in Z$, Suppose $a \sim b, b \sim c$
      \begin{equation*}
        \begin{split}
          8 | 7(a) + b & \wedge 8 | 7(b) + c\\
          8(k) = 7(a) + b & \wedge 8(j) = 7(b) + c \text{, where $k, j \in \mathbb Z$}\\
          8(k) + 8(j) & = 7(a) + b + 7(b) + c\\
          8(k) + 8(j) & = 7(a) + 8(b) + c\\
          8(k) + 8(j) - 8(b) & = 7(a) + c\\
          8(k + j - b) & = 7(a) + c
        \end{split}
      \end{equation*}
    \end{proof}

    Find four elements in the equivalence class $\bar{5}$
    \begin{center}
      $\bar{5} = \{5, 13, 21, 29\}$
    \end{center}
  \end{problem}
\end{document}


% !TEX root =main.tex

 \subsection{C-TLP Cost Analysis}\label{TLP-cost-compare}

 In this section, we analyse  the communication and computation complexity of C-TLP. We consider a generic setting where the protocol deals with $z$ puzzles.

  \begin{table*}[!htbp]
\begin{center}
\caption{\small Computation Cost}\label{table::puzzle-com}
\begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}
   \hline
\cellcolor[gray]{0.9}&\cellcolor[gray]{0.9} &
 \multicolumn{3}{c|}{\cellcolor[gray]{0.9}\scriptsize \underline{ \ \ \ \  \ \ \ \ \ Protocol Function \ \ \ \ \ \ \ \ \ }}&\cellcolor[gray]{0.9}\\

\cellcolor[gray]{0.9} \multirow{-2}{*}{\scriptsize Protocol}&\cellcolor[gray]{0.9} \multirow{-2}{*} {\scriptsize Operation}&\cellcolor[gray]{0.9}\scriptsize$\mathtt{GenPuz}$&\cellcolor[gray]{0.9}\scriptsize$\mathtt{SolvPuz}$&\cellcolor[gray]{0.9}\scriptsize$\mathtt{Verify}$&\multirow{-2}{*} {\cellcolor[gray]{0.9}\scriptsize   Complexity} \\
\hline
\cellcolor[gray]{0.9} &\multirow{3}{*}{\rotatebox[origin=c]{0}{\scriptsize }} \cellcolor[gray]{0.9}\scriptsize Exp.&\scriptsize$z+1$&\scriptsize$T z$ &$-$&\multirow{4}{*}{\rotatebox[origin=c]{0}{\scriptsize $O(T  z)$}}\\
     \cline{2-5}
 \cellcolor[gray]{0.9}     &\cellcolor[gray]{0.9}\scriptsize Add. or Mul.&\scriptsize$z$ &\scriptsize$z$&$-$ & \\
     \cline{2-5}
 \cellcolor[gray]{0.9}         &\cellcolor[gray]{0.9}\scriptsize Commitment&\scriptsize$z$&$-$ &\scriptsize$z$&\\
     \cline{2-5}
\cellcolor[gray]{0.9}   \multirow{-4}{*}{\rotatebox[origin=c]{0}{\scriptsize  C-TLP }}     &\cellcolor[gray]{0.9}\scriptsize Sym. Enc&\scriptsize$z$&\scriptsize$z$ &$-$&\\

 \hline
\end{tabular}
\end{center}

\end{table*}

 \noindent\textbf{\textit{Computation Complexity}}. For a client to generate $z$ puzzles, in total: in step \ref{call-RTLP-Setup}, it performs one exponentiation over $\bmod \phi(N)$. In step \ref{call-RTLP-GenPuz}, it $z$ times calls $\mathtt{TLP.GenPuZ}(.)$. This  in total involves $z$ symmetric key-based encryption,  $z$ modular exponentiations over $\mathbb{Z}_{\scriptscriptstyle N}$ and $z$ modular additions. Also, in  step \ref{commit-} it performs $z$ invocations of a commitment scheme (to commit), i.e. if a hash-based commitment is used then it would involve $z$ invocations of a hash function, and if Pedersen commitment is used then it would involve $2 z$ exponentiations and $z$ multiplications, where  all operations, in the latter commitment,  are done  over a $\bmod q$ for a large prime number: $q$, e.g. $|q|=1024$-bit. Thus, the overall computation complexity of the client   is $O(z)$. For the server to solve $z$ puzzles, it $z$ times calls $\mathtt{TLP.SolvPuz}(.)$. This in total involves $Tz$ modular squaring over $\mathbb{Z}_{\scriptscriptstyle N}$, $z$ modular additions over $\mathbb{Z}_{\scriptscriptstyle N}$, and  $z$ symmetric key based decryption. The server's cost of proving, in step \ref{prove-}, is very low, as it involves only parsing $z$ strings. Therefore, the server total computation complexity is $O(Tz)$. The verification cost, in step \ref{verify-}, only involves $z$ invocation of commitment scheme (to verify  each opening) and it is \emph{independent} of the RSA security parameters.  If the hash-based commitment is used, then it would involve $z$ invocations of a hash function,  if Pedersen commitment is utilised, then in total it would involve $2 z$ exponentiations and $z$ multiplications performed over $\bmod q$. Thus, the  verification's complexity is $O(z)$. Table \ref{table::puzzle-com} summarises the computation analysis results.

 \begin{table*}[!htbp]
\begin{center}
\caption{\small Communication Cost (in bit)}\label{table::puzzle-communication}
\begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|}
   \hline
 {\cellcolor[gray]{0.9}\scriptsize Protocol}&{\cellcolor[gray]{0.9}\scriptsize Model}&
{\cellcolor[gray]{0.9}\scriptsize Client}&{\cellcolor[gray]{0.9}\scriptsize Server}&{\cellcolor[gray]{0.9}\scriptsize  Complexity}\\
 \cline{3-4}

\hline
 \cellcolor[gray]{0.9}  &\cellcolor[gray]{0.9} \multirow{2}{*}{\rotatebox[origin=c]{0}}\scriptsize Standard&\scriptsize$3200 z$&\scriptsize$1524 z$ &\multirow{2}{*}{\rotatebox[origin=c]{0}{\scriptsize $O(z)$ }}\\
     \cline{2-4}
  \multirow{-2}{*}{\rotatebox[origin=c]{0}{\cellcolor[gray]{0.9} \scriptsize  C-TLP }}&\cellcolor[gray]{0.9}\scriptsize R.O.&\scriptsize$2432  z$ &\scriptsize$628  z$& \\

 \hline
\end{tabular}
\end{center}
\end{table*}

 \noindent\textbf{\textit{Communication Complexity}}.  In step \ref{Generate-Puzzle}, the client publishes two vectors: $\vv{\bm{o}}$ and $\vv{\bm{h}}$, with  $2 z$ and $z$ elements respectively.  Each element of $\vv{\bm{o}}$ is a pair $(o_{\scriptscriptstyle j,1},o_{\scriptscriptstyle j,2})$, where $o_{\scriptscriptstyle j,1}$ is an output of symmetric key encryption, e.g.   $|o_{\scriptscriptstyle j,1}|=128$-bit, and $o_{\scriptscriptstyle j,2}$ is an element of $\mathbb{Z}_{\scriptscriptstyle N}$, e.g.  $|o_{\scriptscriptstyle j,2}|=2048$-bit. Also, each element $h_{\scriptscriptstyle j}$ of $\vv{\bm{h}}$ is either an output of a hash function, when a hash-based commitment is used, e.g.  $|h_{\scriptscriptstyle j}|=256$-bit, or an element of $\mathbb{F}_{\scriptscriptstyle q}$ when Pedersen commitment is used, e.g.  $|h_{\scriptscriptstyle j}|=1024$-bit. Therefore, its total bandwidth is about $2432 z$ bits when the former,  or $3200 z$ bits when the latter commitment scheme is utilised. Also, its   complexity is $O(z)$. Note,  in  C-TLP, when a server finds a solution, it does not broadcast anything, instead it moves on  to the next step:  $\mathtt{Prove}(.)$. For the server to prove, in step \ref{prove-},  in total,  it sends $z$ pairs $(m_{\scriptscriptstyle j},d_{\scriptscriptstyle j})$ to the verifier, where $m_{\scriptscriptstyle j}$  is an arbitrary message, e.g.  $|m_{\scriptscriptstyle j}|=500$-bit, and  $d_{\scriptscriptstyle j}$ is either a long enough random value, e.g. $|d_{\scriptscriptstyle j}|=128$-bit, when the hash-based commitment is used, or an element of $\mathbb{F}_{\scriptscriptstyle q}$ when Pedersen scheme is used, e.g. $|d_{\scriptscriptstyle j}|=1024$-bit. Therefore, its bandwidth is about either $628 z$ or $1524 z$ bits when the former or latter commitment scheme is used respectively. The solver's  communication complexity is $O(z)$. Table \ref{table::puzzle-communication} summarises the communication analysis results.


\documentclass[main.tex]{subfiles}
\begin{document}

\section*{Fri Dec 13 2019}

There are two topics left: cosmology and gravitational waves.
Today and Thursday we do cosmology.

\section{Cosmology}

Now we introduce the Planck scale: the Compton wavelength is defined by
%
\begin{align}
  \lambda = \frac{\hbar c }{E}
\,,
\end{align}
%
while the Schwarzschild radius is of the order of
%
\begin{align}
  r_s \sim \frac{GM}{c^2} = \frac{GE}{c^{4}}
\,.
\end{align}

So, we have a quantum gravity regime when \(\lambda < r_S\): when the particle is so localized that it will form a BH by itself. We get:
%
\begin{align}
  \frac{\hbar c}{E} \approx \frac{GE}{c^{4}} \implies
  E \approx \sqrt{\frac{\hbar c^{5}}{G}} \approx \SI{1.96e9}{J} \approx \SI{1.22e19}{GeV}
\,.
\end{align}

In \(c=1\) units, this is also the Planck mass.
It is also useful to define the reduced Planck mass:
%
\begin{align}
  M_p = \frac{E_p}{\sqrt{8 \pi }} = \SI{2.43e18}{GeV}
\,.
\end{align}

Natural units are ones in which
\begin{enumerate}
    \item \(c=1\): velocities are dimensionless: then the unit of length is equal to the unit of time;
    \item \(\hbar = 1\): then angular momenta are also dimensionless: then length and time have the dimensions of \(1/\text{mass}\) or \(1/\text{energy}\).
\end{enumerate}

In natural units the Einstein equations look like:
%
\begin{align}
  G_{\mu \nu } = 8 \pi G T_{\mu \nu }
\,,
\end{align}
%
but \(M_P = \frac{1}{\sqrt{8 \pi G}}\): therefore \(8 \pi G = 1 / M_P^2\), so
%
\begin{align}
  G_{\mu \nu } = \frac{1}{M_P^2} T_{\mu \nu }
\,.
\end{align}

We are going to discuss the Friedmann-Lemaître-Robertson-Walker metric, which describes a homogeneous and isotropic universe.

Homogeneous means symmetry with respect to translations, isotropic means symmetry with respect to rotations.

Something which is \emph{homogeneous but not isotropic} is, for example, the inside of a capacitor. Also, the surface of a cylinder can be an example.

We can have a space which is \emph{isotropic but not homogeneous} only around one point, \emph{global isotropy implies homogeneity}.

We will also require the condition that the universe be \emph{spatially flat}.
If a triangle has angles \(\alpha , \beta , \gamma \) then \(\sign ( \alpha + \beta +\gamma -\pi ) = k\) is a constant along the space and it measures the curvature of the space.

The smaller the curvature (and the larger the length scale of the curvature) the more difficult it is to measure what \(k\) is.

The line element in this kind of space is particularly simple, since we can :
%
\begin{align}
  \dd{s^2} = - \dd{t^2} + a^2(t) \dd{\vec{x}^2}
\,.
\end{align}

Since the metric is diagonal, the only nonvanishing Christoffel symbols are \(\Gamma^{0}_{ij}\) and \(\Gamma^{i}_{0j}\), and both must be proportional to \(\delta_{ij}\).
These symbols are
%
\begin{align}
  \Gamma^{0}_{ij} = \frac{1}{2} g^{00} \qty(-g_{ij,0}) = \delta_{ij} a \dot{a}
\,,
\end{align}
%
where \(\dot{a}\) denotes the derivative of \(a\) with respect to coordinate time, while
%
\begin{align}
  \Gamma^{i}_{0j} = \frac{1}{2} g^{ik} \qty(g_{jk,0}) = \delta_{ij} a \dot{a} \times \frac{1}{a^2} = \delta_{ij} \frac{\dot{a}}{a}
\,.
\end{align}

The trace of the Christoffels are \(\Gamma^{0}_{ii} = 3a \dot{a}\), and \(\Gamma^{i}_{0i} = 3 \dot{a} / a\). We want to calculate \(R_{00} \), \(R_{0i}\) and \(R_{ij}\).
We have \(R_{0i} = 0\) since nothing on the indices depends on space. We also have \(R_{ij} \propto \delta_{ij}\), since all the Christoffels depend only on \(\delta_{ij}\).

We have
%
\begin{align}
  R_{\mu \nu } = \partial_{\alpha} \Gamma^{\alpha }_{ \mu \nu } + \Gamma^{\lambda }_{\mu \nu } \Gamma^{\alpha }_{\lambda \alpha } - \partial_{\nu }\Gamma^{\alpha }_{\mu \alpha } - \Gamma^{\lambda }_{\mu \alpha } \Gamma^{\alpha }_{\nu \lambda }
\,.
\end{align}

Specializing to the \(R_{00} \) case:
\begin{align}
    R_{0 0 } = \partial_{\alpha} \Gamma^{\alpha }_{ 0 0 } + \Gamma^{\lambda }_{0 0 } \Gamma^{\alpha }_{\lambda \alpha } - \partial_{0 }\Gamma^{\alpha }_{0 \alpha } - \Gamma^{\lambda }_{0 \alpha } \Gamma^{\alpha }_{0 \lambda }
  \,.
\end{align}

The \(\Gamma^{\alpha }_{00}\) must vanish. So we get
%
\begin{subequations}
\begin{align}
  R_{00} &= - \partial_{0} \Gamma^{i}_{0i} - \Gamma^{i}_{0j} \Gamma^{j}_{0i}  \\
  &= - \partial_{0} \qty(\frac{3 \dot{a}}{a}) - \frac{\dot{a}}{a} \delta_{ij} \frac{\dot{a}}{a} \delta_{ij}  \\
  &= - \frac{3 \ddot{a}}{a} + \frac{3 \dot{a}^2}{a^2}
  - 3 \frac{\dot{a}^2}{a^2} = - 3 \frac{\ddot{a}}{a}
\,.
\end{align}
\end{subequations}

On the other hand we have
%
\begin{subequations}
\begin{align}
R_{i j } &= \partial_{\alpha} \Gamma^{\alpha }_{ i j } + \Gamma^{\lambda }_{i j } \Gamma^{\alpha }_{\lambda \alpha } - \cancelto{}{\partial_{j }\Gamma^{\alpha }_{i \alpha }} - \Gamma^{\lambda }_{i \alpha } \Gamma^{\alpha }_{j \lambda }  \\
&= \partial_{0} \Gamma^{0 }_{ i j }
+ \Gamma^{\lambda }_{i j } \Gamma^{\alpha }_{\lambda \alpha }
- \Gamma^{\lambda }_{i \alpha } \Gamma^{\alpha }_{j \lambda }
\\
&= \qty(a \ddot{a} - \dot{a}^2)  \delta_{ij}
+ 3 a^2 \delta_{ij} - \dot{a}^2 \delta_{ij} - \dot{a}^2 \delta_{ij}  \\
&= a^2 \delta_{ij} \qty(\frac{\ddot{a}}{a} + 2 \frac{\dot{a}^2}{a^2})
\,.
\end{align}
\end{subequations}

So we have the whole of the Ricci tensor.
The scalar curvature is given by
%
\begin{subequations}
\begin{align}
  R &= g^{00} R_{00} + g^{ij} R_{ij}  \\
  &= + 3 \frac{\ddot{a}}{a} + \delta_{ij} \frac{a^2}{a^2} \delta_{ij}  \qty( 2 \frac{\dot{a}^2}{a^2} + \frac{\dot{a}}{a})  \\
  &= 6 \frac{\dot{a}^2}{a^2} + \frac{6 \ddot{a}}{a}
\,,
\end{align}
\end{subequations}
%
and we have
%
\begin{align}
  G_{00 } = R_{00} - R g_{00} = - 3\frac{\ddot{a}}{a}
  + 3 \frac{\dot{a}^2}{a^2} + 3 \frac{\ddot{a}}{a} = \frac{3 \dot{a}^2}{a^2}
\,,
\end{align}
%
while
%
\begin{subequations}
\begin{align}
  G_{ij} &= R_{ij} - Rg_{ij} \\
  &= a^2 \delta_{ij} \qty(\frac{\ddot{a}}{a} + 2 \frac{\dot{a}^2}{a^2}) - \frac{3 \dot{a}^2}{a^2} a^2  \\
  &= a^2 \delta_{ij} \qty(- \frac{\dot{a}^2}{a^2} - \frac{2 \ddot{a}}{a})
\,.
\end{align}
\end{subequations}

For the SEM tensor we choose a perfect fluid: \(T^{\mu \nu } = \rho u^{\mu } u^{\nu }  + p h^{ \mu \nu }\), where \(h^{\mu \nu } = u^{ \mu }  u^{\nu } + g^{ \mu \nu }\) is the projector on the space orthogonal to the velocity.

We know that, in the expression of
%
\begin{align}
  u^{\mu } = \qty(\dv{t}{\tau }, \dv{\vec{x}}{\tau })^{\top}
\,,
\end{align}
%
the compontent \(u^{0}\) must be positive. We have
%
\begin{align}
  0 = G_{0i} = \frac{T_{0i} }{M_P^2}
\,,
\end{align}
%
but this means that \(u^{i}\) must be zero. \emph{The cosmic fluid is at rest}. This means that we are selecting a special frame: the rest frame of the cosmic fluid, the rest frame of the CMB.

When we look at the CMB we see a large dipolar contribution, due to the motion of the Earth with respect to the cosmic fluid.
The theory is globally Lorenz-invariant, however its realization is not. This means that \(u^{0} = 1\), since \(g_{00} = -1\).

This means that \(h^{\mu \nu } = a^2 \delta^{ij}\) (informal, I mean that the only nonzero components are the spatial ones.)

Then \(T_{00} = \rho \), and \(T_{ij} = a^2 \delta_{ij} P\).

So the EFE are:
%
\begin{subequations}
\begin{align}
  \frac{3 \dot{a}^2}{a^2} &= \frac{\rho }{M_P^2}  & \text{00 equation}\\
  - 2 \frac{\ddot{a}}{a} - \frac{\dot{a}^2}{a^2} &=
  \frac{P}{M_P^2} & \text{ij equations}
\,,
\end{align}
\end{subequations}
%
where we factored out the \(a^2 \delta_{ij}\) in the \(ij\) equations.
``Just for fun'' we discuss the Bianchi identities: \(\nabla_{\mu } G^{\mu \nu }=0\).
If \(\nu =0\) we have
%
\begin{align}
  \partial_{\mu } G^{\mu 0} + \Gamma^{\mu }_{\mu \lambda } G^{\lambda 0} + \Gamma^{0}_{\mu \lambda } G^{\mu \lambda } = 0
\,,
\end{align}
%
but simplifying the indices we get
%
\begin{align}
  \partial_{0} G^{00} + \Gamma^{i}_{i0} G^{00} + \Gamma^{0}_{ij} G^{ij} =0
\,,
\end{align}
%
and substituting in the expressions we have we get
%
\begin{subequations}
\begin{align}
  &\partial_{0} \qty(\frac{3 \dot{a}^2}{a^2})
  + \frac{3 \dot{a}}{a} \frac{3 \dot{a}^2}{a^2}
  + a \dot{a} \delta_{ij} \frac{1}{a^2} \delta_{ij}
  \qty(- \frac{2 \ddot{a}}{a} - \frac{\dot{a}^2}{a^2}) \\
  = & 6 \frac{\dot{a}}{a} \qty(\frac{\ddot{a}}{a} - \frac{\dot{a}^2}{a^2})
  + 9 \frac{\dot{a}^3}{a^3} - 6 \frac{\dot{a}}{a} \frac{\ddot{a}}{a} - 3 \frac{\ddot{a}^3}{a^3} = 0
\,,
\end{align}
\end{subequations}
%
which confirms what we already knew. Verifying \(\nabla_{\mu} G^{\mu i } = 0\) is easier:
%
\begin{align}
    \partial_{\mu } G^{\mu i} + \Gamma^{\mu }_{\mu \lambda } G^{\lambda i} + \Gamma^{i}_{\mu \lambda } G^{\mu \lambda } = 0
\,,
\end{align}
%
because all three of the terms vanish immediately.

Correspongingly, we have \(\nabla_{\mu } T^{\mu \nu } =0 \).
This is a local conservation law, not a global one generally since we do not have 4 Killing vectors.
If \(\nu =0\) we have
%
\begin{subequations}
\begin{align}
  &\partial_{\mu } T^{\mu 0} + \Gamma^{\mu }_{\lambda \lambda  } T^{\lambda 0} + \Gamma^{0}_{\mu \lambda } T^{\mu \lambda } = \\
  =& \partial_{0} T^{00} +
  \Gamma^{i}_{i0} T^{i0} + \Gamma^{0}_{ij} T^{ij} \\
  =& \partial_{0} \rho
+ 3 \frac{\dot{a}}{a} \rho + \dot{a} a \delta_{ij} \frac{1}{a^2} \delta_{ij} P
\,,
\end{align}
\end{subequations}
%
which means
%
\begin{align}
  \dot{\rho} + 3 \frac{\dot{a}}{a} ( \rho +P) = 0
\,,
\end{align}
%
which we can add to the other equations.

It is easier to study the case \(\nu = i\): we get
%
\begin{align}
    &\partial_{\mu } T^{\mu i} + \Gamma^{\mu }_{\lambda \lambda  } T^{\lambda i} + \Gamma^{i}_{\mu \lambda } T^{\mu \lambda } = 0
\,,
\end{align}
%
since all three terms vanish immediately. Since the conservation  equation \(\nabla_{\mu } T^{\mu 0}\) comes from the Einstein equations, we should be able to derive it from the first two Friedmann equations: differentiating the 00 one we get
%
\begin{align}
  6 \qty(\frac{\dot{a}}{a} - \frac{\dot{a}^2}{a^2}) = \dot{\rho} M_P^{-2}
\,,
\end{align}
%
while for the second one, multiplying by \(3 \dot{a} / a\), we get
%
\begin{align}
  - 6 \frac{\dot{a}}{a} \frac{\ddot{a}}{a}
  - 3 \frac{\dot{a}^3}{a^3} = \frac{3 \dot{a}}{a } P M_P^{-2}
\,.
\end{align}

Adding them together we find
%
\begin{align}
  - 9 \frac{\dot{a}^3}{a^3} = M_P^{-2} \qty( \dot{\rho} + 3 \frac{\dot{a}}{a }P )
\,,
\end{align}
%
and from the first FE we have
%
\begin{align}
  9 \frac{\dot{a}^3}{a^3} = 3 \frac{\dot{a}}{a} \rho M_P^{-2}
\,,
\end{align}
%
so we get
%
\begin{align}
  \dot{\rho}
 + 3 \frac{\dot{a}}{a} \qty(\rho +P) = 0
\,.
\end{align}

So, since the equations are not independent, we consider  only two of the three. It is convenient to use the first and the third since they have no second derivatives.

What sources do we put for the equations? First of all, commonly we do \(w = P / \rho \), and sometimes we do \(w = -1\): this means \(\rho = \const\).
This corresponds to \emph{vacuum energy}, associated with the space itself: it does not scale inversely with the volume.

We can have vacuum energy: ``vacuum'' just means we are in a minimum of the potential. Mexican hats and stuff.

In principle, the EFE can be modified in a simple way:
%
\begin{align}
  G_{\mu \nu } + \Lambda g_{\mu  \nu } = \frac{T_{\mu \nu }}{M_P^2}
\,,
\end{align}
%
since the metric is covariantly constant. This can be interpreted as a \emph{constant negative energy density}: It would look like
%
\begin{align}
  T_{\mu \nu } \rightarrow T_{\mu \nu } + \Lambda M_P^2 g_{\mu \nu }
\,.
\end{align}

Then we have
%
\begin{align}
  G_{00} = \frac{1}{M_P^2} \qty(\rho + \Lambda M_P^2)
\,,
\end{align}
%
and
%
\begin{align}
  G_{ij} = \frac{1}{M_P^2} \qty(a^2 \delta_{ij} p - \Lambda M_P^2a^2 \delta_{ij})
\,.
\end{align}

So, we have
%
\begin{align}
  \frac{P_{\Lambda }}{\rho_{\Lambda }} = w_{\Lambda } = -1
\,.
\end{align}

This ratio between pressure and density is characteristic of a cosmological constant.

\end{document}


\chapter{Background}

\section{State of the Art}

\subsection{A very short history of Machine Learning}
``You have to know the past to understand the present.'' - Carl Sagan

The early beginnings of Machine Learning come not after the first electronic
computers or after the first computer programs, as many may believe so. The
fundamentals of this field took shape centuries ago with the discovery of the
so-called Conditional Probability theories. {\bf Bayes Theorem}, named after Thomas
Bayes who first proposed a mathematical model for infering probabilities of
conditioned events, and further developed by Pierre-Simon Laplace in his essay
\footnote{Théorie Analytique des Probabilités} in 1812, can be seen as one of the first models
that can ``learn'' from given data and predict events based on correlated past events.
Another old discovery that is the basis of today's regression models (e.g.:
Linear Regression) is the ``least squares method'', credited to Carl Gauss, but
first published by Adrien-Marie Legendre in 1805. This method was first applied in
astronomy and allowed explorers to navigate oceans by aproximating the movement of
celestial bodies.

Later on, in 1950, Alan Turing proposed in his paper\footnote{Turing, A.M. (1950).
Computing machinery and intelligence. Mind, 59, 433-460.} a {\it learning machine}
that is able to learn and become intelligent and do well in the {\bf Imitation Game}
(now generally called the {\bf Turing Test}).

After this, the discovery of the Percetron and the {\bf Neural Networks} around 1960s drew
some attention in the field, but their current limitations had put Machine Learning on an
impeding state for almost 10 years. It was only with the invention of the
backpropagation algorithm in 1974 by Paul Werbos and the demonstration of its
generalization by Geoffrey Hinton in 1986, that allowed it to be applied in
multi-layered artificial neural networks. This also gave birth to a new sub-field
of Machine Learning that today is called {\bf Deep Learning.}

Along with the research in neural networks, some other models that were developed in that
period are worth to mention. The most important ones are Support Vector Machines and kernels
(models used for data classification and regression, that can be more time-efficient
than neural networks are and provide good performance from a data perspective) and Decision Trees.
The latter, in combination with Ensemble Methods helped researchers invent models like
{\bf Random Forests} and {\bf Adaptive Boosting} that are now state-of-the-art
algorithms for tree models used for a lot of tasks.

\subsection{Current interests in the field}

Coming back to Deep Learning, which is today's main subject of interest of the
Machine Learning community, it is a general approach that combines several state-of-the-art
models of Machine Learning to solve problems such as image classification, AI for
computer games, natural language, etc. Its constituents include neural networks with many
hidden layers, convolutional networks, deep belief networks and recurrent networks.
Also, the Q-Learning algorithm\footnote{Watkins, C.J.C.H. (1989). Learning from Delayed Rewards.
PhD thesis, Cambridge University, Cambridge, England} and the Monte-Carlo search used
in combination with convolutional networks allowed researchers to build semi-supervised
learning programs that could learn to play computer games by themselves\footnote
{https://www.cs.toronto.edu/~vmnih/docs/dqn.pdf} or beat professional human players at
games, such as Go (Google AlphaGo's program first beat Lee Sedol in October 2015).

\subsection{Trends in educational learning}

All advances in the Machine Learning field also conducted in an incresing interest in
educational learning and assessment. With the name of {\bf Educational Data Mining},
this newly emerging discipline deals with studying machine learning and data mining
models in order to gain important knowledge about the structure of an educational
system data (final grades, performance indicators, course drop-outs). Educational
data can be taken from schools and universities (the classical way and also, the way
that this thesis explores), online courses (such as MOOCs\footnote{Massive Open
Online Courses}), or even collaborative learning.

With the use of Machine Learning techniques, student can better decide on what courses
they could take (based on past related grades), whether they have a chance or not to
pass an exam before taking it and what indicators are relevant to their final asessment.
The course department also benefits from the ``learned'' data because it helps them
to better plan the structure of their courses, whether they are on-line or taken at
the university.

\section{Related Work}

This part of the chapter will focus on the work on other people about the study
on student performance prediction and analysis. Some of their research is similar
to that of this thesis, and some others treat only related issues.

(Mehdi Sajjadi et al., 2016)\cite{bibl_1} did some work on approximating final grades
of students in a course on algorithms. In the grading process they used the peer
grading method\footnote{A process in which students grade work of other students
based on a given guideline}, and then applied Machine Learning (both supervised and
usupervised) to aggregate those grades into a final grade. Their results were
not so good compared to the simple method of just using the mean of all peer grades
per an assessment as the final grade.

(Siddharth Reddy et al., 2015)\cite{bibl_2} worked on developing a representational
model of combined students and educational content (assessments and lessons).
This representation is actually a semantic space\footnote{Semantic similarity
between objects represented as a kind of ``metric'' in space} and it can be used
to study the relation between course content and students. Several conclusions can
be drawn from these representations, such as: probability of passing an assessment
or course and knowledge gained from completing a lesson. This article aimed mostly
at MOOCs platforms, like Coursera, EdX and Khan Academy, and the model described
was tested on synthetic student data and also, on real data from Knewton.
Their model's results can be used to personalize the learning process of a course
for each student in order to maximize the educational performance. Also, this
model successfully predicted assessment results.

(Michael Wu, 2015)\cite{bibl_2_1} wrote an interesting Master Thesis in which
describes a Machine Learning Model that simulates MOOC data. Working with data
gathered from EdX, the model once trained, can be able to synthesize student data.
The model was trained to learn about student types, habits and difficulty of course
materials. One of the main results of the thesis was being able to classify
students in 20 important clusters.

(Saeed Hosseini Teshnizi and Sayyed Mohhamad Taghi Ayatollahi, 2015)\cite{bibl_3}
did a comparasion between Logistic Regression and ANNs\footnote{Artificial
Neural Networks} on a dataset composed of 275 undergraduate students and 16
student characteristics (e.g.: age, gender, parent education, employment status,
place of residence, etc.) in order to predict academic failure. They concluded that
the neural network models had a better accuracy than Logistic Regression (84.3\%
versus 77.5\%). They tested 9 ANNs from which the one with 15 neurons in the
hidded layer provided the best results, so ANNs methods were appropiate to be used
in their problem.

Other references\cite{bibl_4},\cite{bibl_5},\cite{bibl_6} also treat prediction
of student academic performance mostly with neural networks and provide good
accuracy with this model (the accuracy is also dependent of the structure of
the dataset, number of examples, number of characteristics and noise in the
data).

(Emaan Abdul Majeed and Khurum Nazir Junejo)\cite{bibl_7} had some great results
using Machine Learning models for predicting student's performance. They claim
that they were capable of predicting the final grade with an accuracy of 96\%.
With a final number of 2500 student records and about 10 attributes for each
record, they managed to predict the value of the final Grade attribute (which
is a Class Variable that can have 6 values: A, B+, B, C+, C, Fail).
Four classifier models were used in their study and we can see in Figure
\ref{fig.figure1}\cite{bibl_7} their performance:

\insfigshw{figure1.png}%
    {Classifiers accuracy}%
    {Classifiers accuracy}%
    {fig.figure1}{0.8}