\chapter{Correctness}
\label{correctness}

Since the purpose of consensus is to maintain consistency across a
replicated state machine, correctness is a key concern. Not only must
the algorithm itself be correct, but others must also be able to
implement it correctly in real systems. We took a pragmatic approach to
correctness in Raft, building a foundation through understanding and
intuition, then applying formal methods to the degree they were
practical.

To establish the correctness of Raft itself, we developed a formal
specification for the basic Raft algorithm and a proof of its safety.
These are described in Section~\ref{correctness:specproof} and can be
found in full in Appendix~\ref{appendix:correctness}. Although many
other components are needed for a complete system (specifically,
membership changes, log compaction, and client interaction), this is an
important step towards proving Raft correct.
Section~\ref{correctness:prior} discusses other methods we tried before
arriving at the current proof.

Our goal is for others to be able to build correct systems using Raft,
and Section~\ref{correctness:testing} describes approaches to doing so.
We hypothesize that systems builders will have an easier time developing
correct implementations if they fully understand Raft; this is another
reason why understandability is so important. We have tried to be clear
and precise in describing Raft, but one problem with natural languages
is that they can easily be imprecise or ambiguous. Thus, we encourage
system builders to compare their understanding with Raft's formal
specification, which is completely precise using mathematical language.

\section{Formal specification and proof for basic Raft algorithm}
\label{correctness:specproof}

We have developed a formal specification and a proof of safety for the
consensus mechanism described in Chapter~\ref{basicraft}; these can be
found in Appendix~\ref{appendix:correctness}.
The formal specification makes the information summarized in
Figure~\ref{fig:basicraft:cheatsheet} completely precise using the TLA+
specification language~\cite{Lamport:2002}. It is about \num{450} lines long
and serves as the subject of the proof.
It is also useful on its own for anyone implementing
\name{}.

The formal specification defines the state in a complete Raft cluster
with an arbitrary number of servers. It defines an initial state
(\emph{Init}) in which all the servers' logs are empty and defines all
possible transitions from one state to another (\emph{Next}). There are
several such transitions: the network may duplicate or drop a message,
and a server may (under the right conditions) receive a message,
timeout, restart, become a leader, advance its commit index, receive a
request from a client, send a RequestVote request, or send an
AppendEntries request. Each transition includes the conditions under
which it may occur. For example, a server may only request a vote if it
is in the candidate state.

The specification models an asynchronous system (it has no notion of
time) with the following assumptions:
%
\begin{itemize}
%
\item Messages may take an arbitrary number of steps (transitions) to
arrive at a server. Sending a message enables a transition to occur (the
receipt of the message) but with no particular timeliness.
%
\item Servers fail by stopping and may later restart from stable storage
on disk.
%
\item The network may reorder, drop, and duplicate messages.
%
\end{itemize}

The formal specification is slightly more general than the Raft
algorithm presented in Chapter~\ref{basicraft}. These differences make
the formal specification applicable to a wider range of implementations
and also make some of its state transitions more orthogonal, which
simplifies the proof. One way in which the formal specification differs
from the algorithm's description is that it uses message-passing rather
than RPC. This requires a minor change to the AppendEntries response
format, but it eliminates the need to pair responses with requests.
The specification also takes more transitions than most
implementations would to arrive at the same end state. Since each
transition is evaluated atomically, this models smaller atomic regions
in an implementation. There are several examples of this:
%
\begin{itemize}
%
\item When a server times out, it does not grant itself a vote in the
same step. Instead, it requests its own vote with an asynchronous
RequestVote request message. Also, after a candidate receives its final
vote, it becomes leader in a separate transition.
%
\item Leaders do not advance their commit index upon receiving an
AppendEntries reply. Instead, they do so in a separate transition. This
improves orthogonality, since a leader that forms a single-server
cluster can also increase its commit index through the same transition.
%
%
\item On receiving an AppendEntries request, a server either returns to
the follower state, truncates just the last entry from the end of its
log, appends just one entry to the end of its log, or replies in one
atomic step (it can then continue to process the request in further
steps). Reducing
this atomic region to just one entry at a time turns out to be important
for implementations that write to persistent storage. For example, when
entries span multiple files, most file systems would not allow
truncating all of the entries atomically. The specification shows that
implementations may safely truncate the entries back to front, one or
more at a time.
%
\item Servers update their current terms and states upon receiving a
message with a larger term, then in a different transition they process
the message.
%
\end{itemize}
%
On the other hand, the specification is not as general as possible; that
would harm its understandability. For example, some transitions set two
variables even when they need not be set atomically.

The proof verifies the State Machine
Safety property. It is complete (it relies on the specification alone)
and relatively precise (it is about \num{3500} words long). The main idea
of the proof is summarized in Section~\ref{basicraft:safety:argument}.
Most of the lemmas (subproofs) show that an invariant holds for all states that
are reachable from the initial state in an execution. Using induction,
they assume the invariant holds in one state and show that it holds in
every possible next state.

It is often necessary in the proof to refer to variables from prior
states in the execution. To make this precise, the specification is
augmented with {\em history variables}; these variables carry
information about past events forward to states that follow. For
example, one history variable called $elections$ maintains a record of
every successful election in the execution, including the complete log
of each server at the time it cast its vote and the complete log of the
new leader. The history variables are never read in the specification
and would not exist at all in a real implementation; they are only
``accessed'' in the proof.

\section{Discussion of prior verification attempts}
\label{correctness:prior}

Prior to arriving at the current proof, we tried three other approaches:
%
\begin{enumerate}
%
\item We first checked an earlier version of Raft in the Murphi model
checker~\cite{Dill:1992}, which explores the complete state space to
check for unsafe conditions. The state space quickly expanded to the
point where Murphi could not finish (in a reasonable amount of
time), so we had to limit the size of the
system to at most four entries in each log, four terms, and five
servers. Murphi found one bug in an early version of Raft, which caused
log inconsistencies when multiple leaders in a row crashed after
incompletely committing log entries.
It also missed an important bug in an early version of Raft,
where the commitment rule did not account for scenarios like that of
Figure~\ref{fig:basicraft:oldTermCommit}.
Murphi most likely missed this bug because of the constrained model size
(fortunately, David \mazieres{} found it).
%
\item We attempted to use the TLA model checker on our specification. We
found bugs in creating the specification this way but
abandoned this approach because it did not scale well to larger models.
%
\item We also attempted to use the TLA proof
system~\cite{Cousineau:2012}, which introduces a hierarchical language
for formally proving properties on TLA specifications and includes a
machine checker for such proofs. We mechanically proved the Leader
Completeness Property using the TLA proof system, but this proof relied
on invariants that have not been mechanically checked (for example, we
did not prove the type safety of the specification). Unfortunately, we
found it too tedious and time-consuming to use the TLA proof system at
the scale of a complete proof. One problem is that TLA is untyped,
making it more general but also more tedious~\cite{Lamport:1999}.
%
\end{enumerate}

We found the tools for correctness to be limited in various ways. In our
experience, model checking was orders of magnitude easier than
developing a proof. It essentially requires writing a simplified Raft
implementation, and then it can be executed and debugged even easier
than a distributed system (model checkers output a full execution trace
when any problems occur). Unfortunately, we were not able to verify our
models with large enough parameters to be fully convinced of their
correctness.

On the other hand, the Raft proof took about six weeks  of learning
and thinking before any significant progress was made. Creating a proof
takes a different skill set from programming and a different sort of
creativity. The end result has helped build our confidence in Raft's
safety, but the proof might have bugs. At the scale of the complete Raft
specification, only a mechanically checked proof could definitively be
bug-free. We think a machine-checked proof for Raft would be feasible
with more capable tools (e.g, Coq~\cite{Bertot:2004}), and one has
recently been created for Multi-Paxos~\cite{Schiper:2014}. However, the
time investment required would probably be on the order of several
months.

\section{Building correct implementations}
\label{correctness:testing}

There are many possible approaches to building a correct implementation
of Raft. The safest approach is to generate an implementation
automatically from a proven Raft specification. If the tools are
correct, this guarantees that there will be no errors in converting the
specification to an implementation. Recent work has shown this to be
feasible for Multi-Paxos~\cite{Schiper:2014}, and we expect it to be for
Raft as well. However, this approach has not been very popular in
practice so far, perhaps because real-world systems have additional
needs, such as performance, that are harder to accommodate in the
generated code.

Without generating an implementation, implementers should strive to
design their implementations to reduce the possibility of creating bugs,
and they should test their implementations to reduce the possibility of
encountering bugs in production. The remainder of this section discusses
several approaches we think may be effective, though we have not
evaluated their effectiveness. Readers may also be interested in the
testing strategy used for Chubby~\cite{Chandra:2007}.

Howard describes a nice design for building ocaml-raft
correctly~\cite{Howard:2014,impl:ocaml-raft}. It collects all the Raft
state transitions in one module, while all code for determining when
transitions should occur is elsewhere. Each transition checks its
pre-conditions using assertions and has no system-level code
intermixed, so the code resembles the core of the Raft specification.
Because all of the code that manipulates the state variables is
collected in one place, it is easier to verify that state variables
transition in restricted ways. A separate module invokes the transitions
at the appropriate times.
Moreover, ocaml-raft can simulate an
entire cluster in a single process, which allows it to assert Raft's
invariants across virtual servers during execution. For example, it can
check that there is at most one leader per term at runtime.

For end-to-end testing, Jepsen and Knossos are useful tools that have
already found bugs in two Raft implementations (in read-only request
handling)~\cite{Kingsbury:etcdconsul}. Jepsen injects network partitions
in a distributed system and determines whether the system loses data.
Knossos analyzes clients' histories of operations against a distributed
system to look for ways those histories are not linearizable. Together,
these can be used as powerful end-to-end tests for Raft systems.

Some of the most difficult to find bugs are those that only occur in
unlikely circumstances such as during leadership changes or partial
network outages. Thus, testing should aim to increase the likelihood of
such events. There are three ways to do this.

First, Raft servers can be configured to encourage rare events for
testing. For example, setting the election timeout very low and the
heartbeat interval very high will result in more leader changes. Also,
having servers take snapshots very frequently will result in more
servers falling behind and needing to receive a snapshot over the
network.

Second, the environment can be manipulated to encourage rare events for
testing. For example, servers can be randomly restarted and cluster
membership changes can be invoked frequently (or continuously) to
exercise those code paths. Starting other processes to contend for
servers' resources may expose timing-related bugs, and the network can
be manipulated in various ways to create events that occur only rarely
in production, such as:
%
\begin{compactitem}
%
\item Randomly dropping messages (and varying the frequency of drops
between servers and links);
%
\item Adding random message delays;
%
\item Randomly disabling and restoring network links; and
%
\item Randomly partitioning the network.
%
\end{compactitem}

