%!TEX root = ../Main.tex
In this section, the basics of the tight-binding approximation for electron transport will be explained. This motivates the use of numerical routines using NumPy.
\subsection{Ballistic quantum transport}
As graphene is a two dimensional material that consists of carbon atoms arranged in a hexagonal pattern. Features in such a material can approach nano meter and sub nano meter scales. Because of the small scale the electrical properties of the material is vastly different from normal materials. Usually when describing the electrical properties of a material, drift-diffusion current models are used. They describe electric charges per area and current per area. This is usually a good description in systems where electron-electron and electron-atom scattering frequently occurs. The distance an electron travels before such an event is called its \textit{mean free path}. However, in small systems as those of NPG-devices, the mean free path can be longer than the system itself. Experiments have shown that electrons can move ballistically in graphene\cite{mayorov_micrometer-scale_2011,baringhaus_exceptional_2014}, that is, without phonon scattering and even at room temperature. Therefore, we model electron transport in NPG using the \textit{ballistic model}. In this model the electrons move through the material as waves. The fact that the electrons moves as waves will prove important later on because it gives rise to \textit{Quantum Interference} which can be exploited as a tool when engineering graphene-based devices\cite{markussen_relation_2010}. Furthermore the model looks at only one electron at a time in the presence of an electron gas. The ballistic model has been used with big success for regular graphene and it seems that it also gives a good approximation for NPGs.
\subsection{\mathinhead{\pi}{\pi}-orbitals and \mathinhead{\pi}{\pi}-electrons}
When modelling the electron transport in graphene one needs to address the orbital structure of carbon lattices. The orbital structure is exactly what motivate the use of tight-binding approximation and Green's functions. The two concepts of tight-binding approximation and Green's functions will be elaborated further in the coming sections.
In its basic form graphene can be divided into rings of carbon atoms as shown in \cref{ring}. In the (\(x,y\))-plane the carbon atoms are bound in \(sp^2\) orbitals as shown in \cref{sp2}.
\begin{figure}[ht]
	\centering
	\begin{subfigure}[b]{0.3\textwidth}
		\begin{tikzpicture}
			\chemfig{C*6(-C-C-C-C-C-)}
		\end{tikzpicture}
		\caption{Graphene lattices consists of hexagonal arrangements of carbon atoms.}\label{ring}
	\end{subfigure}
	~
	\begin{subfigure}[b]{0.3\textwidth}
		\centering
		\resizebox{\textwidth}{!}{
			\begin{tikzpicture}
				\node (x) at (-1,-3) {x};
				\node (y) at (-2,-2) {y};
				\draw[->] (-2,-3) -- (x);
				\draw[->] (-2,-3) -- (y);
				\satom[name=C, color=blue, pos={(0,0)}]{
					blue/60/north east/2/1,
					blue/180/west/1,
					blue/300/south east/2/1
				}
				\satom[name=C, color=blue, pos={(1,1.4)}]{
					blue/0/east/2/1,
					blue/120/north west/1,
					blue/240/south west/2/1
				}
				\satom[name=C, color=blue, pos={(2.74,1.4)}]{
					blue/60/north east/1,
					blue/180/west/2/1,
					blue/300/south east/2/1
				}
				\satom[name=C, color=blue, pos={(3.74,0)}]{
					blue/0/east/1,
					blue/120/north west/2/1,
					blue/240/south west/2/1
				}
				\satom[name=C, color=blue, pos={(2.74,-1.4)}]{
					blue/60/north east/2/1,
					blue/180/west/2/1,
					blue/300/south east/1
				}
				\satom[name=C, color=blue, pos={(1,-1.4)}]{
					blue/0/east/2/1,
					blue/120/north west/2/1,
					blue/240/south west/1
				}
			\end{tikzpicture}}
		\caption{Carbon atoms in a hexagonal lattice are \(sp^2\) hybridised in the (\(x,y\))-plane.}\label{sp2}
	\end{subfigure}
	\caption{Benzene ring and its \(sp^2\) hybridised orbitals.}\label{Benz}
\end{figure}
This hybridisation lock all but one valence electron for the carbon atoms. These electrons exists in a p-orbital in the \(z\)-direction.
\cref{p} shows the valence orbitals of carbon.
\begin{figure}[ht]
	\centering
	\begin{tikzpicture}
		\orbital[pos = {(0,3)}] {s}
		\node[above] at (0,4) {s};
		\orbital[pos = {(2,3)}]{px}
		\node[above] at (2,4) {p$_x$};
		\orbital[pos = {(4,3)}]{py}
		\node[above] at (4,4) {p$_y$};
		\orbital[pos = {(6,3)}]{pz}
		\node[above] at (6,4) {p$_z$};
	\end{tikzpicture}
	\caption{The valence orbitals of carbon.}
	\label{p}
\end{figure}
The last electron in the p\(_z\) orbital does not mix with the tightly bound s, p\(_x\) and p\(_y\) electrons and moves freely. Thus these electrons have higher energies compared to the \(sp^2\) electrons and occupy states at the Fermi level. These electrons dominates transport in the graphene lattice. The p\(_z\) orbital is also known as the \(\pi\)-orbital and as such the electron lying there is called a \(\pi\)-electron. Through a carbon lattice the \(\pi\)-electrons will travel through \(\pi\)-orbitals. For a benzene ring the \(\pi\)-electrons at the highest occupied molecular state will travel through the \(\pi\)-orbitals switching sign as they travel as shown in \cref{sign}.
\begin{figure}[ht]
	\centering
	\pgfdeclarelayer{background}
	\pgfdeclarelayer{middle}
	\pgfdeclarelayer{foreground}
	\pgfsetlayers{background,middle,main,foreground}
	\begin{tikzpicture}
		\begin{pgfonlayer}{background}
			\orbital[pos = {(6,6)}]{-pz}
			\node[above] at (6,7) {-p$_\pi$};
			\orbital[pos = {(4,6)}]{pz}
			\node[above] at (4,7) {p$_\pi$};
			\draw[dashed, very thick] (6,6) -- (4,6);
			\draw[dashed, very thick] (7,4.73) -- (6,6);
			\draw[dashed, very thick] (4,6) -- (3,4.73);
		\end{pgfonlayer}
		\orbital[pos = {(7,4.73)}]{pz}
		\node[above] at (7,5.73) {p$_\pi$};
		\orbital[pos = {(3,4.73)}]{-pz}
		\node[above] at (3,5.73) {-p$_\pi$};
		\begin{pgfonlayer}{foreground}
			\orbital[pos = {(4,3.46)}]{pz}
			\node[above] at (4,4.46) {p$_\pi$};
			\orbital[pos = {(6,3.46)}]{-pz}
			\node[above] at (6,4.46) {-p$_\pi$};
			\draw[dashed, very thick] (4,3.46) -- (6,3.46);
		\end{pgfonlayer}
		\draw[dashed, very thick] (6,3.46) -- (7,4.73);
		\draw[dashed, very thick] (3,4.73) -- (4,3.46);
	\end{tikzpicture}
	\caption{When jumping from one carbon atom to another, the \(\pi\)-electron goes between p\(_\pi\)-orbitals. Such a jump is described by two matrix elements in the system's Hamiltonian.}
	\label{sign}
\end{figure}
\subsection{Tight-binding}\label{tbtheory}
Now that the transport carrying electrons are defined the next step is describing the transport itself. For this purpose we employ the \textit{tight-binding} approximation. In this approximation the electrons are considered being tightly bound to the atoms. Contrary to a free electron gas approximation, the electrons does not spend time in between orbitals, but jump from orbital in atom \(a\) to orbital in atom \(b\). The Hamiltonian is represented as a matrix of hopping elements for a collection of neighbouring atomic orbitals, i.e. molecular orbitals, as well as the energy contained within each orbital (which will be addressed later on). This can be done by describing the orbitals as a Linear Combination of Atomic Orbitals (LCAO). The solution to the Schrödinger equation is then:
\begin{align}
	\Psi_{\mathrm{MO}} = \sum_{\alpha,R}c_{\alpha,R}\phi_{\alpha}(R)
\end{align}
where \(\phi_{\alpha}(R)\) is an atomic orbital at position \(R\), with \(\alpha\) denoting the valence of the orbital (\(2s,2p_x,2p_y,2p_z\)). In electron transport the states close to the Fermi level is of interest. These are namely the highest occupied molecular orbitals (HOMO), or the lowest unoccupied molecular orbitals (LUMO). As stated earlier only the \(\pi\)-electrons is then of interest.
The electrons' motion can be described with the hopping matrix of elements:
\begin{align}
	V_{pp\pi} = \bra{\phi_{\pi}(m)}\hat{H}\ket{\phi_{\pi}(n)}\label{V}
\end{align}
Physically this means that there is a potential \(\pqty{V_{pp\pi}}\) between the \(\pi\) orbitals of neighbouring atoms \(i\) and \(j\). In our tight-binding approximation we consider only hop between nearest neighbours. Furthermore we do not take account for out of plane carbon atoms. The element
\begin{align}
	\epsilon_0 = \bra{\phi_{\pi}(i)}\hat{H}\ket{\phi_{\pi}(i)}
\end{align}
is the average energy of the electron on atom \(i\) and, it is common to define the hopping energy relative to this, i.e. \(\epsilon_0 = 0\).
If the atoms or their environment differs, so does the on-site potential.\newline
\cref{benzex} contains an illuminating example of how the tight-binding approximation can be used to describe the benzene molecule.


\subsection{Example \#5: single time series analysis with interventions}
\label{S:Example_DISP_intervention}
\subsubsection{Data description}
This case is based on Example \#1 (see \ref{S:Example_DISP}) where we removed some part of the data and introduce discrete shifts into it. This example illustrates what typically happens a sensor fails; when a sensor fails, the data start to be missing (i.e. \lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!NaN!) and it often takes from several weeks to several months before the sensor is replaced. When the sensor is replaced, it is in most cases re-initialized at a different initial value than the previous sensor which lead to a discrete shift in the time series, as depicted in Figure~\ref{fig:DataSummary1}. Here in addition to the components employed for Example \#1, we also employ a Local intervention in order to estimate the magnitude of the corrections require to eliminate the discrete shifts created by sensor replacement.

Note that again, in this example, we choose to resample the original data in order to have a timesteps of 6h instead of 1h.

\begin{figure*}[h]
\centering
\begin{subfigure}{\linewidth}
\includegraphics[width=0.95\linewidth]{./docfigs/Example_DISP_INTERVENTION/ALL_AMPLITUDES.pdf}
\caption{Amplitude}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/ALL_TIMESTEPS.pdf}
\caption{Timestep}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/AVAILABILITY.pdf}
\caption{Availability}
\end{subfigure}
\caption{Raw data in the example \#1 where the reference timestep is 1h.}
\label{fig:DataSummary1}
\end{figure*}

\subsubsection{Model description}
\label{SS:ModelConstructionExample1}
The model includes one model class, and the hidden states variables are
\begin{gather*}
\textbf{x}=[x^{\mathtt{LL}}, x^{\mathtt{P1}\text{,yearly}}, x^{\mathtt{P2}\text{,yearly}}, x^{\mathtt{P1}\text{,daily}}, x^{\mathtt{P2}\text{,daily}}, x^{\mathtt{AR}}, x^{\mathtt{LI}}].
\end{gather*}
When using a Level intervention component, the user must provide discrete timestamps where it is required to estimate the magnitude of a discrete shift in the dataset (see \S\ref{SSS:LI}). A user can do so by specifying in the configuration file \colorbox{light-gray}{\lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!data.interventions=[t_{1}, t_{2}, ... , t_{n}]!}. The configuration file for this problem is presented in the Listing \ref{LST:CFGFileExampleInt} where the timestamps where the shift occur are \colorbox{light-gray}{\lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!data.interventions=[735929.875, 736099.875];!}.

\begin{lstlisting}[linewidth=\linewidth, style=Matlab-editor,  basicstyle = \mlttfamily \tiny, backgroundcolor = \color{matlab-yellow}, caption = {Configuration file for the example \#5}, label=LST:CFGFileExampleInt, captionpos=b, float=h!]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% A - Project name
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
misc.ProjectName='Example_DISP_INTERVENTION';
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% B - Data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dat=load('DATA_Example_DISP_INTERVENTION.mat');
data.values=dat.values;
data.timestamps=dat.timestamps;
data.labels={'DISP'};
data.interventions=[735929.875, 736099.875];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% C - Model structure
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Components reference numbers
% 11: Local level
% 12: Local trend
% 13: Local acceleration
% 21: Local level compatible with local trend
% 22: Local level compatible with local acceleration
% 23: Local trend compatible with local acceleration
% 31: Periodic
% 41: Autoregressive
% 51: Kernel regression
% 61: Level Intervention

% Model components
model.components.block{1}={[11 31 31 41 61 ] };

% Model inter-components dependence | {[components form dataset_i depends on components from  dataset_j]_i,[...]}
model.components.ic={[ ] };
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% D - Model parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
model.param_properties={
     % #1           #2             #3      #4    #5               #6           #7       #8              #9              #10
     % Param name   Block name     Model   Obs   Bound            Prior        Mean     Std             Values          Ref
     '\sigma_w',   'LL',           '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            0,              1      %#1
     'p',          'PD1',          '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            365.2422,       2      %#2
     '\sigma_w',   'PD1',          '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            0,              3      %#3
     'p',          'PD2',          '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            1,              4      %#4
     '\sigma_w',   'PD2',          '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            0,              5      %#5
     '\phi',       'AR',           '1',   '1',   [0  1      ],    'N/A',       NaN,     NaN,            0.90399,        6      %#6
     '\sigma_w',   'AR',           '1',   '1',   [0  Inf    ],    'N/A',       NaN,     NaN,            0.035428,       7      %#7
     '\mu_b',      'LI',           '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            0,              8      %#8
     '\sigma_b',   'LI',           '1',   '1',   [NaN  NaN  ],    'N/A',       NaN,     NaN,            0.16276,        9      %#9
     '\sigma_v',   '',             '1',   '1',   [0  Inf    ],    'N/A',       NaN,     NaN,            6.193e-06,      10     %#10
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% E - Initial states values
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initial hidden states mean for model 1:
model.initX{ 1 }=[	25.9  	-0.194	-0.01 	-0.00411	0.0551	-0.0127	0     ]';
% Initial hidden states variance for model 1:
model.initV{ 1 }=diag([ 	8.26E-05	0.000143	0.000106	4.86E-07	4.86E-07	0.00167	1E-20  ]);
% Initial probability for model 1
model.initS{1}=[1     ];

\end{lstlisting}

The model parameters associated with this model are
\begin{gather*}
\bm\theta=[\sigma_{w}^{\mathtt{LL}}, p^{\mathtt{P}, \text{yearly}}, \sigma_{w}^{\mathtt{P}, \text{yearly}} , p^{\mathtt{P}, \text{daily}}, \sigma_{w}^{\mathtt{P}, \text{daily}}, \phi^{\mathtt{AR}}, \sigma_{w}^{\mathtt{AR}}, \mu_{b}^{\mathtt{LI}}, \sigma_{b}^{\mathtt{LI}}, \sigma_{v}].
\end{gather*}
The optimized model parameters values computed using the Newton-Raphson algorithm (see~\ref{SS:THModelParameterEstimation}) with a training period of 180 days  are
\begin{gather*}
\bm\theta^{\text{*}}=[0, 365.2422, 0, 1, 0, 0.903, 0.035, 0, 0.16 6.19\times10^{-6} ].
\end{gather*}
The estimated initial hidden states mean and covariance values are
\begin{align*}
\bm \mu^{*}_{0} & = [	25.9,-0.194,-0.01	,-0.004,0.055,-0.013,0]^{\intercal}, \text{and} \\
\bm\Sigma^{*}_{0} & = \text{diag}([8.26\times10^{-5},	1.4\times10^{-4},	1.1\times10^{-4},	4.86\times10^{-7},	4.86\times10^{-7},	1.67\times10^{-3}  1E-20 ]).
 \end{align*}
The hidden states computed using the estimated model parameters and initial hidden states are presented in Figure~\ref{fig:Example_DISP_INTERVENTIONOptimizedOptimizedExample1}. You can see in Figure \ref{fig:Example_DISP_INTERVENTIONOptimizedOptimizedExample1}b that the level remains constant throughout the entire time series despite the jumps. This is because the discrete shift are estimated by the Level intervention component displayed in Figure \ref{fig:Example_DISP_INTERVENTIONOptimizedOptimizedExample1}e.

\subsubsection{Run the example from the pre-existing configuration file}
\label{SS:LoadConfigFileEx1}
There is a configuration file CFG\_Example\_DISP\_INTERVENTION\_optim.m which is located in the ``config\_files'' folder of the OpenBDLM package.
CFG\_Example\_DISP\_INTERVENTION\_optim.m contains the optimized model parameters and estimated initial hidden states values (see Listing \ref{LST:CFGFileExampleInt}).
There is also a data file DATA\_Example\_DISP\_INTERVENTION\_optim.mat that is located in the ``data/mat'' subfolder.
Therefore, it is possible to run the example \#1 by following the steps below while interacting with the \MATLAB{} command line:
\begin{enumerate}
\item Start OpenBDLM. Type \colorbox{light-gray}{\lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!OpenBDLM_main('CFG_Example_DISP_INTERVENTION_optim.m');!}.
\item Access hidden states estimation menu. Type \colorbox{light-gray}{\lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!3!}.
\item Run the Kalman smoother to estimate the hidden states. Type \colorbox{light-gray}{\lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!1!}.
\item Save and quit. Type \colorbox{light-gray}{\lstinline[basicstyle = \mlttfamily \small, backgroundcolor = \color{light-gray}]!Q!}.
\end{enumerate}

\begin{figure*}[h!]
\begin{center}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/DISP_ObservedPredicted.pdf}
\caption{Observed and estimated displacement data}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/DISP_LL_1.pdf}
\caption{Estimated displacement local level component.}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/DISP_S1_2.pdf}
\caption{Estimated displacement yearly periodic component (first hidden state)}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/DISP_AR_6.pdf}
\caption{Estimated displacement autoregressive component}
\end{subfigure}
\begin{subfigure}{\linewidth}
\centering
\includegraphics[width=0.9\linewidth]{./docfigs/Example_DISP_INTERVENTION/DISP_LI_7.pdf}
\caption{Estimated displacement daily periodic component (first hidden state)}
\end{subfigure}
\caption{Estimated results using OpenBDLM with the optimized model parameters and estimated initial hidden states. The hidden states are estimated from the data presented in Figure~\ref{fig:DataSummary1}a. The solid line and shaded area represent the mean and standard deviation of the estimated hidden states.}
\label{fig:Example_DISP_INTERVENTIONOptimizedOptimizedExample1}
\end{center}
\end{figure*}


