% !TeX spellcheck = en_GB
% !TeX root = memoco-report.tex

\section{Exact method}
\label{chap:cplexm}
The exact algorithm makes use of the IBM CPLEX C APIs to solve a problem to optimality. In order to model the TSP problem a network flow model is used, as described in the assignment text. \\
The specific linear programming model used and its decision variables are presented below. The set $A$ is the set of edges of the graph, which in this case is a complete graph.
\begin{itemize}
	\item $x_{ij}$ is the amount of 'flow' passed from $i$ to $j,~\forall~(i,j)\in A$
	\item $y_{ij} = 1$ if the edge $(i,j)$ ships some flow, $0$ otherwise $\forall~(i,j)\in A$.
\end{itemize}
\begin{align}
	&\min \sum\limits_{i,j:(i,j)\in A} c_{ij}y_{ij}\\
	&~s.t.~\sum_{i:(i,k)\in A}x_{ik} - \sum_{j:(k,j)\in A, j\ne 0}x_{kj}~~~=~1~~~~~~~~~~~~~~~~~~~~~~\forall~k \in N \setminus \{0\}\label{eq:flow}\\
	&~~~~~~\sum_{j:(i,j)\in A} y_{ij}~~~~~~~~~~~~~~~~~~~~~~~~~~=~1~~~~~~~~~~~~~~~~~~~~~~\forall~i \in N \label{eq:sumi}\\
	&~~~~~~\sum_{i:(i,j)\in A} y_{ij}~~~~~~~~~~~~~~~~~~~~~~~~~~=~1~~~~~~~~~~~~~~~~~~~~~~\forall~j \in N \label{eq:sumj}\\
	&~~~~~~~x_{ij}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\le~(|N|-1)~y_{ij}~~~~~~~\forall~(i,j) \in A,j\ne 0 \label{eq:constrxy}\\
	&~~~~~~~x_{ij} \in \mathbb{R}_+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\forall~(i,j) \in A,j\ne 0 \label{eq:constrx}\\
	&~~~~~~~y_{ij} \in \{0,1\}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\forall~(i,j) \in A
\end{align}

Actually, when adding the variables $x$ and $y$ to the model, variables $x_{ij}~\forall~(i,j) \in A,j\ne 0$, instead of being unbounded like in constraint \ref{eq:constrx}, they are forced to be in range $[0,N-1]$. The model is still valid, since constraint \ref{eq:constrxy} also bounds the variables in this range.

\subsection{Creation of the model}
The linear programming model is set up in the function \texttt{setupLP} in file \texttt{CPLEX.cpp}.\\
During the creation of the model, its decision variables $x_{ij}$ and $y_{ij}$ are first added one by one (for each possible value of $i$ and $j$) through the appropriate CPLEX functions to a C array. Variables with $i = j$ are not added, since no loops on the same point is allowed. Considering that this variables have to be referenced later during the definition of the constraints, their position in the CPLEX array is recorded in two bidimensional vectors, one for the $x$, called \texttt{xMap}, and one for $y$ variables, named \texttt{yMap}. In this way variable $x_{ij}$ can be later referenced easily with \texttt{xMap[i][j]} for all $i$ and $j$. After defining the variables of the problem, the constraints \ref{eq:flow} - \ref{eq:constrxy} are inserted. Constraint \ref{eq:constrxy} was reformulated as $x_{ij} - (|N|-1)y_{ij} \le 0$ because the CPLEX APIs require all the variables in the left-hand side and only constants in the right side of the equation.\\
The model can be solved calling the function \texttt{solve}, which calls the IBM CPLEX solving routines for a minimization problem. The solution can then be retrieved using the method \texttt{getSolution} which returns a \texttt{TSPsolution} object, which wraps many useful information about the final solution, and is used for both the exact method and the heuristic one.

\section{Heuristic method}
\label{chap:heuris}

The implemented heuristic is inspired by a popular local search method called Lin-Kernighan heuristic, originally proposed in 1973 in \cite{LinK73}. The algorithm can be considered a generalization of the k-opt algorithm: one of the drawbacks of this algorithm is that the parameter $k$ must be fixed in advance. Instead, the Lin-Kernighan algorithm decides at each iteration, for ascending values of $k$, whether an interchange of $k$ edges provides a better solution. Thus, the algorithm is specified in terms of exchanges that can convert one tour into another: given a feasible interchange of $k$ edges (a \textit{k-opt move}), the algorithm tries to determine if there exists a \textit{(k+1)-opt} move that improves the tour further.
During each iteration, given a feasible tour, the algorithm repeatedly performs exchanges that reduce the length of the current tour, until a tour is reached for which no exchange yields an improvement. This process may be repeated many times from initial tours generated in some possibly randomized way \cite{Helsgaun2000}.\\
So at each iteration the algorithm tries to determine the largest set $X=\{x_1, x_2, ..., x_j\}$ and $Y=\{y_1, y_2, ..., y_j\}$ such that if edges in $X$ (also called the \emph{broken} edges) are removed and replaced by $Y$ (the \emph{joined} edges) the produced tour is a feasible improved (i.e. less costly) solution. Of course, a naive brute force algorithm searching for this sets, would quickly become impractical to use, due to the exponential running time. In order to produce a reasonably efficient local search procedure, the algorithm reduces the search space using the following criteria:

\begin{enumerate}
	\item \emph{Sequential exchange criterion}: each pair of edges $(x_i, y_i)$ and $(y_i, x_{i+1})$ must share one vertex. If $t_1$ and $t_2$ are the vertices of edge $x_1$, then in general for all $i \ge 1$ exchanges are performed this way: $x_i=(t_{2i-1}, t_{2i})$ and $y_i=(t_{2i}, t_{2i+1})$ and $x_{i+1}=(t_{2i+1}, t_{2i+2})$.\\ All \emph{sequential} k-opt moves can be found by concatenating smaller sequential moves, but \emph{non sequential} moves are never considered by this algorithm. An example of such a move is given in \cref{fig:doublebridge}.
	\item \emph{Feasibility criterion}: for every $i \ge 3$, $x_i=(t_{2i-1}, t_{2i})$ is chosen so that if $t_{2i}$ is connected to $t_1$ the resulting configuration is a tour (i.e. a feasible solution). It can be seen that at most one choice for $x_i$ satisfies this constraint, as showed in \cref{fig:feasibility-moves}. Exceptionally, when $i=2$, the originally proposed algorithm allowed for the choice of an $x_i$ which violates this rule. According to the original paper this was done to strengthen the procedure by giving the algorithm a way to recover from previous wrong choices, but allowing this kind of backtracking at every levels would significantly increase the running time;
	\item \emph{Positive gain criterion}: let $g_i=cost(x_i) - cost(y_i)$ be the gain by exchanging two edges, and let $G_i=g_1+g_2+...+g_i$ be the partial sum of the gains up to the $i^{th}$ exchange. This criterion requires that each $y_j$ is chosen in a way such that $G_j$ is positive. This choice is justified by the fact that if a sequence of numbers has a positive sum, there is a cyclic permutation of these numbers such
	that every partial sum is positive \cite{Helsgaun2000};
	\item \emph{Disjunctivity criterion}: sets $X$ and $Y$ must be disjoint.
\end{enumerate}
In the implemented algorithm, the move size threshold which allows for the exceptional violation of the \emph{feasibility criterion} (set to $2$ in the paper), is not fixed but it can be modified in the configuration file \texttt{config.yml}. In this way the influence of this parameter on the solution quality could be tested and optimized.

\begin{figure}[h]
	\centering
	\includegraphics[width=6cm]{double-bridge}
	\caption{A non sequential \emph{double bridge} move with $k=4$}
	\label{fig:doublebridge}
\end{figure}

\begin{figure}[h]
	\centering
	\begin{subfigure}[c]{0.31\textwidth}
		\includegraphics[width=\textwidth]{path-choices}
		\caption{The two possibles edges to break after choosing $y_1$: $a$, $b$}
	\end{subfigure}
	\begin{subfigure}[c]{0.31\textwidth}
		\includegraphics[width=\textwidth]{path-wrong}
		\caption{Breaking edge $b$ violates the feasibility criterion}
	\end{subfigure}
	\begin{subfigure}[c]{0.31\textwidth}
		\includegraphics[width=\textwidth]{path-right}
		\caption{Breaking edge $a$ allows to close the tour correctly}
	\end{subfigure}
	\caption[Candidate edges satisfying and violating the feasibility criterion]{Only one candidate for $x_i$ satisfies the feasibility criterion, which is enforced for $i$ greater than a fixed threshold value. In this case breaking edge $a$ is the right choice, since removing edge $b$ and relinking with edge $r=(t_4,t_1)$ would not produce a feasible tour.}
	\label{fig:feasibility-moves}
\end{figure}

\subsection{Stopping criterion}
The algorithm uses the same stopping criterion suggested in the original paper. In particular, when the algorithm finds a feasible tour with a move of size $k$, it checks whether the total gain is the best seen so far. If it is, then it is the best improvement seen and it saves the current solution, and tries to improve further with a ($k$+1)-opt move. If this does not improve the solution the algorithm returns the solution it saved. On the other hand, if the size $k$ move yields a feasible tour which is not the best seen so far, the algorithm stops, since it knows there is a better move, with size smaller than $k$, that produces a better tour.\\
By accepting only improving solutions, the algorithm is guaranteed to eventually stop, since it cannot loop over the same local optima.

\subsection{Tour structure}
A tour is maintained as a vector $v$ of pairs, where $v_i$ gives a pair with the two vertices which precedes and follows $i$ in the current tour. To this purpose every vertices (point) of the instance is numbered from $0$ to $N-1$ and its number is used as index to access the tour structure. Creation of such structure takes time $O(N)$ from a list of vertices where $N$ is the problem size. This allows constant time checks and retrieval of the two candidates for removal. Moreover, the distance between each vertex (the cost of each edge) is kept in a $N\times N$ sized matrix.