Third, running the tests for a longer period of time will increase the
chance of discovering a rare problem. A larger number of machines can
run tests in parallel. Moreover, entire clusters can run as separate
processes on a single server to reduce network latency, and disk
overheads can be reduced by persisting to RAM only (for example, with a
RAM-based file system such as tmpfs~\cite{tmpfs}). While not entirely
realistic, these techniques can exercise the implementation aggressively
in a much shorter period of time.

\section{Conclusion}

We believe our evaluation of Raft's correctness puts it at least on par
with the algorithms used in most Paxos-based systems. Theoreticians have
typically proven the safety of only narrow specifications of Paxos, but
practitioners deviate from these specifications and extend their systems
significantly. The formal specification for Raft is a nearly complete
implementation of the basic Raft algorithm presented in
Chapter~\ref{basicraft}, so the fraction of a fully elaborated Raft
algorithm that has been proven safe is fairly large. We leave specifying
and proving cluster membership, log compaction, and client interaction
to future work, along
with liveness and availability properties of the basic Raft algorithm.


\chapter{Methodology}
\label{methodology}

\section{Ray tracing}
Our ray tracer uses the GPU-optimised parametric octree traversal algorithm presented by \cite{laine10efficientsvos}. This algorithm is extremely efficient for traversing along rays through a sparse octree as it hierarchically avoids empty space, finding the first intersection of the ray extremely fast.

\begin{figure}
\centering
	\centering
	\subfloat[Intersection of the root with the ray]{\includegraphics[width=3in]{initial_intersection.png}}
	~
	\subfloat[Initial child selection]{\includegraphics[width=3in]{initial_intersection_child.png}}

	\caption{Initial intersection test}
	\label{fig:root_intersect}
\end{figure}

Pseudo-code for the ray casting algorithm is given in algorithm \ref{alg:raycast}. Our data is stored in a regular octree structure, meaning that each node of the tree is divided into 8 identically sized octants. The algorithm then begins by determining the intersection of the root node with the ray, as well as determining the first entered child octant. This is shown in figure \ref{fig:root_intersect}. The main loop then begins.

\begin{algorithm}
\caption{Ray cast algorithm pseudo-code \parencite{laine10efficientsvos}}
\label{alg:raycast}
\begin{algorithmic}[1]
\Procedure{Raycast}{$root, ray$}
	\State $current\_voxel \gets intersect(root,~ray)$			\Comment{Intersection with root}
	\While{$not~terminated$} \Comment{Traverse}
		\If{$current\_voxel~exists$}
			\If{$voxel~smaller~than~pixel$} 					\Comment{Exit conditions}
				\State $\textbf{return}~current\_voxel$
			\ElsIf{$voxel~is~a~leaf$}
				\State $\textbf{return}~current\_voxel$
			\Else
				\State $current\_voxel \gets push(currrent\_voxel, ray)$		\Comment{Descend into child}
			\EndIf
		\EndIf

		\State $current\_voxel \gets advance(current\_voxel, ray)$			\Comment{Advance into next sibling}

		\If{$advance~direction~disagrees~with~ray~direction$}
			\State $current\_voxel \gets pop(current\_voxel, old\_voxel)$			\Comment{Pop last common parent}
		\EndIf
	\EndWhile
\EndProcedure
\end{algorithmic}
\end{algorithm}

The algorithm then checks that the current voxel exists. If the current voxel exists, the exit conditions are checked: the projection of the current voxel is smaller than the pixel on-screen, and whether the voxel is a leaf node, in which case there are no more subdivisions below it. If either of these conditions are met, the algorithm terminates, returning the current voxel. Otherwise, the algorithm executes push, advancing the traversal to the first entered child voxel.

\begin{figure}
\centering
	\centering
	\subfloat[The current voxel prior to push]{\includegraphics[width=3in]{push_initial.png}}
	~
	\subfloat[The current voxel after push]{\includegraphics[width=3in]{push_post.png}}

	\caption{The push operation, 2D case}
	\label{fig:ray_push}
\end{figure}

If the current voxel does not exist, the algorithm advances the traversal to the next voxel intersected by the ray on the current level. The direction of advancement is then checked against the ray direction to ensure the advance was valid. If the direction of advance does not coincide with the direction of the ray, in which case one of the parent nodes of the current voxel differs from one of the parent nodes of the previous voxel, pop is used to return to the last common parent of the two voxels and determine the next child intersection along the ray, after which time traversal continues. The push, advance, and pop operations are described fully by \cite{laine10efficientsvos}.

\begin{figure}
\centering
	\subfloat[The current voxel prior to advance]{\includegraphics[width=3in]{push_post.png}}
	~
	\subfloat[The current voxel after advance]{\includegraphics[width=3in]{advance_post.png}}

	\caption{The advance operation, 2D case}
	\label{fig:ray_advance}
\end{figure}

As empty space is quickly advanced over, preventing unnecessary traversal deeper into the tree, and voxels are never revisited, this algorithm quickly determines whether a ray intersects with a volume stored within an octree. This efficient traversal allows us to cast rays against a volume to produce a real-time ray traced image.

\begin{figure}
\centering
	\subfloat[The initially intersected voxel]{\includegraphics[width=3in]{emptyspace_1.png}}
	~
	\subfloat[Push]{\includegraphics[width=3in]{emptyspace_2.png}}
	\\
	\subfloat[Advance]{\includegraphics[width=3in]{emptyspace_3.png}}
	~
	\subfloat[Push]{\includegraphics[width=3in]{emptyspace_4.png}}
	\\
	\subfloat[Advance, the first intersected voxel is found]{\includegraphics[width=5in]{emptyspace_5.png}}

	\caption{How empty space is avoided, 2D case}
	\label{fig:empty-space}
\end{figure}

\subsection{Storage}
Our data structure uses the same basic storage mechanisms as \cite{laine10efficientsvos}. The tree structure is stored separately from the related shading data, as the majority of processing time is spent in traversal. The extra time it takes to look up shading attributes for shading is therefore traded for a more compact traversal structure. A pointer to a lookup table pointing to attributes for the whole volume is stored at 8 kilobyte boundaries within the tree data.

The tree structure encodes each non-leaf node as a child descriptor, containing a pointer to the children of the current node, an 8-bit mask detailing which of the current node's children exists, and another 8-bit mask which determines which of the node's children are non-leaves (in other words, which children have their own child descriptors stored at the child pointer.)

The child descriptors for the children of a node are then stored together in a block, referenced by this child pointer. The non-leaf mask can then be used to access a particular child using an index from 0 to 7 using a 256 bit lookup table which relates the non-leaf mask of a parent voxel to the index of the desired child:

\[
	child\_offset = lookup(non\_leaf\_mask << child\_index)
\]

The lookup table contains values from 0 to 7, containing the offset of the desired child given a particular non-leaf mask. This lookup table and the relevant implementation is shown in appendix \ref{app:lookup-table}.

\subsubsection{Voxel attributes}
The attributes stored for each voxel are the main way in which our storage scheme varies from that used in \cite{laine10efficientsvos}. In \cite{laine10efficientsvos}, only a colour and a normal, representing the volume after ambient occlusion is pre-calculated, are required for shading. For our purposes, additional attributes are required per-voxel, such as index of refraction and reflectance.

Attributes are stored after the traversal information, along with a lookup table that points to blocks of attributes, grouped by parent voxel. The index in the lookup table can be obtained by considering the offset of the parent's child descriptor from the start of the data, as so:

\[
	lookup\_index = \frac{parent\_desc\_addr - start\_addr}{child\_desc\_size}
\]

The child descriptor size is a constant, referring to the size in bytes of each child descriptor.

This index is then used to retrieve the block of attributes containing the current voxel's attributes, and then the $child\_offset$ obtained above is used to obtain the attributes for the current voxel:

\[
	voxel\_attributes = lookup\_table[lookup\_index] + child\_offset
\]

The resulting pointer points to a structure containing the packed attributes required to shade the current voxel. For our renderer, that includes colour, normal, reflectance, and index of refraction, where the colour also contains an alpha channel which is used to determine transparency. The number of bits used to store each attribute is detailed below:\\

\begin{tabular}{|l|r|l|}
\hline

Attribute & Size in bits & Details \\
\hline

Colour	& 32 bits	& 8 bits for red, green, blue, and alpha components \\
		& 			& between 0.0 and 1.0 \\
\hline

Normal	& 32 bits	& Encoded as detailed in \cite{laine10efficientsvos}, \\
		&			& providing up to 14 bits of precision for smooth \\
		&			& normals \\
\hline

Reflectance & 16 bits & A floating point value between 0.0 and 1.0 \\
\hline

Index of refraction & 16 bits & A floating point value between 1.0 and 4.0 \\
\hline

\end{tabular} \\

The 16-bit floating point values for reflectance are stored as integers between $-2^{15}$ and $2^{15}$, as these are the minimum and maximum values that can be stored in a signed 16-bit integer. These values are scaled such that the minimum value (0.0 for reflectance and 1.0 for refraction) is encoded as $-2^{15}$, and the maximum value as $2^{15}$. Minimum and maximum values were chosen to maximise the precision of the packed values, although the values are packed as 16-bit integers purely for the reason that two 16-bit integers fit exactly into a 32-bit bit-field. If more attributes were added as needed, the sizes of these packed values could potentially be reduced as needed.

The minimum and maximum values for reflectance were chosen as values outside of this range are not physically sensible, as reflectance is defined as the fraction of received electromagnetic radiation (in this case, light) that is reflected by a surface. Values between 0 and 1 for refraction are also not physically sensible, although 4 was chosen as an arbitrary cut-off.

Floating point values are packed into integral bitfields using the following formula, where min and max are the minimum and maximum values to be considered, and bits is the number of bits allocated:

\[	range = max - min \]
\[	int\_max = 1 << (bits - 1) \]
\\
\[	packed\_value = floor((value - min) \cdot \frac{int\_max}{range}) \]

These values are then unpacked as needed. In some cases, this might not be necessary. For example, when checking for changes in index of refraction, the integral value can be used instead.

\section{Reflection rays}
\begin{figure}
\centering
	\includegraphics[width=14cm]{reflection.png}
	\caption{The relationship between the angle of incidence $\theta_i$ and the angle of reflection $\theta_r$}
	\label{fig:reflection}
\end{figure}

In order to determine the contribution of light reflected by the scene, a reflection ray must be cast in the angle of reflection in order to find any surfaces that may be reflecting light back. The law of reflection tells us that the angle of incidence, the angle between the normal of a surface and the ray hitting it, is equal to the angle of reflection \parencite{heath99history}. The GLSL (OpenGL Shader Language) specification gives a vector form of this equation using the dot product \parencite{glslspec}, where $I$ is the incident vector and $N$ is the normal of the surface:

\[
	reflection~direction = \vec{I} - 2 * \vec{N} * (\vec{N} \cdot \vec{I})
\]