%!TEX root = ../thesis.tex
% ******************************* Thesis Appendix A ****************************

\ifpdf
    \graphicspath{{Appendix1/Figs/Raster/}{Appendix1/Figs/PDF/}{Appendix1/Figs/}}
\else
    \graphicspath{{Appendix1/Figs/Vector/}{Appendix1/Figs/}}
\fi

\chapter{Methods}
\section{Measuring focal length of scan lens}\label{appendix:scanlens}

The focal length of the scan lens was initially unknown but its position for collimation was, and so a reasonable assumption of its focal length was possible.
To compound certainty the focal length was found experimentally.
To accurately measure the focal length of an unknown lens the focal length of a lens of known focal length is needed to collimate the light.
In this experiment the tube lens of focal length \SI{200}{\milli\meter} was used.
By measuring the width of a laser beam prior ($w_{before}$) to and after ($w_{after}$) the collimating lens pair, the magnification is calculated very accurately and the unknown focal length is found by:

\begin{align}
	M=\frac{f_2}{f_1}=\frac{w_{before}}{w_{after}}  \rightarrow \frac{f_2}{M} =f_{1}
\end{align}

To measure a beam width very accurately a straight sharp edge is placed in the beam path and slowly iterated through, the resultant beam power is then measured using a power meter.
To ensure there is no beam cropping on the power meter another lens was used to focus the intensity correctly, the same lens and its position was used in each measurement to keep with consistency.
The beam power was measured and plotted which produces an integrated Gaussian profile (see \eqref{eq:guass_prop}) otherwise known as an error function.
Mathematically this is described by equation~\eqref{eq:knife}.

\begin{align}
	I(x,y) &= I_0 e^{\frac{-2x^2}{w_x^2}}e^{\frac{-2y^2}{w_y^2}}\label{eq:guass_prop}\\\nonumber
	P_{TOT} &= I_0 \int_{\infty}^{\infty}e^{\frac{-2x^2}{w_x^2}} dx \int_{\infty}^{\infty}e^{\frac{-2y^2}{w_y^2}} dy\\\nonumber
	P(X) &= P_{TOT} - \int_{\infty}^{X}e^{\frac{-2x^2}{w_x^2}} dx I_0 \int_{\infty}^{\infty}e^{\frac{-2x^2}{w_x^2}} \\\nonumber
	&= \frac{P_{TOT}}{2} - \sqrt{\frac{\pi}{2}} I_0 \omega_y \int_{\infty}^{X}e^{\frac{-2x^2}{w_x^2}}\\
	& = \frac{P_{TOT}}{2} \left[1 - erf\left(\frac{\sqrt{2}X}{\omega_x}\right) \right] \label{eq:knife}
\end{align}

Fitting of this curve was implemented using MatLAB's curve fitting package which utilises the method of least squares fitting, see Figure \ref{fig:laser_width}.
The fit result produced values of laser beam width as $w_{before} = \SI{3.76\pm0.04}{\milli\meter}$ and $w_{after} = \SI{0.71\pm0.1}{\milli\meter}$.
% The value of $w_{after}$ was supplied in Table \ref{table:laser} however, for posterity is was remeasured locally in case the value had changed or was incorrect.
This gives a magnification $M$ of \SI{5.37 \pm 0.1}{} therefore the focal length of the scan lens is \SI{37.3\pm0.1}{\milli\meter}.
This also showed that the fill of the \SI{12}{\milli\meter} back aperture was \SI{3.76\pm0.04}{\milli\meter} hence the NA of the \num{0.3} objective used would be \SI{\approx 0.094}{}.

\begin{figure}
\centering
\includegraphics[width=0.7\linewidth]{./laser_width}
\caption[Laser Width Fitting]{Plot showing the fitting of two error functions based on the knife edge translation through a laser beam propagation, producing laser beam widths of $w_{after} = \SI{0.71\pm0.1}{\milli\meter}$ and $w_{before} = \SI{3.76\pm0.04}{\milli\meter}$}
\label{fig:laser_width}
\end{figure}

% \section{System alignments protocol}

%Stationary back apeture.
\chapter{Useful derivations}
\section{Convolution theorem}\label{appendix:convolution_theorem}

