\label{sec:arbitrage}
\begin{figure*}[!ht]
    \centering
    \includegraphics[width=\textwidth]{figures/looped arb.png}
    \caption{General form of the looped Arbitrage, composed of several instances of meta swaption.}
    \label{fig:meta_arb}
\end{figure*}

In this section we are going to elaborate on the term of arbitrage by redefining it in swaption market in the following way:
An arbitrage in the swaption market is an opportunity when a party, named exploiter, can exercise a chain of swaptions simultaneously, beginning from the exploiter's asset and also ending in the same asset, and profits by gaining more assets than the start point. Fig~\ref{fig:meta_arb} shows the general form of an arbitrage made up of several instances of \MetaSwaption forming a loop.

% \begin{definition}{\it Arbitrage Owner}
% In an arbitrage, the one who buys all the swaptions is called the Arbitrage Owner. In our examples she mostly is Alice. The Arbitrage Owner is also called the \Atwo Key Holder interchangeably.
% \end{definition}

We introduce four different types of arbitrages that are possible by adoption of our \MetaSwaption as their building blocks:
\begin{itemize}
    \item \textbf{Early deposition} arbitrage
    \item \textbf{Late deposition} arbitrage
    \item \textbf{Margin-free} arbitrage
    \item \textbf{Bonded} arbitrage
\end{itemize}

For further analysis, we give an example of arbitrage use cases. Alice, the exploiter whose initial asset is ACoin, is going to form an arbitrage making a chain of swaptions between Bob, Carol, Dave and Erin that take place concurrently. In section~\ref{sec:tangle} we will explain the procedure of signing contracts for each party in details but first we discuss about the general overview of our execution processes. For convenient reason, we index each swaption by order, \ie indexes of swaptions between Alice and Bob, and Alice and Carol, and Alice and Dave and Alice and Erin are respectively one to four.

Using the normal form of arbitrage shown in Fig.~\ref{fig:sep-arb}, the exploiter has to pay margin in every single swaption besides generating lots of transactions and thus, transaction fees. To solve this and to exercise the swaptions concurrently, we use the overlapping technique which changes the structure of our arbitrage model to Fig.~\ref{fig:overlap-arb}.

The overlapping technique is the action of extending the output's required signatures of all transactions to other parties in order to make additional guarantee.

\begin{figure}[htp]
    \caption{Arbitrage with and without overlapping technique}
    \subfloat[Arbitrage architecture using a loop of swaptions]{
    \includegraphics[width=0.45\textwidth]{figures/arb-sep.png}
    \label{fig:sep-arb}
  }~
  \subfloat[Arbitrage architecture using overlapping technique]{
  \includegraphics[width=0.45\textwidth]{figures/arb-overlap.png}
  \label{fig:overlap-arb}
  }
\end{figure}

% \begin{definition}{\it Genesis swaption}
% In an arbitrage, the swaption in which \Atwo key holder and \keyone key holder are faced together is called the Genesis Swaption. This swaption is supposed to be the first one processed in an arbitrage.
% \end{definition}

%\subsection{Model}
% \subsection{Lined Arbitrage}
% \ahC{Are these lines in the good position?}

\subsection{Early Deposition Arbitrage}
\label{sec:line_arb}

Consider the following variation of our main example. Alice already has an amount of ACoin equal to the needed principal. First of all, she starts a swaption with Bob. After Bob deposits his principal, Alice can use his BCoins on her later swaption contracts. Then she trades these locked BCoins with Carol's CCoins, and these CCoins with Dave's DCoins and finally trades these DCoins with Erin's ACoins. According to the definition of arbitrage, now she has more ACoins than she primarily had. Since Alice primarily has enough ACoins, she only uses early deposition swpations. She technically can use a late deposition swaption for the first swaption, but since in that case she has to pay larger premium, it is not rational.
She also uses the swaption overlapping to transfer her assets between different swaption contracts.
In Fig~\ref{fig:line_arb} this technique is shown. All parties share all transaction before any thing gets broadcast. After that, the procedure goes on as follows:

\begin{figure*}
    \centering
    \includegraphics[width=\textwidth]{figures/arbitrage1-fateme.png}
    \caption{Example of an arbitrage, where Alice owns all ACoins primarily needed. On each transaction, signatures, output amount, and locktimes are specified. Pink-bordered transactions are broadcast by Alice, blue-bordered ones by Bob, green-bordered by Carol, purple-bordered by Dave and cyan-bordered by Erin. If there is a line between two transactions, then the source transaction is considered to be an input of the destination transaction.}
    \label{fig:line_arb}
\end{figure*}

\begin{itemize}
    \item \textbf{Contract funding}: Alice starts her contract with other parties simultaneously, by sharing the funding transaction with them. Then she decides whether to reveal \Aone key or not. If she does, all the swaptions go to the next stage. The locktimes are set descending from swaption number one to four, so that Alice can not cheat. In fact, Alice has to reveal \Aone before $T$, the minimum locktime among all swaptions, since otherwise at least one of them has expired and the entire arbitrage is not plausible any more. Note that if any of the funding stages fail, the entire arbitrage fails.

    \item \textbf{Principal deposition}: In this stage, every one has to deposit their principal. All swaptions are early deposition swaptions, so all the locktimes are ascending from swaption number one to four. Possible scenarios:
    \begin{itemize}
        \item One of the parties defaults. In this case, all parties after the defaulter also default. Hence, the first defaulter looses his margin and all the other parties transfer their margin with the next party in the swaption with the next index and the last party transfers her margin to Alice.
        \item All parties deposit their principal and go to the next stage.

    \end{itemize}

    % \item \textbf{Leader Lock}:The locktimes in the first swaption are ascending and in the rest of swaptions are descending. The reason is that in the first one Bob holds the \keyone key and in other ones Alice holds it. Note that Bob has the M + P + 3T locktime but in fact he has to reveal \keyone key before M + P, because otherwise Alice defaults and Bob loses his margin. parties take back their own money. By arranging timelocks in this way, no portion of parties can cheat on others by cooperating. Possible scenarios:

    % \begin{itemize}
    %     \item Bob defaults. he looses one of his margins as discussed in {\it Late Deposition} swaption, while other
    %     \item Bob reveals \keyone key by broadcasting Alice's option funding transaction. Then Alice broadcasts the Erin's Option Funding transaction, and other opponents do the same respectively. And we go to next stage. If any of them does not do this, the only one who looses money is that party.
    % \end{itemize}
    % \ahC{is it clear and okay or not? We can mention that all of the swaptions in the point of view of other opponent than Alice is just like an instance of Meta Swaption, accordingly no body can cheat by cooperation on others}

    \item \textbf{Option funding}: It is time for Alice to use her option. She reveals \Atwo key for Erin, then each party reveals it for the previous one in order. Therefore, the locktimes are descending in all swaptions from swaption number one to four.
\end{itemize}

\subsection{Late Deposition Arbitrage}
\label{sec:margined_arb}
% \subsubsection{Margined Arbitrage}
Now, consider the case that Alice does not own enough ACoin to start such a procedure. She has to pay ACoin to Bob using a portion of ACoins she gets from Erin. This would only be possible if she had the ability to spend Bob's BCoins and do all the tradings with it and finally deposit the ACoins taken form Erin to the first swaption. To do so, she can use the late deposition swaption as the first swaption. We call it the late deposition arbitrage. Fig.~\ref{fig:margined_arb} depicts such an arbitrage. There are four swaptions, and Alice pays only premium in all of them. She also has to deposit margin in the first swaption. Alice's margin is only there to prevent her from cheating due to the cyclic locktimes on the funding stages (in the next section we will briefly explain this problem and our proposed solution). Therefore, there are five margins and four swaptions. The first swaption to start is the same as the last swaption to finish and it is actually between Erin and Bob (swaption number one). The five phases of late deposition arbitrage are:

\begin{figure*}
    \centering
    \includegraphics[width=\textwidth]{figures/arbitrage-late.pdf}
    \caption{The schematic for late deposition arbitrage. The transactions with two border colors, can be broadcasted with both corresponding parties.}
    \label{fig:margined_arb}
\end{figure*}