\subsection{Neighbourhood function}
\label{ssec:neighbourhood}
In a local search algorithm the neighbourhood function describes which solutions are explored at every step. In this case every neighbour is generated with a $k$-opt move from the initial solution and the algorithm tries to increase $k$ at each step.\\
In the described algorithm, for a given $i$, a step consists in breaking an edge of the tour $x_i$ and replacing it with  and edge $y_i$ chosen with the criteria described in \cref{chap:heuris}. Every step generates a new neighbour.
If we fix the vertex $t_{2i-1}$ belonging to joined edge $y_{i-1}$, there are exactly two edges that can be broken. That's because the \emph{sequential exchange criterion} requires that $x_i$ must share an endpoint with $y_{i-1}$ and this endpoint is exactly $t_{2i-1}$. Additionally, by the \emph{feasibility criterion}, there is only one choice of $x_i$ that will produce a feasible tour, while breaking the other will inevitably split the graph into two connected components (as seen in \cref{fig:feasibility-moves}). \\
Starting from vertex $t_{2i-1}$ the algorithm analyses the two possibilities giving the precedence to the edge with higher cost, since is the best one to remove. Only if the feasibility criterion is violated the procedure will try to remove the other edge.\\
In order to choose an edge $y_i$, the algorithm finds all possible edges starting in $t_{2i}$ which are
\begin{itemize}
	\setlength\itemsep{0.05em}
	\item not part of the current solution;
	\item not already broken (i.e. $\notin X$);
	\item not already joined (i.e. $\notin Y$).
\end{itemize}
A simple approach would be to choose as $y_i$ the candidate edge with the lowest cost, since we want to maximize the gain. The paper suggests using a less greedy approach, by looking also at the successive edge $x_{i+1}$. This has the additional benefit of avoiding useless search, as would happen by joining a promising candidate only to find out, when selecting the next edge to break, that no such operation is possible (for example because the only alternative has already been broken). \\
Thus for each candidate edge to join, the possible $x_{i+1}$ are analysed, and the potential gain of adding $y_i$ and removing $x_{i+1}$ is computed. Since the algorithm does not know which choice of $x_{i+1}$ gives the feasible tour, if neither choice can be discarded because of other reasons (e.g. already broken, intensification constraints), both choices are considered and the potential gain is the average of the two gains. So the potential gain is the gain expectation that can be achieved by joining $y_i$ and breaking $x_{i+1}$. Ideally, the neighbourhood function should predict which candidate $x_{i+1}$ is the actual feasible choice that the algorithm will eventually make. Unfortunately, checking this for every possible candidate is quite costly for instances with considerable size, since checking if a sequence of edges represent a feasible tour takes time $O(N)$ on average, and the number of candidates grows linearly with $N$ too.\\
Instead of using the average potential gain to rank the candidates for joining, two alternative approaches using the worst gain and the best possible gain has been tested. Calibration tests on an instance of 90 points determined that this approach produced slightly better results than the others.

%\begin{enumerate}
%	\item Start from a (possibly random) feasible solution;
%	\item Choose an initial vertex $s$;
%	\item Remove an edge $x_1 = (s, v)$ which belongs to the current solution and add an edge $y_1 = (v, z)$ ($z \ne s$) which does not belong to the current solution, such that the gain of this move (removal and insertion) is positive;
%	\item Perform step 3 with the following additional constraints:
%	\begin{itemize}
%		\item the edge to remove ($x_i$) must share 1 vertex with the previous added edge ($y_{i-1}$);
%		\item the edge to remove $x_i = (a, b)$ must be chosen such that if $b$ reconnects to the starting vertex $s$ with edge $(b, s)$, the produced solution is feasible;
%		\item the gain (decrease of objective value) of the solution found with previous constraint must be greater than the best increase found so far.
%	\end{itemize}
%	If the second and third conditions are satisfied, the procedure saves this feasible solution, updates the best gain, and proceeds to step 5. Otherwise it tries the other possibility for $x_i$. If this fails too the procedure stops, and the last saved solution is returned;
%	\item Repeat step 4. When no improving solution can be found set the current best solution as starting solution and restart from step 2.
%\end{enumerate}

\subsection{Enhancements}
This basic algorithm scheme can be enhanced in many ways. The next sections describe some strategies implemented in this project.

\subsubsection{Search intensification}
\label{sssec:intensification}
Between the iterations the algorithm may find some 'good' edges which belongs to the optimal solution or to some reasonably good one. Subsequently some time may be lost by repeatedly breaking and adding them, while not exploring some more promising neighbours. \\
In addition these 'good' edges are likely to be present in many of the best solutions (local optima) found between iterations. In order to direct the search towards more promising solutions, the algorithm keeps track of the edges shared by best $S$ solutions by computing their intersection.\\
On the other hand, if the top-S solutions do not include the global optimum, this approach  may prevent the algorithm from breaking some edges which do not belong to the optimum, thus preventing the algorithm from finding it.\\ To mitigate this problem, the intensification procedure is applied only after a specified number of improving moves (i.e. after a fixed $i$). This means that the algorithm has a way to escape this additional constraint for a small number of moves, allowing it to recover from previous sub-optimal choices.\\
Additionally, after a local optima is found, the objective value is tested to see if it is better than one of the top-S solutions and in this case the worst solution is replaced with the new one and the intersection is updated.\\
A max-heap data structure is used in order to efficiently replace the worst (i.e. with higher objective value) local optima, and the collection of edges of each tour is maintained in a \texttt{std::set} ordered container, which allows the intersection procedure to take time $O(N\cdot S)$ where $N$ is the number of edges in a feasible tour.\\
Instead of considering just the top-S solutions to do the intersection, the original paper proposed to keep the intersection of all tours from the beginning. During some early tests this seemed to worsen the results with respect to the runs without intensification, so this change was made, and a small reduction of running time has been registered, since the algorithm excludes some choices from its neighbourhood.
In choosing the parameter $S$ it is important to keep in mind that intensification is done only after $S$ local optima are found, so one should ensure that this number is suitable for the problem dimension, since a very large number with a small problem would probably be ineffective.

\subsubsection{Avoiding duplicate solutions}
\label{sssec:checkout}
The authors of the algorithm stated that 30\% to 50\% of running time could be saved by keeping track of previous local optima and stopping the algorithm if the current local optima is the same seen before. This is justified by the fact that if the algorithm couldn't improve this solution before, it's unlikely it can do it now. While this sounds reasonable, in the proposed implementation no particular speed-up was registered. In part, this may be due to different computing capabilities, considering that the algorithm was devised in 1973.\\
Since trying to improve a previously found local optima will likely fail, the proposed algorithm adopts a slightly different strategy in this eventuality: instead of stopping, it restarts from a different starting edge and proceeds normally until it finds a different solution, or it determines no better tour exists. While this does not guarantee an improvement in running time, it makes the algorithm redirect the search in a different direction, which is probably more useful that exploring the neighbourhood of a previous solution.\\
To do this, an \texttt{std::set} data structure is used, which maintains a sorted collection (ordered by tour cost) of all the feasible tours found at each iteration. This container guarantees logarithmic insertion and search operations.\\
As a possible improvement to this strategy, one could keep track of the edges modified while converging to the previously encountered solution, and make sure that at least some of these are not added again, which can potentially lead to the same solution again, or to a very similar one.

\clearpage
\subsection{Random restart}
The described heuristic is run from a randomized initial solution, like the one in \cref{fig:randomtour}. This simple strategy allows the algorithm to escape local optima and differentiate the provided solutions. Using an initial solution generated with a fast constructive heuristic has been tried, and a faster convergence has been registered, even though the produced solution was often not better than the solution generated from a random initial solution.
Despite this, the starting tour has a significant impact on the heuristic performance, since it determines the edges that will be tried for the first move. Indeed the algorithm often does not explore more than the first two-three candidates to be joined. This explains why the initial tour greatly contributes to the final result.\\
By restarting the heuristic many times on the same instances of the synthetic dataset of size $> 90$, on average, the heuristic will produce tours 0.5\% from the optimal one, but the best solution found during a reasonable number of restarts is usually much closer to the optimal one. This strategy has been implemented in the file \texttt{utilities.cpp}, where the procedure \texttt{runILK} is defined for this purpose. Setting the desired number of restarts in the \texttt{config.yml} configuration file (parameter \texttt{LK\_iterations}) will restart the algorithm the specified number of times, and the final result will be the best solution found.

\begin{figure}[h]
	\centering
	\includegraphics[width=12cm]{path_50_random}
	\caption{Random initial path on a problem with 50 points}
	\label{fig:randomtour}
\end{figure}

\clearpage
\subsection{Parameters}
\label{ssec:hyperpar}
Table \ref{tab:hyperparameters} includes a description of each parameter to be set in file \texttt{config.yml} before starting the heuristic. Calibration of this parameters are discussed in the next section.

\LTXtable{\linewidth}{parameters}

This heuristic may require some tuning to be usable with bigger problems, since some parameters can significantly increase the running time. To determine the next move, the heuristic considers at most \texttt{max\_neighbours} candidates for joining, and it may do up to \texttt{K} moves per iteration, so the worst case complexity of a single search for the best possible move is $O(max\_neighbours^K)$. This process may be repeated for up to \texttt{I} iterations. Using random restarts this entire procedure is repeated exactly \texttt{LK\_iterations} times. High \texttt{back\-track\-ing\_threshold} values allow the algorithm to violate the feasibility criterion and try more moves, but will also require more time. Low values, like 3 or 4, worked well during testing, even though 2 is more likely the best parameter for instances of size greater than 300.\\
If the algorithm spend too much searching for a move (i.e. searching for an exchange), the \texttt{K} parameter should be lowered. On the other hand, if the algorithm tends to do too many iterations, this number may be limited by lowering \texttt{I}. Reducing \texttt{K} and increasing \texttt{I} allows the algorithm to do a bigger number of smaller improvements. On the other hand increasing \texttt{K} and reducing \texttt{I} will allow for a lower number of better improvements.