Convolution is a mathematical operation between two functions, say $g(t)$ and $f(t)$, with the resultant function being an expression of the overlap of $g$ as it is shifted over $f$ \cite{bracewellFourierAnalysisImaging2004}. Mathematically it can be expressed as an integral over a finite range $\tau$:
\begin{equation}
[f(*g](t) = \int_{-\infty}^{\infty} f(\tau) g(t-\tau)d\tau
\end{equation}

If a Fourier transform is then applied to the convolution of two functions:
\begin{align}
\mathcal{F}([f*g](t)) &= \int_{-\infty}^{\infty} \left[{\int_{-\infty}^{\infty} f(\tau)} g(t-\tau)d\tau\right] e^{-i2 \pi kt} dt \\
\text{and then reverse}&\text{ the order:}\nonumber\\
\mathcal{F}([f*g](t)) &= \int_{-\infty}^{\infty}f(\tau) \left[{\int_{-\infty}^{\infty} } g(t-\tau) e^{-i2 \pi kt} dt\right]   d\tau
\\
\text{From the shift theorem}& \text{ seen in equation \eqref{shift_ivariance}:} \nonumber
\\
\left[{\int_{-\infty}^{\infty} } g(t-\tau) e^{-i2 \pi kt} dt\right] &= \mathcal{F}(g(t-\tau)) = \mathcal{F}(g(t)) e^{-i2 \pi k \tau}\\
\implies \mathcal{F}([f*g](t)) &= \mathcal{F}(g(t)) \int_{-\infty}^{\infty}f(\tau) e^{-i2 \pi k \tau}    d\tau
\\&= \mathcal{F}(g(t)) \mathcal{F}(f(\tau)) \label{convolv}
\end{align}

Showing that \textbf{Convolution} in real space is \textbf{Multiplication} is Fourier space.

\section{Fourier transform}

Any continuous function can be decomposed into a linear summation of harmonic weighted sinusoidal functions. A Fourier transform is a mechanism by which the weightings of this series can be derived. Fourier space uses this transform to represent a function or a signal in frequency space (sometimes known as $k$-space or reciprocal space); it can be seen as a coordinate change from $x$ to $k$ denoted mathematically as~\cite{bloomfieldFourierAnalysisTime2000}:
\begin{equation}
F(k) \equiv\mathcal{F}  \{f(x)\} \equiv \int_{-\infty}^{\infty}f(x) e^{-i2 \pi kx} dx \label{fourier trans}
\end{equation}

This process is also reversible by:

\begin{equation}
f(x) \equiv\mathcal{F}^{-1}  \{F(k)\} \equiv \frac{1}{2 \pi} \int_{-\infty}^{\infty}F(k) e^{-i2 \pi kx} dk
\end{equation}

Fourier transforms have a valuable property in that a shift in real space becomes a complex phase term in $k$ space. This is shown by substituting $x = x-a$ and $dx = dx$ into \eqref{fourier trans}:
\begin{align}
F(k') &=  \int_{-\infty}^{\infty}f(x) e^{-i2 \pi k(x-a)} dx \nonumber\\
&=  e^{-i2 \pi ka} \underbrace{\int_{-\infty}^{\infty}f(x) e^{-i2 \pi kx}dx}_{F(k)}   \label{shift_ivariance}
\end{align}

Hence the additional real space shift only adds a multiplicative factor to the final Fourier transform. This is known as the Shift theorem.

\section{Huygens wavelet theory}

Diffraction is the spreading of light rays after an interaction with an object. Coincident light waves may interfere when diffracted such that the superposition of their resultant waves is constructive or destructive dependent on their relative phase difference. Light incident on an aperture $A(x,y)$ in the plane $S$ can be assumed to be of a plane wave nature. When passing through the aperture, light can then be modelled as being a series of $dS$ spaced point sources that radiate spherical wavefronts under Huygens' principle:

\begin{quote}
``Every point on a propagating wavefront serves as the source of secondary spherical wavelets, such that the wavefront at some later time is the envelope of these wavelets.''~\cite{goodmanIntroductionFourierOptics1996}
\end{quote}

%
% \begin{figure}
% \centering
% \includegraphics[width=0.7\linewidth]{./Diagrams/coordsys}
% \caption{Diagram depicting the coordinate system discussed Section \ref{diffraction}.}
% \label{fig:coordsys}
% \end{figure}

The superposition and hence summation of these emitting wavelets when only travelling forward ($+z$ direction) and contained in a cone of small angles from the optical axis can be evaluated in terms of $dE$, the change in the field at some point in front of the aperture. The change in field goes with $\frac{1}{r}$ where $r$ represents the distance to an arbitrary point and for a real wave can be expressed as:

\begin{equation}
dE = \frac{A(x,y)dS}{r} cos(\omega t -kr)
\end{equation}

Using the coordinates $\alpha,\beta$ to represent the two dimensional plane of the projection of the light passing through the aperture $A(x,y)$ then $r$ and $R$ can be written as:
\begin{align}
R^2 &= \alpha ^2 + \beta ^ 2+ z^2  \\
r^2 &= (\alpha - x)^2 + (\beta - y)^2 + z^2
\end{align}
Where $R$ represents the distance from the optical centre of the aperture to the arbitrary point at $\alpha,\beta$, which can be rewritten as:

\begin{equation}
r = R \sqrt{1 - \frac{2 \alpha x + 2 \beta y}{R^2} + \frac{x^2 + y^2}{R^2}}  \label{r = R}
\end{equation}

Which can be approximated using a binomial expansion to:

\begin{equation}
r = R - \frac{(\alpha x + \beta y)}{R}
\end{equation}

Provided the cone of angles is small, then $r \approx R$ and when only considering the case where $R^2 >> x^2 + y^2$ equation \eqref{r = R} tends to:
\begin{equation}
dE = \frac{A(x,y)}{R} e^{i \omega t - kr} e^{ik \left(\frac{\alpha x + \beta y}{R}\right)} dxdy
\end{equation}

Integrating across the entire aperture (wavefronts are entirely rejected elsewhere):

\begin{align}
E(\alpha,\beta) &= \frac{e^{i \omega t - kr}}{R} \int\int_{A}^{} A(x,y) e^{ik \left(\frac{\alpha x + \beta y}{R}\right)} dxdy
\\  \text{After a normalised } &\text{coordinate switch:} \nonumber \\
u &= \frac{k \alpha}{2 \pi R}  \text{ and }   v = \frac{k \beta}{2 \pi R}
\\ E(u,v)&=\frac{e^{i \omega t - kr}}{R} \int\int_{A}^{} A(x,y) e^{i2 \pi k \left(ux + vy\right)} dxdy
\end{align}

This form is well known and defined as a Fourier transform (with a weighting term) and hence the far field diffraction pattern of an aperture is the Fourier transform of that aperture~\cite{goodmanIntroductionFourierOptics1996}.

\section{Bragg conditons}

%Bragg conditions
Proof of Abbe limit from diffraction theory:

\begin{align}
    \intertext{We define the separation of two diffractive orders through an aperture}
    d \sin \alpha_n = n \lambda \\
    \intertext{We then use the equation of a lens}
    \sin\alpha_n = \frac{p_n}{f} \\
    p_n = \frac{n\lambda f}{d} \\
    \intertext{In the extreme of the limit of resolution, \(p_n\) becomes unity}
    d \le = \frac{\lambda}{\sin\alpha_{\text{max}}} \\
    \intertext{We rearrange to show the classic Abbe limit:}
    d \le = \frac{\lambda_0}{n\sin\alpha_{\text{max}}} = \frac{2\lambda_0}{NA}
\end{align}

\section{Fourier slice theorem}\label{appendix:fourierslice}
From~\cite{kakPrinciplesComputerizedTomographic2001}:

\begin{quotation}
``We derive the Fourier Slice Theorem by taking the one-dimensional Fourier transform of a parallel projection and noting that it is equal to a slice of the two-dimensional Fourier transform of the original object.
It follows that given the projection data, it should then be possible to estimate the object by simply performing a two-dimensional inverse Fourier transform.
We start by defining the two-dimensional Fourier transform of the object function as

\begin{align}
  F(u,v) = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x, y)e^{-i2\pi(ux+uy)}dx dy.
  \intertext{ Likewise define a projection at an angle  \(\theta \), \(P_{\theta}(t)\), and its Fourier transform by}
S_{\theta}(w) =  \int_{-\infty}^{\infty} P_\theta9t) e^{-i2\pi w t} dt
\end{align}
\begin{align}
\intertext{The simplest example of the Fourier Slice Theorem is given for a projection at \(\theta = 0\).
First, consider the Fourier transform of the object along
the line in the frequency domain given by u = 0.
The Fourier transform integral now simplifies to}
F(u,0) = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x, y)e^{-i2\pi(ux)}dx dy.
\intertext{ but because the phase factor is no longer dependent on y we can split the integral into two parts,}
F(u,0) =  \int_{-\infty}^{\infty} \left[  \int_{-\infty}^{\infty} f(x,y,) dy \right] e^{-i2\pi(ux)} dx \label{eq:f(u,0)}
\intertext{ From the definition of a parallel projection, the reader will recognise the term in brackets as the equation for a projection along lines of constant \(x\) or}
P_{\theta = 0} (x) = \int_{-\infty}^{\infty} f(x,y) dy
\intertext{Substituting this in \eqref{eq:f(u,0)} we find:}
F(u,0) =  \int_{-\infty}^{\infty} P_{\theta = 0} (x) e^{-i2\pi(ux)} dx
\intertext{ The right-hand side of this equation represents the one-dimensional Fourier transform of the projection \(P_{\theta = 0}\);
thus we have the following relationship between the vertical projection and the 2-D transform of the object function:}
F(u,0) = S_{\theta=0}(u)
\end{align}

\begin{quotation}
  ``The Fourier transform of a parallel projection of an image \(f(x, y)\) taken at angle \(\theta \) gives a slice of the two-dimensional transform, \(F(u, v)\), subtending an angle \(\theta \) with the \(u\)-axis.''
\end{quotation}
''
\end{quotation}

\chapter{Particle tracking}
\section{Failed quantifications of motion induced error}

Introduced in Section~\ref{sec:spt_maths}, attempts at quantify the error seen due to motion blur that failed.

\subsection{Cross correlation}
\begin{align*}
  \intertext{To analytically compare the expected and real results, the respective functions were cross-correlated using the analytical function:}
%\text{Cross correlation} =
(f \star g)(t)\ \stackrel{\mathrm{def}}{=} \int_{-\infty}^{\infty} &f(x)^* g(x+t) \mathop{dx}
\end{align*}
\begin{align*}
\intertext{The integral of the result across all space gives a single value signifying the quality of correlation between the two functions:}
\int_{-\infty}^{\infty} \int_{-\infty}^{\infty} &f(t)^* g(x+t) \mathop{dx}\mathop{dt}
\intertext{This value will reach unity when $f(x) = g(x)$}
\end{align*}
\begin{align*}
\intertext{The expected PSF was given the additional $t$ parameter as it was more likely that this integral would solve, though, this only solves across all space for unnormalised PSFs:}
\int_{-\infty}^{\infty} \int_{-\infty}^{\infty} &\text{PSF}_{\text{Reality}} (x)^* \text{PSF}_{\text{Expected}} (x+t) \mathop{dx}\mathop{dt} \\
=& \frac{\pi  c (a L+L_{\text{end}})^2}{a L_{\text{end}} L \sqrt{\frac{L_{\text{end}}^2}{c^2 (a L+L_{\text{end}})^2}}} +\frac{2 \pi  c^2 (a L+L_{\text{end}})^2}{L_{\text{end}}^2}\\
+&\frac{\pi  c L_{\text{end}}}{a L \sqrt{\frac{L_{\text{end}}^2}{c^2 (a L+L_{\text{end}})^2}}}-\frac{2 \pi  L_{\text{end}}}{a \sqrt{\frac{1}{c^2}} L \sqrt{\frac{L_{\text{end}}^2}{c^2 (a L+L_{\text{end}})^2}}}\\
+&\frac{2 \pi  c^2 (a L+L_{\text{end}})^2}{a L_{\text{end}} L}
\end{align*}
\begin{align*}
  \intertext{By correlating the normalised functions across a small window $u$ an analytical solution was produced.}