When shading a surface, a reflection ray is cast in this direction in order to check for intersections with the rest of the scene. If any such intersections are found, the intersected surface is shaded recursively down to a specified limit, and then added onto the overall reflected colour for the current surface.

\section{Refraction rays}
\begin{figure}
\centering
	\includegraphics[width=14cm]{refraction.png}
	\caption{The relationship between the angle of incidence $\theta_i$ and the angle of refraction $\theta_r$}
	\label{fig:refraction}
\end{figure}

In order to refract a ray through a surface, the direction of the refracted ray must be calculated. The refracted angle can be calculated by utilising Snell's law, which states a relationship between the angle of incidence $\theta_1$, the angle of refraction $\theta_2$, the index of refraction of the current medium $n1$, and the index of refraction of the medium being entered $n2$ \parencite{glassner89introduction}:

\[
	\frac{\sin\theta_1}{\sin\theta_2} = \frac{n2}{n1}
\]

By using this relationship, it is possible to determine a direction vector for the refracted ray. The GLSL specification again gives a method of calculating a direction vector for a refracted ray, given an incidence vector $I$, a surface normal $N$, and the ratio of the current index of refraction to the new index of refraction $eta$:

\newpage
\lstset{language=C,caption={Calculation of a refraction ray},label=lookuptable}
\begin{lstlisting}[frame=single]
vector refract(vector I, vector N, float eta)
{
	k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I));

	if (k < 0.0)
		return vector(0.0, 0.0, 0.0);
	else
		return eta * I - (eta * dot(N, I) + sqrt(k)) * N;
}
\end{lstlisting}

A refracted ray can then be cast through a material in order to determine the path of light through a medium. When the ray reaches a boundary beyond which the index of refraction changes, the direction of the refraction ray must be recalculated.

One additional consideration must be made, however. The specified normal must be a normal on the plane through which the ray is refracting. In the case of a refraction ray leaving a material, rather than entering it, the normal usually used for rendering a surface will need to be reversed in order to obtain this normal. This can easily be handled by checking the dot product of the normal with the direction of the refracted ray:

\[
	dot = ray.direction \cdot normal
\]

If this dot product is greater than zero, then the surface normal is facing outwards from the direction of the ray, and as such, must be reversed to obtain the normal of the surface through which the ray is being refracted:

\[
	normal = -normal
\]

\subsection{Tracing rays through materials}
In order to handle translucent materials, we must be able to trace a ray through a translucent material. The problem is, given an intersection with a surface, finding the point at which a refraction ray cast from this intersection point exits the surface. One possible solution is to modify the ray casting algorithm, redefining the exit conditions such that it only exits when empty space is found, as in algorithm \ref{alg:raycast_solids}.

\begin{algorithm}
\caption{Ray casting through solids}
\label{alg:raycast_solids}
\begin{algorithmic}[1]
\Procedure{Raycast\_solid}{$root, ray$}
	\State $current\_voxel \gets intersect(root,~ray)$			\Comment{Intersection with root}
	\While{$not~terminated$} \Comment{Traverse}
		\If{$current\_voxel~exists$}
			\State $current\_voxel \gets old\_voxel$
			\State $current\_voxel \gets push(currrent\_voxel, ray)$		\Comment{Descend into child}
		\EndIf

		\State $old\_voxel \gets current\_voxel$
		\State $current\_voxel \gets advance(current\_voxel, ray)$			\Comment{Advance into next sibling}

		\If{$advance~direction~disagrees~with~ray~direction$}
			\State $current\_voxel \gets pop(current\_voxel, old\_voxel)$			\Comment{Pop last common parent}
		\EndIf

		\If{$current\_voxel~nonexistent$}			\Comment{Return when empty space is found}
			\State $\textbf{return}~old\_voxel$
		\EndIf
	\EndWhile
\EndProcedure
\end{algorithmic}
\end{algorithm}

The algorithm will now descend until it finds a leaf node, advancing and popping only once a leaf is found. This algorithm will find the exit point of a ray, but it has the side effect of checking every voxel along the ray's path, at every level. This is very inefficient, and does not take advantage of the volume's tree structure.

On the other hand, if we were to consider the refraction ray discretely, we could follow the path of the ray through the solid, casting back towards the original point of intersection at intervals. Once the active span of the ray as returned by the ray casting algorithm is non-zero, in other words, when the ray has started in empty space and found a surface, we have found the probable exit point of the refraction ray. In order to do this, an interval must be chosen. We chose to use a fixed user-configurable interval, but it may be possible to use a dynamic interval based on the volume being ray traced. The pseudo-code for this operation is given below.

\begin{algorithm}
\caption{Discrete ray cast}
\label{alg:discrete_raycast}
\begin{algorithmic}[1]
\Procedure{Discrete\_raycast}{$root, ray$}
	\State $max\_iterations = \frac{scene\_width}{fixed\_interval}$
	\For{$i = 0;~i<max\_iterations;~++i$}
		\State \Call{Raycast}{origin + i * direction, -direction}
		\If{$resulting~span > 0$} \Comment{We found empty space}
			\State $\textbf{break}$
		\EndIf
	\EndFor
	\State $\textbf{return}~found~surface$
\EndProcedure
\end{algorithmic}
\end{algorithm}

\subsection{Refraction through heterogeneous materials}
It has already been established that the refraction ray's direction must be recalculated when moving from a material with one index of refraction to a material with a different index of refraction. The problem, then, is how to accomplish this for heterogeneous materials.

The above discrete ray cast algorithm can be easily modified to take account of the change in refractive index as it traverses through a material.

\begin{algorithm}
\caption{Discrete ray cast with varying refractive index}
\label{alg:discrete_raycast_heterogeneous}
\begin{algorithmic}[1]
\Procedure{Discrete\_raycast}{$root, ray$}
	\State $max\_iterations = \frac{scene\_width}{fixed\_interval}$
	\State $refractive\_index = hit\_refractive\_index$
	\For{$i = 0;~i<max\_iterations;~++i$}
		\State \Call{Raycast}{origin + i * direction, -direction}
		\If{$resulting~span > 0$} \Comment{We found empty space}
			\State $\textbf{break}$
		\EndIf
		\If{$hit\_refractive\_index != refractive\_index$}
			\If{$\vec{normal} \cdot \vec{direction} > 0$} \Comment{Check if exiting material}
				\State $normal = -normal$
			\EndIf
			\State $direction = \Call{Refract}{direction,~normal,~\frac{refractive\_index}{hit\_refractive\_index}}$
		\EndIf
	\EndFor
	\State $\textbf{return}~found~surface$
\EndProcedure
\end{algorithmic}
\end{algorithm}

\section{Shading}
\begin{figure}
\centering
	\includegraphics[width=14cm]{secondaryrays.png}
	\caption{Secondary rays being spawned for calculating shadow coverage, reflection, and refraction}
	\label{fig:secondaryrays}
\end{figure}

Our shader uses a Blinn-Phong shading model, as described in chapter \ref{litreview}.

When shading a surface, a ray is cast towards each light source to check if it is occluded, in which case the intersection is in shadow. Reflection and refraction rays are also cast and the results are then mixed additively with the final output colour.

We use recursion to handle multiple levels of reflection and refraction to a predefined maximum. Simplified pseudo-code for rendering and shading is given in algorithm \ref{alg:render}.

\begin{algorithm}
\caption{Per-pixel rendering}
\label{alg:render}
\begin{algorithmic}[1]
\Procedure{render\_pixel}{$x, y, tree, projection$}
	\State $out\_colour \gets (0, 0, 0, 0)$
	\State $ray \gets calculate\_ray(x,~y,~projection)$
	\State $intersection \gets \Call{raycast}{tree, ray}$
	\If{$intersection.hit$}
		\State $out\_colour \gets \Call{shade}{tree,~ ray,~ intersection}$
	\EndIf
	\State $\textbf{return} out_colour$
\EndProcedure
\\
\Procedure{shade}{$tree,~ ray,~ intersection$}
	\State $out\_colour \gets (0, 0, 0, 0)$
	\For{$each~light$} \Comment{Shade for each light}
		\State $light\_dir \gets light\_pos - intersection.position$ \Comment{Check shadow}
		\State $shadow\_ray \gets (intersection.position, light_dir)$
		\State $shadow\_intersection \gets \Call{raycast}{tree, shadow\_ray}$
		\If{$shadow\_intersection.hit$}
			\State $\textbf{continue}$
		\EndIf
		\State $out\_colour ~+=~ \Call{diffuse\_reflection}{intersection,~light}$
		\State $out\_colour ~+=~ \Call{specular\_reflection}{intersection,~light}$
	\EndFor
	\\
	\State $reflection\_ray \gets \Call{reflect}{ray,~intersection}$ \Comment{Reflection}
	\State $reflection\_intersection \gets \Call{raycast}{tree, reflection\_ray}$
	\If{$reflection\_intersection.hit$}
		\State $out\_colour ~+=~ \Call{shade}{tree,~ reflection\_ray,~ reflection\_intersection}$
	\EndIf
	\\
	\State $refraction\_ray \gets \Call{refract}{ray,~intersection}$ \Comment{Refraction}
	\State $refraction\_intersection \gets \Call{raycast\_empty}{tree, refraction\_ray}$
	\If{$refraction\_intersection.hit$}
		\State $out\_colour ~+=~ \Call{shade}{tree,~ refraction\_ray,~ refraction\_intersection}$
	\EndIf
\EndProcedure
\end{algorithmic}
\end{algorithm}

\section{Parallelisation}
Ray tracing is parallelised with one thread per pixel on the screen. This thread is then responsible for the primary ray and all secondary rays, and all work involved in generating that pixel, as shown in algorithm \ref{alg:render}. Pixels are considered independently to allow this process to be parallelised. These threads are spawned on the GPU in 32x32 grids to maximise occupancy. This is the maximum grid size on current generation CUDA GPUs, and allows us to achieve high levels of GPU utilisation as shown in figure \ref{fig:utilisation}.