\subsubsection{Calibration}
Some parameters in \cref{tab:hyperparameters} may affect the running time and the solution quality. In order to determine how much these parameters influenced this metrics and to select the best ones for the final tests, some trials were done on two different instances, one of size 90 and one of size 198 taken from TSPLIB\footnote{\url{http://elib.zib.de/pub/mp-testdata/tsp/tsplib/tsplib.html}}. Given some sets of parameters to try, every possible combination has been tested by restarting the heuristic 10 times on each combination. The results are reported in tables and discussed in the next paragraphs. Listed information includes the average percentage error, whether the optimal solution was found, the average number of iterations and the total time required for the 10 iterations. The final score is obtained by iterating the heuristic 10 times on the same instance and takes into account the average percentage relative error (w.r.t. the optimal solution computed using the exact algorithm), called $ARE$ and the total execution time for the 10 iterations, called $TT$. The score is given by \cref{eq:score}.
\begin{equation}
	\text{Score} = \cfrac{1}{1 + (ARE * TT)}
	\label{eq:score}
\end{equation}
These results were obtained by using all the features described before, and by compiling with \texttt{-O3} optimization flag. Both tests were done with \texttt{K = 100}.\\
The calibration procedure is implemented in file \texttt{calibrate.cpp}, and more tests can be done by editing the file and running the script with commands~\texttt{make calibrate \&\& ./bin/calibrate}.

\paragraph{Synthetic instance of size 90}\mbox{}\\
Table \ref{tab:calibration} reports the results of the calibration procedure on an instance with 90 points.
Other tests, which are not reported here, were run using the other two ranking strategies to sort the candidates to be joined, discussed in \cref{ssec:neighbourhood}. Strategies using the best and average gain performed similarly, while the strategy sorting by worst gain performed poorly. Three different calibrations for all three strategies has been run and the average gain strategy was selected because it reached the optimal solution more frequently then the one using the best gain.\\
As can be seen in \cref{tab:calibration}, considering more neighbours during the selection of the edge to join (5 instead of 2) results in a lower average error and higher running time. Additionally with value set to 5 the optimal value was found in all cases but one.\\
Additional tests were done with \texttt{backtracking\_depth} set to 2 and 3. Lowering this parameter reduces running time and also the frequency of finding the optimum, so in the table only the runs with depth 4 or 5 are listed.\\

\LTXtable{\linewidth}{calibration}

\paragraph{TSPLIB d198}\mbox{}\\
In order to select some good parameters for a non trivial instance, and additional calibration was done on a drilling problem with 198 points from TSPLIB, called \texttt{d198}.\\
Since the instance is bigger, tests were done with higher values for \texttt{max\_neighbours}, \texttt{back\-track\-ing\_depth} up to 4 (5 is too much for big instances), and the number of tours used for intensification has been limited to 20 or 50. Table \ref{tab:calibration198} shows the results. This time the score is much lower because of the higher running time, so it has been multiplied by 100, to make it more readable.

\clearpage
\LTXtable{\linewidth}{calibration198}

No execution arrived at the optimal solution, but the original paper suggests that with more restarts better solutions can be found. In three runs with \texttt{max\_neighbours = 5}, \texttt{back\-track\-ing\_depth = 3} the best error of the 10 iterations was below 1.0, in particular 0.374, 0.773 and 0.425 with \texttt{intensification\_depth} to 5, 8 and 10 respectively. In the first case the average error was 4.911, which is the best one reported in the table (in bold). In this case the final score strongly penalises the executions with higher backtracking depth because of the longer execution time, but the average error tends to decrease with \texttt{max\_neighbours = 5} and \texttt{back\-track\-ing\_depth = 3}.


\section*{Exercise 26.2-4}
In the example of Figure 26.6, the maximum flow shown has the value 23.
\\
The minimum cut corresponding to this is
$$
(\left\{s,v_1,v_2,v_4\right\}, \left\{v_3,t\right\}),
$$
since the capacity is
$$
c(v_1,v_3) + c(v_4,v_3) + c(v_4,t) = 12+7+4 = 23.
$$
\\
\\
The augmenting path in (c) cancels flow:
\\
4 units on $(v_1, v_2)$ and $(v_2,v_3)$.


\section{Strings}
\lst{Trie/Prefix Tree}{$\mathcal{O}(n)$ for set and get}{strings/trie.cc}

\begin{code}{Prefix Function}{$\mathcal{O}(n)$}{strings/prefixFunction.cc}
  For a string $s$ return an array in which the $i$-th entry is the
  length of the longest proper prefix of $s[0,\ldots, i]$ which is also
  a suffix.  Note that the $0$-th entry is $0$
\end{code}

\begin{code}{KMP}{$\mathcal{O}(n + m)$}{strings/kmp.cc}
  Returns a list with all the starting indeces where the pattern matches
  the text.
\end{code}

\begin{code}{Manachers}{$\mathcal{O}(n)$}{strings/manachers.cc}
% source: https://www.hackerrank.com/topics/manachers-algorithm
Returns array where $P[i]$ contains the length of the palindrome with
mid-point $i$. There are extra entries for where the mid-point is
inbetween letters. Example for $abbaac$:
\begin{verbatim}
| a | b | b | a | a | a | c |
0 1 0 1 4 1 0 1 2 3 2 1 0 1 0
\end{verbatim}
\end{code}

\begin{code}{Aho-Corasick Automaton}{build: $\mathcal{O}(\sum |t_j|)$, query: $\mathcal{O}(|S|)$}{strings/AHC.cc}
  % See for detailed explaination:
  % http://web.stanford.edu/class/archive/cs/cs166/cs166.1166/lectures/02/Small02.pdf
  % TODO(Alex): Test query() call extensively. Build + insert are okay for sure.
  Data structure to search how often $n$ fixed strings $t_1, \dots, t_n$
  are contained in a variable string $S$. Strings $t_j$ may each have
  values.
\end{code}


\subsection{Training decision trees with Gini impurity}


\documentclass[12pt]{rudin}
\usepackage[]{amsmath}
\usepackage[]{exercise}
\usepackage[]{enumitem}
\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue]{hyperref}

\renewcommand{\ExerciseHeader}{\noindent\textbf{\ExerciseName\ \ExerciseHeaderNB}\ \ExerciseHeaderTitle\ \ExerciseHeaderOrigin\smallskip}
\renewcommand{\ExerciseHeaderOrigin}{(\ExerciseOrigin)}
\renewcommand{\AnswerHeader}{\bigskip\noindent\textbf{Solution \ExerciseHeaderNB}\newline}
\let\set\mathbf

\title{Number Theory Homework I}
\author{RDB}
\date{\today}

\begin{document}

\maketitle

This homework is meant to be a warmup for things covered in 300 along with a
peek at some number theory. Direct proofs, inequalities, induction, the
contrapositive, and perhaps most importantly, \emph{style}.

Homework exists to give you practice. Try to solve the questions on your own
before anything else; you will get the most out of it this way. (Plus, you
won't have any outside resources on quizzes and exams!) Once you've given it a
good try, feel free to collaborate with your classmates or ask me about it.

\paragraph{EXPECTATIONS} Write your proofs with \emph{good style}. What is good
style? Concise yet enlightening. Simple yet pretty. Practical yet fun.
Basically, go read the first chapter of
\href{https://jmlr.csail.mit.edu/reviewing-papers/knuth_mathematical_writing.pdf}{Knuth's masterpiece}
and buy yourself a copy of Strunk and White's \emph{The Elements of Style}.
Your efforts will be repayed tenfold.

For example, suppose you were proving ``the sum of even integers is even.''
\begin{proof}[Terrible proof]
\begin{align*}
    &\exists n, k \ [2n + 2k] \\
    &\implies 2n + 2k = 2(n + k) \\
    &\exists m \ [n + k = m] \\
    &\therefore 2n + 2k = 2m
\end{align*}
\end{proof}
\begin{proof}[Excellent proof]
    If $x$ and $y$ are even integers, then there exist integers $n$ and $k$
    such that
    \begin{equation*}
        x + y = 2n + 2k = 2(n + k).
    \end{equation*}
    Since $n + k$ is an integer, $x + y$ is even.
\end{proof}
Both proofs are (essentially) logically correct, yet one makes me dizzy. Bring
your readers the joy of discovery, not the pain of parsing notation.

\section*{Exercises}%
\label{sec:exercises}

In general, assume that variables like $n$, $m$, and $k$ are integers.

\begin{Exercise}
    \begin{enumerate}[label=(\textbf{\alph*})]
        \item Prove that $n^2$ is even if and only if $n$ is even.

        \item If $\sqrt{2} = a / b$ for coprime integers $a$ and $b$, then $2
            b^2 = a^2$. Use the previous part to derive a contradiction about
            $a$ and $b$, and conclude that $\sqrt{2}$ is irrational.
    \end{enumerate}
\end{Exercise}

\begin{Answer}
    \begin{enumerate}[label=(\textbf{\alph*})]
	    \item (3 points) If $n = 2k$, then $n^2 = 4k^2 = 2(2k^2)$. On the other hand,
		    if $n = 2k + 1$, then $n^2 = 4k^2 + 4k + 1 = 2(2k^2 + 2k) +
		    1$.

	    \item (3 points) Since $2b^2 = a^2$, we see that $a^2$ is even. The previous part
		implies that $a$ is even, say $a = 2k$. Then $2b^2 = 4k^2$, and
		    dividing by $2$ yields $b^2 = 2k^2$. But then $b$ is even,
		    and that contradicts that $a$ and $b$ are coprime.
    \end{enumerate}
\end{Answer}

\begin{Exercise}
    Three natural numbers $x < y < z$ are a \emph{Pythagorean triple} provided that
    \begin{equation*}
        x^2 + y^2 = z^2.
    \end{equation*}
    \begin{enumerate}[label=(\textbf{\alph*})]
	    \item Determine \emph{all} Pythagorean triples where $x$, $y$, and $z$
            are consecutive natural numbers.

        \item Given a natural number $a$, let's say that $n$ is an
            \emph{$a$-Pythagorean integer} if
            \begin{equation*}
                n^2 + (n + a)^2 = (n + 2a)^2.
            \end{equation*}

            For a fixed $a$, how many $a$-Pythagorean integers are there?
    \end{enumerate}
\end{Exercise}

\begin{Answer}
    \begin{enumerate}[label=(\textbf{\alph*})]
	    \item (3 points) This amounts to solving the equation
            \begin{equation*}
                n^2 + (n + 1)^2 = (n + 2)^2,
            \end{equation*}
		    which, after you expand it, is just a quadratic. The only
		    positive solution is $n = 3$, which gives the triple $(3,
		    4, 5)$.

	    \item (3 points) The equation
            \begin{equation*}
                n^2 + (n + a)^2 = (n + 2a)^2
            \end{equation*}
	    is a quadratic in $n$ and has a single positive solution for $a >
		    0$, namely $n = 3a$. So there is only \emph{one}
		    $a$-Pythagorean integer for every $a$.
    \end{enumerate}
\end{Answer}

\begin{Exercise}
    \begin{enumerate}[label=(\textbf{\alph*})]
        \item Prove that
            \begin{equation*}
                \sum_{k = 0}^n a(k) = b(n)
            \end{equation*}
            is equivalent to
            \begin{equation*}
                b(n + 1) - b(n) = a(n + 1); \quad b(0) = a(0).
            \end{equation*}

            [Hint: Use induction to get from the difference to the sum.]

        \item Use the above technique to show that the sum of the first $n$
            positive integers is $n(n + 1) / 2$.

        \item Use the above technique to show that
            \begin{equation*}
                \sum_{k = 1}^n k^3 = \left( \sum_{k = 1}^n k \right)^2.
            \end{equation*}
            [Hint: You know what the right-hand side is from the previous
            part.]
    \end{enumerate}
\end{Exercise}

\begin{Answer}
    \begin{enumerate}[label=(\textbf{\alph*})]
	    \item (4 points) If
            \begin{equation*}
                \sum_{k = 0}^n a(k) = b(n),
            \end{equation*}
	    then obviously $b(n + 1) - b(n) = a(n + 1)$ and $b(0) = a(0)$.

	    On the other hand, suppose that
            \begin{equation*}
                b(n + 1) - b(n) = a(n + 1); \quad b(0) = a(0).
            \end{equation*}
	    We will prove the summation identity via induction. The
	    base case, $n = 0$, is assumed: $b(0) = a(0) = \sum_{k = 0}^0
	    a(k)$. For the inductive step, suppose that
            \begin{equation*}
                \sum_{k = 0}^n a(k) = b(n)
            \end{equation*}
	    for some $n \geq 0$. Then,
            \begin{align*}
		    \sum_{k = 0}^{n + 1} a(k) &= b(n) + a(n + 1) \\
		    			      &= b(n + 1).
            \end{align*}
	    Therefore the equation $b(n) = \sum_{k = 0}^n a(k)$ holds
	    for \emph{all} integers $n \geq 0$.

    \item (2 points) Just check that $\frac{(n + 1)(n + 2)}{2} - \frac{n(n + 1)}{2} = n + 1$ and that $\frac{0(0 + 1)}{2} = 0$.

    \item (2 points) Check that $\left( \frac{n(n + 1)}{2} \right)^2$ satisfies the right
	    equations.
    \end{enumerate}
\end{Answer}

\begin{Exercise}
    The \emph{Fibonacci numbers} $F_n$ are defined by the following recurrence:
    \begin{align*}
        F_0 &= 0 \\
        F_1 &= 1 \\
        F_{n + 2} &= F_{n + 1} + F_n.
    \end{align*}

    \begin{enumerate}[label=(\textbf{\alph*})]
        \item Compute the first ten Fibonacci numbers.

        \item Prove that
            \begin{equation*}
                \sum_{k = 0}^n F_k = F_{n + 2} - 1.
            \end{equation*}
            [Hint: Use the earlier exercise about sums. Or induction.]

        \item The \emph{square} Fibonacci numbers $S_n = F_n^2$ \emph{also}
            satisfy a nice recurrence:
            \begin{equation*}
                S_{n + 3} = 2 S_{n + 2} + 2 S_{n + 1} - S_n.
            \end{equation*}

            Check that this is true up to $n = 6$.
    \end{enumerate}
\end{Exercise}

\begin{Answer}
    \begin{enumerate}[label=(\textbf{\alph*})]
	    \item (2 points) 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

	    \item (2 points) Note that $F_{0 + 2} - 1 = 0 = \sum_{k = 0}^0 F_k$, and that
            \begin{equation*}
		    (F_{n + 3} - 1) - (F_{n + 2} - 1) = F_{n + 1}.
            \end{equation*}

    \item (2 points) The first ten squares are: 0, 1, 1, 4, 9, 25, 64, 169, 441, 1156.
		Using the recurrence
            \begin{equation*}
                S_{n + 3} = 2 S_{n + 2} + 2 S_{n + 1} - S_n
            \end{equation*}
	    along with the initial values $S_0 = 0$, $S_1 = 1$, $S_2 = 1$, we
	    get the same list:
	    \begin{align*}
		    2 (1) + 2 (1) - 0 &= 4 \\
		    2 (4) + 2 (1) - 1 &= 9 \\
		    2 (9) + 2 (4) - 1 &= 25 \\
		    2 (25) + 2(9) - 4 &= 64,
	    \end{align*}
	    and so on.
    \end{enumerate}
\end{Answer}

\begin{Exercise}
    Prove that $n! > 2^n$ for sufficiently large $n$. [Hint: This means that
    there exists some $N$ such that $n! > 2^n$ for $n \geq N$. You have to find
    that $N$ and then prove it. Induction is the way to go here.]
\end{Exercise}

\begin{Answer}
	(4 points)

	Suppose that $n! > 2^n$ for some $n \geq N$. [We haven't yet determined
	$N$, but that's OK! We'll come back to it.] Then, $$(n + 1)! = (n + 1)
	\cdot n! > (n + 1) 2^n.$$ So, if $n + 1 > 2$, or $n > 1$, then $(n +
	1)! > 2^{n + 1}$. In other words, the inductive argument will work as
	long as we start at $N = 2$.

	But we need a good base case, and $N = 2$ doesn't work. Note that $4!
	= 24 > 16 = 2^4$, so $N = 4$ will do the job.
\end{Answer}

\begin{Exercise}
    This exercise involves programming. When you write a program, save it as a
    ``.py'' file and submit it with your homework. (I'll explain how to do this
    in class on Thursday if this doesn't make sense to you.)

    Let $a(n) = 2^n + 1$.

    \begin{enumerate}[label=(\textbf{\alph*})]
        \item Write a Python program to compute $[a(1), a(2), a(3), \dots,
            a(n)]$ for arbitrary $n$. [Hint: Lookup ``python list
            comprehension.'']

        \item Using your program, determine which values of $a(n)$ are prime
            for $1 \leq n \leq 16$. Guess a pattern.

        \item Prove that $a(n)$ is \emph{not} prime if $n$ is odd. [Hint: Prove
            that $3$ divides $a(n)$ if $n$ is odd, probably by induction.] Does
            this prove your pattern? Explain.
    \end{enumerate}
\end{Exercise}

\begin{Answer}
    \begin{enumerate}[label=(\textbf{\alph*})]
        \item (2 points) Simple python program: \texttt{[2**k + 1 for k in
            range(1, 17)]}. There are infinitely many ways you could have
            structured this.

	    \item (2 points) In the given range, the $n$ for which $a(n)$ is prime are $1$,
            $2$, $4$, $8$, and $16$. It \emph{seems} like $a(n)$ might be prime
            when $n$ is a power of $2$.

    \item (3 points) One way is induction. Our statement is ``$3$ divides $2^{2n + 1} + 1$
	    for all nonnegative integers $n$.'' The base case, $n = 0$, is
	    obvious, since $2^{2 \cdot 0 + 1} + 1 = 3$. Suppose that $2^{2n +
	    1} + 1 = 3k$ for some integer $k$. Then, we have $$2^{2(n +
	    1) + 1} + 1 = 4 \cdot 2^{2n + 1} + 1.$$ Our assumption then gives
	    \begin{align*}
		    4 \cdot 2^{2n + 1} + 1 &= 4(3k - 1) + 1 \\
		    		     &= 12k - 4 + 1 \\
				     &= 3(3k - 1),
	    \end{align*}
	    so $3$ divides $2^{2(n + 1) + 1} + 1$ as well.
    \end{enumerate}
\end{Answer}

\begin{Exercise}
    What is your favorite integer? Enter it into
    \url{http://www.numbergossip.com/} and give some of your favorite
    properties.
\end{Exercise}

\begin{Answer}
	(3 points)
	My favorite integer is $6$. My favorite property listed on the site is
	something I don't know how to prove.

	In binary, $6 = (110)_2$. There are an even number of 1's in the
	expansion.

	Also, the proper divisors of 6 are $1$, $2$, and $3$. If you add these
	up, you get $6$: $$1 + 2 + 3 = 6.$$

	Supposedly, \emph{$6$ is the only even number that does both of these
	things at once.} This seems surprising, but maybe it's actually easy to
	prove.  I don't know!
\end{Answer}

\end{document}


% This is part of the TFTB Reference Manual.
% Copyright (C) 1996 CNRS (France) and Rice University (US).
% See the file refguide.tex for copying conditions.

\markright{modulo}
\section*{\hspace*{-1.6cm} modulo}

\vspace*{-.4cm}
\hspace*{-1.6cm}\rule[0in]{16.5cm}{.02cm}
\vspace*{.2cm}

{\bf \large \sf Purpose}\\
\hspace*{1.5cm}
\begin{minipage}[t]{13.5cm}
Congruence of a vector.
\end{minipage}
\vspace*{.5cm}

{\bf \large \sf Synopsis}\\
\hspace*{1.5cm}
\begin{minipage}[t]{13.5cm}
\begin{verbatim}
y = modulo(x,N)
\end{verbatim}
\end{minipage}
\vspace*{.5cm}

{\bf \large \sf Description}\\
\hspace*{1.5cm}
\begin{minipage}[t]{13.5cm}
        {\ty modulo} gives the congruence of each element of the vector
   {\ty x} modulo {\ty N}. These values are strictly positive and lower
   equal than {\ty N}.\\

\hspace*{-.5cm}\begin{tabular*}{14cm}{p{1.5cm} p{8.5cm} c}
Name & Description & Default value\\
\hline
	{\ty x} & vector of real values, positive or negative\\
	{\ty N} & congruence number (not necessarily an integer)\\
\hline	{\ty y} & output vector of real values, $>$0 and $\leq${\ty N}\\

\hline
\end{tabular*}

\end{minipage}
\vspace*{1cm}

{\bf \large \sf Example}
\begin{verbatim}
         x=[1.3 -2.13 9.2 0 -13 2];
         modulo(x,2)
         ans =
               1.3000    1.8700    1.2000    2.0000    1.0000    2.0000
\end{verbatim}
\vspace*{.5cm}

{\bf \large \sf See Also}\\
\hspace*{1.5cm}
\begin{minipage}[t]{13.5cm}
\begin{verbatim}
rem.
\end{verbatim}
\end{minipage}


\hypertarget{hoare-logic-and-its-mechanization}{%
\section{Hoare Logic and its
Mechanization}\label{hoare-logic-and-its-mechanization}}

\begin{itemize}
\tightlist
\item
  means to prove the Hoare triple \{ P \} C \{ Q \} valid
\item
  Hoare logic is a logic for obtaining valid Hoare triples by purely
  deductive reasoning, that is, by mathematical proof
\item
  deductive reasoning means successively applying inference rules to
  axioms and already obtained conclusions to obtain new conclusions
\item
  such proofs usually are extremely long and boring
\item
  and therefore must be performed as automatically as possible (by
  programs that are by themselves reliable \ldots{})
\item
  but: proof problem is undecidable in the general case
\end{itemize}

\hypertarget{weakest-preconditions}{%
\subsection{Weakest Preconditions}\label{weakest-preconditions}}

\begin{itemize}
\tightlist
\item
  given a command C and a postcondition Q
\item
  given a prestate, the following three things may happen:

  \begin{enumerate}
  \def\labelenumi{\alph{enumi})}
  \tightlist
  \item
    execution of C terminates in a poststate that satisfies Q
  \item
    execution of C does not terminate
  \item
    execution of C terminates in a poststate that satisfies $\neg$Q
  \end{enumerate}
\item
  let w be the set of all prestates from a) and b) together
\item
  a weakest precondition W for C and Q is a boolean formula that
  describes exactly this set
\item
  obviously, weakest preconditions are not unique, since with W $\in$ wp(C,
  Q), for instance, W $\land$ true $\in$ wp(C, Q)
\item
  but clearly, all W $\in$ wp(C, Q) are equivalent
\end{itemize}

\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black]
$\models$ { P } C { Q } is equivalent to $\models$ P $\Rightarrow$ wp(C, Q)
\end{tcolorbox}

\hypertarget{rules-of-inference}{%
\subsection{Rules of Inference}\label{rules-of-inference}}

\begin{itemize}
\tightlist
\item
  let f, f 1 , \ldots{}, f n be boolean formulas (here assertions or
  Hoare triples), n $\geqslant$ 0
\item
  an inference rule is a syntactic construct of the following form:
\end{itemize}

\begin{figure}[H]
\centering
\includegraphics[width=50px]{figures/inferenceRule.png}
\caption{Inference Rule}
\end{figure}

\begin{itemize}
\tightlist
\item
  f\_1 , \ldots{}, f\_n are called premises or hypotheses
\item
  f is called conclusion
\item
  if there are no premises (n = 0), the rule is called an axiom
\item
  the conclusion f is valid, if all hypotheses are valid
\end{itemize}

\hypertarget{skip-axiom}{%
\subsubsection{Skip Axiom}\label{skip-axiom}}

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{figures/skipAxiom.png}
\caption{Skip Axiom}
\end{figure}

\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black]
$\{ 6 < x \}$ not equal $\{ x > 6 \}$
\end{tcolorbox}