\int_{-u}^{ u}\int_{-\infty}^{\infty} \hat{\text{PSF}}_{\text{Reality}} (x)^* \hat{\text{PSF}}_{\text{Expected}} (x+t) \mathop{dx}\mathop{dt}
\end{align*}
\begin{align*}
&=-\frac{(a L+L_{\text{end}})}{\sqrt{2 \pi } a L_{\text{end}} L}\sqrt{\frac{L_{\text{end}}^2}{c^2 (a L+L_{\text{end}})^2}}\left(L_{\text{end}} u \left(\text{Ei}\left(-\frac{L_{\text{end}}^2 u^2}{2 c^2 (L_{\text{end}}+a L)^2}\right)+\Gamma \left(0,\frac{u^2}{2 c^2}\right)\right)\right.\\
&-\frac{\sqrt{2 \pi (-c)} (a L+L_{\text{end}}) \left(\text{Erf} \left(\frac{L_{\text{end}} u}{\sqrt{2} (a c L+c L_{\text{end}})}\right)\right)}{\sqrt{2 \pi } a L_{\text{end}} L}-\frac{\sqrt{2 \pi } L_{\text{end}} \left| c\right|  \text{Erf} \left(\frac{u}{\sqrt{2} \left| c\right| } \right)}{\sqrt{2 \pi } a L_{\text{end}} L}
\end{align*}

\begin{figure}
  \centering
  \includegraphics{./mathematica/correlation_analysis}
  \caption{}
  \label{fig:correlation_analysis}
\end{figure}

\subsection{Full width half maximum}

The correlation of two signals is not an absolute error which can be used to make predictions about real-world systems. So, the Full Width at Half Maximum of each of the two signals was considered as this property, in Gaussian-like functions, should provide an analogue for $\sigma(z)$ which may be compared absolutely.
\begin{align*}
\text{PSF}(x,...) &- \lim_{x\to0} \frac{\text{PSF}(x,...)}{2} = 0 \\
\implies \text{FWHM}_{\text{Expected}} &= 2x \\
&= \left|-\frac{\sqrt{2} c \sqrt{\ln{2} +2 i \pi  n} (a L+L_{\text{end}})}{L_{\text{end}}}\right|,n\in \mathbb{Z}
%\text{FWHM}_{\text{Expected}} &= \frac{2 \sqrt{3}}{\sqrt{\frac{a^2 L^2}{c^2 (a L+L_{\text{end}})^2}+\frac{3 L_{\text{end}}^2}{c^2 (a L+L_{\text{end}})^2}+\frac{3 a L_{\text{end}} L}{c^2 (a L+L_{\text{end}})^2}}}
\end{align*}
\begin{align*}
\text{PSF}_{\text{Reality}}(x,...) - \lim_{x\to0} \frac{\text{PSF}_{\text{Reality}}(x,...)}{2} = 0 \\
\intertext{This equation does not solve for $x$ so a Maclaurin expansion was used:}
= -\frac{L_{\text{end}} x^2}{4 \left(c^2 (a L+L_{\text{end}})\right)}+\frac{x^4 \left(a^2 L_{\text{end}} L^2+3 a L_{\text{end}}^2 L+3 L_{\text{end}}^3\right)}{48 c^4 (a L+L_{\text{end}})^3}+O\left(x^5\right)
\end{align*}
\begin{align*}
\implies \text{FWHM}_{\text{Reality}} &= \frac{2 \sqrt{3}}{\sqrt{\frac{a^2 L^2}{c^2 (a L+L_{\text{end}})^2}+\frac{3 L_{\text{end}}^2}{c^2 (a L+L_{\text{end}})^2}+\frac{3 a L_{\text{end}} L}{c^2 (a L+L_{\text{end}})^2}}}\\
\text{FWHM}_\text{Error} &= 2\frac{\text{PSF}_{\text{Expected}} - \text{PSF}_{\text{Reality}}}{\text{PSF}_{\text{Expected}} + \text{PSF}_{\text{Reality}}}\\
& = 2\frac{\sqrt{\ln{2}} \sqrt{a^2 L^2+3 a L_{\text{end}} L+3 L_{\text{end}}^2}-\sqrt{3} L_{\text{end}}}{\sqrt{\ln{2}} \sqrt{a^2 L^2+3 a L_{\text{end}} L+3 L_{\text{end}}^2}+\sqrt{3} L_{\text{end}}}
\end{align*}

When $L\to0$ this result of $\text{FWHM}_\text{Error}$ can be below zero, which would suggest that the result is not an accurate measure of the true error.
This is likely due to the process requiring a series expansion, at $x=0$; as the series expansion is only an approximation of the target function.
Since attaining error from the FWHM fails for small values of $L$ an analysis using area was considered.

\section{Magnetic tweezer alternate proof}\label{appendix:tweezertheory}

%The parameters from \eqref{eq:modelfitting} need to be reviewed and amended if one intends to link them to experimental data as one applies a known force and looks at the displacement of the bead from its initial position and not to stress and strain.

A bead moving through a viscous fluid can be described by Stokes' law \(F = 6 \pi \eta' r \nu \), where \(r\) is the radius of the bead and \(\nu \) is the critical velocity of the bead.
Stokes' law may be written as:

\begin{align}
 F &= 6 \pi \eta' r \frac{dx}{dt} \\
 \implies \frac{F}{\pi r^2} &= 6 \eta' \frac{d}{dt}\frac{x}{r} \\
 \implies \sigma &= 6 \eta' \frac{\epsilon}{dt}
 \intertext{Giving the equation of a dash-pot}
 \dot{\epsilon} = \frac{\sigma}{\eta}
\end{align}

To model the elastic spring, the elastic response of the tissue due to the bead displacement is approximated by the Thomson's solution of a point force in an infinite isotropic medium~\cite{l.d.landaue.m.lifshitzTheoryElasticity1970}.
The displacement (\(\mathbf{u}\)) in cylindrical coordinates (\((p,z)\)) for a point force (\(F_z\)) located at the origin and directed along the (\(z\)) axis is given by:

\begin{align}
 \mathbf{u} = \frac{F_z}{4 \pi \mu r }\left[ \frac{pz}{4(1-v)r^2} \mathbf{\hat{p}}+\left(1- \frac{p^2}{4(1-v)r^2}\right)\mathbf{\hat{z}}\right]\label{eq:thomsons}
\end{align}

Where \(\mathbf{\hat{p}}\) and \(\mathbf{\hat{z}}\) are unit vectors, \(\mu \) is the shear modulus (deformation at constant volume) and \(\nu \) is Poisson's ratio (a negative ratio of transverse to axial strain of a specimen, under an axial force).
As only forces in the \(\mathbf{\hat{z}}\) direction are being considering, Equation~\eqref{eq:thomsons} becomes:

\begin{align}
 u_z &= \frac{F_z}{4 \pi \mu r }\left[\left(1- \frac{p^2}{4(1-v)r^2}\right)\right]
 \intertext{Evaluating the displacement only on the \(z\) axis where \(p=0\), reduces this to:}
 \nabla z &= \frac{F_z}{4\pi \mu r}
 \intertext{In the close proximity to the bead of radius \(r_{\text{bead}} \), the displacement is given by:}
 \frac{\nabla z}{r_{\text{bead}}} = \frac{1}{4 \mu} \frac{F_z}{\pi r_{\text{bead}}^2} & \implies \epsilon = \frac{1}{4\mu} \sigma
\end{align}
Which is equivalent to~\eqref{eq:linearspring} when substituting \(E \) with \(4\mu \).


\section{Cascade Classification}

\ifCPy

\subsection{Haar Feature-based Cascade Classifier for Object Detection}

The object detector described below has been initially proposed by Paul Viola
\cvCPyCross{Viola01}
and improved by Rainer Lienhart
\cvCPyCross{Lienhart02}
. First, a classifier (namely a \emph{cascade of boosted classifiers working with haar-like features}) is trained with a few hundred sample views of a particular object (i.e., a face or a car), called positive examples, that are scaled to the same size (say, 20x20), and negative examples - arbitrary images of the same size.

After a classifier is trained, it can be applied to a region of interest
(of the same size as used during the training) in an input image. The
classifier outputs a "1" if the region is likely to show the object
(i.e., face/car), and "0" otherwise. To search for the object in the
whole image one can move the search window across the image and check
every location using the classifier. The classifier is designed so that
it can be easily "resized" in order to be able to find the objects of
interest at different sizes, which is more efficient than resizing the
image itself. So, to find an object of an unknown size in the image the
scan procedure should be done several times at different scales.

The word "cascade" in the classifier name means that the resultant
classifier consists of several simpler classifiers (\emph{stages}) that
are applied subsequently to a region of interest until at some stage the
candidate is rejected or all the stages are passed. The word "boosted"
means that the classifiers at every stage of the cascade are complex
themselves and they are built out of basic classifiers using one of four
different \texttt{boosting} techniques (weighted voting). Currently
Discrete Adaboost, Real Adaboost, Gentle Adaboost and Logitboost are
supported. The basic classifiers are decision-tree classifiers with at
least 2 leaves. Haar-like features are the input to the basic classifers,
and are calculated as described below. The current algorithm uses the
following Haar-like features:

\includegraphics[width=0.5\textwidth]{pics/haarfeatures.png}

The feature used in a particular classifier is specified by its shape (1a, 2b etc.), position within the region of interest and the scale (this scale is not the same as the scale used at the detection stage, though these two scales are multiplied). For example, in the case of the third line feature (2c) the response is calculated as the difference between the sum of image pixels under the rectangle covering the whole feature (including the two white stripes and the black stripe in the middle) and the sum of the image pixels under the black stripe multiplied by 3 in order to compensate for the differences in the size of areas. The sums of pixel values over a rectangular regions are calculated rapidly using integral images (see below and the \cvCPyCross{Integral} description).

\ifPy
A simple demonstration of face detection, which draws a rectangle around each detected face:

\begin{lstlisting}

hc = cv.Load("haarcascade_frontalface_default.xml")
img = cv.LoadImage("faces.jpg", 0)
faces = cv.HaarDetectObjects(img, hc, cv.CreateMemStorage())
for (x,y,w,h),n in faces:
    cv.Rectangle(img, (x,y), (x+w,y+h), 255)
cv.SaveImage("faces_detected.jpg", img)

\end{lstlisting}

\fi

\ifC
To see the object detector at work, have a look at the HaarFaceDetect demo.

The following reference is for the detection part only. There
is a separate application called \texttt{haartraining} that can
train a cascade of boosted classifiers from a set of samples. See
\texttt{opencv/apps/haartraining} for details.

\cvclass{CvHaarFeature, CvHaarClassifier, CvHaarStageClassifier, CvHaarClassifierCascade}
\label{CvHaarFeature}
\label{CvHaarClassifier}
\label{CvHaarStageClassifier}
\label{CvHaarClassifierCascade}

Boosted Haar classifier structures.

\begin{lstlisting}
#define CV_HAAR_FEATURE_MAX  3

/* a haar feature consists of 2-3 rectangles with appropriate weights */
typedef struct CvHaarFeature
{
    int  tilted;  /* 0 means up-right feature, 1 means 45--rotated feature */

    /* 2-3 rectangles with weights of opposite signs and
       with absolute values inversely proportional to the areas of the
       rectangles.  If rect[2].weight !=0, then
       the feature consists of 3 rectangles, otherwise it consists of 2 */
    struct
    {
        CvRect r;
        float weight;
    } rect[CV_HAAR_FEATURE_MAX];
}
CvHaarFeature;

/* a single tree classifier (stump in the simplest case) that returns the
   response for the feature at the particular image location (i.e. pixel
   sum over subrectangles of the window) and gives out a value depending
   on the response */
typedef struct CvHaarClassifier
{
    int count;  /* number of nodes in the decision tree */

    /* these are "parallel" arrays. Every index \texttt{i}
       corresponds to a node of the decision tree (root has 0-th index).

       left[i] - index of the left child (or negated index if the
         left child is a leaf)
       right[i] - index of the right child (or negated index if the
          right child is a leaf)
       threshold[i] - branch threshold. if feature responce is <= threshold,
                    left branch is chosen, otherwise right branch is chosen.
       alpha[i] - output value correponding to the leaf. */
    CvHaarFeature* haar_feature;
    float* threshold;
    int* left;
    int* right;
    float* alpha;
}
CvHaarClassifier;

/* a boosted battery of classifiers(=stage classifier):
   the stage classifier returns 1
   if the sum of the classifiers responses
   is greater than \texttt{threshold} and 0 otherwise */
typedef struct CvHaarStageClassifier
{
    int  count;  /* number of classifiers in the battery */
    float threshold; /* threshold for the boosted classifier */
    CvHaarClassifier* classifier; /* array of classifiers */

    /* these fields are used for organizing trees of stage classifiers,
       rather than just stright cascades */
    int next;
    int child;
    int parent;
}
CvHaarStageClassifier;

typedef struct CvHidHaarClassifierCascade CvHidHaarClassifierCascade;

/* cascade or tree of stage classifiers */
typedef struct CvHaarClassifierCascade
{
    int  flags; /* signature */
    int  count; /* number of stages */
    CvSize orig_window_size; /* original object size (the cascade is
                            trained for) */

    /* these two parameters are set by cvSetImagesForHaarClassifierCascade */
    CvSize real_window_size; /* current object size */
    double scale; /* current scale */
    CvHaarStageClassifier* stage_classifier; /* array of stage classifiers */
    CvHidHaarClassifierCascade* hid_cascade; /* hidden optimized
                        representation of the
                        cascade, created by
                cvSetImagesForHaarClassifierCascade */
}
CvHaarClassifierCascade;
\end{lstlisting}