\begin{itemize}
    \item \textbf{Contract Funding}: Similar to the early deposition arbitrage, every one has exchanged funding and refund transactions. Three types of these stages:
    \begin{itemize}
        \item Alice's first funding includes margin + premium.
        \item Other fundings of Alice only include premium.
        \item Bob's funding includes margin and an amount of guarantee. Here the amount of guarantee is equal to the margin, so Bob's funding is worth twice other parties margins.
        \item Other parties fundings include only margin.
    \end{itemize}
    Alice reveals the \Aone key by broadcasting Erin's margin deposit transaction. Then, Erin broadcasts Dave's margin deposit transaction and everyone broadcasts the margin deposit transaction of their previous party. No one has the incentive not to broadcast this transaction since if she does not, she is the only one who goes through a loss. When all the margin deposit transactions are broadcast, the arbitrage proceeds to the next stage.

    \item \textbf{Principal deposition}: All swaptions except for the first one are early deposition, so the locktimes of principal deposition on these swaptions are ascending from swaption number two to four. On the other hand, the first swaption is late deposition, so Alice's locktime has to be greater than Bob's. Alice's principal is in fact a portion of the principal that Erin deposits. Similar to the early deposition arbitrage, if any one defaults in this stage, and does not deposit his principal, the faulty party loses his margin (except for when it is Alice that exchanges her margin with Bob's) and other parties margins are exchanged with their previous party. As mentioned earlier, the first swaption is in fact between Erin and Bob, but Alice also puts margin to this swaption. The principal deposition of Erin is an any-one-can-pay transaction. The amount of $M+T'$ needs to be greater than $M+3T$, hence if Erin defaults, Alice can default too. If Erin does not default and broadcasts her principal deposition transaction, Alice takes its output as an input to the principal deposition of the first swaption. We have given Erin a chance that if Alice does not do so, she can take her principal back and of course since Alice has defaulted, she exchanges her margin with Bob's. If everyone deposits their principal, we go to the next stage.
    % \ahC{Revise the entire paragraph}
    \item \textbf{Leader lock}: Alice is waiting for Bob to reveal the \keyone key by broadcasting the Erin's option funding transaction on first swaption. If Bob does so, Erin broadcasts Dave's option funding transaction and every other party broadcasts the previous party's option funding transaction respectively. Locktime for Alice is the shortest and increased from swaption number four to two and for Bob is the longest. Bob's option funding transaction can be broadcasted by both Carol and Bob. Otherwise, other parties can collude and cheat on Bob using the following attack: Bob reveals the \keyone key and others do not broadcast the Bob's option funding and take Bob's margin. Hence, when Bob can broadcast his own option funding, there would not be any problem of this kind.

    Thus, if Bob reveals the key, every other party goes to the next stage. If Bob does not reveal, he loses his margin. If Bob reveals the \keyone key after $P + M$, Alice will take back her margin and immediately reveal the \Atwo key which results in taking Bob's money in both swaptions, thus discouraging Bob from delaying in exposure.

    \item \textbf{Option funding}: This is the time for Alice to use her option. She can reveal the \Atwo key by broadcasting the Erin's option exercise. She takes her surplus and Bob gets his ACoins. She has to reveal it within $E$ locktime. Since in all swpations the buyer party,
    \ie right-hand side party, is in charge of revealing the \Atwo key, the locktimes have to be descending. This means the locktime of the Erin's option expiration transaction has to be both longer and shorter than the Bob's option expiration. This is obviously impossible. Hence, we set the locktimes so that Carol's locktime is longer than Alice's, which makes it possible for Carol and Alice to cheat on Bob, but we solve this problem using the delegation stage. Now, if Alice exercises her option until $E$ locktime, then every party can take their new coins. If Alice does not exercise until $E$, her option is delegated to Bob.

    \item \textbf{Option delegation}: If Alice has not exercised until $E$, Bob broadcasts the Erin's option expiration and Bob's option expiration transactions and all other parties do the same (since it is their only chance to get their coins). The arbitrage is now in the delegation stage. Bob has the option and everyone is waiting for him. If he decides to exercise, everyone gets their new coins, otherwise everyone gets their former coins. The locktimes are descending for all swaptions except for the first one which is ascending (like last stages), since now Bob is the key holder of this stage and he is in charge of revealing the \Delegation key.
    % \fatemeC{The most important consideration is that if Alice has decided not to exercise her option, Bob would also not exercise. Since if it was not beneficial for Alice it would not be beneficial for Bob neither. the reason is that the coins that Alice gets are the same as Bob gets, so if one has lost its value the other one has lost too.(why the hell????)}

\end{itemize}
\begin{figure*}
    \centering
    \includegraphics[width=\textwidth]{figures/arbitrage-bonded.pdf}
    \caption{The bonded arbitrage using ABCD.}
    \label{fig:abcd-arb}
\end{figure*}

\subsection{Margin-Free Arbitrage}
%\vspace{-1mm}
Next, we are going to study the case in which Alice does not have enough ACoin for margin deposition in her swaption with Bob but still she can afford the minimal amount of ACoin as guarantee besides all the premiums. Using the margin-free swaption mentioned in previous section, an arbitrage can be built and exploited satisfying our need. Before all, we have to analyse the amount of guarantee in a margin-free swaption. If this type of swaption is used lonely without further contracts, the minimum valuable amount is enough for the amount of guarantee (even if it is less than premium). However, to use it alongside other contracts, \eg~as the first swaption in an arbitrage setting, Alice needs to set the guarantee value of Bob more than the summation of all the premiums which she wants to spend in her later contracts. Otherwise, Bob is incentivized to pretend himself as the other parties in later contracts, \eg~in our example Carol or Dave or Erin, and cheats on Alice by stealing Alice's premiums in the later swaptions by not exposing the \keyone key and loosing his guarantee. Note that if Bob acts honestly, the guarantees in both sides will be exchanged. In fact, assume the amount of margin is worth $m$ times more than the amount of premium. The margin-free swaption can be used, if the number of parallel swaptions, is less than $m$. Otherwise, it is better to use a late deposition swaption instead. We do not include the figure for margin-free arbitrage, however, it is simply derivable from previous arguments.

\subsection{Bonded Arbitrage}
For final case, we suppose that Alice even does not have enough money for guarantee needs in a margin-free swaption. Alice still can make an arbitrage using the ABCD component devised in previous works, as her first swaption \cite{tefagh2020atomic}. In this way, she does not need more money than the premiums for her arbitrage. We call this type of arbitrage, the bonded arbitrage, since the arbitrage exploiter bonds her initial asset in the first place. The bonded arbitrage is shown in Fig.~\ref{fig:abcd-arb}.
% \ahC{The figure is ABD, we need an ABCD one}

\begin{table*}[]
    \centering
    \begin{tabular}{|c|c|c|c|}
    \hline
        {\normalsize Stage} & {\normalsize LT in column $1$} & {\normalsize LT in column $2i$} & {\normalsize column $2i + 1$}\\
        \hline

        {\normalsize Contract Funding} &
        {\normalsize $(N + 1)T$} &
        {\normalsize $(N - i + 1)T$} &
        {\normalsize $(N - i + 1)T$} \\

        {\normalsize Principal Deposition} &
        {\normalsize $M + T'$} &
        {\normalsize $M + (N - i)T$} & - \\

        {\normalsize Leader Lock} & {\normalsize $P + M$} &
        {\normalsize $P + M + iT$} & - \\

        {\normalsize Option Contract} &
        {\normalsize $E$} &
        {\normalsize $E + (N - i)T$} & - \\

        {\normalsize Option Delegation} &
        {\normalsize $E + NT$} &
        {\normalsize $E + (2N - i)T$} & - \\
        \hline
    \end{tabular}
    \caption{Locktimes for general case in an arbitrage. Each column in the table shows one column in the arbitrage.}
    \label{tab:arb}
\end{table*}

Now, consider the general case for the arbitrage when there are $N$ swaptions.
Table \ref{tab:arb} shows locktimes for each stage in a general arbitrage. Each column in the table shows one column in the arbitrage. Moreover, for simplicity we put locktimes so that different stages do not have overlap in time. In some cases overlapping stages can cause trouble. Two examples are:

\begin{itemize}
    \item $M$ has to be larger than $(N + 1)T$. Otherwise, Alice and Carol can broadcast the Bob defaults transaction and then broadcast the Alice's refund and take Bob's margins.

    \item In the third stage, $P + (N - 1)T$ has to be greater than $T'$. Otherwise, Alice can wait untill $P + M + (N - 1)T$ not depositing principal, then Bob has to broadcast the Bob's leader key expiration and then Alice will deposit and then broadcast the Alice's leader key expiration. So, she takes Bob's margin without loosing anything but premium.
\end{itemize}

Note that Alice in fact has $E$ time to use her option. Then Bob takes the option, so we can say that Alice does not have any option but it is not true for two reasons: 1) Arbitrages are always zero-risk. 2) If she deposits her principal it means that all the parties have cooperated (if one does not, she does not deposit principal and does not lose anything, just the margins are exchanged which is inevitable). When all parties have cooperated and arbitrage is zero-risk every thing is fine so why would Alice not exercise?

Note that in such cases Alice is always going to use her option, so Alice is not in fact delegating her option to Bob, but by having the delegation stage, she only assures Bob that he would not be cheated.
%\ahC{koja tozih dadim ke delegation mitone bejaie oon method e maskhareie Atomic Cross-chain Swap estefade beshe?}

% \ahC{Time Elapsed Experiment.}\\
% \ahC{Reconstruction impossibility}\\
% \fatemeC{Is it reasonable to remove Option parts from Arbitrage. Arbitrages have absolute benefit in a short time, so the option is not needed to be given to Alice. However she can have it by adding the rest of the transactions.}\\


\section{Introduction}
\label{sec:intro}

A common goal in digital simulations of life is to induce the emergence of
certain structures or processes. These might include self-replicating or
autopoietic organisms, evolutionary processes, and intelligent behavior. Often
identifying the growth of these structures and processes is reduced to
identifying a growth in complexity. Hence, designers of artificial life
simulations are interested in the question of measuring complexity.

As artificial life simulations scale, quantitatively assessing the simulation's
success in meeting the designer's criteria is essential.  Identifying and
selecting amongst the design choices of a given simulation in a qualitative
manner is not scalable and likely to admit experimental bias. As an analogy,
imagine constructing a machine-learning model to learn a given task without an
objective function. Curiosity driven exploration and reinforcement learning can
result in the model learning to successfully complete the task.  However, from
the empiricists perspective, assessing the ability of the model at completing
the task is critical. At the very least, some criterion is needed for
evaluating the model, if not training it. Similarly, in artificial life, while
the measure of complexity is typically not used as an objective to guide the
active simulation, it is at least essential to evaluate the post hoc success of
the simulation.

Complexity is notoriously ill-defined, subjective, and difficult to measure
quantitatively~\citep{gell2002complexity, mitchell2009complexity,
wiesner2019measuring}. One of the challenges in measuring complexity is
identifying the ``Goldilocks zone'' between total order and total disorder
where complexity may reside (\emph{c.f.}
figure~\ref{fig:complexity_and_entropy}). Information theoretic measures such
as Shannon entropy~\citep{shannon1948} and Kolmogorov complexity (sometimes
called Algorithmic Information Content)~\citep{kolmogorov1965, solomonoff1964},
are actually measures of randomness. As figure~\ref{fig:complexity_and_entropy}
illustrates, these measures increase monotonically with the disorder of a
system.

\begin{figure}
\centering
\includegraphics[width=0.7\textwidth]{figures/complexity_and_entropy}
\caption{An illustration of the one-hump of complexity (solid line) between
order and disorder. Measures such as Shannon entropy or algorithmic
information content (AIC) (both illustrated by the dashed line) grow
monotonically with disorder.}
\label{fig:complexity_and_entropy}
\end{figure}

Because of this difficulty, many measures of complexity have been
proposed~\citep{lloyd2001measures}, all with differing trade-offs. Often they
fail the ``one-hump'' criterion~\citep{adami2002complexity} increasing with
order or disorder. This is typical of the aforementioned information theoretic
criteria (Shannon entropy and Kolmogorov complexity) and constructions which
use them~\citep{lloyd1988complexity}. Other measures which satisfy the one-hump
test are not easily made operational requiring either a large degree of
subjective input from the designer or are exceedingly difficult to
compute~\citep{crutchfield1989inferring, gell1996information,
grassberger1986toward}.