\clearpage
\hypertarget{rule-of-consequence}{%
\subsection{Rule of Consequence}\label{rule-of-consequence}}

the RoC is of utmost importance:

\begin{itemize}
\tightlist
\item
  it provides the interface between Hoare logic, concerned with
  programming, and „ordinary`` mathematics
\item
  \ldots{} or in other words, it allows to plug in ordinary mathematics
  into Hoare logic
\end{itemize}

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{figures/rulesOfConsquence.png}
\caption{Rules of Consequence}
\end{figure}

We now write this proof of $\models$ \{ x \textgreater{} 7 \} skip \{ x
\textgreater{} 5 \} more concisely and much closer to normal programming
as

\begin{lstlisting}
{ x > 7 }
{ x > 6 }
skip
{ x > 6 }
{ x > 5 }
\end{lstlisting}

\begin{itemize}
\tightlist
\item
  premises:

  \begin{itemize}
  \tightlist
  \item
    we read lines 1 and 2 as implication $\Rightarrow$ (first premise of RoC)
  \item
    we read lines 2 --- 4 as HT (second premise of RoC)
  \item
    we read lines 4 and 5 as implication $\Rightarrow$ (third premise of RoC)
  \end{itemize}
\item
  conclusion:

  \begin{itemize}
  \tightlist
  \item
    we read lines 1 --- 5 as HT (conclusion of RoC)
  \end{itemize}