All the structures are used for representing a cascaded of boosted Haar classifiers. The cascade has the following hierarchical structure:

\begin{verbatim}
    Cascade:
        Stage,,1,,:
            Classifier,,11,,:
                Feature,,11,,
            Classifier,,12,,:
                Feature,,12,,
            ...
        Stage,,2,,:
            Classifier,,21,,:
                Feature,,21,,
            ...
        ...
\end{verbatim}

The whole hierarchy can be constructed manually or loaded from a file or an embedded base using the function \cvCPyCross{LoadHaarClassifierCascade}.

\cvCPyFunc{LoadHaarClassifierCascade}
Loads a trained cascade classifier from a file or the classifier database embedded in OpenCV.

\cvdefC{
CvHaarClassifierCascade* cvLoadHaarClassifierCascade( \par const char* directory,\par CvSize orig\_window\_size );
}

\begin{description}
\cvarg{directory}{Name of the directory containing the description of a trained cascade classifier}
\cvarg{orig\_window\_size}{Original size of the objects the cascade has been trained on. Note that it is not stored in the cascade and therefore must be specified separately}
\end{description}

The function loads a trained cascade
of haar classifiers from a file or the classifier database embedded in
OpenCV. The base can be trained using the \texttt{haartraining} application
(see opencv/apps/haartraining for details).

\textbf{The function is obsolete}. Nowadays object detection classifiers are stored in XML or YAML files, rather than in directories. To load a cascade from a file, use the \cvCPyCross{Load} function.

\fi

\cvCPyFunc{HaarDetectObjects}
Detects objects in the image.

\ifC
\begin{lstlisting}
typedef struct CvAvgComp
{
    CvRect rect; /* bounding rectangle for the object (average rectangle of a group) */
    int neighbors; /* number of neighbor rectangles in the group */
}
CvAvgComp;
\end{lstlisting}
\fi

\cvdefC{
CvSeq* cvHaarDetectObjects( \par const CvArr* image,\par CvHaarClassifierCascade* cascade,\par CvMemStorage* storage,\par double scaleFactor=1.1,\par int minNeighbors=3,\par int flags=0,\par CvSize minSize=cvSize(0, 0),\par CvSize maxSize=cvSize(0,0) );
}\cvdefPy{HaarDetectObjects(image,cascade,storage,scaleFactor=1.1,minNeighbors=3,flags=0,minSize=(0,0))-> detected\_objects}

\begin{description}
\cvarg{image}{Image to detect objects in}
\cvarg{cascade}{Haar classifier cascade in internal representation}
\cvarg{storage}{Memory storage to store the resultant sequence of the object candidate rectangles}
\cvarg{scaleFactor}{The factor by which the search window is scaled between the subsequent scans, 1.1 means increasing window by 10\% }
\cvarg{minNeighbors}{Minimum number (minus 1) of neighbor rectangles that makes up an object. All the groups of a smaller number of rectangles than \texttt{min\_neighbors}-1 are rejected. If \texttt{minNeighbors} is 0, the function does not any grouping at all and returns all the detected candidate rectangles, which may be useful if the user wants to apply a customized grouping procedure}
\cvarg{flags}{Mode of operation. Currently the only flag that may be specified is \texttt{CV\_HAAR\_DO\_CANNY\_PRUNING}. If it is set, the function uses Canny edge detector to reject some image regions that contain too few or too much edges and thus can not contain the searched object. The particular threshold values are tuned for face detection and in this case the pruning speeds up the processing}
\cvarg{minSize}{Minimum window size. By default, it is set to the size of samples the classifier has been trained on ($\sim 20\times 20$ for face detection)}
\cvarg{maxSize}{Maximum window size to use. By default, it is set to the size of the image.}
\end{description}

The function finds rectangular regions in the given image that are likely to contain objects the cascade has been trained for and returns those regions as a sequence of rectangles. The function scans the image several times at different scales (see \cvCPyCross{SetImagesForHaarClassifierCascade}). Each time it considers overlapping regions in the image and applies the classifiers to the regions using \cvCPyCross{RunHaarClassifierCascade}. It may also apply some heuristics to reduce number of analyzed regions, such as Canny prunning. After it has proceeded and collected the candidate rectangles (regions that passed the classifier cascade), it groups them and returns a sequence of average rectangles for each large enough group. The default parameters (\texttt{scale\_factor} =1.1, \texttt{min\_neighbors} =3, \texttt{flags} =0) are tuned for accurate yet slow object detection. For a faster operation on real video images the settings are: \texttt{scale\_factor} =1.2, \texttt{min\_neighbors} =2, \texttt{flags} =\texttt{CV\_HAAR\_DO\_CANNY\_PRUNING}, \texttt{min\_size} =\textit{minimum possible face size} (for example, $\sim$ 1/4 to 1/16 of the image area in the case of video conferencing).

\ifPy
The function returns a list of tuples, \texttt{(rect, neighbors)}, where rect is a \cross{CvRect} specifying the object's extents
and neighbors is a number of neighbors.

\begin{lstlisting}
>>> import cv
>>> image = cv.LoadImageM("lena.jpg", cv.CV_LOAD_IMAGE_GRAYSCALE)
>>> cascade = cv.Load("../../data/haarcascades/haarcascade_frontalface_alt.xml")
>>> print cv.HaarDetectObjects(image, cascade, cv.CreateMemStorage(0), 1.2, 2, 0, (20, 20))
[((217, 203, 169, 169), 24)]
\end{lstlisting}
\fi

\ifC
% ===== Example. Using cascade of Haar classifiers to find objects (e.g. faces). =====
\begin{lstlisting}
#include "cv.h"
#include "highgui.h"

CvHaarClassifierCascade* load_object_detector( const char* cascade_path )
{
    return (CvHaarClassifierCascade*)cvLoad( cascade_path );
}

void detect_and_draw_objects( IplImage* image,
                              CvHaarClassifierCascade* cascade,
                              int do_pyramids )
{
    IplImage* small_image = image;
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* faces;
    int i, scale = 1;

    /* if the flag is specified, down-scale the input image to get a
       performance boost w/o loosing quality (perhaps) */
    if( do_pyramids )
    {
        small_image = cvCreateImage( cvSize(image->width/2,image->height/2), IPL_DEPTH_8U, 3 );
        cvPyrDown( image, small_image, CV_GAUSSIAN_5x5 );
        scale = 2;
    }

    /* use the fastest variant */
    faces = cvHaarDetectObjects( small_image, cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING );

    /* draw all the rectangles */
    for( i = 0; i < faces->total; i++ )
    {
        /* extract the rectanlges only */
        CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );
        cvRectangle( image, cvPoint(face_rect.x*scale,face_rect.y*scale),
                     cvPoint((face_rect.x+face_rect.width)*scale,
                             (face_rect.y+face_rect.height)*scale),
                     CV_RGB(255,0,0), 3 );
    }

    if( small_image != image )
        cvReleaseImage( &small_image );
    cvReleaseMemStorage( &storage );
}

/* takes image filename and cascade path from the command line */
int main( int argc, char** argv )
{
    IplImage* image;
    if( argc==3 && (image = cvLoadImage( argv[1], 1 )) != 0 )
    {
        CvHaarClassifierCascade* cascade = load_object_detector(argv[2]);
        detect_and_draw_objects( image, cascade, 1 );
        cvNamedWindow( "test", 0 );
        cvShowImage( "test", image );
        cvWaitKey(0);
        cvReleaseHaarClassifierCascade( &cascade );
        cvReleaseImage( &image );
    }

    return 0;
}
\end{lstlisting}

\cvCPyFunc{SetImagesForHaarClassifierCascade}
Assigns images to the hidden cascade.

\cvdefC{
void cvSetImagesForHaarClassifierCascade( \par CvHaarClassifierCascade* cascade,\par const CvArr* sum,\par const CvArr* sqsum,\par const CvArr* tilted\_sum,\par double scale );
}

\begin{description}
\cvarg{cascade}{Hidden Haar classifier cascade, created by \cvCPyCross{CreateHidHaarClassifierCascade}}
\cvarg{sum}{Integral (sum) single-channel image of 32-bit integer format. This image as well as the two subsequent images are used for fast feature evaluation and brightness/contrast normalization. They all can be retrieved from input 8-bit or floating point single-channel image using the function \cvCPyCross{Integral}}
\cvarg{sqsum}{Square sum single-channel image of 64-bit floating-point format}
\cvarg{tilted\_sum}{Tilted sum single-channel image of 32-bit integer format}
\cvarg{scale}{Window scale for the cascade. If \texttt{scale} =1, the original window size is used (objects of that size are searched) - the same size as specified in \cvCPyCross{LoadHaarClassifierCascade} (24x24 in the case of \texttt{default\_face\_cascade}), if \texttt{scale} =2, a two times larger window is used (48x48 in the case of default face cascade). While this will speed-up search about four times, faces smaller than 48x48 cannot be detected}
\end{description}

The function assigns images and/or window scale to the hidden classifier cascade. If image pointers are NULL, the previously set images are used further (i.e. NULLs mean "do not change images"). Scale parameter has no such a "protection" value, but the previous value can be retrieved by the \cvCPyCross{GetHaarClassifierCascadeScale} function and reused again. The function is used to prepare cascade for detecting object of the particular size in the particular image. The function is called internally by \cvCPyCross{HaarDetectObjects}, but it can be called by the user if they are using the lower-level function \cvCPyCross{RunHaarClassifierCascade}.

\cvCPyFunc{ReleaseHaarClassifierCascade}
Releases the haar classifier cascade.

\cvdefC{
void cvReleaseHaarClassifierCascade( \par CvHaarClassifierCascade** cascade );
}

\begin{description}
\cvarg{cascade}{Double pointer to the released cascade. The pointer is cleared by the function}
\end{description}

The function deallocates the cascade that has been created manually or loaded using \cvCPyCross{LoadHaarClassifierCascade} or \cvCPyCross{Load}.

\cvCPyFunc{RunHaarClassifierCascade}
Runs a cascade of boosted classifiers at the given image location.

\cvdefC{
int cvRunHaarClassifierCascade( \par CvHaarClassifierCascade* cascade,\par CvPoint pt,\par int start\_stage=0 );
}

\begin{description}
\cvarg{cascade}{Haar classifier cascade}
\cvarg{pt}{Top-left corner of the analyzed region. Size of the region is a original window size scaled by the currenly set scale. The current window size may be retrieved using the \cvCPyCross{GetHaarClassifierCascadeWindowSize} function}
\cvarg{start\_stage}{Initial zero-based index of the cascade stage to start from. The function assumes that all the previous stages are passed. This feature is used internally by \cvCPyCross{HaarDetectObjects} for better processor cache utilization}
\end{description}

The function runs the Haar classifier
cascade at a single image location. Before using this function the
integral images and the appropriate scale (window size) should be set
using \cvCPyCross{SetImagesForHaarClassifierCascade}. The function returns
a positive value if the analyzed rectangle passed all the classifier stages
(it is a candidate) and a zero or negative value otherwise.

\fi

\fi

\ifCpp

\cvclass{FeatureEvaluator}
Base class for computing feature values in cascade classifiers.

\begin{lstlisting}
class CV_EXPORTS FeatureEvaluator
{
public:
    enum { HAAR = 0, LBP = 1 }; // supported feature types
    virtual ~FeatureEvaluator(); // destructor
    virtual bool read(const FileNode& node);
    virtual Ptr<FeatureEvaluator> clone() const;
    virtual int getFeatureType() const;

    virtual bool setImage(const Mat& img, Size origWinSize);
    virtual bool setWindow(Point p);

    virtual double calcOrd(int featureIdx) const;
    virtual int calcCat(int featureIdx) const;

    static Ptr<FeatureEvaluator> create(int type);
};
\end{lstlisting}

\cvCppFunc{FeatureEvaluator::read}
Reads parameters of the features from a FileStorage node.

\cvdefCpp{
bool FeatureEvaluator::read(const FileNode\& node);
}

\begin{description}
\cvarg{node}{File node from which the feature parameters are read.}
\end{description}

\cvCppFunc{FeatureEvaluator::clone}
Returns a full copy of the feature evaluator.