We propose yet another a measure complexity, Hierarchical Information Content
(HIC). The central tenet of HIC is that complexity growth is found at the
compositions of ordered and disordered systems. We elaborate and defend the
motivating principles of HIC in section~\ref{sec:finding_complexity}. We do not
intend for HIC to serve as an ersatz for complexity in a general sense, and in
fact we make make no further attempt to rigorously define complexity. Rather,
we propose HIC as a measure which quantitatively captures some of the essential
aspects of complex systems. We promptly disclose two limitations of HIC. First,
HIC is not intended to work well for every case, but to work well for many
cases that are of interest, particularly in simulations of artificial life.
Second, while HIC can be used with few assumptions, in many instances it may
gain utility from the subjective input by the designer of the system.


\documentclass[p.tex]{subfiles}
\begin{document}
\section{Overview}\label{sec:overview}

In this section, we demonstrate our proof system with a small example.

\begin{figure}
\begin{lstlisting}
  s := 0;
  t := 0;
  i := 0;
  while (i < n) { // s = i(i+1)/2 & t = 0
    s := s+i;
    i := i+1;
  };
  i := 0;
  while (i < n) { // s = n(n+1)/2 & t = i(i+1)/2
    t := t+i;
    i := i+1;
  };
  assert (s = t)
\end{lstlisting}
  \caption{%
    An imperative program with two loops computing equivalent
    functions.
  }\label{fig:overview-example}
\end{figure}

Consider the small imperative program in \cref{fig:overview-example}.
The program has two loops that both compute the $n^{th}$ triangle
number (i.e. the sum from 0 to $n$). As human observers we can clearly
see that the assertion at the end of the fragment is valid: Every run
of this program results in a state where $s$ and $t$ have the same
value. The key to this observation is the similarity between the two
loops.

Unfortunately, traditional proof methods are not poised to take
advantage of the simple structure of this program. In a traditional
Hoare Logic approach, for example, the prover must find \emph{loop
invariants} which support the assertion at the end of the program.
The code fragment contains sufficient loop invariants that support the
assertion. However, these invariants rely on nonlinear arithmetic,
and thus most automated approaches will fail to find them.
%
Moreover this approach has completely missed the simplicity of the
given problem: The two loops together contain simple relationships
which support the conclusion. However, the proof methodology we have
adopted thus far forces us to consider the loops \emph{separately}.

Our approach seeks to augment the traditional proof method of Hoare
Logic by providing an elegant technique for considering various parts of the
same program \emph{simultaneously}. By carefully applying this
technique, a prover can solve proof burdens like the one specified in
\cref{fig:overview-example} more simply.
Specifically, in this example, the prover can decide to consider both
loops simultaneously.

\end{document}


%! language = Latex
\section{Summary statistics for the final study sample}
\label{cha:summary-statistics}
\begin{table}[!htp]
    \begin{center}
        \begin{subtable}[c]{0.6\textwidth}
            \begin{center}
                \begin{tabular}{rc|cc}
                    &        & {\textbf{\acs{mdd}}} & {\textbf{\acs{hc}}} \\ \cline{2-4}
                    & n      & 934                  & 934                 \\ \cline{2-4}
                    \multirow{2}{*}{\textbf{Sex}}     & female & 556                  & 548                 \\
                    & male   & 378                  & 368                 \\ \cline{2-4}
                    \multirow{3}{*}{\textbf{Scanner}} & 1      & 285                  & 512                 \\
                    & 2      & 395                  & 236                 \\
                    & 3      & 254                  & 186                 \\
                \end{tabular}
                \subcaption{Summary of sample size (n), sex and scanner site.}
            \end{center}
        \end{subtable}

        \vspace{5mm}

        \begin{subtable}[c]{0.8\textwidth}
            \begin{center}
                \begin{tabular}{rr|SSSS}
                    &                     & {\textbf{Mean}} & {\textbf{SD}} & {\textbf{Min}} & {\textbf{Max}} \\ \cline{2-6}
                    \multirow{2}{*}{\textbf{\acs{mdd}}} & Age ($n=934$)       & 37.76           & 12.94         & 16             & 65             \\
                    & \acs{tiv} ($n=933$) & 1575.94         & 152.97        & 1115.00        & 2189.00        \\  \cline{2-6}
                    \multirow{2}{*}{\textbf{\acs{hc}}}  & Age ($n=934$)       & 34.15           & 12.42         & 17             & 65             \\
                    & \acs{tiv} ($n=933$) & 1575.61         & 156.38        & 1146.23        & 2706.76        \\
                \end{tabular}
                \subcaption{Summage of Age (in years) and \acs{tiv} (\acl{tiv}).}
            \end{center}
        \end{subtable}

        \vspace{6pt}
        \caption[Summary statistics for the final study sample.]{Summary statistics for the final study sample. \\
        \footnotesize
        \setlength{\tabcolsep}{4pt}
        \renewcommand{\arraystretch}{1.0}
            \begin{tabular}{llll}
                \hspace{-6pt} Abbreviations: & \acs{hc}  & - & \acl{hc}  \\
                & \acs{mdd} & - & \acl{mdd} \\
            \end{tabular}
        }
    \end{center}
\end{table}

\FloatBarrier

\section{Predictive Analytics Competition 2018}
\label{cha:pac-2018}
The medical machine learning lab from Prof. Dr. Tim Hahn invited teams from all over the world to develop a model classifying patients suffering from \ac{mdd} and \ac{hc} individuals based on structural Magnetic Resonance Imaging (sMRI) data. This competition was called \emph{Predictive Analytics Competition 2018} (\acs{pac} 2018).

\subsection*{Data}
The data for this competition - comprising structured \ac{mri} datasets with and without MDD from $N\,=\,\num{2240}$ subjects - was provided by the \emph{Institute of Translational Psychiatry}, Münster.
The images were preprocessed in advanced with the SPM toolbox CAT-12  (Matlab 9.0 / SMP12 rev. 6685 / CAT12 v.1184)  and quality checked. The participants got, additional to the diagnosis, the age, gender, \ac{tiv} and the scanner-site to consider them as covariates.

The data was split into a training and test set in advance (Table~\ref{tab:pac_datasplit}). The test set was held back and only used in the final step to designate the winner.

\begin{table}[!ht]
    \renewcommand{\arraystretch}{1.4}

    \begin{center}
        \begin{tabular}{rS[table-format=4.0]S[table-format=3.0]}
            \multicolumn{1}{c}{} & \textbf{Training} & \textbf{Test} \\
            \acs{mdd}            & 1033              & 273           \\
            \acs{hc}             & 759               & 175           \\ \cline{2-3}
            \textbf{Total}       & 1792              & 448
        \end{tabular}
        \vspace{6pt}
        \caption[Split between training and test data for the \acs{pac} 2018.]{Split between training and test data for the \ac{pac} 2018. \\

        \vspace{-6pt}
        \setlength{\tabcolsep}{4pt}
        \renewcommand{\arraystretch}{1.0}
            \begin{tabular}{llll}
                \hspace{-6pt} Abbreviations: & \acs{hc}  & - & \acl{hc}  \\
                & \acs{mdd} & - & \acl{mdd} \\
            \end{tabular}
            \label{tab:pac_datasplit}
        }
    \end{center}
\end{table}

\subsection*{Timeline}

\begin{table}[H]
    \renewcommand{\arraystretch}{1.4}
    \begin{center}
        \begin{tabular}{rrll}
            Registration opened:           & \nth{1}  & February & 2018 \\
            Training data available:       & \nth{1}  & March    & 2018 \\
            Test data available:           & \nth{27} & April    & 2018 \\
            Test prediction upload opened: & \nth{4}  & May      & 2018 \\
            Test prediction upload closed: & \nth{31} & May      & 2018 \\
        \end{tabular}
    \end{center}
\end{table}

The \enquote{\ac{pac} Award Winner 2018} was announced in a ceremony held at annually meeting of the \emph{Organization for Human Brain Mapping} (OHBM) in Singapore at the \nth{21} June 2018.

\subsection*{Results}
In total 49 teams registered with at least 170 participants. The winner was determined by the highest balanced accuracy score on the held-back test set. The team with the highest score was \enquote{paranoidandroid} (Table\ref{tab:top5pac2018}) and won the \ac{pac} 2018 Award.

\begin{table}[!h]
    \renewcommand{\arraystretch}{1.4}
    \begin{center}
        \begin{tabular}{clSSS}
            & \multicolumn{1}{l}{\textbf{Team}} & \textbf{BA} & \textbf{TPR} & \textbf{TNR} \\ \cline{2-5}
            \nth{1} & paranoidandroid                   & 0.65        & 0.53         & 0.77         \\
            \nth{2} & utastoot                          & 0.64        & 0.51         & 0.77         \\
            \nth{3} & berlin\_brain\_decoders           & 0.64        & 0.58         & 0.69         \\
            \nth{4} & depression                        & 0.63        & 0.59         & 0.67         \\
            \nth{5} & neuronauts\_p                     & 0.63        & 0.61         & 0.64
        \end{tabular}
        \vspace{6pt}
        \caption[Test results on the held-back test set by the top five teams at the \ac{pac} 2018.]{Test results on the held-back test set by the top five teams at the \ac{pac} 2018. \\

        \vspace{-6pt}
        \setlength{\tabcolsep}{4pt}
        \renewcommand{\arraystretch}{1.0}
            \begin{tabular}{llll}
                \hspace{-6pt} Abbreviations: & BA  & - & balanced accuracy                \\
                & TPR & - & true positive rate (sensitivity) \\
                & TNR & - & true negative rate (specificity) \\
            \end{tabular}

        }
        \label{tab:top5pac2018}
    \end{center}
\end{table}

\FloatBarrier

\section{Additional tabular presentations}
This section contains the tabular presentation of the graphical visualized data in the paper.

\input{supplements_chances_and_stats_tables.tex}
\FloatBarrier

\section{Influence of the scanner distribution}
\label{cha:influence-of-scanner-distribution}
Scanner site distributions were not well balanced in the \ac{pac} sample.
This imbalance was even stronger in our randomly drawn sub-samples. To determine the influence of the different scanner-sites on model accuracy, we took the same methodical approach that we used for the “train sample size effect analysis” and determined the scanner distribution for each set. Following, we calculated Spearman’s rho between the scanner-distribution and the accuracy of the hold-out test set ($n=300$). The scanner-distribution for each set was approximated using Gini’s index. Here, we show that the scanner distribution has a statistically significant influence on test set accuracy but explains only \SI{0.79}{\percent} of the variance.