\end{itemize}

\clearpage
\hypertarget{general-proof-procedure}{%
\subsection{General Proof Procedure}\label{general-proof-procedure}}

\begin{itemize}
\tightlist
\item
  To prove \{P\} C \{Q\}, we start with the postcondition Q, go
  backwards over the command C to determine a precondition R such that
  the HT \{R\} C \{Q\} is valid, and construct the implication P
  -\textgreater{} R.
\item
  This implication is called a verification condition (VC).
\item
  If this VC is valid, then the original HT \{P\} C \{Q\} is valid too.
\item
  this process can be mechanized, that is, performed fully automatically
  be means of a - computer
\item
  there might be many possible preconditions, which one do we choose?
\item
  we always choose the syntactically weakest precondition
\item
  that is, we can assume as little as possible
\end{itemize}

\begin{lstlisting}
Example
{ x > 7 } -- given precondition P
{ x > 5 } -- compute precondition R
skip
-- go backwards over the command C
{ x > 5 } -- start here with given postcondition Q now construct VC P $\Rightarrow$ R,
          -- that is, "x > 7 $\Rightarrow$ x > 5"
\end{lstlisting}

\hypertarget{computing-preconditions-and-software-engineering}{%
\subsubsection{Computing Preconditions and Software
Engineering}\label{computing-preconditions-and-software-engineering}}

\begin{itemize}
\tightlist
\item
  looks strange in the first moment to start with the postcondition to
  arrive at the precondition
\item
  but: \textbf{the postcondition describes the actual task of the
  program and is thus given}
\item
  the precondition will be determined to find out under which
  circumstances the postcondition can be achieved
\item
  happily, determining preconditions from postconditions is much simpler
  than the other way round
\item
  thus, determining VCs (via computing preconditions) can be done
  automatically by a tool called a \textbf{verification condition
  generator}
\item
  the VCs can then (hopefully automatically) be discharged (proved
  valid) by a second tool called a theorem prover
\end{itemize}

\hypertarget{textual-substitution}{%
\subsubsection{Textual Substitution}\label{textual-substitution}}

This is an operation that essentially can be performed by means of
search and replace of a text editor, and thus can be implemented on a
machine.

\begin{lstlisting}
x[x<-z+2] yields (z + 2)
-- or
y[x<-z+2] yields y
-- [x<-z+2] this will replace all x with z+2
\end{lstlisting}

\hypertarget{assignment-axiom}{%
\subsection{Assignment Axiom}\label{assignment-axiom}}

\begin{itemize}
\tightlist
\item
  The assigning command can be seen as something like renaming an
  expression in the precondition.
\item
  You take the expression in the execution part and assign this defition
  of the variable (in the execution part) to the same variable in the
  precondition.
\item
  If the new precondition can still meet the postcondition (after
  execution), the Hoare is valid.
\end{itemize}

\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{figures/assigningAxiom.png}
\caption{Assignment Axiom Examples}
\end{figure}

\hypertarget{composition-command}{%
\subsection{Composition Command}\label{composition-command}}

The composition command is used to do one or more things one after the
other.

\begin{figure}[H]
\centering
\includegraphics[width=0.7\textwidth]{figures/compositionrule.png}
\caption{Composition Rule}
\end{figure}

\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{figures/compositionExample.png}
\caption{Composition Example}
\end{figure}

\hypertarget{example-strange-swap}{%
\subsubsection{Example Strange Swap}\label{example-strange-swap}}

\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{figures/exampleStrangeSwap.png}
\caption{Strange Swap Example}
\end{figure}

\hypertarget{conditional-rule}{%
\subsection{Conditional Rule}\label{conditional-rule}}

\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{figures/conditionalRule.png}
\caption{Conditional Rule}
\end{figure}

\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{figures/exampleConditional.png}
\caption{Conditional Rule Example}
\end{figure}

\clearpage


\section{Introduction}
\label{Transport Intro}
For reference, some common equations and brief overviews of the three categories of particles will be given in this chapter. The Maxwell equations \eqref{Gauss}--\!\,\eqref{Ampere}, the continuity equation for charge density and current density \eqref{continuity}, the Lorentz force equation \eqref{Lorentz}, Newton's second law of motion \eqref{Newton2}, and the \ac{MHD} approximation of Ohm's Law \eqref{Ohm} are each useful for basic plasma physics. Thorough derivations for these and related equations can be found in several textbooks, including \citet{gombosi98} and \citet{jackson99}.