\cvdefCpp{
Ptr<FeatureEvaluator> FeatureEvaluator::clone() const;
}

\cvCppFunc{FeatureEvaluator::getFeatureType}
Returns the feature type (HAAR or LBP for now).

\cvdefCpp{
int FeatureEvaluator::getFeatureType() const;
}

\cvCppFunc{FeatureEvaluator::setImage}
Sets the image in which to compute the features.

\cvdefCpp{
bool FeatureEvaluator::setImage(const Mat\& img, Size origWinSize);
}

\begin{description}
\cvarg{img}{Matrix of type  \texttt{CV\_8UC1} containing the image in which to compute the features.}
\cvarg{origWinSize}{Size of training images.}
\end{description}

\cvCppFunc{FeatureEvaluator::setWindow}
Sets window in the current image in which the features will be computed (called by \cvCppCross{CascadeClassifier::runAt}).

\cvdefCpp{
bool FeatureEvaluator::setWindow(Point p);
}

\begin{description}
\cvarg{p}{The upper left point of window in which the features will be computed. Size of the window is equal to size of training images.}
\end{description}

\cvCppFunc{FeatureEvaluator::calcOrd}
Computes value of an ordered (numerical) feature.

\cvdefCpp{
double FeatureEvaluator::calcOrd(int featureIdx) const;
}

\begin{description}
\cvarg{featureIdx}{Index of feature whose value will be computed.}
\end{description}
Returns computed value of ordered feature.

\cvCppFunc{FeatureEvaluator::calcCat}
Computes value of a categorical feature.

\cvdefCpp{
int FeatureEvaluator::calcCat(int featureIdx) const;
}

\begin{description}
\cvarg{featureIdx}{Index of feature whose value will be computed.}
\end{description}
Returns computed label of categorical feature, i.e. value from [0,... (number of categories - 1)].

\cvCppFunc{FeatureEvaluator::create}
Constructs feature evaluator.

\cvdefCpp{
static Ptr<FeatureEvaluator> FeatureEvaluator::create(int type);
}

\begin{description}
\cvarg{type}{Type of features evaluated by cascade (HAAR or LBP for now).}
\end{description}

\cvclass{CascadeClassifier}
The cascade classifier class for object detection.

\begin{lstlisting}
class CascadeClassifier
{
public:
	// structure for storing tree node
    struct CV_EXPORTS DTreeNode
    {
        int featureIdx; // feature index on which is a split
        float threshold; // split threshold of ordered features only
        int left; // left child index in the tree nodes array
        int right; // right child index in the tree nodes array
    };

    // structure for storing desision tree
    struct CV_EXPORTS DTree
    {
        int nodeCount; // nodes count
    };

    // structure for storing cascade stage (BOOST only for now)
    struct CV_EXPORTS Stage
    {
        int first; // first tree index in tree array
        int ntrees; // number of trees
        float threshold; // treshold of stage sum
    };

    enum { BOOST = 0 }; // supported stage types

    // mode of detection (see parameter flags in function HaarDetectObjects)
    enum { DO_CANNY_PRUNING = CV_HAAR_DO_CANNY_PRUNING,
           SCALE_IMAGE = CV_HAAR_SCALE_IMAGE,
           FIND_BIGGEST_OBJECT = CV_HAAR_FIND_BIGGEST_OBJECT,
           DO_ROUGH_SEARCH = CV_HAAR_DO_ROUGH_SEARCH };

    CascadeClassifier(); // default constructor
    CascadeClassifier(const string& filename);
    ~CascadeClassifier(); // destructor

    bool empty() const;
    bool load(const string& filename);
    bool read(const FileNode& node);

    void detectMultiScale( const Mat& image, vector<Rect>& objects,
                           double scaleFactor=1.1, int minNeighbors=3,
						   int flags=0, Size minSize=Size());

    bool setImage( Ptr<FeatureEvaluator>&, const Mat& );
    int runAt( Ptr<FeatureEvaluator>&, Point );

    bool is_stump_based; // true, if the trees are stumps

    int stageType; // stage type (BOOST only for now)
    int featureType; // feature type (HAAR or LBP for now)
    int ncategories; // number of categories (for categorical features only)
    Size origWinSize; // size of training images

    vector<Stage> stages; // vector of stages (BOOST for now)
    vector<DTree> classifiers; // vector of decision trees
    vector<DTreeNode> nodes; // vector of tree nodes
    vector<float> leaves; // vector of leaf values
    vector<int> subsets; // subsets of split by categorical feature

    Ptr<FeatureEvaluator> feval; // pointer to feature evaluator
    Ptr<CvHaarClassifierCascade> oldCascade; // pointer to old cascade
};
\end{lstlisting}

\cvCppFunc{CascadeClassifier::CascadeClassifier}
Loads the classifier from file.

\cvdefCpp{
CascadeClassifier::CascadeClassifier(const string\& filename);
}

\begin{description}
\cvarg{filename}{Name of file from which classifier will be load.}
\end{description}

\cvCppFunc{CascadeClassifier::empty}
Checks if the classifier has been loaded or not.

\cvdefCpp{
bool CascadeClassifier::empty() const;
}

\cvCppFunc{CascadeClassifier::load}
Loads the classifier from file. The previous content is destroyed.

\cvdefCpp{
bool CascadeClassifier::load(const string\& filename);
}

\begin{description}
\cvarg{filename}{Name of file from which classifier will be load. File may contain as old haar classifier (trained by haartraining application) or new cascade classifier (trained traincascade application).}
\end{description}

\cvCppFunc{CascadeClassifier::read}
Reads the classifier from a FileStorage node. File may contain a new cascade classifier (trained traincascade application) only.

\cvdefCpp{
bool CascadeClassifier::read(const FileNode\& node);
}

\cvCppFunc{CascadeClassifier::detectMultiScale}
Detects objects of different sizes in the input image. The detected objects are returned as a list of rectangles.

\cvdefCpp{
void CascadeClassifier::detectMultiScale( const Mat\& image,
                           vector<Rect>\& objects,
                           double scaleFactor=1.1,
                           int minNeighbors=3, int flags=0,
                           Size minSize=Size());
}

\begin{description}
\cvarg{image}{Matrix of type  \texttt{CV\_8U} containing the image in which to detect objects.}
\cvarg{objects}{Vector of rectangles such that each rectangle contains the detected object.}
\cvarg{scaleFactor}{Specifies how much the image size is reduced at each image scale.}
\cvarg{minNeighbors}{Speficifes how many neighbors should each candiate rectangle have to retain it.}
\cvarg{flags}{This parameter is not used for new cascade and have the same meaning for old cascade as in function cvHaarDetectObjects.}
\cvarg{minSize}{The minimum possible object size. Objects smaller than that are ignored.}
\end{description}

\cvCppFunc{CascadeClassifier::setImage}
Sets the image for detection (called by detectMultiScale at each image level).

\cvdefCpp{
bool CascadeClassifier::setImage( Ptr<FeatureEvaluator>\& feval, const Mat\& image );
}

\begin{description}
\cvarg{feval}{Pointer to feature evaluator which is used for computing features.}
\cvarg{image}{Matrix of type  \texttt{CV\_8UC1} containing the image in which to compute the features.}
\end{description}

\cvCppFunc{CascadeClassifier::runAt}
Runs the detector at the specified point (the image that the detector is working with should be set by setImage).

\cvdefCpp{
int CascadeClassifier::runAt( Ptr<FeatureEvaluator>\& feval, Point pt );
}

\begin{description}
\cvarg{feval}{Feature evaluator which is used for computing features.}
\cvarg{pt}{The upper left point of window in which the features will be computed. Size of the window is equal to size of training images.}
\end{description}
Returns:
1 - if cascade classifier detects object in the given location.
-si - otherwise. si is an index of stage which first predicted that given window is a background image.

\cvCppFunc{groupRectangles}
Groups the object candidate rectangles

\cvdefCpp{void groupRectangles(vector<Rect>\& rectList,\par
                     int groupThreshold, double eps=0.2);}
\begin{description}
\cvarg{rectList}{The input/output vector of rectangles. On output there will be retained and grouped rectangles}
\cvarg{groupThreshold}{The minimum possible number of rectangles, minus 1, in a group of rectangles to retain it.}
\cvarg{eps}{The relative difference between sides of the rectangles to merge them into a group}
\end{description}

The function is a wrapper for a generic function \cvCppCross{partition}. It clusters all the input rectangles using the rectangle equivalence criteria, that combines rectangles that have similar sizes and similar locations (the similarity is defined by \texttt{eps}). When \texttt{eps=0}, no clustering is done at all. If $\texttt{eps}\rightarrow +\inf$, all the rectangles will be put in one cluster. Then, the small clusters, containing less than or equal to \texttt{groupThreshold} rectangles, will be rejected. In each other cluster the average rectangle will be computed and put into the output rectangle list.
\fi


\documentclass[a4paper,10pt,hidelinks]{article}

\usepackage[margin=2cm]{geometry}

\usepackage{tikz}
\usepackage{hyperref}
\usepackage{algorithm}
\usepackage{algpseudocode}
\usepackage{amsmath}
\usepackage{amssymb}

\usepackage{listings}
\lstset{
	numbers=left,
	breaklines=true,
	tabsize=4
}

\newcommand{\algorithmautorefname}{Algorithm}

%opening
\title{Practical Assignment 2\\
Social Network Analysis}
\author{Bert Peters\\
s1147919}

\begin{document}

\maketitle

\section{Clustering Coefficient}

\begin{enumerate}
	\item A tree, by definition, has no loops, and therefore has a clustering coefficient of 0. Another example is a bipartite graph. This type of graph can only have cycles of at least length 4. This is because it is impossible for two edges in the same partition to have a connection. Cycles of length 4 do not contribute to the clustering coefficient, because that only counts the number of triangles, i.e. the number of cycles of length 3.

	\item There are several possible such graphs. One of them is shown in \autoref{fig:graph-no-clustering}.

	\item Contructing an unclustered graph is trivial for when $m \leq n$, because we can construct a circle graph of size $n$ and remove edges to arrive at the desired number of edges. The algorithm is shown in \autoref{algo:algo-no-clustering} and runs in $O(m)$.

		The algorithm works by adding repeatedly connecting each node $v_i$ to another node $v_{i + \delta}$. This delta is increased over iterations, and is given by $\delta = 3^s$ where $s$ is the current iteration number, starting at 1. This ensures that we do not create new loops shorter than 4, which is what we need in order to prevent clustering.
\end{enumerate}

\begin{figure}
	\centering
	\begin{tikzpicture}[every node/.style={draw=black,thick,circle}]
		\node (A) at (0,4){A};
		\node (B) at (-2,2){B};
		\node (C) at (0,2){C};
		\node (D) at (2,2){D};
		\node (E) at (-2,0){E};
		\node (F) at (0,0){F};
		\node (G) at (2,0){G};
		\node (H) at (-2,-2){H};
		\node (I) at (0,-2){I};
		\node (J) at (2,-2){J};

		\draw (A) -- (C);
		\draw (B) -- (C);
		\draw (C) -- (D);
		\draw (B) -- (E);
		\draw (C) -- (F);
		\draw (E) -- (F);
		\draw (D) -- (G);
		\draw (F) -- (G);
		\draw (E) -- (H);
		\draw (H) -- (I);
		\draw (F) -- (I);
		\draw (I) -- (J);
		\draw (G) -- (J);

		\draw (B) -- (G);
		\draw (D) -- (E);

		\draw (E) -- (J);
		\draw (G) -- (H);

	\end{tikzpicture}
	\caption{An undirected graph with 10 nodes, 15 edges, and a clustering coefficient of 0.}
	\label{fig:graph-no-clustering}
\end{figure}

\begin{algorithm}
	\caption{Constructing a graph with no clustering.}
	\label{algo:algo-no-clustering}

	\begin{algorithmic}
		\State $E \gets \emptyset$
		\State $s \gets 1$
		\While{$|E| < m \land 3^s < n$}
		\For{$v_i \in V \land |E| < m$}
		\State $E \gets E \cup \{\{v_i, v_{i + 3^s \text{ mod } n} \}\}$
		\EndFor
		\State $s \gets s + 1$
		\EndWhile
	\end{algorithmic}

\end{algorithm}