\FloatBarrier

\section{Adjustment of SVM regularization based on sample size}
\label{cha:adjustment-svm-regularization}
The regularization of a linear \ac{svm} depends on the absolute number of outliers in a sample. To exclude the possibility that the use of default hyperparameters (a constant value of $C = 1$) caused the effect that we observed, we have adjusted the \ac{svm} regularization (our $C$ hyperparameter) based on the size of each analyses sub-sample. In this adjustment, a constant value $k$ is divided by the sample size. To approximate the default parameter $C=1$ on average, we have set $k=75$. For example, $C$ would be $C = 100/75 = \num{1.33}$ for a sample size of $n=100$. In this case, the adjusted regularization did not deliver results as good as what we observed with $C=1$ (see Figure~\ref{fig:adj_c_overall},~\ref{fig:adj_c_test}). Therefore, we conclude that the default value of $C=1$ across changing N values did not increase the probability of misestimating accuracy as sample size decreased.

% Supplement Figure 1
\begin{figure}[ht]
    \captionsetup[subfigure]{justification=justified,singlelinecheck=false}
    \begin{subfigure}[t]{0.61\textwidth}
        \input{images/overall_set_size_svm_adj_c_chances.pgf}
        \caption{Probabilities for linear \acp{svm} to yield an accuracy exceeding a certain threshold as a function of sample size employing \ac{loocv}.}
    \end{subfigure}
    \hspace{3.0mm}
    \begin{subfigure}[t]{0.34\textwidth}
        \input{images/overall_set_size_svm_adj_c_stats.pgf}
        \caption{Minimum, maximum and mean results for the linear \acp{svm} as a function of sample size employing \ac{loocv}. }
    \end{subfigure}
    \caption[Effects of varying overall sample sizes with an adjusted $C$ parameter.]{Effects of varying overall sample sizes employing \ac{loocv} with an adjusted $C$ parameter with $C=\frac{75}{\text{sample size}}$.}
    \label{fig:adj_c_overall}
\end{figure}

% Supplement Figure 2
\begin{figure}[ht]
    \captionsetup[subfigure]{justification=justified,singlelinecheck=false}
    \begin{subfigure}[t]{0.61\textwidth}
        \input{images/train_set_size_svm_adj_c_chances.pgf}
        \caption{Probabilities for linear \acp{svm} to yield an accuracy exceeding a certain threshold as a function of training sample size.}
    \end{subfigure}
    \hspace{3.0mm}
    \begin{subfigure}[t]{0.34\textwidth}
        \input{images/train_set_size_svm_adj_c_stats.pgf}
        \caption{Minimum, maximum and mean results for the linear \acp{svm} as a function of training sample size.}
    \end{subfigure}
    \caption[Effects of varying train sample sizes with an adjusted $C$ parameter.]{Results as a function of training set sizes with a fixed test set size of $N = 300$ and an adjusted $C$ parameter with $C=\frac{75}{\text{sample size}}$.}
    \label{fig:adj_c_test}
\end{figure}
\FloatBarrier

\section{Alternative Machine Configurations}
\label{cha:alternative-machine-configurations}
To exclude the possibility that the observed effects can only be traced back to our specific configuration, we have tested other usual configurations. The configurations consist of a preprocessing and a classification. In the preprocessing step, we used a method for reduction of feature space and a method for features selection. The reduction of the feature space was achieved with a \ac{pca}, where only a certain number the first components were used. Afterwards, for feature selection, an ANOVA was calculated and a specific number of feature beginning with the highest F-value were taken. The actual configuration used for preprocessing is listed in Table~\ref{tab:preprocessing}.
For the classification, we chose three specific machines:
\begin{enumerate}
    \item An \ac{svm} with a linear kernel and default parameter. ($C = \num{1.0}$)
    \item An \ac{svm} with an \ac{rbf} kernel and default parameter ($C = \num{1.0}$; $\gamma = 1/n_\text{feature}$)
    \item A Random Forrest and default parameter ($n_\text{estimators}=\num{100}$)
\end{enumerate}

In combination with the preprocessing, this results in 48 configurations. Since the found effect is limited to the test set size, we have only repeated our analyses for the test set for each of these configurations.

\begin{table}[!htp]
    \begin{center}

        \begin{tabular}{rr|ccccc}
            & & \multicolumn{5}{c}{\textbf{\acs{pca} $n_\text{components}$}} \\
            &             & no       & all      & \num{500} & \num{50} & \num{10} \\
            \cline{2-7}
            \multirow{6}{*}{{\textbf{ANOVA $k_\text{best}$}}} & no & $\times$ & $\times$ & $\times$ & $\times$
            & $\times$
            \\
            & \num{10}    & $\times$ & $\times$ & $\times$  & $\times$ &          \\
            & \num{100}   & $\times$ & $\times$ & $\times$  &          &          \\
            & \num{1000}  & $\times$ & $\times$ &           &          &          \\
            & \num{10000} & $\times$ &          &           &          &          \\
            & \num{50000} & $\times$ &          &           &          &          \\

        \end{tabular}
        \vspace{6mm}
        \caption[Configurations for the preprocessing]{The $\times$ marks the used combinations of configurations for the preprocessing. The \emph{no}-label means that this preprocessing step were left out.}
        \label{tab:preprocessing}
    \end{center}
\end{table}

\FloatBarrier

\subsection{Results}
\label{cha:alternative-machine-configuration-results}
The results are comparable to the originally used configuration, an \ac{svm} with a linear kernel and no preprocessing (see Figure~\ref{fig:no_PCA_no_selection_RandomForest} to~\ref{fig:PCA_all_components_1000_best_selected_LinearSVC} and Table~\ref{tab:no_PCA_no_selection_RandomForest} to~\ref{tab:PCA_all_components_1000_best_selected_LinearSVC}). The results thus underline a generally valid character of the findings.
An outlier in the results can be found for a specific configuration, a \ac{pca} with 10 components and the \ac{svm} with an \ac{rbf} kernel (see Figure~\ref{fig:PCA_10_components_no_selection_SVC} and Table~\ref{tab:PCA_10_components_no_selection_SVC}). This result can be explained due to overfitting, the machine constantly returns one constant class as a prediction.
\FloatBarrier

\subsubsection{Graphical results representation}

\input{supplements_alternative_machines_graphical.tex}

\FloatBarrier

\subsubsection{Tabular results representation}
\input{supplements_alternative_machines_tabular.tex}


\section{Summary and Conclusion}

To conclude, we have explored how capacitive touch sensors can be applied to the guitar to create an expressive MPE instrument. The interaction design for this instrument is not yet perfected, but offers a direction for further development.

We have proposed a framework for mathematically interpreting the sensor data which can scale to any number of frets or strings, which means that this system can scale indefinitely to accommodate any sized system.

We have evaluated how the prototype is overall effective in delivering the desired expressive features, but requires some refinement to be truly creatively liberating.


\documentclass[10pt,twocolumn,letterpaper]{article}
\usepackage{amsmath}

\begin{document}
\title{Doubly Linked Lists}
\maketitle

\section{Operators}

\begin{enumerate}
\item \textit{head}
\item \textit{tail}
\item \textit{rhead}
\item \textit{rtail}
\item \textit{append}
\item \textit{prepend}
\item \textit{len}
\end{enumerate}

\section{Special Constants}
\begin{enumerate}
\item \textit{nil}
\end{enumerate}

\section{Axioms}

These have not been proven to be a full axiomatization.

$l_i$ are list constants and $e_i$ are elements.

\begin{equation}
\begin{aligned}
&len(\textit{nil}) = 0 \\
&l = nil \vee len(tail(l)) = len(l) - 1 \\
&l = nil \vee len(rtail(l)) = len(l) - 1 \\
&l_1 = l_2 \implies (head(l_1) = head(l_2) \wedge tail(l_1) = tail(l_2)) \\
&l_1 = l_2 \implies (rhead(l_1) = rhead(l_2) \wedge rtail(l_1) = rtail(l_2)) \\
&tail(rtail(l)) = rtail(tail(l)) \\
&len(l) = 1 \implies tail(l) = nil \\
&len(prepend(l, e)) = len(l) + 1 \\
&len(append(l, e)) = len(l) + 1 \\
&head(prepend(l, e)) = e  \\
&rhead(append(l, e)) = e  \\
&tail(prepend(l, e)) = l  \\
&rtail(append(l, e)) = l  \\
%%&tail(prepend(nil, e)) = nil \\
%%&rtail(prepend(nil, e)) = nil \\
%%&tail(append(nil, e)) = nil \\
%%&rtail(append(nil, e)) = nil
\end{aligned}
\end{equation}

\section{Ideas}
\begin{enumerate}
\item From Nikolaj Bjorner's thesis: Could express as a word unification problem (with concatenation as primitve operator). But, this is doubly exponential in the worst case.
\item However, I wonder if it's possible to have concatenation as a 'hidden' operator, used only in decision procedure rules. Not sure if that makes any sense. It would be nice to recognize that two connected FIFOs are equivalent to a single FIFO
\end{enumerate}
\end{document}


\subsection{Core}
This section decribes all the functions in the file ``ptwXY\_core.c''.