\begin{subequations}
 \begin{align}
  \nabla\cdot\mathbf{E}&=\frac{\rho_e}{\epsilon_0}&\quad\text{Gauss's Law}
  \label{Gauss}\\
  \nabla\times\mathbf{E}&=-\frac{\partial\mathbf{B}}{\partial t}&\quad\text{Faraday's law of induction}
  \label{Faraday}\\
  \nabla\cdot\mathbf{B}&=0&\quad\text{Gauss's law for magnetism}
  \label{Gauss m}\\
  \nabla\times\mathbf{B}&=\mu_0\mathbf{J}+\mu_0\epsilon_0\frac{\partial\mathbf{E}}{\partial t}&\quad\text{Amp\`{e}re's law}
  \label{Ampere}
 \end{align}
\end{subequations}
\begin{align}
 \nabla\cdot\mathbf{J}&=-\frac{\partial\rho_e}{\partial t}&\quad\text{continuity equation}
 \label{continuity}\\
 \mathbf{F}&=q\left(\mathbf{E}+\mathbf{v}\times\mathbf{B}\right)\quad\text{(N)}&\quad\text{Lorentz force}
 \label{Lorentz}\\
 \mathbf{F}&=m\mathbf{a}\quad\text{(N)}&\quad\text{Newton's 2nd law of motion}
 \label{Newton2}\\
 \mathbf{J}&=\sigma\left(\mathbf{E+v\times B}\right)\quad\text{(A m$^{-2}$)}&\quad\text{Ohm's law}
 \label{Ohm}
\end{align}

In these equations, $\epsilon_0$ is the electric constant (also called the permittivity of free space), $\mu_0$ is the magnetic constant (also called the permeability of free space), $\sigma$ is the electrical conductivity, treated here as a constant, $q$ is the charge, $\rho_e$ is the charge density, $m$ is the mass, $\mathbf{J}$ is the electric current density, and $\mathbf{E}$ and $\mathbf{B}$ are the electric and magnetic fields. $\mathbf{F}$, $\mathbf{v}$, and $\mathbf{a}$ represent force, velocity, and acceleration.

In \ac{MHD}, the fields are induced by plasma motion, so the fields vary on the same time and length scales as the plasma variables. If high frequency variations in the electric field are not included, and only the non-relativistic regime is considered, the displacement current in Amp\`{e}re's law can be neglected, leading to Equation~\ref{AmpereMHD}.
\begin{align}
 \nabla\times\mathbf{B}&=\mu_0\mathbf{J}&&\quad\text{MHD Amp\`{e}re's law}
 \label{AmpereMHD}
\end{align}
\indent By substituting Equation~\ref{Faraday} and the curl of Equation~\ref{AmpereMHD} into the curl of Equation~\ref{Ohm}, $\mathbf{E}$ and $\mathbf{J}$ can be eliminated to derive the magnetic induction equation \eqref{MHDinduction}. The first term on the right describes the resistive diffusion of the magnetic field in the plasma while the second term describes the convection of the magnetic field by the plasma.
\begin{align}
 \frac{\partial\mathbf{B}}{\partial t}=\frac{1}{\sigma\mu_0}\nabla^2\mathbf{B}+\nabla\times\left(\mathbf{v}\times\mathbf{B}\right)&&\quad\text{magnetic induction equation}
 \label{MHDinduction}
\end{align}

Since Equation~\ref{Gauss m} states that the divergence of the magnetic field vector $\mathbf{B}$ is zero, $\mathbf{B}$ can be written in terms of a vector potential $\mathbf{A}$:
\begin{align}
 \mathbf{B}=\nabla\times\mathbf{A}\quad\text{(T)}.
 \label{B field}
\end{align}

By substituting Equation~\ref{B field} into Equation~\ref{Faraday}, Faraday's law of induction can be written as a quantity with a vanishing curl. Such a quantity can be rewritten as the gradient of a scalar function, the scalar potential $\Phi$, leading to an equation for $\mathbf{E}$ in terms of the potentials $\mathbf{A}$ and $\Phi$:
\begin{align}
 \mathbf{E}=-\nabla\Phi-\frac{\partial\mathbf{A}}{\partial t}\quad\text{(V m$^{-1}$)}.
 \label{E field}
\end{align}

For electrostatics, all derivatives with respect to time are zero. In this case, the divergence of Equation~\ref{E field} combined with Equation~\ref{Gauss} will give the Poisson equation, or in the absence of charges, the Laplace equation:
\begin{align}
 \nabla^2\Phi &= -\frac{\rho_e}{\epsilon_0},&\quad\text{Poisson's equation}
 \label{Poisson}\\
 \nabla^2\Phi &= 0.&\quad\text{Laplace's equation}
 \label{Laplace}
\end{align}

Due to the historical precedent of the symbols used in these and other common equations, a symbol may have different meanings depending on the equation in which it is used (i.e., `E' can represent `electric field' or `energy'). Even though the meaning of the symbol can usually be discerned from the context of the equation, an attempt has been made to use distinct symbols throughout this dissertation, or use subscripts to clarify a symbol's meaning when necessary. In the specific case of `E', the bold font $\mathbf{E}$ is used to represent the electric field vector and $\left|\mathbf{E}\right|$  to represent the magnitude of the electric field. The plain font E is always used here to represent energy.

Particle transport and acceleration are important topics of research in heliophysics. An understanding of the composition and nature of the gas and plasma found in space is vital to the forecasting of space weather. This research focuses on ways to investigate three categories of particles: the solar wind (\S~\ref{Solar Wind}), pickup ions, and energetic particles, as shown in Figure~\ref{fig:H_Distribution}. The following is intended to provide sufficient background for the scope of this dissertation research.
\begin{figure}
  \centering
  \includegraphics[width=.65\textwidth]{Chap2/H_Distribution}
  \caption[Example of proton distributions for the quiet solar wind near 5 AU.]{Example of proton distributions for the quiet solar wind near 5 AU. Shown are the bulk distribution of the solar wind, the interstellar pickup ions that drop off at twice the solar wind speed, and the high-energy protons that make up the suprathermal tail. Figure from \citet{gloeckler01b}.}
  \label{fig:H_Distribution}
\end{figure}

\section{The Solar Wind}
\label{Solar Wind}

\subsection{Current Knowledge}
\label{SW Current Knowledge}
While he was not the first to postulate its existence, the physics of the solar wind was first explained by Eugene Parker in 1958 \citep{parker58}. Beginning with subsonic speeds close to the Sun, plasma accelerates away from the solar surface and reaches supersonic speeds in the corona. It continues to expand in a radial direction outward until it interacts with the material in interstellar space at the edge of the heliosphere, the Sun's sphere of influence. The wind draws the solar magnetic field along with it, creating spiral-shaped field lines as the Sun rotates \citep{parker59}. Mankind's understanding of the processes that govern the solar wind has increased as spacecraft have taken in situ measurements, but there are still some properties that remain unexplained, such as the precise origin of certain types of wind, as discussed below.

The solar wind travels a distance of one \ac{AU} before reaching Earth's orbit, where most of the current measurements have been taken (Table~\ref{tab:solar wind}). It is generally divided into two components, commonly referred to as the ``fast'' and ``slow'' solar wind. Originally, these terms were used to differentiate the wind by the speed with which it traveled, but more recent studies have shown that the two types of wind are more efficiently distinguished by their charge state composition (e.g., O$^{7+}$/O$^{6+}$) since the plasma can change speeds as it flows through space \citep{geiss95b, gloeckler03a}. Rather than the terms ``fast'' and ``slow'', more appropriate labels are descriptive of the wind's origin: ``coronal hole'' and ``streamer'' wind. These two types of wind are generated by different processes and have different compositions, temperatures, speeds, and origins.
\begin{table}[htbp]
	\centering
		\begin{tabular}{l|c|c}
		                                                               & Coronal Hole Wind & Streamer Wind     \\ \hline
      bulk speed \footnotesize{$\left(\text{km s}^{-1}\right)$}    & 750               & 400               \\ \hline
      thermal speed \footnotesize{$\left(\text{km s}^{-1}\right)$} & 32                & 35                \\ \hline
      H$^+$ density \footnotesize{$\left(\text{cm}^{-3}\right)$}   & 2.5               & 8.7               \\ \hline
      frozen-in temperature \footnotesize{$\left(\text{K}\right)$} & 8 x 10$^5$        & 1.4--1.6 x 10$^6$ \\ \hline

		\end{tabular}
	\caption[Average characteristics of the solar wind at 1 AU.]{Average characteristics of the solar wind at 1 AU. The temperature is derived from the freeze-in temperature of C$^{6+}$/C$^{5+}$, which freezes in near the solar wind source altitude. Data compiled from \citet{vonsteiger95, gloeckler98a, ipavich98, mccomas00, feldman05}.}
	\label{tab:solar wind}
\end{table}

As solar wind ions escape from the photosphere and travel up through the corona, they experience collisions with energetic electrons that ionize them to different degrees. As they travel farther through the corona, continuously accelerating, the density of coronal electrons decreases and the particles experience fewer collisions. When the timescale for ionization or recombination becomes longer than the timescale of the solar wind to expand through a density scale height, the charge state of the ion is said to be ``frozen in,'' branding the ion with the coronal region and electron temperature of its origin \citep{hundhausen68}. The streamer wind has a distinct characteristic of being enriched in elements with a low ($\le$ 10 eV) \ac{FIP} by a factor of 3--4 over the photospheric value. The coronal hole wind does not show this density enhancement, and measurements have revealed abundances of low-\ac{FIP} elements that match ratios in the photosphere \citep{vonsteiger93}. The streamer wind also has a higher and more variable freeze-in temperature than the coronal hole wind. One explanation for this describes solar plasma trapped and heated in large coronal loops that are eventually opened by interchange reconnection, releasing the plasma \citep{gosling95, fisk98, fisk99a}.

The coronal hole wind originates in the open flux regions of the Sun, which contain low-density plasma and concentrations of magnetic flux that are all the same polarity. During solar minimum these regions are clustered around the poles of the Sun, while during solar maximum they appear at all latitudes. Plasma in open flux regions is also released from flux loops, but the high concentration of open flux increases the probability that the loops will open before they can heat and fractionate the plasma. The anti-correlation between freeze-in temperature and solar wind speed shown in Table~\ref{tab:solar wind} can be interpreted in a simplistic way as a sign of different sized loops. The long-lived loops that produce the streamer wind will expand and rise slowly into the corona, where the temperatures are hotter, before being opened \citep{fisk98, fisk01a}. The short-lived loops that yield the coronal hole wind are opened while they are still small and close to the cooler surface \citep{fisk99a, fisk03, wimmer03b}.


\section{Graph Algorithms}
\label{appendix:AppendixA}

\subsection{The DFS Algorithm}

An Example + Complexity

\subsection{Topological Sort}


\chapter{Machine learning approach for true track tagging}
Applying cuts to track features in order to differentiate between true and false reconstructed tracks improved their ratio. A more effective
approach in classifying a track as true or false might be achieved with a machine learning algorithm for classification.
Unlike one-dimensional cuts, a machine learning
algorithm can be implemented to benefit from correlations between the input features for a more accurate identification of true tracks. The utilised
machine learning library is XGBoost \cite{xgboost}. It is used for supervised learning problems \cite{supervised} which are explained in the following section.

%\section{Introduction to XGBoost}
\section{Supervised learning}
%XGBoost is a gradient boosting machine learning algorithm \cite{gradient}, which primarily uses decision trees as a predictive model for classification and regression analysis.
Supervised learning is used to predict a target variable $y_i$ based on the training data $x_i$ containing multiple features. The model
in supervised learning describes the mathematical structure, which determines the prediction from its input data.
A linear model is a common example, where the predictions
are linear combinations of the weighted input features:
\begin{align}
  \hat{y}_i = \sum_j \Theta_j x_{ij}
\end{align}
The coefficients $\Theta_j$ are a priori undetermined parameters that need to be learned from the training data.
Therefore, the task of training is in determining the optimal parameters
for the target variable $y_i$ based on the input $x_i$. In order to train a model, an objective function, which measures how well
the model fits the training data, needs to be defined and optimised.
Those functions consist of the training loss function $L(\Theta) $ and the regularisation term $\Omega (\Theta)$.
\begin{align}
  \text{obj}(\Theta) = L(\Theta) + \Omega(\Theta)
\end{align}

The training loss function is commonly defined as the mean squared error or logistic loss for logistic regression \cite{logistic}:
\begin{align}
  &L(\Theta) = \sum_i (y_i - \hat{y}_i)^2 \\
  &L(\Theta) = \sum_i [y_i \ln{(1 + \text{e}^{-\hat{y}_i})} + (1 - y_i) \ln{(1 + \text{e}^{-\hat{y}_i})}]
\end{align}
Logistic regression refers to the statistical model that uses logistic functions to model binary dependent variables. \\
The regularisation term limits the complexity of a model in order to prevent overfitting. Overfitting occurs when the model fits the training data too well that it adjusts
to random fluctuations with no causal relation. Predictions of new unseen data then become worse, as the learner is not able to generalise well.

\section{Decision tree ensemble}
Decision trees are tree-structured diagrams, which classify a target variable based on a series of decisions. They consist of internal nodes, which denote
a test on an attribute, branches, which represent the outcome of the tests, and leaf nodes, which are the nodes of a decision tree that do not split the data any further. \\
The model used by the XGBoost library is the ensemble of decision trees, which consists of a set of classification and regression trees (CART) \cite{cart}.
A CART assigns a prediction score to each of the leaves.
The prediction of a single tree is usually not sufficiently accurate,
therefore the prediction of numerous trees is summed together. This method can be written mathematically as:
\begin{align}
  \hat{y}_i &= \sum_{k=1}^K f_k(x_i)\,, \: f_k \in \mathcal{F} \\
  \text{obj}(\Theta) &= \sum_i l(y_i, \hat{y}_i) + \sum_{k=1}^K \Omega(f_k)
\end{align}
Where $K$ is the number of trees, $l(y_i, \hat{y}_i)$ is the loss function that measures the difference between the predictions and the
target variable, $\mathcal{F}$ the set of all possible CARTs, and $f$ a decision function of the respective CART. A decision tree ensemble is shown exemplarily in
Figure \ref{fig:random_forest}.

\begin{figure}
  \centering
  \includegraphics[height=0.6\textwidth]{images/random_forest.png}
  \caption{Representation of a decision tree ensemble \cite{random_forest}.}
  \label{fig:random_forest}
\end{figure}

\section{Boosted trees}
%The model used for boosted trees and a random forest is both the tree ensembles with the only difference being the training method.
%Random forests and boosted decision trees are both tree ensembles that differ only in their training method.
Unlike random forest algorithms \cite{random}, in which a multitude of decision trees are created independently and combined at the end,
it is also possible to build one tree at a time and
combine them iteratively. This method is the gradient boosting machine learning algorithm \cite{gradient}, which is used by XGBoost. \\
Optimising the objective functions for
boosted decision trees (BDT) is achieved by additive training. This means that previous trees are fixed and only one new tree per step $t$ is added.
This can be written
down as follows:
\begin{align}
  \hat{y}_i^{(t)} = \sum_{k=1}^t f_k(x_i) = \hat{y}_i^{(t-1)} + f_t(x_i)
\end{align}

The tree added in each step is supposed to optimise the objective and can be written at step $t$:

\begin{align}
  \text{obj}^{(t)} &= \sum_{i=1} \left[g_i f_t(x_i)] + \frac{1}{2}h_i f_t^2(x_i)\right] + \Omega(f_t)  \\
  g_i &= \partial_{\hat{y}_i^{(t-1)}} l(y_i, \hat{y}_i^{(t-1)}) \\
  h_i &= \partial^2_{\hat{y}_i^{(t-1)}} l(y_i, \hat{y}_i^{(t-1)})
\end{align}
By using the second-order Taylor expansion of the loss function instead of only the first one, a more precise approximation of the loss function is determined in comparison
to regular gradient boosting algorithms \cite{newton_boosting}.
Furthermore, the value of the objective function only depends on $g_i$ and $h_i$, giving XGBoost the advantage of using custom loss functions including logistic regression.
However, the regularisation term still needs to be defined. One definition that works well in practice and is thus used by XGBoost is:
\begin{align}
  \Omega (f) = \gamma T + \frac{1}{2}\lambda \sum_{j=1}^T \omega_j^2
\end{align}
Here, $\omega$ is the vector of scores on leaves, $\gamma$ is the minimum loss reduction required to make
another partition on a leaf, $T$ is the number of leaves, and $\lambda$ is the Ridge regularisation term \cite{ridge}, which shrinks the $\omega_j$ to control the
regularisation term. \\
With this definition, the objective function for a single tree can be compressed to:
\begin{equation} \label{eqn:obj}
  \text{obj} = -\frac{1}{2}\sum_{j=1}^T \frac{G_j^2}{H_j + \lambda} + \gamma T
\end{equation}
Here, $G_j$ and $H_j$ are the sums over all $g_i$ and $h_i$, respectively. Equation \ref{eqn:obj} is a measure of how good a tree structure is. Its structure score
is determined by the statistics $g_i$ and $h_i$ in the leaves, with a smaller score indicating a better tree structure.
Since it is not feasible to enumerate all possible trees to find the best one, only one level at a time is optimised.
For each split of a leaf into a new left leaf L and right leaf R, the gained structure score is defined as:
\begin{equation}
  \text{Gain} = \frac{1}{2}\left[\frac{G_{\text{L}}^2}{H_{\text{L}} + \lambda} + \frac{G_{\text{R}}^2}{H_{\text{R}} + \lambda} - \frac{(G_{\text{L}} + G_{\text{R}})^2}{H_{\text{L}}+H_{\text{R}}+\lambda}\right] -\gamma
\end{equation}

Optimal splits are then determined by calculating the structure score of all possible split solutions. \\

\section{Machine learning setup}
The data used to train the learner %is identical to the one from section \ref{sec:feature} and
consist of 400000 events with ten generated $\SI{200}{\mega\eV}$ protons each
traversing the telescope described in section \ref{sec:setup}. The protons
are reconstructed with Corryvreckan, with the true tracks being identified with the MC truth from Allpix$^2$. A total number of 92546 tracks
are reconstructed, with 36340 being true tracks.
The learner is tested on a previously unseen dataset, simulated with the same configuration used in
\ref{sec:feature} and consists of 100000 protons with ten protons per event.
To determine the optimal number of boosting rounds, early stopping is utilised on a validation set, consisting of 100000 generated protons. This means, that
the model will train until the validation score stops improving for ten consecutive boosting rounds to rule out statistical fluctuations.
The number of boosted rounds is then determined by the highest validation score.
In this case, the validation score refers to the area under the ROC curve, which was explained in \mbox{section \ref{sec:feature}}. \\
The learner performs a logistic regression and outputs a probability for classifying a track as true or false.
A single tree is created in each iteration, called boosting round, to minimise the loss function.

To determine, whether all features are independent of each other, their correlations are calculated, which is shown in Figure \ref{fig:corr}. Here, the correlation
refers to the Pearson correlation coefficient \cite{pearson} describing the ratio of the covariance of two variables and the product of their standard deviations. \\
Most features show only small positive correlations with each other. The most noticeable exceptions are the cluster positions, which correlate particularly high within each
triplet. All charge deposition features and the $\chi^2$ value show almost no correlation with any other features, though this does not necessarily mean that they are
useful features for separating true and false tracks. \\
Less useful features
are not expected to contribute significantly to classification, but also do not disrupt the learning process, as trees do not split as often on variables with little impact.
However, problems may arise by taking too many features into account, as only limited training data is available to compensate for inefficient splits on features.
To prevent too many splits on less useful features,
the cluster positions on the six sensors in the horizontal and vertical direction are not given as input to the machine learner,
due to their high correlation with each other and their overall small number of splits, shown in Figure \ref{fig:importance_global} in the appendix.
Thus, the remaining 15 features include the $\chi^2$, the kink angles, and the charge depositions.
\begin{figure}
  %\centering
  \hspace{-2.5cm}
  \includegraphics[height=1.0\textwidth]{plots/correlation_matrix.pdf}
  \vspace{-1.8cm}
  \caption{The Pearson correlation coefficient of the kink angles, the cluster positions, the charge depositions, and the $\chi^2$ value.}
  \label{fig:corr}
\end{figure}

%All features, including $\chi^2$, kink angles, and charge depositions are selected as input for the classifier. Less useful features
%are not expected to contribute significantly to classification, but also do not disrupt the learning process, as trees do not split as often on variables with little impact.
%Thus, no problems will arise by taking all features into account, as long as the training data is sufficiently large to be able to compensate for inefficient splits on trees.
The parameters, which are predetermined and can not be inferred from the training of the learner, are called hyperparameters. These parameters are used
to control the learning process and need to be tuned to improve the performance of the classifier.
Taking many hyperparameters and hyperparameter values into account comes at the
cost of a large computation time. For this reason, four parameters are chosen to be optimised. These are firstly the maximum depth of each tree, which influences the
complexity of the model and the likeliness of overfitting. With the learning rate $\eta$, overfitting can be alleviated as it shrinks the feature weights
by the specified factor. It takes values from zero to one, with smaller values describing smaller corrections from further trees.
The minimum loss reduction required for an additional partition on a leaf is referred to as $\gamma$. The minimum sum of instance weight $\theta$
needed in a child has a similar impact. Leaf nodes with a sum of weights less than the specified value will prevent further tree partition steps.
Both $\theta$ and $\gamma$ take values from [0, $\infty$[ and are a measure for how complex the model will be.
For these parameters, larger values represent a slower learning algorithm.
%more conservative algorithm, which means that the learner .

A grid search from the python \cite{python} library Scikit-learn \cite{scikit} is used to determine an optimal
value for each of the parameters mentioned above. The values given as input into the grid search
are shown in Table \ref{tab:grid}.

  \begin{table}
    \centering
    \caption{Parameter values of the grid search. The tree depth refers to the maximum depth of a tree, $\eta$ refers to the learning rate,
    $\gamma$ is a threshold for the allowed minimum loss reduction in a partition step, and $\theta$ is the minimum sum of instance weight needed in a child.}
    \begin{tabular}{c c c c}
      \toprule
      tree depth & $\eta$ & $\gamma$ & $\theta$ \\
      \midrule
      3 & 0.05 & 0.5 & 1  \\
      4 & 0.1  & 1   & 25  \\
      5 & 0.3  & 2 & 50  \\
      6 & 0.7  & 5   &  \\
    \end{tabular}
    \label{tab:grid}
  \end{table}
To compare each different combination of the hyperparameter values quantitatively and obtain an estimation of the uncertainty, a 5-fold cross-validation is performed. This means that
the training data set is split into five equally
large sets, with the learner training on four of them and evaluating on the last one. Each of the five sets serves as the test data once, which means that for each
parameter combination five runs are performed. The area under the ROC curve serves as the scoring function to measure how good the prediction on the test data set is.
The mean of the five AUC values represents the score, which is compared in the grid search. Thus, cross-validation helps to compensate for variability in the simulated
data to derive an accurate estimate of the predictive power of the model. \\
The maximal AUC of $0.706(1)$ is achieved with a maximum tree depth of 4, $\eta=0.7$, $\gamma=5$ and $\theta=25$. By setting $\gamma=5$, the result of the grid search of the remaining
parameters can be visualized and is shown in Figure \ref{fig:grid}. \\
Varying the values of the hyperparameters only causes small changes in the mean test AUC, especially the learning rate has a negligible influence on the AUC. Taking the
standard deviations into account shows that the variation of the hyperparameters does not have a significant impact on the performance of the learner.
%makes it impossible to determine whether the best combination of hyperparameters has the highest AUC. However, due to the
%small differences, no significant impact is to be expected in this case.
The above-mentioned hyperparameter values are chosen for training and testing the model, as they belong to  the model with the highest nominal AUC.

\begin{figure}[H]
  \centering
  \includegraphics[height=0.6\textwidth]{plots/grid_search_weights.pdf}
  \caption{The mean test AUC for the different hyperparameter configurations with the error bars indicating the standard deviation of the mean. The
  smaller bars (red, green, pink, yellow) refer to $\eta$, the larger bars (turquoise, orange, purple) to $\theta$ and the point marked in red to the best model.}
  \label{fig:grid}
\end{figure}

\section{Machine learning results}
To compare the performance of the learner on the training and test datasets, the normalised distributions of the output probabilities of tracks being true are investigated.
These are shown in Figure \ref{fig:output} alongside the corresponding differences.

\begin{figure}
  \hspace{-0.45cm}
  %\centering
  \begin{subfigure}{0.51\textwidth}
      \centering
      \includegraphics[height=0.82\textwidth]{plots/output_normed_weights.pdf}
  \end{subfigure}
  \begin{subfigure}{0.51\textwidth}
      %\centering
      \hspace{-0.15cm}
      \includegraphics[height=0.82\textwidth]{plots/output_difference_weights.pdf}
  \end{subfigure}
  \caption{Normalised probability distributions of tracks being true and false for the training and test data set shown on the left.
  The corresponding difference between the performance of the training and test data is shown on the right.}
  \label{fig:output}
\end{figure}

The distributions of the training and test data predictions only show small differences, indicating that no significant overtraining occurs during the training process.
%For both true and false tracks, the greatest deviations are found at their most probable value, between 0.8 and 0.9.
Both true and false tracks have a maximum of around 0.8 as their most probable value, though the peak for the true tracks is higher due to the larger number
of false tracks assigned to small probabilities of being true tracks. While the number of true tracks increases with the assigned probabilities up to
approximately 0.8, the false tracks have a second maximum for small probabilities, which is as high as their maximum around 0.8.
This means that
with the given input, a lot of false combinations of clusters still show similar properties to true tracks.
Also noteworthy is, that a negligible number of tracks has a probability of 0.9 and higher.

The impact of the individual features to classify the reconstructed tracks can be quantified with the number of times each feature was split.
In Figure \ref{fig:importance}, the feature importance scores of the input features are shown. \\
All three features, namely the $\chi^2$ value and the horizontal kink angles  $\phi_{x,3}$ and $\phi_{x,4}$,
proved to be useful for classifying tracks with cuts, have a high feature score, highlighting their importance for separating true and false tracks.
Other features with a high number of splits, like the vertical kink angle of the second sensor,
can still be useful for the learner in combination with other features even though their use for classifying on their own is insignificant.
\begin{figure}
  \centering
  \includegraphics[height=0.6\textwidth]{plots/feature_importance_all.pdf}
  \caption{The number of splits of each feature that is used as input for the learner.}
  \label{fig:importance}
\end{figure}

To evaluate the predictive power of the learner, a ROC curve can be constructed for several thresholds of classifying tracks as true and false based on the
boosted decision tree output.
The ROC curves for the test and training data set are shown in Figure \ref{fig:auc_comparison} alongside
the ROC curves of the feature cuts from section \ref{sec:feature}.
With the AUC of each ROC curve, the performances of the classifying methods can be compared. \\%Table \ref{tab:AUC} lists each of the AUCs.
Only small differences between the ROC curve of the training and test dataset indicate that no significant overfitting occurs.
The ROC curves of the learner have a noticeably higher AUC than the individual feature cuts and have a better ratio of
TPR and FPR for each possible cut, showing the effectiveness
of using machine learning for track classification in comparison to individual feature cuts. For the best combination of cuts, the ratio of the TPR and FPR is still worse than
comparable points on the ROC curve of the test data. This means that for the same FPR of the two methods, the learner consistently achieves a better TPR.

\begin{figure}[H]
  \centering
  \includegraphics[height=0.6\textwidth]{plots/roc_curve_all.pdf}
    \caption{ROC curves of the machine learner for the training and test data set. In comparison, the ROC curves for the individual feature cuts as well as the
    TPR and FPR of the best combination of cuts for all three features are depicted. A black diagonal line, representing random classification, is shown
    in contrast.}
  \label{fig:auc_comparison}
\end{figure}

%\begin{table}
%  \centering
%  \begin{tabular}{c | c c c c c}
%    \toprule
%      & Train & Test & $\chi^2$ & $\phi_{x,3}$ & $\phi_{x,4}$\\
%    \midrule
%    AUC & 0.770 & 0.754 & 0.615 & 0.617 & 0.587 \\
%  \end{tabular}
%  \caption{Area Under the Curve for the feature cuts and the train and test data of the machine learner.}
%  \label{tab:AUC}
%\end{table}
Further optimisation of the machine learning results is possible, considering that each cluster can at most be associated with one true track.
Only keeping the track of clusters with the highest probability of being true enables further rejection of
false tracks. The ROC curve of the test data with the rejection of tracks is shown in Figure \ref{fig:rejection}. \\
With the rejection of tracks, the AUC on the test data set decreases to $0.702$. This is due to the rejection of many true negative tracks, which in turn increases
the false positive rate. Since the goal is to improve the quality of the pCT image, the false positive rate is not an ideal quantity, as true negative tracks
are not taken into account for pCT anyway.
%However, the rejection of true negative tracks does not decrease the quality of the pct image, as these tracks are not taken into account anyway.

\begin{figure}[H]
  \centering
  \includegraphics[height=0.6\textwidth]{plots/roc_curve_learner_rejection_weights.pdf}
  \caption{ROC curves of the training and test data set and the test data set including the rejection of all but one track from clusters on the first and last plane.}
  \label{fig:rejection}
\end{figure}

To evaluate this method, the precision score $P=t_p/(t_p + f_p)$ and the recall score $R=t_p/(t_p + f_n)$ are calculated and compared with the baseline classifier. The precision
score describes the ability of the learner to not classify negative events as positive. The recall score, referring to the same quantity as the true positive rate,
is the ability to classify all positive events correctly.
Figure \ref{fig:precision} shows the precision of the learner and the individual feature cuts as a function of the recall.

%\begin{figure}
%  \hspace{-0.6cm}
%  %\centering
%  \begin{subfigure}{0.51\textwidth}
%      \centering
%      \includegraphics[height=0.82\textwidth]{plots/roc_curve_precision_train.pdf}
%  \end{subfigure}
%  \begin{subfigure}{0.51\textwidth}
%      %\centering
%      %\hspace{0.95cm}
%      \includegraphics[height=0.82\textwidth]{plots/feature_cuts_precision.pdf}
%  \end{subfigure}
%  \caption{Precision as a function of the recall for the train and test data set including the rejection of all but one track from clusters of the first and last
%           sensor for the test dataset. As a comparison, the precision curves are also shown for cuts on the $\chi^2$, $\phi_{x,3}$, and $\phi_{x,4}$ features.}
%  \label{fig:precision}
%\end{figure}

\begin{figure}[H]
  \centering
  \includegraphics[height=0.6\textwidth]{plots/roc_curve_precision_all.pdf}
  \caption{Precision as a function of the recall for the training and test data set including the rejection of all but one track from clusters of the first and last
           sensor for the test dataset. As a comparison, the precision curves are also shown for cuts on the $\chi^2$, $\phi_{x,3}$, and $\phi_{x,4}$ features.}
  \label{fig:precision}
\end{figure}
The AUC of the precision curve increases with the rejection of tracks,
indicating a better performance with the rejection method. In comparison to the regular test data set, the precision score
of the test data set with the rejection of tracks increases noticeably for recall scores larger than 0.1.
%This is also reflected in the AUC values of the curves, with the precision curve of the rejection method having the highest AUC.
Furthermore, a higher precision score of the test data set in comparison to the individual feature cuts for all recall scores highlights the advantages of the machine
learning approach. The precision is especially stable for the test dataset with the rejection method for recall scores larger than $0.1$,
which means that high recall scores
are achievable without decreasing the precision score significantly.
However, this also means that no working point can be chosen that has an exceptionally high precision score. Useful choices for working points might be around
a recall score of $0.8$ with a precision score of approximately $0.636$ due to a noticeable decrease of precision for higher recall scores.