\section{Densest Subgraph}

We start by computing the average degree and the current density. For a graph with a given $n, m$ this is easy, because the average degree is $\frac{2m}{n}$ and the density is half of that. We run our algortihm, by iteratively removing the nodes with a degree lower than the average degree from our $V$ and $E$, and repeat the process until we cannot delete nodes anymore.

Using the above algorithm, we arrive at the results as shown in \autoref{tab:densest-subgraph}. We see that after iteration 1, we already find our maximum, with a density of 1.5. After that, we still delete nodes twice, until we arrive at a graph with two nodes and cannot delete nodes any more.

\begin{table}
	\centering
	\begin{tabular}{r || l | r | r}
		Iteration & Subgraph & Density & Avg. degree\\
		\hline
		0   & $\{A B C D E F H I J K L\}$ & $\frac{16}{11} \approx 1.45 $ & $\frac{32}{11} \approx 2.9 $ \\
		1   & $\{A B E F J K\}$ & $ \frac{9}{6} = 1.5 $ & $ \frac{18}{6} = 3 $ \\
		2   & $\{B E F J\}$ & $\frac{5}{4} = 1.25$ & $\frac{10}{4} = 2.5$ \\
		3   & $\{E F\}$ & $\frac{1}{2} = 0.5$ & $\frac{2}{2} = 1$
	\end{tabular}
	\caption{Using the greedy algorithm to find the densest subgraph.}
	\label{tab:densest-subgraph}
\end{table}

\section{Twitter Network Extraction}

\subsection{Parsing the tweets}