\begin{figure}
\centering
	\includegraphics[width=8cm]{gpu0.png}
	\caption{GPU utilisation for our rendering kernel, as determined using Nvidia's nsight profiler}
	\label{fig:utilisation}
\end{figure}

This approach allows us to achieve real-time rendering for simple scenes, and given the results of \cite{laine10efficientsvos} should also allow more complex scenes to be rendered. However, the limitation of this approach is that, as more work is added to each thread, every thread in a grid must follow the most computationally heavy computation path due to the highly parallelised nature of GPUs. Possible solutions to this problem are presented in chapter \ref{conclusion}.

\section{Test data}
Benchmarks for the software were taken by recording the average number of frames per second (FPS) over one minute for a given screen resolution, as well as data resolution. Screen resolution is measured in pixels, while data resolution is measured in nodes of the tree at the lowest level of the tree. This resolution is given by the formula:

\[
	resolution = 2^{max\_scale~ -~ 1}
\]

Such that data generated down to the 11$^{th}$ level has a resolution of $2^{10} = 1024$ in each dimension. This is also referred to as a resolution of $1024^3$.

Each scene has been tested across various screen resolutions as well as data resolutions in order to demonstrate how the algorithms scale with respect to screen ruesolution and data resolution.

In order to evaluate our renderer's performance we have considered the differences in performance for a sample scene with no shadows, reflection or translucency, as screen resolution and data resolution are varied. We consider this data our control sample, and following samples for rendering with shadows, reflection, and translucency is compared with this control.

We have then evaluated the relationships between screen resolution, data resolution, and performance for these samples, as well as compared the overall performance for these samples against our control to determine the effect on performance of considering these effects.

These tests were conducted on a single Nvidia GTX 670.

\section{Implementation}
Our implementation utilises CUDA for all rendering, bypassing the rasterisation process almost entirely. An OpenGL texture is created at program launch, and this texture is then written to by the rendering kernel using OpenGL-CUDA interoperation.

\subsection{OpenGL-CUDA interop}
OpenGL-CUDA interop is accomplished using a pixel buffer object (PBO) that is shared between CUDA and OpenGL. A PBO is stored in GPU memory, eliminating unnecessary copying to main CPU memory. When required by CUDA, the PBO is mapped to a device pointer accessible by cuda, and must be unmapped before it can be accessed again by OpenGL. The PBO can then be unpacked into an OpenGL texture directly, allowing the CUDA-generated buffer to be written to the screen.

A code listing demonstrating how a PBO and a texture are created, and how this PBO is registered with CUDA is available below in code listing \ref{texturecreation}. A code listing for The gpuErrChk macro's code listing is available in appendix \ref{app:cuda-utils}. Once the PBO is created, it can be mapped to a device pointer as shown in code listing \ref{map-buffer}. Once unmapped, its contents can then be unpacked to a texture for display on the screen as demonstrated in \ref{pbo-unpack}. As all of these operations occur directly within GPU memory, unnecessary coping to main memory is avoided.

\subsection{Matrix maths}
Matrix maths is accomplished using GLM, the OpenGL Mathematics library. This is a C++ library which implements all of the features of GLSL and includes CUDA support, making it suitable for writing 3D rendering code and shaders in CUDA.

\newpage
\lstset{language=C,caption={Creation of the OpenGL PBO and texturre},label=texturecreation}
\begin{lstlisting}[frame=single]
void* glFb;

GLuint pbo;
GLuint texid;

// Create pixel buffer object
glGenBuffers(1, &fbo);

// Create buffer texture
glGenTextures(1, &texid);

// Initilaise pixel buffer object with size
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER,
	viewport.w * viewport.h * 4 * sizeof(GLubyte),
	nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

// Initialise texture with width, height, and format
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
				GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);

// Register pixel buffer object with cuda
gpuErrchk(cudaGraphicsGLRegisterBuffer(&glFb, pbo,
			cudaGraphicsRegisterFlagsNone));
\end{lstlisting}

\newpage
\lstset{language=C,caption={Binding the PBO so that CUDA kernels can access it},label=map-buffer}
\begin{lstlisting}[frame=single]

// Bind cuda graphics resources
gpuErrchk(cudaGraphicsMapResources(1, &glFb, 0));

// Get a device pointer to it
gpuErrchk(cudaGraphicsResourceGetMappedPointer(&ptr, &size,
												glFb));

// Pass device pointer to CUDA kernel

// Unmap pbo
gpuErrchk(cudaGraphicsUnmapResources(1, &glFb, 0));
\end{lstlisting}

\lstset{language=C,caption={Unpacking of a PBO to an OpenGL texture},label=pbo-unpack}
\begin{lstlisting}[frame=single]
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBindTexture(GL_TEXTURE_2D, texid);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
				GL_RGBA, GL_UNSIGNED_BYTE, 0);
\end{lstlisting}


\section{Literature review on the importance of roll damping}

\subsection{Parametric roll}

\emph{"Parametric roll (a shortening of the formal term "parametric roll resonance") is a dynamic stability phenomena in which an amplification of roll motion is caused by periodic variation of transverse stability in waves. The phenomenon of parametric roll is predominantly observed in head, following, bow and stern-quartering seas when the ship's encounter frequency is approximately twice that of the ship's roll natural frequency and the ship's roll damping is insufficient to dissipate additional energy (accumulated because of parametric resonance)."} \parencite{imo_second_nodate}

\subsection{Influence of roll damping}
\subsubsection{}
\emph{"When a ship rolls in calm water after being disturbed, the roll amplitudes decrease successively due to roll damping, see figure 4. A rolling ship generates waves and eddies, and experiences viscous drag. All of these processes contribute to roll damping. Roll damping may play a critical role in the development of parametric roll resonance. \textbf{If the "loss" of energy per cycle caused by damping is more than the energy "gain" caused by the changing stability in longitudinal seas, the roll angles will not increase and the parametric resonance will not develop.} Once the energy "gain" per cycle is more than the energy "loss" due to damping, the amplitude of the parametric roll starts to grow."} \parencite{imo_second_nodate}

\subsubsection{}
\emph{"An accurate description of the roll damping is crucial for prediction of critical roll responses such as parametric roll. Sufficient damping can be the difference between a severe roll response and a hardly noticeable response."} \parencite{soder_ikeda_2019}


\chapter{Chapter with equations}
\label{chap:chapter_1}

This is the first equation:
\begin{equation}
  1 + 1 = 2.
  \label{eq:1}
\end{equation}

\noindent
This is the second equation:
\begin{equation}
  1 \times 1 = 1.
  \label{eq:2}
\end{equation}


\section{Evaluation}

To measure the effect of FST and CYK filtering methods on the speed,
sensitivity and specificity of RNA similarity searches, we used an
improved version of our internal \textsc{Rfam}-based benchmark
\citep{Nawrocki09,NawrockiEddy07}.  Briefly, this benchmark was
constructed as follows. The sequences of the seed alignments of 503
\textsc{Rfam} (release 7) families were single linkage clustered by
pairwise sequence identity, and separated into two clusters such that
no sequence in one cluster is more than 60\% identical to any sequence
in the other. The larger of the two clusters was assigned as the query
(preserving their original \textsc{Rfam} alignment and structure
annotation), and the sequences in the smaller cluster were assigned as
true positives in a test set. We required a minimum of five sequences
in the query alignment. 51 \textsc{Rfam} families met these criteria,
yielding 450 test sequences which were embedded at random positions in
a 10 Mb ``pseudogenome''.  Previously we generated the pseudogenome
sequence from a uniform residue frequency distribution
\citep{NawrockiEddy07}.  Because base composition biases in the target
sequence database cause the most serious problems in separating
significant CM hits from noise, we generated a more realistic
pseudogenome sequence using a 15-state fully connected hidden Markov
model (HMM) trained by Baum-Welch expectation maximization
\citep{Durbin98} on genome sequence data from a wide variety of
species.  Each of the 51 query alignments was used to build a CM and
search the pseudogenome in local mode, a single list of all hits for
all families were collected and ranked, and true and false hits were
defined (as described in \citet{NawrockiEddy07}).

The minimum error rate (MER) (``equivalence score'') \cite{Pearson95}
was used as a measure of benchmark performance. The MER score is
defined as the minimum sum of the false positives (negative hits above
the threshold) and false negatives (true test sequences which have no
positive hit above the threshold), at all possible choices of score
threshold in the ranked list of all hits from the 51 searches. The MER
score is a combined measure of sensitivity and specificity, where a
lower MER score is better.  We calculate two kinds of MER scores. For
a \emph{family-specific} MER score, we choose a different optimal
threshold in each of the 51 ranked lists, and for a \emph{summary} MER
score, we choose a single optimal threshold in the master list of all
hits.  The summary MER score reflects the performance level for a
large scale analysis of many families because it demands a single
query-independent E-value reporting threshold for significance.  The
family-specific MER score indicates the performance that could be
achieved with manual inspection and curation of the hits in each
family to determine family specific E-value thresholds.

Using this benchmark, we addressed several questions about the
performance of FST calibrated HMM filtering and CYK filters.

First, we had to determine the most sensitive CM search strategy
irrespective of speed so that we had a best-case performance against
which to judge the filtered searches. We tested the Inside and CYK
algorithms, both with and without query-dependent bands (QDBs). For
the banded runs we used a $\beta=10^{-15}$ tail loss probability for
QDB calculation that previous work has indicated sacrifices
essentially zero sensitivity \citep{NawrockiEddy07}.  As shown in
Table~\ref{Tab:merlist}, using the banded Inside algorithm resulted in
the lowest summary and family specific MER of the four methods tested
(rows 1-4 in Table~\ref{Tab:merlist}). Interestingly, banded Inside
outperforms non-banded Inside (row 1 in Table~\ref{Tab:01}); this is
because enforcement of the bands eliminates about a dozen high scoring
alse positive hits that drive up the MERs.  This result led us to use
banded Inside with $\beta=10^{-15}$ as the final (post-filtering) search
strategy when benchmarking filtered search strategies.

Next, we addressed FST parameterization.  What is the best value to
use for the $F$ parameter, which specifies the fraction of sequences
allowed below the filter score threshold? The black solid points in
Figure~\ref{Fig:mervtime} shows the benchmark running time of FST
calibrated HMM filtered searches versus MER for different values of
$F$. The choice of $F$ is a tradeoff of accuracy for speed.
%Because maintaining sensitivity is our primary concern
We chose a default of $F=0.993$ as a reasonable value that obtains a
speedup of about 25-fold with a minimal loss of accuracy
(Figure~\ref{Fig:mervtime} and Table~\ref{Tab:merlist}, row 3 compared
to 13).

What is the best value to use for the $S_{min}$ parameter, which
specifies the minimum target survival fraction $S$ during filter
thresholding? Table~\ref{Tab:merlist} shows benchmark results for FST
HMM filtering with $F=0.993$ and three different $S_{min}$ values
(rows 14-16). We choose to set the default $S_{min}=0.02$ because it
gives a slightly lower MER than not enforcing an $S_{min}$ (row 10) at
about a 10\% cost in running time. The effect of $S_{min}=0.02$ can be
seen in more detail in Tables~\ref{Tab:survcat} and \ref{Tab:evaries}.
Table~\ref{Tab:survcat} shows that although enforcing $S_{min}$
significantly reduces the speedup for families in which the FST
determined $S$ is less than $0.02$, it has a small overall effect on
the total speedup.  Table~\ref{Tab:evaries} compares the speedup and
filter sensitivity of using no $S_{min}$ and using $S_{min}=0.02$ for
different final reporting thresholds, showing that although the time
cost of enforcing $S_{min}=0.02$ increases as the final threshold
becomes more strict, the boost to sensitivity also increases.