\subsubsection{ptwXY\_new} \label{ptwXYnewSec}
This function allocates memory for a new \highlight{ptwXYPoints} object and initializes it by calling \highlight{ptwXY\-\_initialize}.
\setargumentNameLengths{interpolationString}
\CallingC{ptwXYPoints *ptwXY\_new(}{statusMessageReporting *smr,
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{char const *interpolationString,}
    \addArgument{double biSectionMax,}
    \addArgument{double accuracy,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int userFlag );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{interpolationString}{The string representation of interpolation.}
    \argumentBox{biSectionMax}{The maximum disection allowed.}
    \argumentBox{accuracy}{The interpolation accuracy of the data.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \argumentBox{userFlag}{A user defined integer value not used by any ptwXY function.}
    \vskip 0.05 in \noindent
The value of \highlight{interpolation} and \highlight{interpolationString} must agree; otherwise, an error will be reported.
For all but \highlight{ptwXY\_interpolationOther} these must match the string returned by the function \highlight{ptwXY\_interpolationToString}.
For \highlight{ptwXY\_interpolationOther}, the string can be anything that is not one of the standard interpolation string.

If this function fails, NULL is returned.

\subsubsection{ptwXY\_new2}
This function calls \highlight{ptwXY\_new} with the biSectionMax = 12, accuracy = 1e-3, userFlag = 0 and with interpolationString set to the
proper string. This function should not be used for the interpolation value of \highlight{ptwXY\_interpolationOther}.
\CallingC{ptwXYPoints *ptwXY\_new(}{statusMessageReporting *smr,
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_initialize}
This function initializes a \highlight{ptwXYPoints} object and must be called for a \highlight{ptwXYPoints} object
before that object can be used by any other function in this package.
\setargumentNameLengths{interpolationString}
\CallingC{fnu\_status ptwXY\_initialize(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{char const *interpolationString,}
    \addArgument{double biSectionMax,}
    \addArgument{double accuracy,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int userFlag );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to a \highlight{ptwXYPoints} object to initialize.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{interpolationString}{The string representation of interpolation.}
    \argumentBox{biSectionMax}{The maximum disection allowed.}
    \argumentBox{accuracy}{The interpolation accuracy of the data.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \argumentBox{userFlag}{An user defined integer value not used by any ptwXY function.}
    \vskip 0.05 in \noindent
The primary and secondary caches are allocated with functions \highlight{ptwXY\_reallocatePoints} and
\highlight{ptwXY\_reallocateOverflowPoints} respectively.

\subsubsection{ptwXY\_create}
This functions combines \highlight{ptwXY\_new} and \highlight{ptwXY\_setXYData}.
\CallingC{ptwXYPoints *ptwXY\_create(}{statusMessageReporting *smr,
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{char const *interpolationString,}
    \addArgument{double biSectionMax,}
    \addArgument{double accuracy,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int64\_t length,}
    \addArgument{double *xy,}
    \addArgument{int userFlag );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{interpolationString}{The string representation of interpolation.}
    \argumentBox{biSectionMax}{The maximum disection allowed.}
    \argumentBox{accuracy}{The interpolation accuracy of the data.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \argumentBox{length}{The number of points in xy.}
    \argumentBox{xy}{The new points given as $x_0, y_0, x_1, y_1, \; \ldots, \; x_n, y_n$ where n = length - 1.}
    \argumentBox{userFlag}{An user defined integer value not used by any ptwXY function.}
    \vskip 0.05 in \noindent
If this function fails, NULL is returned.

\subsubsection{ptwXY\_create2}
This function calls \highlight{ptwXY\_create} with the biSectionMax = 12, accuracy = 1e-3, userFlag = 0 and with interpolationString set to the
proper string. This function should not be used for the interpolation value of \highlight{ptwXY\_interpolationOther}.
\setargumentNameLengths{interpolation}
\CallingC{ptwXYPoints *ptwXY\_new(}{statusMessageReporting *smr,
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int64\_t length,}
    \addArgument{double *xy );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \argumentBox{length}{The number of points in xy.}
    \argumentBox{xy}{The new points given as $x_0, y_0, x_1, y_1, \; \ldots, \; x_n, y_n$ where n = length - 1.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_createFrom\_Xs\_Ys}
This functions is like \highlight{ptwXY\_create} except the x and y data are given in separate arrays.
\setargumentNameLengths{interpolationString}
\CallingC{ptwXYPoints *ptwXY\_createFrom\_Xs\_Ys(}{statusMessageReporting *smr,
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{char const *interpolationString,}
    \addArgument{double biSectionMax,}
    \addArgument{double accuracy,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int64\_t length,}
    \addArgument{double *Xs,}
    \addArgument{double *Ys,}
    \addArgument{int userFlag );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{interpolationString}{The string representation of interpolation.}
    \argumentBox{biSectionMax}{The maximum disection allowed.}
    \argumentBox{accuracy}{The interpolation accuracy of the data.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \argumentBox{length}{The number of points in xy.}
    \argumentBox{Xs}{The new x points given as $x_0, x_1, \; \ldots, \; x_n$ where n = length - 1.}
    \argumentBox{Ys}{The new y points given as $y_0, y_1, \; \ldots, \; y_n$ where n = length - 1.}
    \argumentBox{userFlag}{An user defined integer value not used by any ptwXY function.}
    \vskip 0.05 in \noindent
If this function fails, NULL is returned.

\subsubsection{ptwXY\_createFrom\_Xs\_Ys2}
This function calls \highlight{ptwXY\_createFrom\_Xs\_Ys} with the biSectionMax = 12, accuracy = 1e-3, userFlag = 0 and with interpolationString set to the
proper string. This function should not be used for the interpolation value of \highlight{ptwXY\_interpolationOther}.
\setargumentNameLengths{interpolation}
\CallingC{ptwXYPoints *ptwXY\_Xs\_Ys2(}{statusMessageReporting *smr,
    \addArgument{ptwXY\_interpolation interpolation,}
    \addArgument{int64\_t primarySize,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int64\_t length,}
    \addArgument{double *Xs,}
    \addArgument{double *Ys );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{interpolation}{The type of interpolation to use.}
    \argumentBox{primarySize}{Initial size of the primary cache.}
    \argumentBox{secondarySize}{Initial size of the secondary cache.}
    \argumentBox{length}{The number of points in xy.}
    \argumentBox{Xs}{The new x points given as $x_0, x_1, \; \ldots, \; x_n$ where n = length - 1.}
    \argumentBox{Ys}{The new y points given as $y_0, y_1, \; \ldots, \; y_n$ where n = length - 1.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_copy}
This function clears the points in \highlight{dest} and then copies the points from \highlight{src} into \highlight{dest}.
It also copies all other data like the interplation flag.  The \highlight{src} object is not modified.
\setargumentNameLengths{dest}
\CallingC{fnu\_status ptwXY\_copy(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *dest,}
    \addArgument{ptwXYPoints *src );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{dest}{A pointer to the destination \highlight{ptwXYPoints} object.}
    \argumentBox{src}{A pointer to the source \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_copyPointsOnly}
This function clears the points in \highlight{dest} and then copies the points from \highlight{src} into \highlight{dest}.
Unlike \highlight{ptwXY\_copy}, this function does not copy any of the other data (e.g., the interpolation flag).
The \highlight{src} object is not modified.
\setargumentNameLengths{dest}
\CallingC{fnu\_status ptwXY\_copyPointsOnly(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *dest,}
    \addArgument{ptwXYPoints *src );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{dest}{A pointer to the destination \highlight{ptwXYPoints} object.}
    \argumentBox{src}{A pointer to the source \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_clone}
This function creates a new \highlight{ptwXYPoints} object and sets its points to the points in its first argument.
This function calls \highlight{ptwXY\_simpleCoalescePoints}. Also see \highlight{ptwXY\_clone2}.
\setargumentNameLengths{status}
\CallingC{ptwXYPoints *ptwXY\_clone(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_clone2}
This function is like \highlight{ptwXY\_clone} but does not call \highlight{ptwXY\_simpleCoalescePoints}.
\setargumentNameLengths{status}
\CallingC{ptwXYPoints *ptwXY\_clone2(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_cloneToInterpolation}
This function calls \highlight{ptwXY\_clone} and set the interpolation of the returned \highlight{ptwXYPoints} instance to
\highlight{interpolation} without adding any points.
\setargumentNameLengths{interpolation}
\CallingC{ptwXYPoints *ptwXY\_cloneToInterpolation(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{ptwXY\_interpolation interpolation );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{interpolation}{The interpolation of the return \highlight{ptwXYPoints} instance.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_slice}
This function creates a new \highlight{ptwXYPoints} object and sets its points to the points from index \highlight{index1} inclusive
to \highlight{index2} exclusive of \highlight{ptwXY}.
\setargumentNameLengths{secondarySize}
\CallingC{ptwXYPoints *ptwXY\_slice(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t index1,}
    \addArgument{int64\_t index2,}
    \addArgument{int64\_t secondarySize}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{index1}{The lower index.}
    \argumentBox{index2}{The upper index.}
    \argumentBox{secondarySize}{Initial size of the secondary cahce.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_domainSlice}
This function creates a new \highlight{ptwXYPoints} object and sets its points to the points from the points between the domain
\highlight{domainMin} and \highlight{domainMax} of \highlight{ptwXY}. If \highlight{fill} is true, points at \highlight{domainMin} and
\highlight{domainMax} are added if not in the inputted \highlight{ptwXY}.
\setargumentNameLengths{secondarySize}
\CallingC{ptwXYPoints *ptwXY\_domainSlice(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double domainMin,}
    \addArgument{double doaminMax,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int fill}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{domainMin}{The lower domain value.}
    \argumentBox{domainMax}{The upper domain value.}
    \argumentBox{secondarySize}{Initial size of the secondary cahce.}
    \argumentBox{fill}{If not 0, points at domainMin and domainMax are added if needed.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_domainMinSlice}
This function creates a new \highlight{ptwXYPoints} object and sets its points to the points from the points between the domain
\highlight{domainMin} to the end of \highlight{ptwXY}. If \highlight{fill} is true, point at \highlight{domainMin} is added if
not in the inputted \highlight{ptwXY}.
\setargumentNameLengths{secondarySize}
\CallingC{ptwXYPoints *ptwXY\_domainMinSlice(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double domainMin,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int fill );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{domainMin}{The lower domain value.}
    \argumentBox{secondarySize}{Initial size of the secondary cahce.}
    \argumentBox{fill}{If not 0, a point at domainMin is added if needed.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_domainMaxSlice}
This function creates a new \highlight{ptwXYPoints} object and sets its points to the points from the points between the domain of
the beginning of \highlight{ptwXY} to \highlight{domainMax}. If \highlight{fill} is true, point at \highlight{domainMax} is added if
not in the inputted \highlight{ptwXY}.
\setargumentNameLengths{secondarySize}
\CallingC{ptwXYPoints *ptwXY\_domainMaxSlice(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double domainMax,}
    \addArgument{int64\_t secondarySize,}
    \addArgument{int fill );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{domainMax}{The upper domain value.}
    \argumentBox{secondarySize}{Initial size of the secondary cahce.}
    \argumentBox{fill}{If not 0, a point at domainMax is added if needed.}
    \vskip 0.05 in \noindent
If an error occurs, NULL is returned.

\subsubsection{ptwXY\_getInterpolation}
This function returns the value of \highlight{ptwXY}'s interpolation member.
\CallingC{ptwXY\_interpolation ptwXY\_getInterpolation(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_getInterpolationString}
This function returns a pointer to \highlight{ptwXY}'s interpolationString member.
\CallingC{char const *ptwXY\_getInterpolationString(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_getStatus}
This function returns the value of \highlight{ptwXY}'s status member.
\CallingC{nfu\_status ptwXY\_getStatus(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_getUserFlag}
This function returns the value of \highlight{ptwXY}'s userFlag member.
\CallingC{int ptwXY\_getUserFlag(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_setUserFlag}
This function sets the value of the \highlight{ptwXY}'s userFlag member to userFlag.
\CallingC{void ptwXY\_setUserFlag(}{ptwXYPoints *ptwXY,
    \addArgument{int userFlag);}}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{userFlag}{The value to set ptwXY's userFlag to.}

\subsubsection{ptwXY\_getAccuracy}
This function returns the value of \highlight{ptwXY}'s accuracy member.
\CallingC{double ptwXY\_getAccuracy(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_setAccuracy}
This function sets the value of the \highlight{ptwXY}'s accuracy member to accuracy.
\CallingC{double ptwXY\_setAccuracy(}{ptwXYPoints *ptwXY,
    \addArgument{double accuracy );}}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{accuracy}{The value to set ptwXY's accuracy to.}
Becuase the range of accuracy is limited, the actual value set may be different then the
argument accuracy. The actual value set in ptwXY is returned.

\subsubsection{ptwXY\_getBiSectionMax}
This function returns the value of \highlight{ptwXY}'s biSectionMax member.
\CallingC{double ptwXY\_getBiSectionMax(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_setBiSectionMax}
This function sets the value of the \highlight{ptwXY}'s biSectionMax member to biSectionMax.
\CallingC{double ptwXY\_setBiSectionMax(}{ptwXYPoints *ptwXY,
    \addArgument{double biSectionMax );}}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{biSectionMax}{The value to set ptwXY's biSectionMax to.}
Becuase the range of biSectionMax is limited, the actual value set may be different then the
argument biSectionMax. The actual value set in ptwXY is returned.

\subsubsection{ptwXY\_reallocatePoints}
This function changes the size of the primary cache.
\setargumentNameLengths{forceSmallerResize}
\CallingC{fnu\_status ptwXY\_reallocatePoints(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t size,}
    \addArgument{int forceSmallerResize );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{size}{The desired size of the primary cache.}
    \argumentBox{forceSmallerResize}{If true (i.e., non-zero) and size is smaller than the current size, the primary cache
        is resized. Otherwise, the primary cache is only reduced if the inputted size is significantly smaller than the current size.}
    \vskip 0.05 in \noindent
The actual memory allocated is the maximum of {\tt size}, the current length of the primary cache and \highlight{ptwXY\_minimumSize}.

\subsubsection{ptwXY\_reallocateOverflowPoints}
This function changes the size of the secondary cache.
\setargumentNameLengths{ptwXY}
\CallingC{fnu\_status ptwXY\_reallocateOverflowPoints(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t size );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{size}{The desired size of the secondary cache.}
    \vskip 0.05 in \noindent
The actual memory allocated is the maximum of {\tt size} and \highlight{ptwXY\_minimumOverflowSize}. The function
\highlight{ptwXY\_coalescePoints} is called if the current length of the secondary cache is greater than the inputted size.

\subsubsection{ptwXY\_coalescePoints}
This function adds the points from the secondary cache to the primary cache and then removes the points from the secondary cache. If the
argument \highlight{newPoint} is not-NULL it is also added to the primary cache.
\setargumentNameLengths{forceSmallerResize}
\CallingC{fnu\_status ptwXY\_coalescePoints(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t size,}
    \addArgument{ptwXYPointsPoint *newPoint,}
    \addArgument{int forceSmallerResize );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{size}{The desired size of the primary cache.}
    \argumentBox{newPoint}{If not NULL, an additional point to add.}
    \argumentBox{forceSmallerResize}{If true (i.e. non-zero) and size is smaller than the current size, the primary cache
        is resized. Otherwise, the primary cache is only reduced if the new size is significantly smaller than the current size.}
    \vskip 0.05 in \noindent
The actual memory allocated is the maximum of {\tt size}, the new length of the \highlight{ptwXY} object and \highlight{ptwXY\_minimumSize}.

\subsubsection{ptwXY\_simpleCoalescePoints}
This function is a simple wrapper for \highlight{ptwXY\_coalescePoints} when only coalescing of the existing points is needed.
\CallingC{fnu\_status ptwXY\_simpleCoalescePoints(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_clear}
This function removes all points from a \highlight{ptwXYPoints} object but does not free any allocated memory. Upon return, the
length of the \highlight{ptwXYPoints} object is zero.
\setargumentNameLengths{ptwXY}
\CallingC{fnu\_status ptwXY\_clear(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_release}
This function frees all the internal memory allocated for a \highlight{ptwXYPoints} object.
\setargumentNameLengths{ptwXY}
\CallingC{fnu\_status ptwXY\_release(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_free}
This function calls \highlight{ptwXY\_release} and then calls free on \highlight{ptwXY}.
\CallingC{ptwXYPoints *ptwXY\_free(}{ptwXYPoints *ptwXY );}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \vskip 0.05 in \noindent
Any \highlight{ptwXYPoints} object allocated using \highlight{ptwXY\_new} will be freed calling \highlight{ptwXY\_free}.
Once this function is called, the \highlight{ptwXYPoints} object should never be used.
The return value is always NULL.

\subsubsection{ptwXY\_length}
This function returns the length (i.e., number of points in the primary and secondary caches) for a \highlight{ptwXY} object.
\CallingC{int64\_t ptwXY\_length(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_getNonOverflowLength}
This function returns the length of the primary caches (note, this is not its size).
\CallingC{int64\_t ptwXY\_getNonOverflowLength(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}

\subsubsection{ptwXY\_setXYData}
This function replaces the current points in a \highlight{ptwXY} object with a new set of points.
\setargumentNameLengths{length}
\CallingC{fnu\_status ptwXY\_setXYData(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t length,}
    \addArgument{double *xy );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{length}{The number of points in xy.}
    \argumentBox{xy}{The new points given as $x_0, y_0, x_1, y_1, \; \ldots, \; x_n, y_n$ where n = length - 1.}

\subsubsection{ptwXY\_setXYDataFromXsAndYs}
This functions is like \highlight{ptwXY\_setXYData} except the x and y data are given in separate arrays.
\CallingC{fnu\_status ptwXY\_setXYDataFromXsAndYs(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t length,}
    \addArgument{double *Xs,}
    \addArgument{double *Ys );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{length}{The number of points in xy.}
    \argumentBox{Xs}{The new x points given as $x_0, x_1, \; \ldots, \; x_n$ where n = length - 1.}
    \argumentBox{Ys}{The new y points given as $y_0, y_1, \; \ldots, \; y_n$ where n = length - 1.}

\subsubsection{ptwXY\_deletePoints}
This function removes all the points from index \highlight{i1} inclusive to index \highlight{i2} exclusive. Indexing is 0 based.
\CallingC{fnu\_status ptwXY\_deletePoints(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t i1,}
    \addArgument{int64\_t i2 );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{i1}{The lower index.}
    \argumentBox{i2}{The upper index.}
    \vskip 0.05 in \noindent
As example, if an \highlight{ptwXY} object contains the points (1.2, 4), (1.3, 5), (1.6, 6), (1.9, 3) (2.0, 6), (2.1, 4)
and (2.3, 1). Then calling \highlight{ptwXY\_deletePoints} with i1 = 2 and i2 = 4 removes the points (1.6, 6) and (1.9, 3).
The indices i1 and i2 must satisfy the relationship ( 0 $\le$ i1 $\le$ i2 $\le n$ ) where $n$ is the length of the
\highlight{ptwXY} object; otherwise, no modification is done to the \highlight{ptwXY} object
and the error \highlight{nfu\_badIndex} is returned.

\subsubsection{ptwXY\_getLowerIndexBoundingX}
This function sets the index such that the xs[index] $<=$ x $<$ xs[index] where xs is the list of x-values for \highlight{ptwXY}.
If x is outside the domain of xs, index is set to -1. If x is the upper domain, it is length - 1 (i.e., for the last two points, the condition
is xs[index] $<=$ x $<=$ xs[index]).
\CallingC{fnu\_status ptwXY\_getLowerIndexBoundingX(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x,}
    \addArgument{int64\_t *index );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The domain value.}
    \argumentBox{index}{The set index.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_getPointAtIndex}
This function checks that the index argument is valid, and if it is, this function returns the result
of \highlight{ptwXY\_getPointAtIndex\_Unsafely}. Otherwise, NULL is returned.
\CallingC{ptwXYPoint *ptwXY\_getPointAtIndex(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t index );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{index}{The index of the point to return.}

\subsubsection{ptwXY\_getPointAtIndex\_Unsafely}
This function returns the point at index. This function does not check if index is valid and
thus is not intended for general use. Instead, see \highlight{ptwXY\_getPointAtIndex} for a general use version of this function.
\CallingCLimited{ptwXYPoint *ptwXY\_getPointAtIndex\_Unsafely(}{ptwXYPoints *ptwXY,
    \addArgument{int64\_t index );}}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{index}{The index of the point to return.}

\subsubsection{ptwXY\_getXYPairAtIndex}
This function calls \highlight{ptwXY\_getPointAtIndex} and if the index is valid it returns the point's x and y values via the
arguments *x and *y. Otherwise, *x and *y are unaltered and an error signal is returned.
\CallingC{nfu\_status ptwXY\_getPairAtIndex(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t index,}
    \addArgument{double *x,}
    \addArgument{double *y );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{index}{The index of the point to return.}
    \argumentBox{*x}{The point's x value is returned in this argument.}
    \argumentBox{*y}{The point's y value is returned in this argument.}

\subsubsection{ptwXY\_getPointsAroundX}
This function sets the \highlight{lessThanEqualXPoint} and \highlight{greaterThanXPoint} arguments
to the two points that bound the point $x$.
\setargumentNameLengths{lessThanEqualXPoint}
\CallingCLimited{ptwXY\_lessEqualGreaterX ptwXY\_getPointsAroundX(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x ),}
    \addArgument{ptwXYOverflowPoint *lessThanEqualXPoint,}
    \addArgument{ptwXYOverflowPoint *greaterThanXPoint );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{lessThanEqualXPoint}{The lower bounding point.}
    \argumentBox{greaterThanXPoint}{The upper bounding point.}
    \vskip 0.05 in \noindent
If the \highlight{ptwXY} object is empty then the return value is \highlight{ptwXY\_less\-Equal\-GreaterX\_\-empty}.
If $x$ is less than domainMin, then \highlight{ptwXY\_less\-Equal\-GreaterX\_\-less\-Than} is return.
If $x$ is greater than doaminMax, then \highlight{ptwXY\_less\-Equal\-GreaterX\_\-greater\-Than} is return. If $x$ corresponds to a
point in the \highlight{ptwXY} object then \highlight{ptwXY\_\-less\-Equal\-GreaterX\_\-equal} is returned. Otherwise,
\highlight{ptwXY\_\-less\-Equal\-GreaterX\_\-between} is returned.

\subsubsection{ptwXY\_getPointsAroundX\_closeIsEqual}
This function is like \highlight{ptwXY\_getPointsAroundX} except that when \highlight{eps} is greater than 0.,
it will set \highlight{closeIsEqual} to a non-zero value if a point is with relative \highlight{eps} of \highlight{x}.
\highlight{*closePoint} is set to the which of \highlight{lessThanEqualXPoint} or \highlight{greaterThanXPoint}
is closer.  If \highlight{x} is below \highlight{*closePoint}, then closeIsEqual is set to -1. If it is above then closeIsEqual is set to 1.
Otherwise, closeIsEqual is set to 0.
\setargumentNameLengths{lessThanEqualXPoint}
\CallingCLimited{ptwXY\_lessEqualGreaterX ptwXY\_getPointsAroundX\_closeIsEqual(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x ),}
    \addArgument{ptwXYOverflowPoint *lessThanEqualXPoint,}
    \addArgument{ptwXYOverflowPoint *greaterThanXPoint ),}
    \addArgument{double eps,}
    \addArgument{int *closeIsEqual,}
    \addArgument{ptwXYPoint **closePoint );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{lessThanEqualXPoint}{The lower bounding point.}
    \argumentBox{greaterThanXPoint}{The upper bounding point.}
    \argumentBox{eps}{}
    \argumentBox{closeIsEqual}{}
    \argumentBox{closePoint}{}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_getValueAtX}
This function gets the $y$ value at $x$, interpolating if necessary.
\setargumentNameLengths{ptwXY}
\CallingC{fnu\_status ptwXY\_getValueAtX(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x,}
    \addArgument{double *y );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{y}{Upon return, contains the $y$ value.}
    \vskip 0.05 in \noindent
If the x value is outside the domain of the \highlight{ptwXY} object, $y$ is set to zero and the returned value
is \highlight{nfu\_X\-Outside\-Domain}.

\subsubsection{ptwXY\_setValueAtX}
This function sets the point at $x$ to $y$, if $x$ does not corresponds to a
point in the \highlight{ptwXY} object then a new point is added.
\CallingC{fnu\_status ptwXY\_setValueAtX(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x,}
    \addArgument{double y );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{y}{The $y$ value.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_setValueAtX\_overrideIfClose}
\highlight{FIXME}

This function
\CallingC{fnu\_status ptwXY\_setValueAtX\_overrideIfClose(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x,}
    \addArgument{double y,}
    \addArgument{double eps,}
    \addArgument{int override );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{y}{The $y$ value.}
    \argumentBox{eps}{}
    \argumentBox{override}{}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_mergeFromXsAndYs}
This function calls \highlight{ptwXY\_mergeFrom} to add the points give by \highlight{xs} and \highlight{ys} into \highlight{ptwXY}.
\setargumentNameLengths{length}
\CallingC{fnu\_status ptwXY\_mergeFromXsAndYs(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t length}
    \addArgument{double *xs,}
    \addArgument{double *ys );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{length}{The number of values in xs.}
    \argumentBox{xs}{The $x$-values to merge.}
    \argumentBox{ys}{The $y$-values to merge.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_mergeFromXYs}
This function calls \highlight{ptwXY\_mergeFrom} to add the points give by \highlight{xs} and \highlight{ys} into \highlight{ptwXY}.
\CallingC{fnu\_status ptwXY\_mergeFromXYs(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t length}
    \addArgument{double *xys );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{length}{The number of values in xs.}
    \argumentBox{xs}{The (x,y) pairs to merge.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_mergeFrom}
This function merges the points gives by \highlight{xs} and \highlight{ys} into \highlight{ptwXY}.
\CallingC{fnu\_status ptwXY\_mergeFrom(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int incY}
    \addArgument{int64\_t length}
    \addArgument{double *xs,}
    \addArgument{double *ys );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{incY}{Not used.}
    \argumentBox{length}{The number of values in xs.}
    \argumentBox{xs}{The $x$-values to merge.}
    \argumentBox{ys}{The $y$-values to merge.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_appendXY}
This function appends the point \highlight{(x,y)} to the end of \highlight{ptwXY}. Note, \highlight{x} must be greater than domainMax.
\CallingC{fnu\_status ptwXY\_appendXY(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x,}
    \addArgument{double y );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{x}{The $x$-value to append.}
    \argumentBox{y}{The $y$-value to append.}
    \vskip 0.05 in \noindent

\subsubsection{ptwXY\_setXYPairAtIndex}
This function sets the $x$ and $y$ values at index.
\CallingC{fnu\_status ptwXY\_setXYPairAtIndex(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{int64\_t index}
    \addArgument{double x,}
    \addArgument{double y );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{index}{The index of the point to set.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{y}{The $y$ value.}
    \vskip 0.05 in \noindent
If index is invalid, \highlight{nfu\_badIndex} is returned. If the $x$ value is not valid for index (i.e. $x \le x_{\rm index-1}$
or $x \ge x_{\rm index+1}$) then \highlight{nfu\_badIndexForX} is return.

\subsubsection{ptwXY\_getSlopeAtX}
This function calculates the slope at the point $x$ assuming linear-linear interpolation. That is, for $x_i < x < x_{i+1}$,
the slope is $( y_{i+1} - y_i ) / ( x_{i+1} - x_i )$. If $x = x_j$ is the point in \highlight{ptwXY} at
index $j$ then for side = `+', $i = j$ is used in the above slope equation. Else, if side = `-', $i = j-1$ is used in the above slope equation.
\CallingC{fnu\_status ptwXY\_getSlopeAtX(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double x,}
    \addArgument{const char side,}
    \addArgument{double *slope );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{index}{The index of the point to set.}
    \argumentBox{x}{The $x$ value.}
    \argumentBox{y}{The $y$ value.}
    \vskip 0.05 in \noindent
If side is neither '-' or '+', the error \highlight{nfu\_badInput} is returned.

\subsubsection{ptwXY\_domainMinAndFrom --- Not for general use}
This function returns the domainMin value and indicates whether the minimum value resides in the primary
or secondary cache.
\setargumentNameLengths{dataFrom}
\CallingCLimited{nfu\_status ptwXY\_domainMinAndFrom(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{ptwXY\_dataFrom *dataFrom,}
    \addArgument{double *domainMin );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{dataFrom}{The output of this argument indicates which cache the minimum value resides in.}
    \argumentBox{domainMin}{The value of the domain min.}
    \vskip 0.05 in \noindent
The return value from this function is domainMin. If there are no data in the \highlight{ptwXYPoints} object, then \highlight{dataFrom} is set
to \highlight{ptwXY\_dataFrom\_Unknown}. Otherwise, it is set to \highlight{ptwXY\_data\-From\_Points} or \highlight{ptwXY\_dataFrom\_Overflow} if the
minimum value is in the primary or secondary cache respectively.

\subsubsection{ptwXY\_domainMin}
This function returns the domainMin value returned by \highlight{ptwXY\_domainMinAndFrom}. The calling function should check that the
\highlight{ptwXYPoints} object contains at least one point (i.e., that the length is greater than 0). If the length is 0, the return value is
undefined.
\CallingC{nfu\_status ptwXY\_domainMin(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double *domainMin );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{domainMin}{The value of the domain min.}

\subsubsection{ptwXY\_domainMaxAndFrom --- Not for general use}
This function returns the domainMax value and indicates whether the maximum value resides in the primary or secondary cache.
\CallingCLimited{nfu\_status ptwXY\_doaminMaxAndFrom(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{ptwXY\_dataFrom *dataFrom,}
    \addArgument{double *domainMax );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{dataFrom}{The output of this argument indicates which cache the maximum value resides in.}
    \argumentBox{domainMax}{The value of the domain max.}
    \vskip 0.05 in \noindent
The return value from this function is domainMax. If there are no data in the \highlight{ptwXYPoints} object, then \highlight{dataFrom} is set
to \highlight{ptwXY\_dataFrom\_Unknown}. Otherwise, it is set to \highlight{ptwXY\_data\-From\_Points} or \highlight{ptwXY\_dataFrom\_Overflow} if the
maximum value is in the primary or secondary cache respectively.

\subsubsection{ptwXY\_domainMax}
This function returns the doaminMax value returned by \highlight{ptwXY\_domainMinAndFrom}. The calling function should check that the
\highlight{ptwXYPoints} object contains at least one point (i.e., that the length is greater than 0). If the length is 0, the return value is
undefined.
\CallingC{nfu\_status ptwXY\_domainMax(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double *domainMax );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{domainMax}{The value of the domain max.}

\subsubsection{ptwXY\_range}
This function returns the minimum and maximum y values in \highlight{ptwXY}.
\CallingC{nfu\_status  ptwXY\_getYMin(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double *rangeMin,}
    \addArgument{double *rangeMax );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{rangeMin}{The value of the range min.}
    \argumentBox{rangeMax}{The value of the range max.}

\subsubsection{ptwXY\_rangeMin}
This function returns the minimum y value in \highlight{ptwXY}.
\CallingC{nfu\_status  ptwXY\_getYMin(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double *rangeMin );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{rangeMin}{The value of the range min.}

\subsubsection{ptwXY\_rangeMax}
This function returns the maximum y value in \highlight{ptwXY}.
\CallingC{nfu\_status ptwXY\_getYMax(}{statusMessageReporting *smr,
    \addArgument{ptwXYPoints *ptwXY,}
    \addArgument{double *rangeMax );}}
    \argumentBox{smr}{The \highlight{statusMessageReporting} instance to record errors.}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{rangeMax}{The value of the range max.}

\subsubsection{ptwXY\_initialOverflowPoint --- Not for general use}
This function initializes a point in the secondary cache.
\CallingCLimited{void ptwXY\_initialOverflowPoint(\hskip -1. in}{
    \addArgument{ptwXYOverflowPoint *overflowPoint,}
    \addArgument{ptwXYOverflowPoint *prior,}
    \addArgument{ptwXYOverflowPoint *next );}}
    \argumentBox{ptwXY}{A pointer to the \highlight{ptwXYPoints} object.}
    \argumentBox{prior}{The prior point in the linked list.}
    \argumentBox{next}{The next point in the linked list.}

\subsubsection{ptwXY\_interpolationToString}
This function returns the string representation of \highlight{interpolation}.
\setargumentNameLengths{interpolation}
\CallingC{char const *ptwXY\_interpolationToString(}{ptwXY\_interpolation interpolation );}
    \argumentBox{interpolation}{The interpolation values.}

\subsubsection{ptwXY\_stringToInterpolation}
This function returns the \highlight{ptwXY\_interpolation} value for \highlight{interpolationString}.
\setargumentNameLengths{interpolationString}
\CallingC{ptwXY\_interpolation *ptwXY\_stringToInterpolation(\hskip -1. in}{
    \addArgument{char const *interpolationString );}}
    \argumentBox{interpolationString}{The interpolation string.}


\documentclass[12pt]{article}
\usepackage[final]{graphicx}

\usepackage{float}
%\usepackage[caption = false]{subfig}

\usepackage[lofdepth,lotdepth]{subfig}

\title{Advanced Lane Detecion Project}
\author{Mingrui Wu}
\date{}

\begin{document}

\maketitle

\section{Camera Calibration}
The colde for this step is in py/camera\_calibration.py. Camera calibration is done by following the materials taught in the class. Twenty chess board images are provided in the camera\_cal folder.
\begin{enumerate}
	\item For each image, find the inner corners by $cv2.findChessboardCorners$. For this function the number of corners in x and y direstions are 9 and 6 respectively.
	\item Append the corners found in the previous step to an array $imgpoints$, at the same time append pre-calculated mesh grid points to another array $objp$.
	\item Having scanned all the twenty images, apply $cv2.calibrateCamera$ to calcuate the calibration paramters.
	\item For each of the twenty images, apply $cv2.undistort$ to correction the distortion, where the calibration parameters needed by this function are computed in the last step.
\end{enumerate}

An example of camera calibration is given in image \ref{fig:camera_calib}. The two images on the left column are the inpute images, while the two on the right column are the images after distortion correction.

\begin{figure}[h]
\centering
\subfloat[input image]{
\includegraphics[width=0.4\textwidth]{calibration1.jpg}
}
\qquad
\subfloat[undistorted image]{
\includegraphics[width=0.4\textwidth]{undist_calibration1.jpg}
}
\qquad
\subfloat[input image]{
\includegraphics[width=0.4\textwidth]{calibration2.jpg}
}
\qquad
\subfloat[undistored image]{
\includegraphics[width=0.4\textwidth]{undist_calibration2.jpg}
}
\caption{Camera calibration}
\label{fig:camera_calib}
\end{figure}

The undisorted images for all the twenty images provided in the  camera\_cal folder can be found in  camera\_cal/calib\_result folder.

\section{Pipline}
In my code, LaneDetector is the class for performing lane detection. The code is in py/lane\_detector.py. Within this class, the member function LaneDetector.lane\_detect describes the whole pipeline.

Take the input image Fig \ref{fig:input} as an example, the whole piple line consists of the following steps:

\begin{enumerate}
	\item \textbf{Loading pre-computed parameters.} First, an object of the LandDetectParam class is created. And this object contains all the parameters needed for the whole lane detection pipeline. In particular, it will load the pre-calculated paramters for camera calibration and perspective transform. The parameters are stored in the file lane\_detect\_param.pkl. The code for this part is in py/lane\_detect\_param.py

	\item \textbf{Distortion correction.} Using the pre-calculated camera calibration parameters mentioned in the last section, the first step is to apply $cv2.undistort$ to the input image to get the undistorted image. The undistorted result for \ref{fig:input} is given in \ref{fig:undistort}

	\item  \textbf{Binary thresholding}  BinaryThresholder is the class for this step. The code is in py/binar\_thresholding.py. Following the class materials, this done by combining the result from gradient and color transformation.
		\begin{enumerate}
			\item \textbf{Sobel gradient} The input image is first transformed to a gray scale image. Then the Sobel operator is applied to the gray scale image to obtain the gradient image. Then based on the gradient strengh in x and y directions, the magnitude and the direction of the gradient at each pixel, binary thresholding is performed.

			\item  \textbf{S space} The input image is transformed into HLS space first. Then binary thresholding is performed based on the S-space value.
			\item \textbf{Combination} The two binary images obtained from the last two steps are combined by OR operation. In addition, the pixels whose S-space value is lower than a threshold are filtered out.

			\item \textbf{RGB filtering} If the image obtained in the last step still have many pixels  (more than 40\%), then the pixels whose RGB value is lower than a threshold are further filtered out. This step is helpful to remove some edges caused by shadows.

		\end{enumerate}
	The binarization example is given in \ref{fig:binarization}

	\item \textbf{Perspective transform.}
		\begin{enumerate}
			\item \textbf{Pre-calculation.} Parameters for perspective transform are pre-calcuated. The code is in py/camera\_calibration.py. Four source points and destinations points are selected manually. Then the matrices for both perspective and inverse perspective transform are obtained by applying the function $cv2.getPerspectiveTransform$. This is done by applying $cv2.warpPerspective$ function.

			\item \textbf{Perspective transform.} The function $cv2.warpPerspective$ is applied to the binary image obtained in the binary thresholding step.
		\end{enumerate}
	The wapred image is given in \ref{fig:warped}.

	\item \textbf{Polynomial fit.} Having obtained the warped image in the last step, PolyFitter is the class for identifying lane pixels and curve fitting. The code is in py/poly\_fitter.py. There are two sub steps:
		\begin{enumerate}
			\item \textbf{Lane pixel identifcation} When processing an individual image or the first frame of a video, the approach based on histogram provided in the class material is applied. First the left and right starting points are selected based on the maximum column sum of the left half and right half of the binary image. Then for the left and the right lanes, we search along the y direction for the non-zero pixels around the current columns. And the staring points are updated based on the mean position of the non-zero pixels that have been found. This is coded in the function PolyFitter.find\_lane\_pixels. When processing videos, the lane pixels are searched along the polynomial curves obtained from the previous frame. The code for this in the function PolyFitter.search\_around\_poly.

			\item \textbf {Poly fit.} Having obtained the lane pixels, numpy.polyfit is applied to fit a quadratic curve. Here an important approach is to enforce the \textbf{consistency} between two consequtive frames. If the current fit is too different from the previous frame, then current fit is ignored. Otherwise, a weighted average of the previous and current fit is computed as the latest polynomial fit. The code for this in PolyFitter.update\_fit.
		\end{enumerate}
	The fitted polynomial curves are given in the image \ref{fig:polyfit}.

	\item \textbf{Calculate radius of curvature and the position of the vehicle.}
		\begin{enumerate}
			\item \textbf{Computing the radius of curature.} The radius of curvature of the left and the right lanes can be calculated once we have the parmaters of the fitted polynomial curves. But here the curves are fitted by the salced the coordinates of the lane pixels. The funtion is PolyFitter.meansure\_curvature\_real. The mean of these two radius of curvature is returned as the raidus of curvature of the road.

			\item \textbf{Computing the position of the vehicle.} Based on the two fitted polynomail curves, we can get the x coordinates of the two points corresponding to the maximum y value of the image. Then the mean value of these two x coordinates is the estimation of the vehicle's position. Note that here we need to scale the result to reflect the real distance rather than the number of pixels. The code is given in LaneDetector.compute\_vehicle\_pos.
		\end{enumerate}

	\item \textbf{Render the lane image}. Having obtained all the information in the previous steps, the lane image can be rendered by filling the regions surronded by the lane points. An example of the lane image is given in \ref{fig:lane}.

\end{enumerate}

\begin{figure}[h]
\centering
\subfloat[input image]{
\includegraphics[width=0.4\textwidth]{test5.jpg}
\label{fig:input}}
\qquad
\subfloat[undistorted image]{
\includegraphics[width=0.4\textwidth]{undist_test5.jpg}
\label{fig:undistort}}
\qquad
\subfloat[binary image]{
\includegraphics[width=0.4\textwidth]{bin_test5.jpg}
\label{fig:binarization}}
\qquad
\subfloat[warped image]{
\includegraphics[width=0.4\textwidth]{warp_test5.jpg}
\label{fig:warped}}
\qquad
\subfloat[poly image]{
\includegraphics[width=0.4\textwidth]{fit_test5.jpg}
\label{fig:polyfit}}
\qquad
\subfloat[lane image]{
\includegraphics[width=0.4\textwidth]{lane_test5.jpg}
\label{fig:lane}}
\caption{Lane detection pipeline}
\end{figure}

\section{Resuls}
\subsection{Results on test images}
The lane detection results for the images in the folder test\_images are given in the folder output\_images. Each test image has 5 result images: undistortion, binary thresholding, warp, poly fit and lane detection. The title of the 5 images start with undist, bin, warp, fit and lane respectively.

\subsection{Results on videos}
The pipeline described above works well on project\_video.mp4. The result is ld\_project\_video.mp4 in the github.

The pipeline is also tested on chanllenge\_video.mp4. It also works although there are some small wobbles. The result is ld\_challenge\_video.mp4.

\section{Discussion}
The above pipeline works well on project\_video.mp4 and chanllenge\_video.mp4. In order to overcome the drastic changes in the curve fitting between two consecutive frames, which can lead to the failure of the lane detection, I enforce the consistency of the cure fit between two consecutive frames. This can smooth the estimation and prevent the fitted curve from changing drastically.

However, this cannot work in harder\_challenge\_video.mp4 because the lane curves change much more than the other two videos. So a better trade off and a better fusion of the vairous information (colore, gradient, cure fit, etc) to detect lane pixels are needed.

\end{document}