We parse the tweets using a python script in \autoref{lst:preprocess}. It takes a list of files as arguments from the command line or data from the standard input. First, it splits the string twice on the first occurrence of a tab. It attempts to parse mentions out of a tweet using a regular expression. The expression used is a non-word character\footnote{A word character is defined as either an ascii letter character (upper case and lower case), a digit, or an underscore character (`\texttt{\_}'). Everything else, including the `\texttt{\^}' (start of string) and `\texttt{\$}' (end of string) metacharacters is considered a non-word character.}, followed by an `\texttt{@}', followed by $[1, 15]$ word characters\footnote{The specification of what is a valid twitter username can be found at \url{https://support.twitter.com/articles/101299}}, followed by by a non-word character. Requiring a non-word character before the mention filters out email addresses, which occur frequently in the dataset. The resulting usernames are put in lowercase, because twitter usernames are case-insensitive.

The script determines a mapping from usernames to integers, because this is more convenient to handle programmatically in the analysis. It outputs a Gephi-edgelist compatible list of mentions to the standard output, and a Gephi-nodelist compatible username mapping to the standard error.

There are still a number of things that the parser does wrong. The most prevalent error happens when users have no separator (either white space or punctuation) between a mention and the following text. In this case, it is impossible to determine where the username ends and the tweet continues. This can only be solved when you know all usernames in your dataset.

This problems described above can, however, be solved by using the twitter api. It provides any mentions included in a message as meta data, removing the need for complicated parsers. Implementing this is outside the scope of this assignment.

\subsection{Dataset statistics}

\begin{table}
	\centering
	\begin{tabular}{l || r | r | c | r | r | c | r}
		\multicolumn{1}{c ||}{Dataset} & \multicolumn{1}{c |}{$|V|$} & \multicolumn{1}{c |}{$|E|$} & $D$ & \multicolumn{1}{c |}{$|V_{giant}|$} & \multicolumn{1}{c |}{$|E_{giant}|$} & $D_{giant}$ & Diameter\\
		\hline
		\texttt{twitter-small} & 47568 & 53449 & $2.4 \cdot 10^{-5}$ & 32351 & 44135 & $4.2 \cdot 10^{-5}$ & 21 \\
		\texttt{twitter-larger} & 398388 & 691080 & $4.4 \cdot 10^{-6}$ & 328358 & 648832 & $6.0 \cdot 10^{-6}$ & 23 \\
		\texttt{twitter} & 8663906 & 57959449 & $7.7 \cdot  10^{-7}$ & 8402847 & 57813254 & $8.2 \cdot 10^{-7}$ & ?
	\end{tabular}
	\caption{Dataset statistics}
	\label{tab:dataset-stats}
\end{table}

We consider the graph as an undirected graph. We use our parser program to get some statistics about our dataset. The results are shown in \autoref{tab:dataset-stats}. For the degree distribution, we reuse the python script from the previous assignment. This gives us the distribution as shown in \autoref{fig:graph-no-clustering}.

Edges occurring multiple times are counted towards node degrees, but not towards the number of edges. In other words, the equation $\sum\limits_{v_i} k(v_i) = 2|V|$ does not hold.

For density, we take the measure $D = \frac{|V|}{|E|(|E| - 1)}$. Since, in a social network, the average degree does not depend on the number of nodes in the network, we we expect the density to drop linearly with the number of nodes. This is because $\lim_{n \rightarrow \infty} \frac{cn}{n (n - 1)} = \frac{1}{n}$. Furthermore, there should be a slightly lower  density in the entire network and that in the giant component. This is because the network contains a lot of isolated nodes, i.e. people that have tweeted, but not mentioned, and who have not been mentioned.

\begin{figure}
	\centering
	\includegraphics[scale=0.8]{degree-distributions.pdf}
	\caption{Degree distribution for all datasets.}
	\label{fig:degree-distributions}
\end{figure}

\begin{figure}
	\centering
	\includegraphics[scale=0.8]{distance-distribution}
	\caption{Approximate distance distributions for all datasets. Bars are relative within one dataset.}
	\label{fig:distance-distributions}
\end{figure}

It is infeasible to compute the exact distance distribution for all networks, as this requires computing $\frac{1}{2} n (n-1)$ distances. To do so would require $O(nm)$ time, to perform $n$ breadth first searches. Instead, we use an approximation. For this, we perform 100 breadth first searches and count how often each distance occurs. We then normalize by dividing by the total number of paths found, and arrive at the distribution as shown in \autoref{fig:distance-distributions}.

\subsection{Top Twitter users}
To compute the top 20 twitter users in our dataset, we consider the following centrality measures:

\begin{description}
	\item[Degree centrality] which is simply the degree of the node. For this experiment, we use the the out degree of a node for this. We then sort the nodes in descending order. We define it as $DC(u) = \max(\forall v \in V : k^\rightarrow(v))$.

	\item[Eccentricity centrality] which is the longest shortest path starting from a node. The idea is, that if your eccentricity is low, you are fairly central. It is defined as $EC(u) = \max(\forall v \in V : d(u, v))$.

	\item[Closeness centrality] which is somewhat related to the eccentricity centrality, but is slightly different, because we take the average path length rather than the total path length. This gives us $CC(u) = \frac{\sum_{v \neq u \in V}}{|V| - 1}$.
\end{description}

We then apply these measures to the \texttt{twitter-small} dataset. The results are shown in \autoref{tab:small-top-users}. For eccentricity, there are quite a few nodes with the same value.\footnote{This can be easily seen by observing that the $\forall u \in V: ecc(u) \leq \text{diameter}(G) \land ecc(u) \in \mathbb{N}$ by definition. This means that we do not have a lot of distinct values the eccentricity can take.} In this case, we use degree as a tie-breaker.

\begin{table}
	\centering
	\begin{tabular}{l || l | l | l}
		& \multicolumn{1}{c |}{$DC$} & \multicolumn{1}{c |}{$EC$} & \multicolumn{1}{c}{$CC$} \\
		\hline
		1 & theiphoneblog & mashable & theiphoneblog \\
		2 & ryanbarr & theiphoneblog & mashable\\
		3 & mashable & ryanbar & tweetmeme\\
		4 & scottbourne & scottbourne & iphone\_dev\\
		5 & scancafe & scancafe & tweetdeck\\
		6 & squarespace & squarespace & allthingsiphone \\
		7 & tweetmeme & tweetmeme & techcrunch \\
		8 & iphone\_dev & iphone\_dev & squarespace \\
		9 & tweetdeck & tweetdeck & kevinrose\\
		10 & kevinrose & kevinrose & randomslagathor \\
		11 & tomtom & techcrunch & musclenerd \\
		12 & techcrunch & engadget & engadget \\
		13 & patrickaltoft & iphoneincanada & scottbourne \\
		14 & iphoneincanada & tuaw & tuaw \\
		15 & quickpwn & guykawasaki & scancafe \\
		16 & engadget & musclenerd & iphoneincanada \\
		17 & tinteract &  chrispirillo & razorianfly \\
		18 & tuaw & parislemon & djsakebomb \\
		19 & guardiantech & trackle & reneritchie \\
		20 & igncom & johnbiggs & tmitechnews
	\end{tabular}
	\caption{Top 20 users in \texttt{twitter-small} according to different measures.}
	\label{tab:small-top-users}
\end{table}

We can not easily and objectively compare these rankings on quality, but we can numerically compare how different they are. We do this by counting inversions. This can be done in $O(l^2)$, with $l$ the number of items in our list. This is fairly doable for a top 20. Also, we have to account for nodes that are in one, but not in the other list. For this, we count it as an inversion against everything else, which means it has $l$ inversions.

When we take a look at the resulting top-users in \autoref{tab:small-top-users}, we can see that all three centrality measures are somewhat in agreement over the top users. This is not unexpected, as all three measures used for determining the rankings are somewhat correlated. For example, having a low eccentricity helps to get a lower closeness, and your closeness is very much influenced by your own outdegree.

\subsection{Community detection}
We attempt to detect the communities using Gephi. Ideally, we are looking for about 12 communities, as a lower amount would provide very little information and a higher amount would not be visually interprable. When setting the resolution to 1.0, we get thousands of communities. When we set it to 10.0, we find only 4 communities. Halfway in between at 5.0 we find 14 communities, which can be roughly interpreted as some subject on which users tweet.

\subsection{Visualisation}
To visualise the giant component of the \texttt{twitter-small} network, we use Gephi. Using the community detection described in the previous section, we color the nodes. Furthermore, we scale the nodes according to their betweenness centrality. The resulting network can be seen in \autoref{fig:visualisation}. While improving upon this visualisation, Gephi gave up, so I gave up on visualising.

\begin{figure}
	\centering
	\includegraphics[scale=0.8]{visualisation.pdf}
	\caption{Visualisation of the \texttt{twitter-small} network. Colors are according to communities, and node size is proportional to betweenness centrality.}
	\label{fig:visualisation}
\end{figure}

\subsection{Analysing the \texttt{twitter-larger} dataset}
\begin{table}
	\centering
	\begin{tabular}{l || l | l | l}
		& \multicolumn{1}{c |}{$DC$} & \multicolumn{1}{c |}{$EC$} & \multicolumn{1}{c}{$CC$} \\
		\hline
		1 & uberguineapig & uberguineapig & uberguineapig \\
		2 & mobil\_tipps & mobil\_tipps & mashable\\
		3 & dloblack & iphone\_mob & iphone\_mob \\
		4 & iphonedevnews & muenchner\_kindl & techcrunch \\
		5 & iphone\_nikki & iphone\_jedi & tweetmeme \\
		6 & macandiphone & maclounge & startonlinetwit \\
		7 & riggledo & botiphone & razorianfly \\
		8 & muenchner\_kindl & savvybanana & sebastianpage \\
		9 & danlaforce & ezf\_executives & tuaw \\
		10 & iphone\_jedi & kaisersoeze & muenchner\_kindl \\
		11 & tm\_iphone & tommytrc & dudeman718 \\
		12 & allthingsiphone & magicbaseball1 & tm\_iphone \\
		13 & inflight\_wifi & flipbooks & topiphone \\
		14 & ipodtouchroom & jwforson & krapps \\
		15 & esteves08 & the\_borg & mayhemstudios \\
		16 & supsappel & bildarchiv & kaisersoeze \\
		17 & iphone3gupdates & shellykramer & theiphoneblog \\
		18 & tramain360 & randomslagathor & bradgal \\
		19 & csrandom & appgirlreviews & scobleizer \\
		20 & locaconpistolas & earthxplorer & tm\_technology
	\end{tabular}
	\caption{Top 20 users in \texttt{twitter-larger} according to different measures.}
	\label{tab:larger-top-users}
\end{table}

Since we use our own parser (see appendices) we can quite easily run the statistics on the \texttt{twitter-larger} dataset. The results are incorporated in \autoref{tab:dataset-stats}, \autoref{fig:degree-distributions}, and \autoref{fig:distance-distributions}. Furthermore, we can compute the eccentricity for every node exactly using the algorithm by F.W. Takes et al. and arrive at the eccentricity for each node in approximately 17,000 breadth first searches. This is about 20 times faster than the naive approach.

The closeness centrality is a bit more challenging to compute. Instead, we approximate it by sampling the distance between 10,000 randomly selected nodes and everything else, and averaging those results.\footnote{While this method is a lot of work, it is doable in about an hour, while doing the entire computation would take slightly over a day.} As a slight bonus, calculating the eccentricities also gives us the diameter of the network, which is shown in \autoref{tab:dataset-stats}. What is interesting, is that the diameter of \texttt{twitter-larger} is only slightly greater than the diameter of \texttt{twitter-small}, despite the former being about ten times smaller than the latter. This is a property often observed in social networks.

\subsection{Bonus: Analysing the complete \texttt{twitter} dataset}
Our \texttt{C++} code is efficient enough to compute the dataset statistics in reasonable time while only needing 6 GiB of memory.\footnote{The system used had an Intel i7 CPU running at 3.4 GHz and 16 GiB of memory, but only a single thread and 6 GiB of memory was used.} The data is shown in \autoref{tab:dataset-stats}, \autoref{fig:degree-distributions}, and \autoref{fig:distance-distributions}. We used the same approximation of the distance distribution that we used for the other datasets, which took about 40 minutes to compute.

We can also still sample the network

Computing all eccentricities however was more challenging. At the time of writing, we have spent over 21 hours of computation doing a total of 2,872 breadth first searches, with 1,302,102 eccentricities not yet known. This gives us an average of one BFS every 26 seconds. This, along with the observation that we find at least one eccentricity per search, gives us an upper bound of 391 days for the remaining computation. I therefore do not except a result to this. While I have observed a speed up of over 100 using the algorithm, I still do not expect to see a result before the deadline. Mostly because the system will be rebooted Sunday at 03:00, losing all my progress.

It could still be possible to compute the rankings, as the eccentricity bounds for most low eccentricity nodes become tight very quickly, and for other nodes the bounds are at least very close. Doing so is outside the scope of this project however.

\pagebreak

\appendix

\section{preprocess.py}
\label{lst:preprocess}
\lstinputlisting[language=python]{preprocess.py}
\pagebreak

\section{Makefile}
\lstinputlisting[language=make]{Makefile}
\pagebreak

\section{parser.cpp}

\lstinputlisting[language=c++]{parser.cpp}

\pagebreak

\section{TwitterGraph.hpp}

\lstinputlisting[language=c++]{TwitterGraph.hpp}

\pagebreak

\section{TwitterGraph.cpp}

\lstinputlisting[language=c++]{TwitterGraph.cpp}

\pagebreak

\section{eccentricity.cpp}
This file contains the method used to compute the eccentricity of all nodes and the diameter of the network. It is adapted from the presentation \emph{Determining the Diameter of Small World Networks} by F.W. Takes and W.A. Kosters. The original presentation containing the algorithm can be found at \url{http://liacs.leidenuniv.nl/~takesfw/SNACS/diameter.pdf}.

\lstinputlisting[language=c++]{eccentricity.cpp}

\pagebreak

\section{closeness.cpp}

This file contains the method used to approximate the closeness of a particular node.

\lstinputlisting[language=c++]{closeness.cpp}
\end{document}


\chapter{The Formal Specification}

\section{Methodology}
The computer has been formally specified at the architectural level.
 The specification methodology used was {\bf Lambda} \cite{ahl:lambda}.
Designed especially
 for hardware specification, it is implemented as an ML
based system upon the Sun workstations.
A semi-automated theorem prover  forms the
core of Lambda, which enables properties of specifications to be
examined, and reifications to be verified.

The system is designed to synthesise a working design from a
behavioural specification, by reifying the design until it
describes individual components ---{\em forward synthesis}.
 In such a way the correctness of a design
can be guaranteed without performing a verification.
Written in the language ML it has a similar syntax, but with extensions to the language.
This enables part of a specification to be executed as  ML functions,
allowing the hardware's  properties to be simulated in software.

The  Lambda specification language is more powerful than an
executable programming language. Rather than describing a function
or procedure to convert from the input to the output, one just specifies  preconditions and
postconditions.

{\samepage
For example, the function:-
{\tt
\begin{verbatim}
        fun square_root (x:Natural) = iota y. y*y==x;
\end{verbatim}
}

describes the square root function in Lambda but not ML.
}
Timing constraints can also be included into {\em rewrite rules}
{\tt
\begin{verbatim}
        val sqrt_unit#(x,y)=
                forall t.
                     y (t+100) == square_root (x t);
\end{verbatim}
}
This describes a combinatorial square root unit which outputs at time
t+100 the square root of the input at time t.

Functional units can  be joined together by use of common variable bindings
{\tt
\begin{verbatim}
        val double_sqrt_unit#(x,z)=
              sqrt_unit(x,y) /\ sqrt_unit(y,z);
\end{verbatim}
}
Such functions, along with the definition of the types of the variables of X,Y and Z, can be parsed by  Lambda to produce an environment of rules.
These rules can be used to prove hypotheses, such as that the time for a double\_sqrt\_unit to evaluate an expression would take 200 units of time.

This system allows someone to specify any component  or module as a collection of related inputs and outputs.
A number of components can  be linked together to form a larger module,
or a complete design.

%\newpage
Unfortunately, none of  the components I used had
been formally specified. While I  produced some specifications based on the informal specifications in the databooks their correctness  can never be guaranteed.

Specification from scratch is an extremely slow process, and I was not able to describe the whole computer in this depth in the time available.
 I  described the operation of the computer at a very high level, and then  expanded the description of the ALU to a greater depth.

\section {First Specification}

My first specification was based upon an example specification of a simple computer in the Lambda Manual.
It was written in a early version of Lambda, which had a syntax more complex than that of ML.
First it was necessary to specify the types of data which the computer dealt with.
Abstract datatypes of 15 and 32 bit integers were defined without giving their internal structure.
Allowable
operations ---comparison and addition for 15 bit numbers, all ALU
operations for 32 bit numbers--- were stated as existing and being
total. Their exact functions were not given.
 Random Access Memory
was then defined as a function of 15 bit addresses to  32 bit data words.

The computer can at any moment in time  be described by  the contents of every  register
and  memory location.
 As an instruction is executed this state   changes,
unless it is halted or in an infinite loop.

The state of the
computer was described as a tuple of
\begin{verbatim}
        <memory, execution unit state, alu state>
\end{verbatim}
where the execution unit state was
\begin{verbatim}
        <PC,X,Y,skip,halt>
\end{verbatim}
    and the
ALU state was
\begin{verbatim}
        <ACC,z,n,v,c>
\end{verbatim}

 The operation of the whole machine was  given as a transition from
state to state.
Each transition was caused by the  execution of
 a single instruction.
The most complex part of this specification was the description of the read and write operations.
This was because of the memory mapping of registers.
The read function was supplied with the computer state and a 15 bit address to return a 32 bit integer.
A separate function was used to validate the address prior to the read access.
The write function took as parameters a  state, an address and a new value, returning a new state. This allowed both registers and RAM to be updated.

The transition from one state to another during instruction execution was described by a function which  fetched the next instruction, and incremented the PC.
It then calculated the source  address and moved its contents to the  destination address.
If the halt flag was set this function did nothing.
Before each read the address was validated ---any illegal access terminated the function and set the halt flag.
If the skip flag was set the program counter was merely incremented and the flag cleared; no instruction was executed.

This does actually resemble the actual process of instruction fetch
and execute, except that the halt and skip flags do not actually
exist.
Skipping is performed by hard-wired logic, and the halt state is merely another state within the control unit's Moore Machine.
These differences are invisible to the user.
At this level the operation of the computer is being described, even if it differs slightly from the actual implementation.

\section{Second Specification}

By Christmas a new version of Lambda was available, with a syntax more  similar to ML. The design of the Ultimate RISC had become clearer, partly through the initial specification, but also as I  designed the ALU.

I therefore upgraded the specification to support both the new notation and to be consistent with the revised design.

This was done by first expanding the 15-bit and 32-bit integer abstract data types to  boolean tuples, with functions for conversion between these representations and that of natural numbers.

I then wrote all the operations performed by a 74381 ALU IC as
functions acting upon boolean four-tuples. A general function was
written to apply the operation selected by the control lines.
 The production of carry signals from the 74182 carry lookahead generators were
also specified.
In both cases the specifications were based upon
data sheets from TI and AMD.
It was then possible to describe the ALU components by relating outputs as
the result of the functions applied upon the inputs of a previous time
---the temporal difference being the propagation delay of the device.

The logic equations of the PALS were all specified likewise, enabling the
entire combinatorial portion of the ALU to be accurately described.

The remainder of the specification was derived from the first  specification of the Ultimate RISC.

I did not go about proving the two specifications were identical.
Nor did I
 try to prove properties of the new specification, such as
the non-folding of
RAM addresses and the persistence of data within.
 Given estimates of
the time to verify the correctness of specifications of other computers,
there would have been no possibility of both verifying the specifications and
attempting to build anything.
The verification would probably  form a complete project,
requiring someone far more experienced in machine assisted proofs than myself.
Instead I  produced a simulation, by modifying the specification  to  execute in ML.

 To enable my
specification to be executed I had to remove all instances of
postconditions and timing constraints.
The other problem was `feedback'.
The 74381 units produce signals which are
passed to the carry generators. These then  return a carry signals to be evaluated with the earlier inputs.
These were simulated by iterations of the functions.

I also wrote a `monitor' for the simplified specification which provided a
front end for the simulation with facilities such as memory read/write,
instruction assembly and dissassembly, register manipulation and
program execution.

There were  subtle differences between ML and Lambda. Notably ML's integers were more restricted than Lambda's type Natural.
 Both the Edinburgh SML and the faster New Jersey ML had only 32 bit signed integers, rendering conversion between these numbers and 32 bit boolean tuples difficult.
The specification only executed satisfactorily in PolyML,
which was   prone to unannounced field upgrades, so that functions   available in February did not work in April.

\section{Summary}

Overall the specification and simulation comprise
 1400 lines, and are somewhat more difficult to understand at a
glance than P-CAD circuit diagrams. Much of the code is devoted to
mathematical and component definitions. For the success of hardware
specification languages I believe it will be necessary to produce
libraries of verified maths functions, components  and standard cells.

 It is not a complete specification of the hardware of the
 Ultimate RISC.
 For this the computer must be described as a collection
of units, communicating via control signals and synchronised by a
clock.
The time delays of all operations must be specified, along
with the ability of the host to control the clock and write to
registers.

The simulation has been used to test the operation of the ALU,
especially the programming of the PALS,  uncovering a couple
of mistakes which could have proved  costly.
It also demonstrated that the carry flag had to be set prior to a subtraction,  a fact the compiler writer needed.

While I have not performed any proofs, specifying the computer was a valuable exercise.
 Describing the machine at a high level, I was forced to consider many details which any other method of description would ignore;
 this clarified the hardware implementation.

The specification of an existing design did seem easier than the forward synthesis method for which Lambda aims to provide.
Forward synthesis should reduce the number of proofs required, and thus increase the speed of designing with formal methods.

Even without the verification between levels, a specification which describes the computer is of use  describing the system to a software developer.
For this to be the case the software designers  need to be able to understand the notation.
This is an argument in favour of using a more widely known notation such as {\bf Z}, which seems to be primarily for software development.
If programs were specified in the same notation as the hardware  the two would be able to be integrated in order to prove facts about the combined system.

Ideally the specification should have been continued till every component was specified along with the interconnections.
A netlist could have been extracted and sent to the BEPI machine for automated wiring, and the PAL and EPLD programs also generated.
If these processes could be at least partially automated, then the Lambda system could form the core of an an automated design and manufacture system.
Without such a system,   manual intervention ---whether P-Cad design or wire-wrapping--- introduces elements of risk. For the full benefit of formal methods the implementation must match the specification.