How much does FST calibrated HMM filtering impact sensitivity and
specificity?  Tables~\ref{Tab:merlist}, \ref{Tab:survcat} and
\ref{Tab:evaries} demonstrate FST's impact on benchmark performance.
Table~\ref{Tab:survcat} shows that the actual sensitivity (actual $F$)
achieved by the filter on our benchmark is $0.924$. The summary and
family MER for an HMM filtered search using $F=0.993$ and
$S_{min}=0.02$ are $144$ and $134$ (Table~\ref{Tab:merlist} row 10
down from $130$ and $109$ for a non-filtered search (row 3).

How does using FST to determine filter thresholds compare to using a
single target survival fraction $S$ as a thresholding method?
Figure~\ref{Fig:mervtime} plots benchmark summary MER versus running
time for different filtering strategies: FST with various $F$ values
and target $S$ thresholding for various $S$ values. Target $S$
thresholding is faster than FST for achieving MER values down to about
$160$, but FST is faster if lower MERs are desired.
Tables~\ref{Tab:merlist}, \ref{Tab:survcat}, and \ref{Tab:evaries}
also compare FST with target survival fraction target $S$ methods.

\begin{comment}
FST outperforms all possible single predicted survival fraction $S$ thresholds for HMM
filtering. No single threshold yields both faster and more sensitive
benchmark results than does FST (Figure~\ref{Fig:03}). The target $S$ cutoff
that most closely mirrors FST is X. Figure Z also shows the
performance of a HMM filtered run that uses thresholds that give
predicted survival fractions of 0.01 (``S=0.01'' point); which is also
very close to FST. Using an HMM threshold that yields a survival
fraction of $0.01$ was put forth by \citet{WeinbergRuzzo06} as a good
compromise between speed and sensitivity and our results support their
findings when a single threshold is used.

It is only possible for FST to outperform all single E-value
thresholds because it sets HMM thresholds in a model-specific manner.
FST determines that an HMM filter is very effective for some models
and sets those thresholds high, and for models where an HMM filter is
less effective, the threshold must be set lower to achieve the target
sensitivity. Table X breaks down the 51 benchmark families into groups
based on the predicted survival fraction from an FST calibrated HMM
filter with $F=0.99$. The benchmark statistics for each group are compared against
the most closely performing single value HMM filter threshold of X.
In general, FST correctly determines the appropriate HMM filter
threshold per family to maintain sensitivity while maximizing
acceleration.
\end{comment}

Is FST robust to a wide range of final E-value thresholds? With FST,
the filter threshold increases as the final threshold increases
(becomes more strict), increasing the filter's efficiency while
theoretically maintaining the same level of sensitivity,
$F$. Table~\ref{Tab:evaries} shows the effect of varying the final
E-value threshold on the sensitivity and speed of FST calibrated HMM
filters on the benchmark dataset. As E decreases, the sensitivity
remains relatively constant while the speedup increases, until
$E=1e-3$ is reached, at which point sensitivity begins to decrease,
suggesting FST is less reliable for stricter thresholds.  Fortunately,
enforcing $S_{min}=0.02$ corrects this problem. This is because many
FST calibrated thresholds for final thresholds $E<1e-3$ correspond to
$S<0.02$, so enforcing $S_{min}$ lowers the filter threshold and
increases sensitivity.

\begin{comment}
In general, the sensitivity remains
relatively constant as the final threshold and the acceleration due to
the filters increases modestly.
Note that an E-value cutoff of 0.0001
in a 10 Mb database corresponds to the same bit score cutoff as an
E-value cutoff of 1.0 in a 100 Gb database. Because FST calibrated
filter thresholds depend only on the final bit score cutoff, identical
(theoretical) acceleration due to filtering would occur in both of
these searches.
\end{comment}

What impact does the QDB CYK filtering approach have on speed,
sensitivity and specificity?  Rows 6-9 of Table~\ref{Tab:merlist} show
benchmark performance using only a CYK filter with QDB and different
tail loss $\beta$ values.  The filter thresholds were determined using
a simple scheme, by setting the filter E-value threshold as 100 times
the final E-value threshold. This thresholding strategy proved
adaquate, using it with a CYK filter with $\beta=10^{-10}$ results in
about a four-fold speedup with a negligible loss in sensitivity
relative to a non-filtered run (row 3).  Further, this strategy yields
significantly better performance than running non-filtered CYK with
identical $\beta=10^{-10}$ (row 5), while only requiring about 10\%
longer to run.  This clearly suggests it is more useful to use QDB CYK
as a filter for Inside than as the final scoring algorithm as we did
previously \citep{NawrockiEddy07}.

Is it useful to combine a FST calibrated HMM filter and a QDB CYK
filter?  As mentioned above, FST calibrated HMM filters with $F=0.993$
and $S_{min} = 0.02$ result in about a 25-fold speedup and QDB CYK
filters with $\beta=10^{-10}$ result in about a four-fold
speedup. Combining these two filtering strategies by running the HMM
first, searching the surviving fraction with QDB CYK, and using Inside
only on the fraction that survives both, results in about a three-fold
speedup relative to only using HMM filters with a negligible loss of
accuracy (compare rows 15 and 18 of Table~\ref{Tab:merlist}.  This
strategy is about 70 times faster than the top performing strategy,
non-filtered Inside search with $\beta=10{^-15}$ at a small cost to
sensitivity. And it is more than 200 times faster than non-banded
Inside, while achieving a lower summary MER. Based on this, we've made
this two filter strategy the default filtering strategy in
\textsc{infernal} version 1.01.

\begin{comment}
\begin{itemize}
\item
Q1: Is FST accurate: is sensitivity near $F$?
\item
A1a: Yes, in that it gives better sensitivity that 0.01.
\item
A1b: ? What fraction of TPs are missed overall, per family?

\item
Q2: Do we gain sensitivity by trusting FST when it tells us NOT to
filter (or to filter permissively)?
\item
A2: ? Look at families where filtering is turned off (or S > X=0.01),
is FST RMARK performance for these families much better than for
RaveNnA or S=0.01 families?

\item
Q3: Do we gain speed by trusting FST when it tells us to filter more
strictly than S=0.01? Do we sacrifice sensitivity in these cases?

\item
A3: ? Look at families where filtering is strict (S < X=0.01),
is FST RMARK performance for these families much worse than for
RaveNnA or S=0.01 families? Are the run times faster?
\end{itemize}
\end{comment}


\chapter{The TIGL Geometry Library}\label{tiglIntro}

\section{What is TIGL}\label{tiglIntro}
In order to perform the modeling of wings and fuselages as well as the computation of surface points effectively, a
geometry library was developed in C++. The library provides external interfaces
for C and FORTRAN. Some of the requirements of the library were:

\begin{itemize}
 \item Ability to read and process the information stored in a CPACS file for
 wings and fuselages,
 \item Possibility to extend to engine pods, landing gear and other
 geometrical characteristics, e.g.,
 \item Ability to build up the three-dimensional airplane geometry for further
 processing,
 \item Ability to compute surface points in cartesian coordinates by using
 parameters such as $\xi$, $\zeta$, $\eta$, segment number,
 \item Possibility to be expanded by additional functions such as area or volume
 computations,
 \item Possibility to export the airplane geometry in the IGES format.
\end{itemize}

The developed library uses the Open Source software OpenCASCADE to represent the airplane geometry by B-spline surfaces
in order to compute surface points and also to export the geometry in the IGES format.
OpenCASCADE is a development platform written in C++ for CAD, CAM, and CAE
applications which has been continuously developed for more than ten years.
The functionality covers geometrical primitives (for example points,
vectors, matrix operations), the computation of B-spline surfaces and boolean operations on volume models.

Apart from the already specified requirements above, the geometry library
offers query functions for the geometry structure. These functions can be used
for example to detect how many segments are attached to a certain segment,
which indices these segments have, or how many wings and fuselages the current
airplane configuration contains. This functionality is necessary because not
only the modeling of simple wings or fuselages but also the description of quite complicated
structures with branches or flaps is targeted.

\section{TIGLViewer}
In order to review the geometry information of the central data set a visualization
tool, TIGLViewer, was developed. The TIGLViewer allows the visualization of the used airfoils and
fuselage profiles as well as of the surfaces and the entire airplane model.
Furthermore, the TIGLViewer can be used to validate and test the implemented
functions of the geometry library, for example the calculation of points on the
surface or other functions to check data that belong to the geometry structure.


\documentclass[superscriptaddress,pra,nofootinbib,notitlepage, floatfix]{revtex4-1}
\usepackage{amssymb}
\usepackage{dsfont}
\usepackage{complexity}
\usepackage[utf8]{inputenc} % allow utf-8 input
\usepackage[T1]{fontenc}    % use 8-bit T1 fonts
\usepackage{hyperref}       % hyperlinks
\usepackage{url}            % simple URL typesetting
\usepackage{booktabs}       % professional-quality tables
\usepackage{amsfonts}       % blackboard math symbols
\usepackage{nicefrac}       % compact symbols for 1/2, etc.
\usepackage{microtype}      % microtypography
\usepackage{lipsum}
\usepackage{amsmath}
\usepackage{physics}
\usepackage{placeins}
%\newcommand{\ketbra}[2]{\ket{#1}\!\bra{#2}}
\usepackage{bbold}
\usepackage{tikz}
\usepackage{forest}
\usepackage{multirow}
\usetikzlibrary{calc,arrows.meta,positioning, shapes.geometric, arrows, shapes.symbols,shapes.callouts,patterns}

\tikzset{
    every node/.style={font=\sffamily\small},
    main node/.style={thick,circle ,draw},
    visible node/.style={thick,rectangle ,draw}
}
%\usepackage[dvipsnames]{xcolor}
% \usepackage{subfig}
%\usepackage{subcaption}
\usepackage{qcircuit}
\usepackage{graphicx}
\usepackage{graphics}
\usepackage{amsthm}
%\usepackage{subcaption}
\usepackage[caption=false]{subfig}
\usepackage{latexsym}
\usepackage{floatrow}
\usepackage{mathtools}
\usepackage{verbatim}
\usepackage{upgreek}
\usepackage{textgreek}
\usepackage{thmtools}
\usepackage{thm-restate}

\usepackage{hyperref}

\usepackage{cleveref}

\newtheorem{theorem}{Theorem}
\newtheorem{corollary}[theorem]{Corollary}
\newtheorem{proposition}[theorem]{Proposition}
\newtheorem{lemma}[theorem]{Lemma}
\newcommand{\vect}[1]{\boldsymbol{#1}}
\DeclareMathOperator{\EX}{\mathbb{E}}
\newcommand{\Var}{\mathrm{Var}}
\declaretheorem[name=Lemma,numberwithin=section]{lm}

\begin{document}

\title{Qubit Complexity Notes}

\date{\today}

\maketitle

\section{Automatic Computation of the Metric Tensor and Christoffel Symbols}

In order to determine the complexity of some unitary $U$, denoted $C[U]$, we must determine the length of the geodesic extending from $I$ to $U$ with respect to some metric on the space of unitaries.
In general, a metric on the space of unitaries is given by:

\begin{equation}
  ds^2 = \text{Tr}(i dU U^{\dagger} T_I) \mathcal{I}_{IJ} \text{Tr}(i dU U^{\dagger} T_J)
\end{equation}

where the $T_I$ are the generators of $SU(2^{N})$, for some $N$-qubit system. Given some parametrized unitary $U(\boldsymbol{\theta})$, we can write this metric explicity in terms of derivatives with respect to the parameters, as
$dU = \partial_{\boldsymbol{\theta}} U \ d\boldsymbol{\theta}$.
\newline

The case considered in the paper [CITE] considers a two-qubit system, with a parametrization as follows:

\begin{equation}
U(\boldsymbol{\theta}) = \exp( -i H(\boldsymbol\theta)) = \exp \left( -i [ \theta_x X + \theta_y Y + \theta_z Z ] \right)
\end{equation}

\bibliographystyle{unsrt}
\bibliography{ref}

\end{document}


%!TEX root = ../tikz-figures.tex

\section*{Trees}

\begin{equation*}
	\index{foreach}
	\index{foreach!backwards}
	\index{variable!pgfmathsetmacro}
	\index{variable!from expression}
	\index{variable!pgfmathparse}
	\index{clip}
	\index{path!curved}
	\index{node on path!fraction position}
	\index{math functions!mod}
	\begin{tikzpicture}
		\pgfmathsetmacro{\qpoints}{4}; % Number of q_n's to draw
		\pgfmathsetmacro{\qlabels}{2}; % Number of q_n's to label
		\begin{scope}
			\coordinate (x) at (0,0);
			\clip ($(x)+(135:7)$) rectangle ($(x)+(5,0)$);
			\fill[lightgray] (x) -- ($(x)+(135:3)$) .. controls +(1,1) and +(-1,-0.5) .. ($(x)+(45:3)$) -- (x);
			\draw (x) edge +(135:7) edge +(45:7);
			\draw ($(x)+(135:3)$) .. controls +(1,1) and +(-1,-0.5) .. ($(x)+(45:3)$)
				coordinate[pos=0.2] (q)
				coordinate[pos=0.8] (qinf);
			\draw (x) edge (q) edge (qinf);
			\fill[lightgray!50!white] (q) -- +(110:4) -- +(70:4) --cycle;
			\node[point] at (q) [label=below left:$q$] {};
			\draw (q) edge +(110:4) edge +(70:4);
			\draw[dotted] (qinf) edge +(110:4) edge +(70:4);
			\foreach \n in {0, ...,\qpoints}
			{
				\coordinate (q\n) at ($(qinf) + (0,{2/(2^\n)})$) {};
			}
			\foreach \n in {0, ...,\qpoints}
			{
				\pgfmathsetmacro{\m}{\qpoints-\n}
				\pgfmathparse{100/(mod(\m,2)+1)}
				\fill[lightgray!\pgfmathresult!white] (q\m) -- +(110:4) -- +(70:4) --cycle;
				\draw (q\m) edge +(110:4) edge +(70:4);
				\node[point] at (q\m) {};
			}
			% \draw (qinf) -- (q0);
			\draw node at ($(x) + (3,1)$) {$\us x^{\mathrm{NonPara}(X)}$} edge[->] ($(x) + (0,1.5)$);
		\end{scope}
		\foreach \n in {0,...,\qlabels}
		{
			\draw node at ($(qinf) + (0,{2/(2^\n)}) + (1.5,1)$) {$q_\n$} edge[->] (q\n);
		}
		\node[point] at (x) [label=right:$x$] {};
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{path!curved}
	\index{node on path}
	\index{function plot}
	\index{transformation!slant}
	\begin{tikzpicture}
		\begin{scope}
			\filldraw[lightgray] (0,0) node[point] {} -- (-2,4) -- (0,4) --cycle;
			\draw[dotted] (0,0) -- (-2,4);
			\draw[dotted] (0,0) -- (2,4);
			\draw (0,3) node (Ca) {} -- (1.5,4) node (Cb) {};
			\draw[decoration={calligraphic brace,amplitude=5pt}, decorate, line width=1.25pt]
				($(Cb) + (0.1,-0.1)$) -- node[below right] {$C$} ($(Ca) + (0.1,-0.1)$);
			\node at (-0.75,3) {$\dom(\ell)$};
		\end{scope}
		\begin{scope}[xshift=-120, yshift=-110, scale=1.5]
			\draw[->] (0,0) -- node[left] {$f$} (0,2);
			\draw (0,0) node (a1a) {} -- (2,0) node (a1b) {};
			\draw[decoration={calligraphic brace,amplitude=5pt}, decorate, line width=1.25pt]
				($(a1b) + (0,-0.1)$) -- node[yshift=-12] {$C$} ($(a1a) + (0,-0.1)$);
			\begin{scope}
				\draw (0,0) node (l1a) {} .. controls +(0.2,0) and (0.3,0.2) .. (0.5,0.2) node (l1b) {};
			\end{scope}
			\begin{scope}[yshift=10]
				\draw (0.5,0.2) node (l1c) {} .. controls +(0.3,0) .. (1,0.3) node (l1d) {};
			\end{scope}
			\begin{scope}[yshift=15]
				\draw (1,0.3) node (l1e) {} .. controls +(0,0.3) .. (1.5,0.6) node (l1f) {};
			\end{scope}
			\begin{scope}[yshift=30]
				\draw (1.5,0.6) node (l1g) {} -- (2,0.8) node (l1h) {};
			\end{scope}
			\begin{scope}[every path/.style={lightgray, dotted}]
				\draw (l1b) -- (l1c);
				\draw (l1d) -- (l1e);
				\draw (l1f) -- (l1g);
			\end{scope}
		\end{scope}
		\begin{scope}[xshift=40, yshift=-110, scale=1.5]
			\draw[->] (0,0) -- node[left] {$\wh \ell$} (0,2);
			\draw (0,0) node (a2a) {} -- (2,0) node (a2b) {};
			\draw[decoration={calligraphic brace,amplitude=5pt}, decorate, line width=1.25pt]
				($(a2b) + (0,-0.1)$) -- node[yshift=-12] {$C$} ($(a2a) + (0,-0.1)$);
			\begin{scope}[yslant=0.35]
				\draw (0,0) node (l1a) {} .. controls +(0.2,0) and (0.3,0.2) .. (0.5,0.2) node (l1b) {};
				\draw (0.5,0.2) node (l1c) {} .. controls +(0.3,0) .. (1,0.3) node (l1d) {};
				\draw (1,0.3) node (l1e) {} .. controls +(0,0.3) .. (1.5,0.6) node (l1f) {};
				\draw (1.5,0.6) node (l1g) {} -- (2,0.8) node (l1g) {};
			\end{scope}
		\end{scope}
		\begin{scope}[xshift=0, yshift=-110, scale=1.5]
			\draw[->] (-0.4,0.8) -- (0.4,0.8);
		\end{scope}
		% \begin{scope}[every path/.style={dashed}]
		% 	\draw (Ca) -- (a1a);
		% 	\draw (Cb) -- (a1b);
		% 	\draw (Ca) -- (a2a);
		% 	\draw (Cb) -- (a2b);
		% \end{scope}
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{path!partly rounded}
	\index{array!two-dimensional}
	\index{foreach}
	\index{variable!pgfmathsetmacro}
	\index{arrows!bar}
	\begin{tikzpicture}
		\def\twigs{{{0.0,0.1},{0.1,0.1},{0.3,0.15},{0.4,0.2},{0.5,0.3},{0.6,0.3},{0.7,0.4},{0.8,0.45}, {1.0,0.55},{1.2,0.6},{1.3,0.6},{1.5,0.7},{1.6,0.7},{1.7,0.75},{1.8,0.8},{1.9,0.8},{2.0,0.9}}}
		% \def\twigs
		\pgfmathsetmacro{\twigmax}{16}
		\coordinate (p) at (0,0);
		\begin{scope}[xscale=2, yscale=1, xshift=-30, yshift=100]
			\filldraw[lightgray] (p) {[rounded corners=15] -- (0.8,0.5) -- (2.3,0.5)} -- cycle;
			\foreach \i in {0,...,\twigmax}
			{
				\draw (\twigs[\i][0],0) node[point] (a\i) {} -- (\twigs[\i][0],\twigs[\i][1]);
			}
			\draw[dashed] (-0.2,0.5) -- (2.2,0.5);
			\draw[Bar-Bar] (2.4,0) --node[right] {$2\ep$} (2.4,0.5) ;
			\draw[brace]
				(2,-0.2) -- node[yshift=-10] {$A^*$} (1,-0.2);
			\draw[brace]
				(2,-0.8) -- node[yshift=-10] {$A$} (0,-0.8);
		\end{scope}
		\node[point] at (p) {};
		\draw[dotted] (p) edge (-4,4) edge (4,4);
		\node at (0.4,1.5) {$Y^*$};
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{arrows!bar}
	\begin{tikzpicture}
		\begin{scope}[every node/.style={point}]
			\node (p) at (0,0) [label=below:$p$] {};
			\node (m) at (0,2) {};
			\node (x) at (-2,4) [label=right:$x$] {};
			\node (y) at (2,4) [label=left:$y$] {};
		\end{scope}
		\node (ml) at ($(m) + (1.5,-0.3)$) {$x \wedge y$};
		\draw[->] (ml)  -- (m);
		\draw (p) -- (m) -- (x);
		\draw (m) -- (y);
		\begin{scope}[every path/.style={blue,{Bar-Bar}}]
			\draw ($(p)+(-0.6,0)$) -- node[left] {$\ell(x \wedge y)$} ($(m)+(-0.6,0)$);
			\draw ($(p)+(-0.2,0)$) -- ($(m)+(-0.185,-0.077)$) -- node[below left] {$\ell(x)$} ($(x)+(-0.141,-0.141)$);
			\draw ($(p)+(0.2,0)$) -- ($(m)+(0.185,-0.077)$) -- node[below right] {$\ell(y)$} ($(y)+(0.141,-0.141)$);
			% \draw ($(p)+(-0.2,0)$) -- ($(m)+(-0.2,0)$) -- node[right left] {$\ell(x)$} ($(x)+(-0.141,-0.141)$);
		\end{scope}
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{variable!tikzmath}
	\index{foreach!tikzmath}
	\index{math library}
	\index{library!math|see {math library}}
	\index{every!node}
	\index{every!path}
	\begin{tikzpicture}[xscale=2, yscale=1.5]
		\begin{scope}[every node/.style={point},every path/.style={thick}]
			\node (o0) at (0,0) {};
			\node (n0) at (-1,1) {};
			\node (n000) at (-1.833,1.833) {};
			\node (n01) at (-0.5,1.5) {};
			\node (n010) at (-0.833,1.833) {};
			\node (n011) at (-0.167,1.833) {};
			\draw[blue] (o0) -- (n0) -- (n000);
			\draw[red] (n0) -- (n01) -- (n011);
			\draw[blue] (n01) -- (n010);
			\begin{scope}[xshift=40]
				\tikzmath{
					coordinate \p;
					\omegapoints = 10;
					\p = (1,1);
					\colour = 0;
					\t = 1;
					int \n; % Need this otherwise nodes get named like o1.0, while '\draw (o\n)' evaluates like '\draw (o1)', for some stupid reason.
					for \n in {1,...,\omegapoints}{
						{
							\node (o\n) at (\p) {};
						};
						int \prev;
						\prev = \n - 1;
						if \colour==0 then {
							\colour = 1;
							\p = (\p) + ({-1/(\n+1)},{1/(\n+1)});
							{
								\draw[red] (o\prev) -- (o\n);
							};
						} else {
							\colour = 0;
							\p = (\p) + ({1/(\n+1)},{1/(\n+1)});
							{
								\draw[blue] (o\prev) -- (o\n);
							};
						};
					};
				}
				\coordinate (top) at (0.693,3.1);
			\end{scope}
			\node (ninf) at ($(top) + (0,0.4)$) {};
			\node (ninf0) at ($(top) + (-0.4,0.8)$) {};
			\node (ninf1) at ($(top) + (0.4,0.8)$) {};
			\draw[blue] (ninf) -- (ninf0);
			\draw[red] (ninf) -- (ninf1);
		\end{scope}
		\node at ($(top) + (0,0.2)$) {$\vdots$};
		\node [below=1pt of o0] {$()$};
		\node [left=1pt of n0] {$((0,1))$};
		\node [left=1pt of n000] {$((0,3))$};
		\node [right=1pt of n01] {$((0,1),(1,1))$};
		\node [right=1pt of n011] {$((0,1),(1,2))$};
		\node [above=1pt of n010] {$((0,1),(1,1),(0,1))$};
		% \node at ($(n010) + (-0.5,1)$) {$((0,1),(1,1),(0,1))$};
		\node [right=1pt of o1] {$((1,1))$};
		\node [left=1pt of o2] {$((1,1),(0,1))$};
		\node [right=1pt of ninf] {$((1,1), (0,1), \ldots)$};
		\node [left=1pt of ninf0] {$((1,1), (0,1), \ldots,(1,1))$};
		\node [above=1pt of ninf1] {$((1,1), (0,1), \ldots,(0,1))$};
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{node shaped as coordinate}
	\index{decorations library!coloured}
	\begin{tikzpicture}
		\coordinate	(p) at (0,0);
		\coordinate	(b) at (1,3);
		\coordinate	(t) at (2,6);
		\draw[blue] (p) --
			node[shape=coordinate,pos=0.1] (a0) {}
			node[shape=coordinate,pos=0.3] (a1) {}
			node[shape=coordinate,pos=0.6] (a2) {}
			node[shape=coordinate,pos=0.7] (a3) {}
			node[shape=coordinate,pos=0.9] (a4) {}
			node[shape=coordinate,pos=1.0] (a5) {}
			(b);
		\begin{scope}
			\clip (-2,6) rectangle (1,0);
			\foreach \n in {0,...,5}
			{
				\draw[gray] (a\n) -- ($(a\n)+(-2,6)$);
			}
		\end{scope}
		\draw[blue] (b) -- (t);
		\node at (2,6.5) {$B_\alpha$};

		\draw[->] (3,3) -- node[midway, above] {$r_\alpha$} (5,3);

		\draw[{Bar-Bar}] (7,0) -- (7,6);
		\node at (7,6.5) {$\Q \cap [0,1]$};

		\path (7,0) --
			node[point,pos=0.2] (x0) {}
			node[point,pos=0.25] {}
			node[point,pos=0.4] {}
			node[point,pos=0.55] {}
			node[point,pos=0.6] {}
			node[point,pos=0.65] {}
			node[point,pos=0.8] {}
			node[point,pos=0.9] (x1) {}
			(7,6);

		\draw[brace] ($(x1) + (0.5,0)$) -- node[midway, xshift=35] {$\{q_0, \ldots, q_n\}$} ($(x0) + (0.5,0)$);

		\draw[thick, red] (b) -- (t);
		\draw[brace, pen colour={red}] ($(t)+(0.5,0)$) -- node[midway, xshift=40, yshift=-4, red] {$B_\alpha \setminus \bigcup_{\beta<\alpha}B_\beta$} ($(b)+(0.5,0)$);

		\path (b) --
			node[point,pos=0.1] {}
			node[point,pos=0.2] {}
			node[point,pos=0.3] {}
			node[point,pos=0.6] {}
			node[point,pos=0.8] {}
			(t);
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{array!listofitems}
	\index{package!pgfplots|see pgfplots}
	\index{package!listofitems|see array!listofitems}
	\index{foreach!tikzmath}
	\index{variable!tikzmath}
	\index{math library}
	\index{pgfplots}
	\index{pgfplots!colormap}
	\index{if statement!tikzmath}
	\index{limit visualisation}
	\begin{tikzpicture}
		\setsepchar{:/;/,}
		\readlist\branches{0,red;20,blue;15,red;30,blue;10,blue:0,blue;15,red;20,blue;15,red;15,red}
		\edef\brancheslen{\listlen\branches[1]}
		\pgfplotsset{colormap={redblue}{color=(blue) color=(red)}}
		\newcommand{\drawbranch}[6]{ % x, y, direction, size, colour, nodename
			\begin{scope}[xshift=#1,yshift=#2,xscale=#3]
				\begin{axis}[
					hide axis,
					point meta rel=per plot,
					width=#4,
					height=#4,
					colormap name=redblue,
					clip=false,
					xmin=0,
					ymin=0,
					anchor=south west
				]
					\addplot[
						mesh,
						mark=none,
						point meta={sin(1000/x))>0 ? 1 : 0},
						colormap access=piecewise constant,
						samples=200,
						domain=0.00001:5,
						ultra thick
					]
						{x};
					\node[point,minimum size=4,#5] at (0,0) (#6) {};
				\end{axis}
			\end{scope}
		}
		\drawbranch{0}{0}{-1}{100}{blue}{c0}
		\drawbranch{-30}{30}{1}{198}{blue}{c1}
		\drawbranch{0}{60}{-1}{165}{red}{c2}
		% \drawbranch{10}{70}{1}{100}{blue}{c3}
		\tikzmath{
			real \x, \y;
			int \dir;
			int \branch;
			for \branch in {1,2}{
				if \branch==1 then {
					\x = -60;
					\dir = -1;
				} else {
					\x = 60;
					\dir = 1;
				};
				\y = 120;
				int \i;
				for \i in {1,...,\brancheslen}{
					\x = \x + \branches[\branch,\i,1]*\dir;
					\y = \y + \branches[\branch,\i,1];
					\dir = 0 - \dir;
					let \col = \branches[\branch,\i,2];
					{\drawbranch{\x}{\y}{\dir}{80}{\col}{b{\branch}n{\i}}};
				};
			};
		}
		\node[xshift=-35,yshift=230] {$\vdots$};
		\node[xshift=65,yshift=220] {$\vdots$};
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{foreach}
	\index{variable!pgfmathsetmacro}
	\index{limit visualisation}
	\index{brace!with label}
	\begin{tikzpicture}
		\pgfmathsetmacro{\xpoints}{8}; % Number of x_n's to draw
		\coordinate (r) at (0,0);
		\coordinate (t1) at (-2,4);
		\coordinate (t2) at (2,4);
		\draw[thick,red] (r) -- (t2);
		\foreach \n in {0, ...,\xpoints}
		{
			\coordinate (x\n) at ($(r) + {0.75/(2^\n)}*(t2)$) {};
			\draw[thick,red] (x\n) -- ($(x\n) + (2,1)$);
			% \coordinate (x\n) at ($(r) + (t1)$);
			% \coordinate (x) at ($(r) + 4*(t1)$);
		}
		\draw[thick,blue] (r) -- (t1);
		\node[point,blue] at (r) {};
		\draw[brace] ($(t1) + (-0.75,0.25)$) -- node[above=6pt,red] {Eloïse wins} ($(t1) + (0.75,0.25)$);
		\draw[brace] ($(t2) + (-0.5,0.25)$) -- node[above=6pt,blue] {Abelard wins} ($(t2) + (2,0.25)$);
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{brace!with label}
	\index{clip!cut away}
	\index{cut away|see {clip!cut away}}
	\begin{tikzpicture}
		\begin{scope}[xscale=0.9]
			\fill[lightgray] (-4,3) -- (0,0) -- (-2,3);
			\draw (1,-1) -- (-3,3) node [above] {$\rho(x_0)$};
			\fill[lightgray] (-1.5,3) -- (0,0) -- (1.5,3);
			\draw (0,0) -- (0,3) node [above] {$\rho(x_0) + 1$} node (t1) {};

			\begin{scope}
				\clip[decoration={zigzag, amplitude=1pt, segment length=10pt}, decorate] (0,-1) -- (2,0) -- (0,3) -- (-1,0) -- (0,-1);
				\fill[lightgray] (2,3) -- (0,0) -- (4,3);
				\draw (0,0) -- (3,3);
				\fill[lightgray] (4.5,3) -- (0,0) -- (6.5,3);
				\draw (0,0) -- (5.5,3);
			\end{scope}
			\node at (1.8,1.3) {$\cdots$};

			\draw[very thick,{-|}] (0,0) -- node[pos=1,right=2pt] {$I$} node[pos=0.6] (x1) {} ($0.8*(t1)$);
			\node[point,red] at (x1) [label=left:$x_1$] {};

			\draw[brace] (-1.5,3.7) -- node[above=4pt] {$C$} (1.5,3.7);

			\node[point] at (0,0) [label=below left:$x_0$] {};
		\end{scope}
		\begin{scope}[xscale=0.9, xshift=200]
			\fill[lightgray] (-4,3) -- (0,0) -- (-2,3);
			\draw (1,-1) -- (-3,3) node [above] {$\rho(f(x_0))$};
			\fill[lightgray] (-1.5,3) -- (0,0) -- (1.5,3);
			\draw (0,0) -- (0,3) node [above] {$\rho(f(x_0)) + 1$} node (ft1) {};

			\begin{scope}
				\clip[decoration={zigzag, amplitude=1pt, segment length=10pt}, decorate] (0,-1) -- (2,0) -- (0,3) -- (-1,0) -- (0,-1);
				\fill[lightgray] (2,3) -- (0,0) -- (4,3);
				\draw (0,0) -- (3,3);
				\fill[lightgray] (4.5,3) -- (0,0) -- (6.5,3);
				\draw (0,0) -- (5.5,3);
			\end{scope}
			\node at (1.8,1.3) {$\cdots$};

			\draw[very thick,{-|}] (0,0) -- node[pos=1,right=2pt] {$f(I)$} node[pos=0.9] (fx1) {} ($0.9*(ft1)$);
			\node[point,blue] at (fx1) [label=left:$f(x_1)$] {};

			\draw[brace] (-1.5,3.7) -- node[above=4pt] {$f(C)$} (1.5,3.7);

			\node[point] at (0,0) [label=below left:$f(x_0)$] {};
		\end{scope}
	\end{tikzpicture}
\end{equation*}

\begin{equation*}
	\index{brace!with label}
	\index{calc!projection}
	\begin{tikzpicture}
		\begin{scope}[xscale=0.83]
			\fill[lightgray] (-1.5,3) -- (0,0) -- (-3.5,3);
			\draw (0.875,-1.05) -- (-2.5,3) node [above] {$\alpha_0$};
			\fill[lightgray] (-1,3) -- (0,0) -- (3.25,3);
			\draw (0,0) -- (1.75,3) node [above,xshift=0] {$\alpha_0 + 1$} node (t1) {};

			\path (0,0) -- node[pos=0.6, shape=coordinate] (x1p) {} ($0.8*(t1)$) node (ti) {};

			\fill[lightgray!30!white] ($(0,3)!(x1p)!(6,3) + (-1.5,0)$) -- (x1p) -- ($(0,3)!(x1p)!(6,3) + (-0.5,0)$);
			\draw (x1p) -- node[pos=0.6, shape=coordinate] (x1) {} ($(0,3)!(x1p)!(6,3) + (-1,0)$) node [above] {$\alpha_0 + 2$};
			\node[point] at (x1) [label=left:$x_1$] {};

			\draw[very thick,{-|}] (0,0) -- node[pos=1,right=2pt] {$I$} (ti);
			\node[point] at (x1p) [label=right:$x_1'$] {};

			\draw[brace] (-1,3.7) -- node[above=4pt] {$C$} (3.25,3.7);

			\node[point] at (0,0) [label=below left:$x_0$] {};
		\end{scope}
		\begin{scope}[xscale=0.83, xshift=220]
			\fill[lightgray] (1,3) -- (0,0) -- (-3.25,3);
			\draw (0.6125,-1.05) -- (-1.75,3) node [above, xshift=0] {$\beta_0$} node (ft1) {};
			\fill[lightgray] (1.5,3) -- (0,0) -- (3.5,3);
			\draw (0,0) -- (2.5,3) node [above] {$\beta_0 + 1$};

			\path (0,0) -- node[pos=0.3, shape=coordinate] (fx1p) {} ($0.8*(ft1)$) node (fti) {};

			\fill[lightgray!30!white] ($(0,3)!(fx1p)!(6,3) + (1,0)$) -- (fx1p) -- ($(0,3)!(fx1p)!(6,3) + (0,0)$);
			\draw (fx1p) -- node[pos=0.6, shape=coordinate] (fx1) {} ($(0,3)!(fx1p)!(6,3) + (0.5,0)$) node [above] {$\beta_0 + 1$};
			\node[point] at (fx1) [label=right:$f(x_1)$] {};

			\draw[very thick,{-|}] (0,0) -- node[pos=1,left=2pt] {$f(I)$} (fti);
			\node[point] at (fx1p) [label=left:$f(x_1')$] {};

			\draw[brace] (-3.25,3.7) -- node[above=4pt] {$f(C)$} (1,3.7);

			\node[point] at (0,0) [label=below left:$f(x_0)$] {};
		\end{scope}
	\end{tikzpicture}
\end{equation*}


\documentclass[12pt]{article}

\usepackage{amsmath}
\usepackage{fullpage}

\title{OpenGL Game Programming Notes}
\author{Richard Cole}
\date{}

\begin{document}

\maketitle

\section{Journal}

\subsection{Sat Jul 20 11:01:34 PDT 2013}

I want to learn more about procedural generation of landscape and
voxel models. If we have say 100x100x100 region of voxels that works
out to be 1M voxels. 1000x1000x1000 works out to be 1G of voxels thus
voxels need to be merged into regions.

Perhaps the an easier place to start is with a height map. The first
question is how to render a height map. You can make 4 triangles
around a height map.

Start with a square (0, 0, 256, 256). Randomly assign heights to each
vertex. Add mid points at 4 midpoints at (128+-128, 128+-128). Assign
heights that are a pertabation from the mid point by a random
offset. Continue until width of the square is 1. One needs to ensure
that points are not written to more than once otherwise cliffs arise.

Another idea is to generate random gradients at different frequencies
and to then apply these to the terrain. This seems to be the idea of
perlin noise generators.

\subsection{Sat Jul 20 10:34:06 PDT 2013}

Movement is not smooth basically because movement occurs in the
simulation system and the simulation system is discrete. To smooth out
the movement things can be done with animation type effects. For
movement the user can have a direction and velocity, when rendered we
can take into account the time of the rendering.

This idea is extended to animation transtitions. When transitioning
from one animtation to the next one needs to interpolate between the
last active frame of the previous animation and the current animation.

Thus for a model we really want to know the current animation frame
and the next animation frame to interpolate between the two. The game
is based on a discrete simulation structure. Animations from models
need to be mapped onto ticks. A creature can make one decision per
tick. The players avitar similarly performs at most one action per
tick. The current simulation rate is 10 ms which seems a reasonable
rate at which to modify the avitars behaviour.

Currently loading the game artifacts takes quite a while. This is
actually time spend performing the gson deserialization. Combining the
texture together greatly increased the number of models which can be
rendered at a specific time. I need to move to a model where the scene
graph is loaded in the GPU memory and only small modifications are
made such as updating rotations of model skeletons.

There needs to be more preprocessing of the models to get them into a
format that is suitable for rendering. All textures need to be loaded
ahead of time.

Should add tool selection using the tab key. This will allow more
tools to be added to the game, so for example one can have a tool that
modifies the viewport parameters.

Should add gravity to keep the character grounded. Should also modify
the ground pattern to be a single cube rather than very many small
cubes.

Models are trees. The nodes have lists of translations and rotations
associated with them. A value alpha selects between two elements in
the lists and then interpolation is performed to find the actual
rotations and translation required.

We'd like this to occur on the GPU. For rendering using shaders there
are about 15 arrays that we can use. So for each point we'd like to
pass a single alpha value and then interp the position.

It might be easier to develop this code first in isolation and then
define a translation into the required format.

The question is then how to pass in the rotation and translation
matricies.

\section{Basic Mathematics}

This article is trying to get in place the basic mathematics to
understand how to use OpenGL.

We use row vectors, e.g. $x$, and denote associated column vector
$x\top$. We work in a homoginous coorindate system rather than the
cartesian space.

\[
   x = (x_1,\dots,x_4)
\]

The projection from homoginous coordinates to cartesian space is

\[
   x \mapsto \frac{1}{x_4}(x_1, x_2, x_3)
\]

Direction vectors have unit length. We can direction vectors for the 4
axis. $i_1,\dots,i_3$ for the three major direction. Matricies
are indicated by upper case.

\[
   M = \left ( \begin{array}{ccc}
     m_{1,1} & \dots & m_{4,1}  \\
     \vdots & \dots & \vdots  \\
     m_{4,1} & \dots & m_{4,4}
     \end{array}
   \right )
\]

The camera has a view point defined by a position, $p$,
forward direction $f$ and upward direction $u$. Moving
forward a scalar distance $d$ is

\[
   p = p + df
\]

The sideways direction $s$ is defined as $f \times u$. A translation
matrix for translation in the $x$ direction is

\[
  T(x) = \left (
  \begin{array}{cccc}
     1 & 0 & 0 & x_1      \\
     0 & 1 & 0 & x_2      \\
     0 & 0 & 1 & x_3      \\
     0 & 0 & 0 & 1
  \end{array}
  \right )
\]

Matricies are applied on the left so

\[
  T(x) p^\top = (p_1 + p_4 x_1, p_2 + p_4 x_2, p_3 + p_4 x_3, p_4)
\]

The projection back into 3 space gives

\[
  (p_i / p_4 + p_4 x_i / p_4)_{i} = (p_i/p_4 + x_i)_{i}
\]

The mouse moves in two dimensions $r = (r_1, r_2, 0, 0)$. We translate
these directions to angles $\theta = (\theta_1, \theta_2, \theta_3, 0)$. The
character has a position $p$.

Let $M(\theta, i)$ be a rotation around the axis $i$. The view
transform is then

\[
  T(p) R(\theta_2, s) R(\theta_1, u_1)
\]

where $s = u_2 R(\theta_1, u_1)$.

This is the transform of the eye from it's initial position. For
OpenGL we need the inverse. Transformations and rotations have an easy
inverse you just negate vector or the angle.

\[
   (AB)^{-1} = B^{-1} A^{-1}
\]

Therefore we obtain the

\[
  R(-\theta_1, u_1) R(\theta_2, s) T(-p)
\]

\subsection{Matrices as Vectors}

If we have vectors $v_1, v_2, v_3$ and a matrix $M$. The $v_1 M$ is a
vector composed of the projection of $v_1$ on each column of $M$. If
we take a matrix formed with $V = (v_1^\top, v_2^\top, v_3^\top)^\top$
then $VM$ has in row $i$ $v_iM$.

\subsection{OpenGL Transforms}

The OpenGL modes are MODELVIEW $M$, PROJECTION $P$, TEXTURE $T$, and
COLOR $C$.

\[
  p' = pMP
\]

I don't known when $T$ and $C$ are applied.

If you apply two transformations $M_1$ followed by $M_2$ then OpenGL
applies them in reverse order, e.g.

\[
  p' = M_2 * M_1
\]

\subsection{Rotation Matrix}

Rotation of an angle $theta$ about a vector $x$ is given by:

\[
  S(x) = \left ( \begin{array}{ccc}
     0    & -x_3 & x_2    \\
     x_3  & 0    & -x_1   \\
     -x_2 & x_1  & 0      \\
  \end{array} \right )
\]

and

\[ u_{i,j} = \left \{ \begin{array}{ll}
     1 & \mbox{if}\:\:\: i = j \\
     0 & \mbox{otherwise}\:
   \end{array} \right .
\]

then for $i, j$ in $1 .. 3$

\[
  r_{i,j}(\theta, x) =
    x_i x_j + (u_{i,j} - x_ix_j)\cos \theta + s_{i,j}(x) \sin \theta
\]

and otherwise

\[
  r_{i,j} = u_{i4} u_{j4}
\]

This matrix is applied in the following manner.

\[
  p' = R(\theta, x) p^\top
\]

\end{document}