\documentclass[11pt]{article}

\usepackage{hyperref}
\usepackage{amssymb}
\usepackage{amsmath}

\title{Alignment-free relative abundance with $K$-mers}
\author{Bob Carpenter}
\date{\today}

\begin{document}

\maketitle

\abstract{\noindent Given RNA-seq data and a reference transcriptome,
  we provide a statistical model of relative abundance of transcripts
  without the need to align the reads to the transcriptome by reducing
  the reads and reference transcripts to $K$-mers.}

\section{Bases and $K$-mers}

The four \emph{DNA bases} are adenine (\texttt{A}),
cytosine (\texttt{C}), guanine (\texttt{G}), and thymine (\texttt{T}).
The set of DNA bases is
\[
  \mathbb{B} = \{ \texttt{A}, \texttt{C}, \texttt{G}, \texttt{T} \}.
\]
A \emph{$K$-mer} is an $K$-tuple of bases,
\[
  x = (x_1, \ldots, x_K),
  \ \textrm{where}
  \ x_1, \ldots, x_k \in \mathbb{B}^K.
\]
The set of $K$-mers is
\[
  \mathbb{B}^K
  = \{ (x_1, \ldots, x_K)
      : x_1, \ldots x_K \in \mathbb{B} \}.
\]
The set of $K$-mers of all lengths is
\[
  \mathbb{B}^* = \bigcup_{k=0}^{\infty} \mathbb{B}^k.
\]

\section{The transcriptome}

A \emph{transcriptome} is an indexed multiset of $K$-mers, each of
which may be of a different length,
\[
  T = T_{1}, \ldots, T_{G},
\]
with $T_{g, 1:K_g} \in \mathbb{B}^*$.  In data structure terms, the
transcriptome $T$ is a ragged array of bases.

\section{RNA-seq data}

Simple (unpaired) \emph{RNA-seq data}, after processing, consists of an indexed set of base
sequences, each of which is called a \emph{read},
\[
  R = R_1, \ldots, R_N, \ \textrm{where} \ R_n \in \mathbb{B}^J.
\]
Although not strictly necessary, we assume for simplicity that all of
the reads in the RNA-seq data are of the same length.

With \emph{paired-end} RNA-seq data, each read consists of two short RNA
sequences read from the same transcript with an unknown gap between
them on the transcriptome, so the data may be represented as
\[
  P = P_1, \ldots, P_N, \ \textrm{where} \ P_n \in \mathbb{B}^J \times
  \mathbb{B}^J.
\]
Again, although not strictly necessary, we assume all sequences are
the same length to simplify notation.

\section{Shredding $K$-mers}

Suppose $K \leq N$.  Then the $N$-mer $x_{1:N}$ can be shredded into
a sequence of $(N - K + 1)$ $K$-mers by
\[
  x_{1:N} \ \mapsto \
  x_{1:K}, \ x_{2:K+1}, \ \ldots, \ x_{N-K+1:N}.
\]
For example,
\[
  \texttt{AACAC} \ \mapsto \
  \texttt{AA}, \ \texttt{AC}, \ \texttt{CA}, \ \texttt{AC}.
\]
A sequence (or multiset) of $K$-mers may be summarized with a function
$\textrm{count}_K:\mathbb{B}^* \rightarrow \mathbb{B}^K \rightarrow
\mathbb{N}$, where
$\textrm{count}_K(x)(y)$ is the number of times the $K$-mer
$y$ appears in the $N$-mer $x$.  Continuing the example above,
\begin{eqnarray*}
  \textrm{count}(\texttt{AACAC})(\texttt{AA}) & = & 1,
  \\
  \textrm{count}(\texttt{AACAC})(\texttt{AC}) & = & 2,
  \\
  \textrm{count}(\texttt{AACAC})(\texttt{CA}) & = & 1,
\end{eqnarray*}
and all other counts are zero.

A complete set of RNA-seq data $X = X_1, X_2, \ldots, X_N$ may then be reduced to
$K$-mer counts by summing the counts of the individual reads $x_{n, 1:J}$
\[
  \textrm{count}_K(X) = \sum_{n=1}^N \textrm{count}_K(X_n).
\]

Paired-end RNA-seq data can be shredded elementwise.  For
example, consider extracting 3-mers from a paired read.
\[
  \texttt{ATCAG} / \texttt{CGCGC}
  \ \mapsto \
  \texttt{ATC}, \texttt{TCA}, \texttt{CAG},
  \texttt{CGC}, \texttt{GCG}, \texttt{CGC},
\]
Counts are defined for individual paired reads and a complete set of
RNA-seq data as above.

\section{Indexing $K$-mers}

Define a bijection from the set of $K$-mers, $\mathbb{B}^K$, to the
first $4^K$ counting numbers, $\{ 0, 1, \ldots 4^K-1 \}$,
by treating each base as a digit in base 4 and reading the
$K$-mer as a number.  Following alphabetic order, let
\[
  \texttt{A} = 0,
  \quad \texttt{C} = 1,
  \quad \texttt{G} = 2,
  \quad \texttt{T} = 3.
\]
The resulting indexing sorts the $K$-mers into lexicographic order.
For example, with $K = 2$, the sixteen 2-mers are as follows.

\begin{center}
\begin{tabular}{ll|ll|ll|ll}
  \texttt{AA} & 0 & \texttt{CA} & 4 &   \texttt{GA} & 8 & \texttt{TA} & 12
  \\
  \texttt{AC} & 1 & \texttt{CC} & 5 &   \texttt{GC} & 9 & \texttt{TC} & 13
  \\
  \texttt{AG} & 2 & \texttt{CG} & 6 &   \texttt{GG} & 10 & \texttt{TG} & 14
  \\
  \texttt{AT} & 3 & \texttt{CT} & 7 &   \texttt{GT} & 11 & \texttt{TT} & 15
\end{tabular}
\end{center}
There are roughly one thousand 5-mers, because $4^5 = 1024$.  There are
roughly one million 10-mers and one billion 15-mers.

$K$-mer counts can be tabulated and stored very efficiently by using
this numbering to index into an array.  The complete set of 10-mer
counts from an RNA-seq experiment can be efficiently indexed and
stored in 4MB of memory using 32-bit counts (8MB with 64-bit counts).
Even smaller memory footprints may be achieved by packing smaller
integer representations; this could be beneficial if it enables the
counts to be stored in cache.  Shredding into 15-mers would take 4GB
(8GB) and clearly exceed cache capacity.  Beyond 15-mers, direct
indexing becomes prohibitive on readily available hardware, and either
a hashing scheme would be required or a lossy Bloom filter in order to
store approximate counts.  The memory used by hashing will be
proportional to the number of unique $K$-mers in the RNA-seq data.

Therefore,
$\textrm{count}_K(x)$ is a (sparse) $4^K$-vector where the
$K$-mers are indexed in lexicographic order (i.e., read as base 4
numbers).

\section{Statistical model}

In a transcriptome consisting of $G$ base sequences, the only
parameter is a vector $\alpha \in \mathbb{R}^G$, representing
intercepts in a multi-logit regression.  $\theta_g$ represents the
relative abundance of sequence $g$ in the transcriptome.

\subsection{Parameterizing simplexes}

A $K$-\emph{simplex} is a $K$-vector $\theta$ of non-negative values
such that $\textrm{sum}(\theta) = 1.$  An arbitrary $K$-vector $\alpha
\in \mathbb{R}^K$ can be transformed to a simplex using the softmax
function,
\[
  \textrm{softmax}(\alpha)
  = \frac{\exp(\alpha)}
         {\textrm{sum}(\exp(\alpha))},
\]
where $\exp(\alpha)$ is defined elementwise.   By construction,
$\textrm{softmax}(\alpha)$ is a simplex, because
$\textrm{softmax}(\alpha)_i > 0$ and
$\textrm{sum}(\textrm{softmax}(\alpha)) = 1$.

As a function from $K$-vectors to $K$-simplexes, softmax is many to
one, because adding a constant to each component of $\alpha$ leads to
the same result,
\[
  \textrm{softmax}(\alpha)
  = \textrm{softmax}(\alpha + \lambda \cdot \textbf{1}_K),
\]
where $\lambda \in \mathbb{R}$ and $\textbf{1}_K$ is $K$-vector
of ones.

The function softmax0 defines a smooth, one-to-one mapping from
$\mathbb{R}^{K-1}$ to $K$-simplexes by
\[
  \textrm{softmax0}(\beta) = \textrm{softmax}([0 \ \, \beta]).
\]
That is, a zero element is appended to the front of the $(K-1)$-vector.
This changes the interpretation of the elements from being only
determined relative to each other to having their scale defined
relative to the fixed first element.

\subsection{Transcriptome matrix}

A sequence $T_g$ in the transcriptome can be transformed into a
$4^K$-simplex representing the probability of observing a given
$K$-mer given a read of transcript $g$.  The entire transcriptome can
then be converted to a $(4^K \times G)$-matrix $X$. where column $g$ is the
simplex representing the probability of a $K$-mer being observed given
that the read was from transcript $T_g$.

\subsubsection{Uniform read location}

Even if the reads are distributed uniformly along a transcript, the
distribution of $K$-mers will not be uniform because of edge effects
and because $K$-mers may appear more than once if $K$ is small.

For example, consider a transcript \texttt{ATGGCAATG} of nine bases.
If reads are size six and we select 4-mers within those reads,
the possibilities are as follows.
\begin{center}
  \begin{tabular}{l|l}
    \textit{Reads} & 4\textit{-mers}
    \\ \hline \hline
    \texttt{ATGGCA} & \texttt{ATGG, TGGC, GGCA}
    \\ \hline
    \texttt{\hspace{0.5em}TGGCAA} & \texttt{\hspace{3em}TGGC, GGCA, GCAA}
    \\ \hline
    \texttt{\hspace{1em}GGCAAT} & \texttt{\hspace{6em}GGCA, GCAA, CAAT}
    \\ \hline
    \texttt{\hspace{1.5em}GCAATG} & \texttt{\hspace{9em}GCAA, CAAT, AATG}
  \end{tabular}
\end{center}
The distribution of 4-mers resulting from uniformly distributed reads
is not expected to be uniform, but rather as follows.
\begin{center}
  \begin{tabular}{r|c||r|c}
    3\textit{-mer} & \textit{Proportion} & 3\textit{-mer} & \textit{Proportion}
    \\ \hline \hline
    \texttt{ATGG} & 1/12 & \texttt{GCAA} & 3/12
    \\ \hline
    \texttt{TGGC} & 2/12 & \texttt{CAAT} & 2/12
    \\ \hline
    \texttt{GGCA} & 3/12 & \texttt{AATG} & 1/12
  \end{tabular}
\end{center}

Assuming each position in the transcript is equally likely to produce
a read of size $J$, then $X_{1:4^K, g}$ is the $4^K$-simplex defined
by composing count functions,
\[
  X_{1:4^K, \, g}
  = \frac{\textrm{count}_K\left(\textrm{count}_J(T_g)\right)}
         {\textrm{sum}\left(\textrm{count}_K\left(\textrm{count}_J(T_g)\right)\right)},
\]
where the outer function $\textrm{count}_K$ is type lifted additively
over functions as in the example.  Specifically, for a sequence $s$,
and integers $K \leq J \leq \textrm{size}(s)$, the $4^K$-vector of
$K$-mer counts found in uniformly distributed reads of size $J$ is
\[
  \textrm{count}_K(\textrm{count}_J(s))
  = \sum_{j = 0}^{4^J - 1} \textrm{count}_J(s)(j) \cdot \textrm{count}_K(j).
\]
In words, the result $\textrm{count}_K(\textrm{count}_J(s))$ is a
function from $K$-mer identifiers to their relative abundance in
uniformly distributed $J$-gram reads over the sequence $s$.  The term
$\textrm{count}_K(j)$ is a sparse vector mapping $K$-mers to their
count in the $J$-mer represented by the integer $j$.  This is then
weighted by $\textrm{count}_J(s)(j)$, which is the count of the $J$-mer $j$ in
the sequence $s$.

\subsubsection{Non-uniform read location}

The probabilty of reads is non-uniform for several reasons.  Two
causes that have large impacts are hexamer (6-mer) binding and
position within the transcript.  In the first case, the probability of
reads being chosen from a transcript varies up to two orders of
mangitude or more based on the hexamer appearing in the first six
positions of the read.  Furthermore, the strength of these effects
depends on the priming protocol used.  In the second case, the
probability of a read can vary up to an order of magnitude or more
based on its relative position along the transcript.

Given the relative probabilities of reads originating at 6-mers, the
uniform transcriptome matrix may be adjusted by reweighting based on
the probability of the 6-mers.

Given a formula for relative probability along the transcript, the
transcriptome matrix may be further adjusted for positional effects.
In the end, the result is still a $(4^K \times G)$ transcriptome
matrix $X$.

Taken together, suppose we have transcript $T_g$ of size $N$, reads
of size $J$, and $p(n)$ is the probability of a read of size $J$
originating from position $n$.

\subsection{Observed data}

The observation $y$ is a sparse $4^K$-vector of $K$-mer counts
corresponding to the shredded reads.

\subsection{Transformed transcriptome matrix}

The transcriptome is representing as a $4^K \times G$ matrix $X$ as
described above.  The parameter $\alpha \in \mathbb{R}^G$ is a
$G$-vector whose values indicate the relative level of expression of
each transcript on the log scale; $\theta = \textrm{softmax}(\alpha)$
is the corresponding $G$-simplex representing the relative abundance
$\theta_g$ of each transcript $T_g$ in the transcriptome.

The key step is the transform of the transcript abundances,
represented by $\theta = \textrm{softmax}(\alpha)$, to $K$-mer
abundances, as represented by
$\phi = X \cdot \textrm{softmax}(\alpha)$.  Because
$\textrm{softmax}(\alpha)$ is a $G$-simplex and the columns of $X$ are
$4^K$-simplexes, the product $X \cdot \textrm{softmax}(\alpha)$ is a
$4^K$ simplex---it just reweights the gene-level $K$-mer expressions
represented by the columns by the gene expressions represented by
$\textrm{softmax}(\alpha)$.

\subsection{Sampling distribution}

The sampling distribution $p(y \mid X, \alpha)$  for the observed
$K$-mer counts $y$ given the transcriptome matrix $X$ and log odds
expression simplex $\theta$ is defined to be multinomial,
\[
  y \sim \textrm{multinomial}(X \cdot \textrm{softmax}(\alpha)).
\]

\subsection{Prior}

The prior is a normal centered at the origin,
\[
  \alpha_g \sim \textrm{normal}(0, \lambda),
\]
for some scale $\lambda > 0$.  The smaller the scale $\lambda$, the
more parameter estimates for $\alpha_g$ are shrunk toward zero, and
thus the less relative difference in expression is allowed.

If we intend to get true zero estimates for some genes with a
continuous prior, we will need to make penalized maximum likelihood
estimates with an L1-type penalty.  Keeping to sampling notation, this
is represented by a double-exponential exponential (aka Laplace)
distribution,
\[
  \alpha_g \sim \textrm{double-exponential}(0, \lambda).
\]

\subsection{Posterior}

The posterior is determined by Bayes's rule up to an additive constant
that does not depend on the parameters $\alpha$ as
\[
  \log p(\alpha \mid X, y) = \log p(y \mid X, \alpha) + \log p(\alpha) +
  \textrm{const.}
  \]

\subsubsection{Posterior gradient}

Efficient maximum penalized likelihood estimation and full Bayesian inference
require evaluating gradients of the posterior with respect to the parameters
$\alpha$.  The gradient is\footnote{The derivative is easy to work out
  by passing \url{matrixcalculus.org} the query
  \begin{center}\texttt{y' * log
(X * exp(a) / sum(exp(a))) - a' * a / (2 * lambda)}\end{center}
and then simplifying using $\textrm{softmax}$.}
%
\[
  \begin{array}{l}
  \nabla\!_{\alpha} \, \log p(\alpha \mid X, y) + \log p(\alpha)
  \\[4pt]
  \qquad = \
    t \odot \textrm{softmax}(\alpha)
    - \textrm{softmax}(\alpha)^{\top}\! \cdot t \cdot \textrm{softmax}(\alpha)
    - \frac{\displaystyle \alpha}{\displaystyle \lambda},
\end{array}
\]
where
\[
  t = X^{\top}\! \cdot (y \oslash (X \cdot \textrm{softmax}(\alpha)))
\]
and $\odot$ represents elementwise multiplication and $\oslash$
elementwise division.

\section{Estimating expression}

\subsection{Bayesian posterior mean estimate}

The Bayesian \emph{posterior mean estimate} is the parameter's
expected value conditioned on the observed data,
\begin{eqnarray*}
  \widehat{\alpha}
  & = & \mathbb{E}\!\left[\alpha \mid X, y \, \right]
  \\[6pt]
  & = & \int_{\mathbb{R}^G} \alpha \cdot p(\alpha \mid X, y) \, \textrm{d}\alpha.
\end{eqnarray*}
The posterior mean estimate minimizes expected square estimation error
for $\alpha$ if the model is well specified.

Given a sampler that can produce Markov chain Monte Carlo (MCMC) draws
distributed according to the posterior
\[
  \alpha^{(m)} \sim p(\alpha \mid X, y),
\]
the posterior mean estimate may be calculated as
\[
  \widehat{\alpha} \approx \frac{1}{M} \sum_{m = 1}^M \alpha^{(m)}.
\]
As $M \rightarrow \infty$, the approximation converges to the true
value.  Assuming the Markov chain is geometrically ergodic, the MCMC
central limit theorem applies, providing a convergence rate of
$\mathcal{O}\left(1 / \sqrt{M}\right)$.  In practice, a few hundred
effective draws brings the expected error on $\widehat{\alpha}$ due to
MCMC down to less than a tenth of the posterior standard deviation of
$\alpha$.

\subsection{Maximum a posteriori estimate}

The \emph{max a posteriori} (MAP) estimate for $\alpha$ is given by
choosing the parameter value $\alpha^*$ that maximizes the posterior
density,
\[
  \alpha^* = \textrm{arg\,max}_{\alpha} \,
  \log \textrm{multinomial}(y \mid x \cdot \textrm{softmax}(\alpha))
  + \log \textrm{normal}(\alpha \mid 0, \lambda \cdot \textrm{I}).
\]
This is not a Bayesian estimate because it does not average over
posterior uncertainty.

\subsection{Maximum penalized likelihood estimate}

A pure frequentist estimate may be defined by casting the normal prior
on the parameters as a penalty function based on the $\textrm{L}_2$
norm,
\[
  -\frac{1}{2 \cdot \lambda^2} \cdot \alpha^{\top}\!\! \cdot \alpha.
\]

Replacing the normal prior in the definition of the MAP estimate with
the $\textrm{L}_2$ penalty defined above, the
\emph{penalized maximum likelihood estimate} (MLE) is defined as
\[
  \alpha^* = \textrm{arg\,max}_{\alpha} \,
  \log \textrm{multinomial}(y \mid x \cdot \textrm{softmax}(\alpha))
  - \frac{1}{2 \cdot \lambda^2} \cdot \alpha^{\top}\!\! \cdot \alpha.
\]

\section*{References}

\begin{itemize}
\item Biases in Illumina transcriptome sequencing caused by random
  hexamer priming Kasper D. Hansen,1,* Steven E. Brenner,2 and
  Sandrine Dudoit1,3.  Nucleic acids research.
\end{itemize}

\end{document}


\chapter{Static Gesture Recognition}\label{staticChapter}

As mentioned in Subsection~\ref{DynamicStaticText}, the gestures can be divided into two main groups: static gestures and dynamic gestures.
The static gestures can be understood as a position and orientation of fingers and a hand in a single moment. The dynamic gestures are defined as a movement of hands in time.
The problem of static gesture recognition is a subject of this chapter.
The proposed approach is presented, followed by the introduction to the evaluation scheme.
In the last section, the performed experiments are described, which were used to examine the effectiveness of proposed approach.

\section{Proposed Methods}

The static gesture recognition problem can be stated as a problem invariant to time.
That means that for each detected hand, it's position and orientation can be treated as a new data point, uncorrelated to previously shown gestures.
With this assumption, one can easily generate multiple samples from the sensors in short time, but it also gives an opportunity to look at the static gesture recognition problem as a problem of classification.

In literature, most of the approaches uses two-dimensional representation of gestures, which makes recognition problems relatively simple and therefore allows to use simple classification algorithms, e.g., k-NNs~\cite{gestureRecognitionToolbox}.
The three-dimensional representation of data is more complicated to model by the set of features and finally successfully label.
The 3D data yield by the sensor is represented in the sensor's coordinate system.
Due to this fact, even a small change of the position or orientation of a hand with respect to the location of the sensor can negatively affect the gesture recognition system.
All of those distortions should not prevent the system from recognizing those gestures if they are similar.
To meet those requirement, it is needed to define what is the ``small'' change in orientation resulting in treating the static gestures as the same one.

\begin{figure}[htb]
\centering
 \includegraphics[width=0.6\columnwidth]{figures/SVM.png}
 \caption[]{SVM is a classification algorithm looking for the hyperplane that maximizes the margin between classes\footnotemark}
 \label{svmmargin}
\end{figure}

In application of the library presented in this thesis, it is assumed that the learning process can be done offline, while strict online requirements has to be met for the recognition part.

To meet listed requirements, the Support Vector Machines (SVMs)\cite{Cortes:SVM} were used as a robust classification algorithm.
The SVMs were chosen as there exist a solid mathematical background supporting the simple idea of maximizing the margin between classes.
The SVMs are popular in the recent research trends and are commonly used in biology, robotics or IT for solving data classification problems.
Another advantage is the existence of the open-source library libSVM \cite{libSVM}, which contains an efficient implementation of the SVM in many programming languages.
In the original work, SVMs were designed to be able to classify between two classes, but the idea was expanded to utilize the one-vs-all classification allowing to differentiate between multiple classes.
This might be a drawback, as for $n$ classes, it is necessary to train $n$ SVMs, each to classify one class against all samples from the rest of the classes.
The efficiency of SVMs depends on correctly choosing the kernel function used to map the separation problem into higher dimension with expectation to achieve a classification problem that can be separated.
There exists several kernel functions:
\begin{itemize}
\item linear: $K(x_i, x_j) = x_i^Tx_j$,
\item polynomial: $K(x_i, x_j) = (\gamma x_i^Tx_j + r)^d, \gamma > 0$,
\item radial basis function (RBF): $K(x_i, x_j) = exp(-\gamma ||x_i - x_j||^2), \gamma > 0$,
\item sigmoid: $K(x_i, x_j) = tanh(\gamma x_i^Tx_j+r)$,
\end{itemize}
where $\gamma$, $r$, and $d$ are kernel parameters.
According to the authors of the library \cite{libSVM}, linear kernels perform the best, when used for linearly separable problems, while RBF kernels are the most versatile ones and are recommended for most of the applications.

\footnotetext{\url{http://en.wikipedia.org/wiki/File:Svm_max_sep_hyperplane_with_margin.png}}

The problem of classification assumes that each sample consists of set of features, which describe a sample and can be used to distinguish it from the other samples.
Additionally, each sample has a known or unknown label, which define the membership of the sample to the classification class.
The samples with known labels can be used to train the classification system.
The trained classification system is used to predict the labels for the unlabelled samples.

In application of gesture recognition the classification is divided into two modes: the training part (offline) and the recognition part (online).
The static gesture processing flow is presented in Fig.~\ref{staticsol}.
In the training part, the library is provided with the recorded, labelled samples of static gestures.
From those samples, the sets of features are computed, which are used to train the classifier.
The recognition part assumes to have trained classifier.
The recognition part is provided with samples of static gestures without labels.
For each sample the sets of features are computed and then given as input to the trained classifier.
The classifier provides the information of the predicted gesture's class membership (label) for each input sample.

\begin{figure}[htb]
\centering
 \includegraphics[width=1\columnwidth]{figures/StaticGestures2.jpg}
 \caption[]{Proposed solution blocks for learning and recognition parts of static gestures recognition problem}
 \label{staticsol}
\end{figure}

While the presented approach can be treated as state-of-the-art approach it still cannot be used without defining proper feature sets for gesture recognition.
The naive solution would be to use the raw data from Leap Motion sensor as the feature set.
This solution was tested, but provided poor results as the raw data points are dependent on the position, orientation and scale of hand.
Even a small movement in any direction resulted in decrease of classification accuracy.
The literature suggests to compute a set of features invariant to wanted transformations, which can allow to fully distinguish between different classes \cite{BishopML,libSVM}.
To achieve feature set with those properties, is has to been introduced taking into account the application.
Also, as the gesture recognition problem using the data similar to the data provided by the Leap Motion sensor has not been yet examined by the researches, seeking right feature set is a task of the thesis.
The task is approached in experimental Section~\ref{static:exp}.

\section{Evaluation Methodology}

\subsection{Assumptions}\label{staticAssumptions}
To provide a user with a library working in different conditions, it was assumed that a gesture is treated as the same one independently with respect to the translation, rotation and scale of the hand.
This assumption means that the static gesture rotated by unknown angles, translated in the sensor coordinate system and also with different hand sizes should still be recognized as the same gesture.
Invariance to the rotation, translation and scale poses a great challenge to the recognition, but allows the future users of the API to fully utilize the power of the library.
It is worth mentioning that, it does not reduce the possible applications of the library, as an assignment of a static gesture to an already defined class allows to find the transformation between the model of the class and the observed gesture.
This transformation can be used to examine the parameters of the instance of the model, e.g., rotation of the hand.

\subsection{Recorded Datasets}

To propose and test the quality of the features ten static gestures were chosen:
\begin{enumerate}
\item the peace sign,
\item a fist,
\item full hand with space between each finger,
\item ``I love you'' sign from American Sign Language,
\item sign ``gun'' created by putting thumb and forefinger up, while holding the rest fingers in a fist,
\item all fingers in a fist with exception of thumb, which is up,
\item the sign X made with the forefingers of both hands,
\item the sing ``Time'' used e.g. by coaches in basketball games.
\item sign simulating rotating a knob by two fingers,
\item sign simulating rotating a knob by five fingers.
\end{enumerate}

\begin{figure}[htb]
\centering
 \includegraphics[width=1.0\columnwidth]{figures/static_gestures.png}
 \caption{Recorded static gestures used for evaluation}
 \label{staticgesturesdata}
\end{figure}
The gestures are also presented in Fig.~\ref{staticgesturesdata}.

The sample data of each gestures were recorded using the continuous mode of recording, while moving the hands in different directions and changing the orientation of the hands.
The hands were moved and rotated as each repeated static gesture is always a little bit different from the previously recorded samples.
In total, for each of the proposed classes, each author of this thesis recorded approximately 1000 samples.
The recorded dataset was called the static 10 set and was used in further evaluation.

Having samples with known labels, the whole dataset was separated into training and testing sets in relation $2:1$.
For the training, the k-fold cross-validation (CV) scheme was used, which searches for optimal $C$ and $\gamma$ parameters of SVM.
This method is used to find the optimal parameters of the classification system, while estimating the performance is done on the testing data not used in the training part.
In a standard version of the CV, the gathered data is divided into two sets: one containing $k-1$ parts of the data and the other $1$ part of the data.
The first is used to train the classification system, while the rest of the gathered data is used to estimate how well the system is learnt.
In the next iteration, the CV parts are shuffled by still having the ratio of training and validation sets.
After the training, the final performance is estimated by calculating the percent of correctly recognized labels to the total size of the testing set.

\section{Experiments}
\label{static:exp}

\subsection{Evaluation of Feature Sets}

The goal of the first experiments was to find the proper set of features. Several feature sets were proposed and tested. The first vector of features consisted of:
\begin{itemize}
\item number of fingers in a frame,
\item euclidean distances between consecutive finger's tips,
\item absolute angles between consecutive fingers.
\end{itemize}

This feature set did not take into account the relative position of fingers to the hand.
The second feature set is the first feature set extended by the distances between consecutive finger tips and the position of the hand's palm.
The third feature set contains features from the second feature set extended by the five angles between fingers and normal of hand's palm.
The firstly tested set of all static gestures contained other then described gestures, but some of them were undistinguishable for the Leap Motion as the gestures did not have any visible fingers.
Few of those gestures like fist or ``Time'' were used in classification to examine, how and if the recorded data with almost no information can be used to classify more challenging gestures.
But for experiments the five gestures set was also chosen, which could be distinguishable using the data provided by Leap Motion.
The gestures: peace, hand, ''I love you'', fist with thump up and rotating knob by 5 fingers were chosen and called the static 5 set.
The experiments were also conducted for the static 5 set.
The results achieved using proposed feature sets on the static 5 set and the static 10 set are presented in Table~\ref{staticfeat}.

\begin{table}[htp!]
	\label{staticfeat}
	\caption{Results obtained by proposed feature sets using the libSVM library}
    \begin{tabular}{ccccc}
    \hline
    ~                                                   & $5$ gestures, CV & $5$ gestures, testing set & $10$ gestures, CV  & $10$ gestures, testing set \\ \hline \hline
    feature set $1$                     & $87.1\%$ & $87.9\%$ & $70.0\%$ & $68.4\%$   \\ \hline
    feature set $2$                     & $87.1\%$ & $87.9\%$ & $70.0\%$ & $68.4\%$          \\ \hline
    feature set $3$                     & $87.1\%$ & $87.9\%$ & $70.0\%$ & $68.4\%$           \\ \hline
    feature set $4$                     & $81.2\%$ & $81.0\%$ & $68.4\%$ & $68.6\%$          \\ \hline
    feature set $5$                     & $86.5\%$ & $85.1\%$ & $77.1\%$ & $77.5\%$          \\ \hline
    feature set $6$                     & $92.8\%$ & $93.1\%$ & $80.5\%$ & $81.2\%$           \\ \hline
    \end{tabular}
\end{table}

For the problem of recognition on the static 5 set, three first feature sets resulted in over $87\%$ recognition rate on testing sets.
The same tests for the problem of recognition of $10$ gestures resulted in lower recognition rates.
For feature sets 1--3 the recognition rate was below $70\%$, which could be unsatisfying from the perspective of the purpose of the application.
The results for feature sets 1--3 are the same, which suggests than additional information in the feature set 2--3 is not used for classification.
The further analysis revealed that the fingers in the data provided by Leap Motion SDK are numbered accordingly to the position in Z axis of the tip of the finger.
This means that when finger's tips are approximately on the same position in Z axis, the numbering can change rapidly and proposed features are compared between different fingers.
To achieve features that would be invariant to the numbering of the fingers, the feature set was slightly modified.
Instead of containing the absolute angles and distances between consecutive fingers, it was proposed to contain the five greatest values of angles and five greatest values of distances between all combinations of finger pairings.
The same sorting approach was used for the angles and distances between fingers and hand's palm.
The feature sets $1$, $2$, $3$ with sorting scheme were respectively called feature sets $4$, $5$, $6$.
Again, the static 5 set and the static 10 set were used to evaluate those methods.
The results are presented in Table~\ref{staticfeat}.
This approach was tested on the same training set and allowed to increase the recognition rate.
The best results in both tasks were achieved in case of feature sets $6$.
The simple alleviation of finger numbering problem allowed to top the previous results with recognition rates $93.096\%$ for the static five set and $81.235\%$ for the static 10 set.

\begin{table}[htp!]
\begin{center}
	\label{staticfeatlin}
	\caption{Results obtained by proposed feature sets using the libLinear library}
    \begin{tabular}{ccccc}
    \hline
    ~                                                   & $5$ gestures, CV & $5$ gestures, testing set & $10$ gestures, CV  & $10$ gestures, testing set \\ \hline \hline
    feature set $1$                     & $78.3\%$ & $78.3\%$  & $50.6\%$ & $50.6\%$ \\ \hline
    feature set $2$                     & $78.3\%$ & $78.3\%$  & $50.6\%$ & $50.6\%$ \\ \hline
    feature set $3$                     & $78.3\%$ & $78.3\%$  & $50.6\%$ & $50.6\%$ \\ \hline
    feature set $4$                     & $78.2\%$ & $78.2\%$  & $50.7\%$ & $50.6\%$ \\ \hline
    feature set $5$                     & $79.5\%$ & $79.5\%$  & $55.3\%$ & $55.3\%$ \\ \hline
    feature set $6$                     & $88.1\%$ & $88.1\%$  & $64.7\%$ & $64.8\%$ \\ \hline
    \end{tabular}
    \end{center}
\end{table}

While using more data and longer feature sets usually allows to achieve better results, it also increases the learning time.
In case of $5000$ training samples the typical training process of radial SVM took approximately $12$ hours on a desktop PC with Intel Core i7 and 6 GB of RAM.
This computing time can be unacceptable by the users of the library.
This is why the tests with another SVM library, libLinear~\cite{libLinear} were performed.
The libLinear's implementation of SVM utilizes linear kernels and is dedicated for large data training sets with multiple number of features.
This library reduced the training time to about $5$ seconds.
Again, the same tests as for the libSVM were performed to compare both approaches.
All achieved results are presented in Table~\ref{staticfeatlin}.
For the static 5 set, the libLinear achieved $88.1\%$ on the testing set while using feature set 6 compared to $93.1\%$ achieved by libSVM in the same condition.
In this case, the libLinear might be good choice as the recognition rate is lower only by about $5\%$.
For the static 10 set, libLinear achieved $64.830\%$ compared to $81.235\%$ of LibSVM, which is a significantly lower recognition rate.
It's up to user to decide which library to use, but in most recognition applications, the library can be learnt offline and only used online.
That is why, the authors of this thesis recommend the SVM with RBF kernels for static gesture recognition task.

From the results obtained by the libSVM and libLinear on different feature sets, the feature set $6$ was chosen as the one yielding the best results and used in further analysis.

\begin{figure}[htb]
\centering
 \includegraphics[width=0.8\columnwidth]{figures/staticClassesRecognitionRates.png}
 \caption{Recognition rates of classes for the feature set $6$}
 \label{staticClassesRecognitionRates}
\end{figure}

For the problem of recognition on the static 10 set, an additional experiment on the testing set was performed, which presents the recognition rates achieved for each class.
As a result, the confusion matrix was computed, which can be used to check which static gesture is hard to recognize. The ig.~\ref{staticClassesRecognitionRates} shows the results of the experiment.
Gestures containing two hands have the smallest recognition rate.
The reason for such low recognition rate can be caused by reading error from the device, which performs poorly with overlapping objects.
For gesture ``Time'', the perpendicular position of hands to the Leap Motion and joined finger tips of one palm to the other are another problem. It can be also noticed that the fist is often confused with exposed thumb gesture (no. $6$).

\subsection{Preprocessing}

Another factor, that might have an influence on the results is the preprocessing part, which should allow to partially remove noise from the data and thus increase the recognition rates.
The preprocessing has been presented in Section~\ref{preprocessingSection}.
The preprocessing operates in the window of hands poses recorded over time, which size can be modified.
The typical library usage allowed to gather data with $60Hz$, while it is assumed that the recognition can be performed with a lower framerate. The difference can be efficiently used by defining the appropriate preprocessing window.
For this reason, the experiments with no preprocessing and preprocessing with width size equal to $5$, $10$, $15$, $20$, $30$ were performed and the influence on the recognition rate was examined.
The results are presented in Table~\ref{staticpre}.
The achieved results confirm the need and importance of proper data preparation in task of data classification.
For gesture recognition task using static 5 set, preprocessing allowed to increase the recognition rate from $93.1\%$ to over $99\%$ for window sizes equal or wider than $15$.
In recognition of static 10 set, the preprocessing allowed to increase recognition rate from $81.2\%$ to over $84\%$ for windows sizes equal or wider than $10$.
From those results, the preprocessing width of $10$ was chosen as the one allowing to significantly improve recognition rate in almost any possible application of the library.
The preprocessing of width $10$ was used for all further experiments if not stated otherwise.

\begin{table}[htp!]
\begin{center}
	\label{staticpre}
	\caption{The recognition rate achieved with feature set $6$ and different sizes of preprocessing window}
    \begin{tabular}{ccccc}
    \hline
    preprocessing                                                   & $5$ gestures, CV & $5$ gestures, testing set & $10$ gestures, CV  & $10$ gestures, testing set \\ \hline \hline
    off                     & $92.8\%$ & $93.1\%$  & $80.5\%$ & $81.2\%$ \\ \hline
    width = $2$               & $95.6\%$ & $96.5\%$  & $82.7\%$ & $83.2\%$ \\ \hline
    width = $5$               & $95.9\%$ & $96.7\%$  & $83.1\%$ & $83.6\%$ \\ \hline
    width = $10$              & $98.8\%$ & $99.0\%$  & $83.6\%$ & $84.1\%$ \\ \hline
    width = $15$              & $99.0\%$ & $99.2\%$  & $84.1\%$ & $84.5\%$ \\ \hline
    width = $20$              & $99.1\%$ & $99.2\%$  & $84.3\%$ & $84.8\%$ \\ \hline
    width = $30$              & $99.2\%$ & $99.4\%$  & $84.8\%$ & $85.3\%$ \\ \hline
    \end{tabular}
    \end{center}
\end{table}

\subsection{Postprocessing}

All of already presented experiments, treated the classification results of consecutive hand poses as time-independent and not correlated with each other.
In real applications, it can be safely assumed that the consecutively detected hands are similar to each other and there is a non-zero probability that those hands define the same gesture.
The remaining question to be answered was the impact of combining the consecutive recognition results for the achieved, total recognition rate.
It is important to use not only the class labels for the tested dataset, but also the measure of classification rate for all possible classes provided by SVM.
This data can be combined to measure the membership rate for each class in a window of chosen width.
Then the predicted class is the class with a maximal measure.
Formally, when there is a need to classify between $k$ classes, the result for $i$-th data in dataset can be represented as:
\begin {equation}
l(i) = [l_{i1}, l_{i2}, ..., l_{ik}],
\end{equation}
where $l_{ik}$ is the probability measure of $i$-th data belonging to the $k$-th class.
Using a window of width $w$, the new estimate of classes l' can be computed using the equation:
\begin{equation}
l'(i,w) = F( l(i-w), l(i+1-w), ..., l(i) ),
\end{equation}
where F represents the aggregation function with $w$ vector arguments, e.g., the sum of elements of each input vector.
The recognized label is the number of the vector component with the highest value:
\begin{equation}
\mathrm{label} = \argmax_{k}{\{r(i,w)_k\}}.
\end{equation}

\begin{figure}[htbp!]
\centering
 \includegraphics[width=0.7\textwidth]{figures/Mul5.png}
\centering
 \includegraphics[width=0.7\textwidth]{figures/Mul10.png}
 \caption{Evaluation of different aggregation operators for result combining in case of different window sizes}
 \label{staticoper}
\end{figure}

The first approach to defining the sum operator is the operator of simple adding the elements of vectors $l$.
The second proposition is to multiple the corresponding elements of vectors $l$.
The third approach utilizes the idea of calculating the median elements of vectors $l$.
The three approaches were compared using feature set 6 with preprocessing width equal to 10 for the static 5 and the static 10s sets already used in previous experiments.
Simultaneously, the test were performed for different widths of window and are presented in Fig.~\ref{staticoper}.
For almost all possible widths, the summation operator demonstrated the best recognition rate.
For 5 static gestures, the summation with width equal to 10 allowed to achieve the recognition rate over $99.5$\% gaining over $0.5\%$ when compared to solution without postprocessing.
Interestingly, windows wider than 12 resulted in lower recognition rate than the result obtained by the window width equal to 10.
For 10 static gesture recognition problem, a window of size 50 allowed to improve the recognition rate by over $5\%$ to the value over $89$\%.
In this case, wider window resulted in better results.
Similarly to the preprocessing window size, also in postprocessing too wide window results in delayed recognition rate of a shown gesture.
Also, too wide window may not lead to better results.
Therefore, the postprocessing window size of 10--15 is recommended by the authors of this thesis.

Using summation as the aggregation operator treats the currently achieved result and the results from the previous classifications as equally affecting the current recognition.
Especially for wider windows, it can be assumed that the current measurement is more important than the measurement from the distant past.
That is why, the idea of weighted sum was introduced.
The chosen weights should have the highest weight for the current measurement and smaller values for results that were achieved earlier in time.

\begin{figure}[htbp!]
\centering
 \includegraphics[width=0.7\textwidth]{figures/gaussSum5.png}
\centering
 \includegraphics[width=0.7\textwidth]{figures/gaussSum10.png}

 \caption{Evaluation of weights for postprocessing distributed accordingly to normal distribution}
 \label{staticgauss}
\end{figure}

For this task, the weights can be taken from half of the Gaussian distribution with maximal peak reached for the currently achieved result with weights slowly decreasing for measurements further away in time.
For Gaussian, the mean was assumed to be equal to $0$.
The standard deviation $\sigma$ was the parameter, for which different values were tested.
The results were obtained on the five and ten static sets.
The achieved results are presented in Fig.~\ref{staticgauss}.
For 5 gestures, small $\sigma$ resulted in the weights equal to $0$ for the wider window size and therefore not using the whole information available in the specified window.
For greater $\sigma$, it can be observed that the achieved recognition rate is similar.
The $\sigma$ value equal to $10$ resulted in the best recognition for almost all window sizes.
For problem of 10 static gestures recognition problem, greater $\sigma$ values produced results that are comparable to the results achieved with the summation as aggregation function.
The usage of different weights also comes with greater computing cost.
This approach did not allow to increase the recognition rate and can be omitted without effecting the recognition.

From the presented results, the summation is recommended as the aggregation operator by the authors of this thesis.

\section{Finger recognition}\label{fingerSection}
Finger recognition module is responsible to verify which particular fingers are detected during gesture recognition. The module can be used for additional processing on the user side, for which the information about the visible fingers can often be significant, It can also assist interpretation of data derived from parametrized gestures. The user can also use the module to better fit dataset features to the characteristics of selected gestures.
\subsection{Methods}
For this module the same classification algorithms (kernel functions) were used as those which had the best results in static gesture recognition. As in the case of static gesture recognition libSVM library was used with RBF kernel.
\subsection{Evaluation methodology} \label{fdEvaluationMethodology}
In the objectives for static gesture recognitions (Subsection~\ref{staticAssumptions}) it was mentioned that the process must be independent of the position, rotation, sizes of hand and fingers. This objective applies also to finger recognition. However, for the fingers recognition one additional objective was determined. This process should be independent of fingers arrangement. For example it does not matter whether the forefinger is straightened or bent, because this is the same finger. For the static gesture recognition fingers arrangement should be taken into consideration, because two static gestures, which use the same fingers and have other arrangement of fingers, should be distinguished.

\subsubsection*{Recorded dataset}
The dataset was collected by two different people. Each of them  recorded 32 classes, which reflect all the possible combinations of fingers arrangements. The next step was to select from 32 classes of gestures, those which are the most frequently used by people in everyday life. Those 15 selected classes contained gestures, which are natural for human and do not cause pain. People use them as specific sign like peace sign. From the dataset four data collections were created used in the experiments:
\begin{itemize}
\item dataset A -- 32 gestures recorded by two people -- this dataset consists of 58614 samples,
\item dataset B -- 15 gestures recorded by two people -- 28729 samples,
\item dataset C -- 32 gestures recorded by one person -- 36190 samples,
\item dataset D -- 15 gestures recorded by one person -- 18611 samples.
\end{itemize}

\subsection{Features}
As mentioned in the previous section it is important that the fingers recognition process is independent of things like position of hand or size of finger. Thus, 6 features were selected, which are independent of following parameters.

\begin{enumerate}
\item Finger count.
\item Distance between two nearest base points of a finger (example of base point has been marked in Fig.~\ref{fingfifffeatures}.1 as point B).
To appoint a finger base point a reversed normalized direction vector has to be multiplied by the length of a finger. Then the beginning of this vector is placed in the finger tip position. The end of the vector indicates the finger base point (Fig.~\ref{fingfifffeatures}.1). An example of distance between two nearest base points of a fingers is showed in Fig.~\ref{fingfifffeatures}.2.
\item Ratio of a finger's thickness to the maximal finger's thickness.
Leap Motion controller can return information about the thickness of the fingers (Fig.~\ref{fingfifffeatures}.3). There are known relationships between the thicknesses of the fingers, for example that the thumb is the thickest finger. Just like in the previous feature ratio was used in order to become independent of size of finger.
\item Angles between two nearest fingers.
In Fig.~\ref{fingfifffeatures}.4  this feature has been shown. It is obtained by calculating the angle between finger direction vectors of two consecutive fingers.
\item Angles between a given finger and the first finger relative to palm position.
To calculate this angle three positions are needed:
\begin{itemize}
\item two finger tip positions,
\item a palm position.
\end{itemize}
The next step is to determine the line segments between palm position and finger tip positions. The searched angle is between two designated segments. This angle is shown in Fig.~\ref{fingfifffeatures}.5.
\end{enumerate}

\begin{figure}[htb]
\centering
 \includegraphics[width=0.75\columnwidth]{figures/fingDiffFeatures.png}
 \caption{Features used for finger recognition}
 \label{fingfifffeatures}
\end{figure}

During testing a new feature was created based on the feature 2 called 2b. This feature is a ratio of distance between two nearest base points of a finger to the minimal (non-zero) distance between two nearest base points. It is very similar to the previous one. The difference is that in this case ratio of distances is used instead of the actual values. Thanks to this, the feature 2b is independent of the size of hand.

\section{Experiments}
Tests were performed using cross validation and testing set. In the case of the testing set ratio of training set to testing set was 2:1.

For the tests several combinations of previously described features were created:
\begin{itemize}
\item 1,2,4
\item 1,3,5
\item 1,3,4,5
\item 1,2,3,4,5
\end{itemize}

All sets of features have been tested for all four datasets described in Subsection~\ref{fdEvaluationMethodology}. The recognition rate can be seen in Table~\ref{findiff}. It can be concluded that the highest recognition rate is achieved when all features are used. However, feature 2 is not independent of the size of the hand. Therefore, a new feature has been designed using the ratio of two values obtained from feature 2. Then the test was performed for a set of: 1, 2b, 3, 4, 5 for all datasets. The result for this test is in the last line of the Table~\ref{findiff}. Interestingly, despite the fact that the modified feature is independent of the size of a hand, feature 2b had an inferior influence on the recognition rate. The feature 2, which operates on the actual value of the distance between fingers, had a greater impact on the recognition rate by about $5.4\%$.

\begin{table}[htp!]
\begin{center}
	\label{findiff}
	\caption{Results obtained by experimental feature sets for different data collections}
    \begin{tabular}{p{1.3cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}}
    \hline
    features & dataset A,\linebreak CV[\%] & dataset A,\linebreak testing set[\%] & dataset B,\linebreak CV[\%] & dataset B,\linebreak testing set[\%] & dataset C,\linebreak CV[\%]& dataset C,\linebreak testing set[\%]  & dataset D,\linebreak CV[\%] & dataset D,\linebreak testing set[\%]  \\ \hline \hline
    1,2,4	& 75.4 & 74.9 & 87.3  & 86.9 & 78.4 & 77.9 & 90.6 & 90.3 \\ \hline
    1,3,5     	& 76.3 & 75.4 & 87.5  & 87.1 & 79.6 & 78.9 & 91.5 & 91.2 \\ \hline
    1,3,4,5    	& 78.1 & 75.4 & 87.5  & 87.1 & 79.6 & 78.9 & 91.5 & 91.2 \\ \hline
    1,2,3,4,5   & 83.2 & 81.5 & 90.3  & 89.8 & 85.8 & 85.1 & 93.0 & 92.8 \\ \hline
    1,2b,3,4,5	& 76.6 & 75.8 & 87.6  & 87.3 & 79.8 & 79.2 & 91.6 & 91.2 \\ \hline
    \end{tabular}
    \end{center}
\end{table}

It is worth to mention that it seemed that the feature 4 (angles between two nearest fingers) will have a substantial contribution to finger recognition. However, the results showed that this feature has impact only on dataset A processed using cross-validation, while in other cases brought nothing.

Distinguishing coefficient of particular classes for a set of features: 1, 2, 3, 4, 5 for 15 classes recorded by two people is shown in Fig.~\ref{classRateFD}.

\begin{figure}[htb]
\centering
 \includegraphics[width=0.75\columnwidth]{figures/classRateFD.png}
 \caption{Recognition rates of 15 classes for finger recognition using dataset B}
 \label{classRateFD}
\end{figure}

The graph indicates that classes with the worst recognition rates are:
\begin{itemize}
\item the clenched fist (no fingers), and
\item the hand with stretched out index finger.
\end{itemize}
The rest of the gesture recognition has a level of approximately 90\% and above. Based on these tests it can be deduced that the fewer fingers to differentiate, the worse the outcome is. This is due to the characteristics of the feature sets, because the vast majority of the features is based on dependency between two fingers. So when the number of fingers is low, the finger recognition module receives too little information to differentiate fingers.

\subsubsection*{Preprocessing}
In the second round of tests it was verified how preprocessing will affect the finger recognition process. The set of features 1, 2, 3, 4, 5, which achieved the best recognition rate in previous test, was also used in this test. Also all datasets (A, B, C, D) were used. For tests the preprocessing width of 4 was chosen.

\begin{table}[htp!]
\begin{center}
	\label{findiffpre}
	\caption{Comparison of the recognition rate achieved with and without preprocessing with feature set 1,2,3,4,5}
    \begin{tabular}{p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}p{1.1cm}}
    \hline
    prepro-cessing & dataset A,\linebreak CV[\%] & dataset A,\linebreak testing set[\%] & dataset B,\linebreak CV[\%] & dataset B,\linebreak testing set[\%] & dataset C,\linebreak CV[\%]& dataset C,\linebreak testing set[\%]  & dataset D,\linebreak CV[\%] & dataset D,\linebreak testing set[\%]  \\ \hline \hline
    on        & 83.3 & 82.8  & 90.5 & 90.0 & 86.5 & 86.0 & 93.3 & 93.0 \\ \hline
    off   	  & 83.2 & 81.5 & 90.3  & 89.8 & 85.8 & 85.1 & 93.0 & 92.8 \\ \hline
    \end{tabular}
    \end{center}
\end{table}

Table~\ref{findiffpre} presents the test results for a set of features: 1, 2, 3, 4, 5 with and without preprocessing. It can be concluded that the use of preprocessing in finger recognition slightly improved the recognition rate. This may be due to selected window width, which makes that while preprocessing is working on one specific frame, it takes into account nine contiguous frames. In this setting small irregularities in the data are corrected. If the window would be bigger, anomalies lasting several tens of frames would also be detected. In this situation, new problems would arise, for example, transitions between classes would be much later detected and thus there would be a lot of long lasting incorrect recognitions.


% chapter included in vclmanual.tex
\documentclass[vcl_manual.tex]{subfiles}
\begin{document}

\chapter{Operators}\label{chap:Operators}

\section{Arithmetic operators}

\flushleft

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{+, ++, +=} \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & addition \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(20, 21, 22, 23);
Vec4i c = a + b;           // c = (30, 32, 34, 36)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{-, --, -=,} unary \texttt{-} \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & subtraction \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(20, 21, 22, 23);
Vec4i c = a - b;           // c = (-10, -10, -10, -10)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{*, *=} \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & multiplication \\ \hline
\bfseries Efficiency & 8 bit integers: poor \newline
16 bit integers: good \newline
32 bit integers: good for SSE4.1 and later instruction set, poor otherwise \newline
64 bit integers: good for AVX512DQ instruction set, poor otherwise \newline
float: good \newline
double: good
 \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(20, 21, 22, 23);
Vec4i c = a * b;           // c = (200, 231, 264, 299)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{/, /=}  (floating point) \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & division \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.0f, 1.1f, 1.2f, 1.3f);
Vec4f b(2.0f, 2.1f, 2.2f, 2.3f);
Vec4f c = a / b;  // c = (0.500f, 0.524f, 0.545f, 0.565f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{/, /=}  (integer vector divided by scalar) \\ \hline
\bfseries Defined for & all classes of 8-bit, 16-bit and 32-bit integers, signed and unsigned. Not available for 64-bit integers \\ \hline
\bfseries Description & division by scalar. Results are truncated to integer. All elements are divided by the same divisor. See page \pageref{IntegerDivision} for explanation
 \\ \hline
\bfseries Efficiency & poor \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
int   b = 3;
Vec4i c = a / b;  // c = (3, 3, 4, 4)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{/, /=}  (integer vector divided by constant) \\ \hline
\bfseries Defined for & all classes of 8-bit, 16-bit and 32-bit integers, signed and unsigned. Not available for 64-bit integers \\ \hline
\bfseries Description & division by compile-time constant. All elements are divided by the same divisor. See page \pageref{IntegerDivision} for explanation \\ \hline
\bfseries Efficiency & medium (better than division by scalar variable). \newline Good if divisor is a power of 2 \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example, signed:
Vec4i  a(10, 11, 12, 13);
Vec4i  b = a / const_int(3);  // b = (3, 3, 4, 4)
// Example, unsigned:
Vec4ui c(10, 11, 12, 13);
Vec4ui d = c / const_uint(3); // d = (3, 3, 4, 4)
\end{lstlisting}

\section{Logic operators} \label{LogicOperators}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textless\textless, \textless\textless= \\ \hline
\bfseries Defined for & all integer vector classes \\ \hline
\bfseries Description & bit shift left. All vector elements are shifted by the same amount. \newline
Shifting left by n is a fast way of multiplying by $2^n$ \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b = a << 2;         // b = (40, 44, 48, 52)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textgreater\textgreater, \textgreater\textgreater= \\ \hline
\bfseries Defined for & all integer vector classes \\ \hline
\bfseries Description & bit shift right. All vector elements are shifted by the same amount.\newline
Unsigned integers use logical shift. \newline
Signed integers use arithmetic shift (i.e. the sign bit is copied). \newline
Shifting unsigned right by n is a fast way of dividing by $2^n$
 \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b = a >> 2;         // b = (2, 2, 3, 3)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & == \\ \hline
\bfseries Defined for & all vector classes \\ \hline
\bfseries Description & test if equal. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(10, 11, 12, 13);
Vec4i  b(14, 13, 12, 11);
Vec4ib c = a == b;    // c = (false, false, true, false)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & != \\ \hline
\bfseries Defined for & all vector classes \\ \hline
\bfseries Description & test if not equal. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(10, 11, 12, 13);
Vec4i  b(14, 13, 12, 11);
Vec4ib c = a != b;    // c = (true, true, false, true)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textgreater \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & test if bigger. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(10, 11, 12, 13);
Vec4i  b(14, 13, 12, 11);
Vec4ib c = a > b;     // c = (false, false, false, true)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textgreater= \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & test if bigger or equal. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(10, 11, 12, 13);
Vec4i  b(14, 13, 12, 11);
Vec4ib c = a >= b;     // c = (false, false, true, true)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textless \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & test if smaller. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(10, 11, 12, 13);
Vec4i  b(14, 13, 12, 11);
Vec4ib c = a < b;       // c = (true, true, false, false)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textless= \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & test if smaller or equal. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(10, 11, 12, 13);
Vec4i  b(14, 13, 12, 11);
Vec4ib c = a <= b;      // c = (true, true, true, false)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \&, \&= \\ \hline
\bfseries Defined for & all vector classes \\ \hline
\bfseries Description & bitwise and \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(20, 21, 22, 23);
Vec4i c = a & b;         // c = (0, 1, 4, 5)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \texttt{$\vert$, $\vert=$} \\ \hline
\bfseries Defined for & all vector classes \\ \hline
\bfseries Description & bitwise or \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(20, 21, 22, 23);
Vec4i c = a | b;         // c = (30, 31, 30, 31)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & \textasciicircum \\ \hline
\bfseries Defined for & all vector classes \\ \hline
\bfseries Description & bitwise exclusive or \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(20, 21, 22, 23);
Vec4i c = a ^ b;         // c = (30, 30, 26, 26)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & $\sim$ \\ \hline
\bfseries Defined for & all vector classes \\ \hline
\bfseries Description & bitwise not \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b = ~a;            // b = (-11, -12, -13, -14)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Operator & ! \\ \hline
\bfseries Defined for & all integer and floating point vector classes \\ \hline
\bfseries Description & logical not. Result is a boolean vector \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i  a(-1, 0, 1, 2);
Vec4ib b = !a;          // b = (false,true,false,false)
\end{lstlisting}

%\indenton  % undo flushleft

\section{Integer division} \label{IntegerDivision}

There are no instructions in the x86 instruction set extensions that are useful for integer vector division, and such instructions might be quite slow if they existed. Therefore, the vector class library is using an algorithm for fast integer division. The basic principle of this algorithm can be expressed in this formula:
\vspacesmall \newline
	$a / b \approx a * (2^n / b) >> n$ \newline
\vspacesmall
This calculation goes through the following steps:

\begin{enumerate}
  \item find a suitable value for n
  \item calculate $2^n / b$
  \item calculate necessary corrections for rounding errors
  \item do the multiplication and shift-right, and apply corrections for rounding errors
\end{enumerate}

This formula is advantageous if multiple numbers are divided by the same divisor b. Steps 1, 2 and 3 need only be done once while step 4 is repeated for each value of the dividend a. The mathematical details are described in the file vectori128.h. (See also T. Granlund and P. L. Montgomery: Division by Invariant Integers Using Multiplication, Proceedings of the SIGPLAN 1994 Conference on Programming Language Design and Implementation)
\vspacesmall

The implementation in the vector class library uses various variants of this method with appropriate corrections for rounding errors to get the exact result truncated towards zero.

The way to use this in your code depends on whether the divisor b is a variable or constant, and whether the same divisor is applied to multiple vectors. This is illustrated in the following examples:

\begin{lstlisting}[frame=none]
// Division example A:
// A variable divisor is applied to one vector
Vec4i a(10, 11, 12, 13);// dividend is an integer vector
int   b = 3;            // divisor is an integer variable
Vec4i c = a / b;        // result c = (3, 3, 4, 4)
\end{lstlisting}

\begin{lstlisting}[frame=none]
// Division example B:
// The same divisor is applied to multiple vectors
int b = 3;              // divisor
Divisor_i divb(b);      // this object contains the results
                        // of calculation steps 1, 2, and 3
for (...) {             // loop through multiple vectors
    Vec4i a = ...       // get dividend
    a = a / divb;       // do step 4 of the division
    ...                 // store results
}
\end{lstlisting}

\begin{lstlisting}[frame=none]
// Division example C:
// The divisor is a constant, known at compile time
Vec4i a(10, 11, 12, 13);     // dividend is integer vector
Vec4i c = a / const_int(3);  // result c = (3, 3, 4, 4)
\end{lstlisting}

Explanation:

The class \codei{Divisor\_i} in example B takes care of the calculation steps 1, 2 and 3 in the algorithm described above. The overloaded \codei{/} operator takes a vector on the left hand side and an object of class \codei{Divisor\_i} on the right hand side. This object is created before the loop with the divisor as parameter to the constructor. We are saving time by doing this time-consuming calculation only once while step 4 in the calculation is done multiple times inside the loop by \codei{a = a / divb;}
\vspacesmall

In example A, we are also creating an object of class \codei{Divisor\_i}, but this is done implicitly. The compiler sees an integer on the right hand side of the \codei{/} operator where it needs an object of class \codei{Divisor\_i}, and therefore converts the integer \codei{b} to such an object by calling the constructor \codei{Divisor\_i}(int).

\vspacesmall
The following divisor classes are available:

\vspacesmall
\begin{tabular}{|p{50mm}|p{50mm}|}
\hline
\bfseries Dividend vector type & \bfseries Divisor class required \\ \hline
Vec16c, Vec32c , Vec64c & Divisor\_s \\ \hline
Vec16uc, Vec32uc, Vec64uc & Divisor\_us \\ \hline
Vec8s, Vec16s , Vec32s & Divisor\_s \\ \hline
Vec8us, Vec16us , Vec32us & Divisor\_us \\ \hline
Vec4i, Vec8i, Vec16i & Divisor\_i \\ \hline
Vec4ui, Vec8ui, Vec16ui & Divisor\_ui \\ \hline
\end{tabular}
\vspacesmall

If the divisor is a constant and the value is known at compile time, then we can use the method in example C. The implementation here uses macros and templates to do the calculation steps 1, 2 and 3 at compile time rather than at execution time. This makes the code even faster. The expression to put on the right-hand side of the \codei{/} operator looks as follows:

\vspacesmall
\begin{tabular}{|p{50mm}|p{50mm}|}
\hline
\bfseries Dividend vector type & \bfseries Divisor expression \\ \hline
Vec16c, Vec32c, Vec64c & const\_int \\ \hline
Vec16uc, Vec32uc, Vec64uc & const\_uint \\ \hline
Vec8s, Vec16s, Vec32s & const\_int \\ \hline
Vec8us, Vec16us, Vec32us & const\_uint \\ \hline
Vec4i, Vec8i, Vec16i & const\_int \\ \hline
Vec4ui, Vec8ui, Vec16ui & const\_uint \\ \hline
\end{tabular}
\vspacesmall

The compiler will generate an error message if the parameter to \codei{const\_int} or \codei{const\_uint} is not a valid compile-time constant. (A valid compile time constant can contain integer literals and operators, as well as macros that are expanded to compile time constants, but not ordinary function calls).
\vspacesmall

A further advantage of the method in example C is that the code is able to use different methods for different values of the divisor. The division is particularly fast if the divisor is a power of 2. Make sure to use \codei{const\_int} or \codei{const\_uint} on the right hand side of the \codei{/} operator if you are dividing by 2, 4, 8, 16, etc.
\vspacesmall

Division is faster for vectors of 16-bit integers than for vectors of 8-bit or 32-bit integers. There is no support for division of vectors of 64-bit integers. Unsigned division is faster than signed division.

\chapter{Functions}\label{chap:Functions}

\section{Integer functions}
\flushleft

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & horizontal\_add \\ \hline
\bfseries Defined for & all integer vector classes \\ \hline
\bfseries Description & calculates the sum of all vector elements \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
int   b = horizontal_add(a);  // b = 46
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & horizontal\_add\_x \\ \hline
\bfseries Defined for & all 8-bit, 16-bit and 32-bit integer vector classes \\ \hline
\bfseries Description & calculates the sum of all vector elements. The sum is calculated with a higher number of bits to avoid overflow
 \\ \hline
\bfseries Efficiency & medium (slower than horizontal\_add) \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i   a(10, 11, 12, 13);
int64_t b = horizontal_add_x(a);  // b = 46
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & horizontal\_min, horizontal\_max \\ \hline
\bfseries Defined for & all integer vector classes \\ \hline
\bfseries Description & Returns the lowest or highest element in a vector.\newline VCL version 2.00 or later \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(1, 8, -5, 3);
int   b = horizontal_min(a);  // b = -5
int   c = horizontal_max(a);  // c =  8
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & add\_saturated\\ \hline
\bfseries Defined for & all 8-bit, 16-bit and 32-bit integer vector classes \\ \hline
\bfseries Description & same as operator +. Overflow is handled by saturation rather than wrap-around \\ \hline
\bfseries Efficiency & fast for 8-bit and 16-bit integers. Medium for 32-bit integers \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(0x10000000,  0x20000000,  0x30000000,  0x40000000);
Vec4i b(0x30000000,  0x40000000,  0x50000000,  0x60000000);
Vec4i c = add_saturated(a, b);
//  c = (0x40000000,  0x60000000,  0x7FFFFFFF,  0x7FFFFFFF)
Vec4i d = a + b;
//  d = (0x40000000,  0x60000000, -0x80000000, -0x60000000)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & sub\_saturated\\ \hline
\bfseries Defined for & all 8-bit, 16-bit and 32-bit integer vector classes \\ \hline
\bfseries Description & same as operator -. Overflow is handled by saturation rather than wrap-around \\ \hline
\bfseries Efficiency & fast for 8-bit and 16-bit integers. Medium for 32-bit integers \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(-0x10000000,-0x20000000,-0x30000000,-0x40000000);
Vec4i b( 0x30000000, 0x40000000, 0x50000000, 0x60000000);
Vec4i c = sub_saturated(a, b);
//  c = (-0x40000000,-0x60000000,-0x80000000,-0x80000000)
Vec4i d = a - b;
//  d = (-0x40000000,-0x60000000,-0x80000000, 0x60000000)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & max \\ \hline
\bfseries Defined for & all integer vector classes \\ \hline
\bfseries Description & returns the biggest of two values \\ \hline
\bfseries Efficiency & medium for 64-bit integers with instruction sets lower than SSE4.2. Fast otherwise \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
Vec4i a(10, 11, 12, 13);
Vec4i b(14, 13, 12, 11);
Vec4i c = max(a, b);  // c = (14, 13, 12, 13)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & min \\ \hline
\bfseries Defined for & all integer vector classes \\ \hline
\bfseries Description & returns the smallest of two values \\ \hline
\bfseries Efficiency & medium for 64-bit integers with instruction sets lower than SSE4.2. Fast otherwise \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(10, 11, 12, 13);
Vec4i b(14, 13, 12, 11);
Vec4i c = min(a, b);  // c = (10, 11, 12, 11)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & abs \\ \hline
\bfseries Defined for & all signed integer vector classes \\ \hline
\bfseries Description & calculates the absolute value \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(-1, 0, 1, 2);
Vec4i b = abs(a);     // b = (1, 0, 1, 2)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & abs\_saturated \\ \hline
\bfseries Defined for & all signed integer vector classes \\ \hline
\bfseries Description & calculates the absolute value. Overflow saturates to make sure the result is never negative when the input is INT\_MIN
 \\ \hline
\bfseries Efficiency & medium (slower than abs) \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(-0x80000000, -1, 0, 1);
Vec4i b = abs_saturated(a);  // b=( 0x7FFFFFFF,1,0,1)
Vec4i c = abs(a);            // c=(-0x80000000,1,0,1)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & rotate\_left(vector, int) \\ \hline
\bfseries Defined for & all signed integer vector classes \\ \hline
\bfseries Description & rotates the bits of each element. Use a negative count to rotate right \\ \hline
\bfseries Efficiency & 8 bit: poor \newline
16 bit: medium \newline
32 and 64 bit: good for AVX512DQ instruction set, medium otherwise.
 \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(0x12345678, 0x0000FFFF, 0xA000B000, 0x00000001);
Vec4i b = rotate_left(a, 8);
// b = (0x34567812, 0x00FFFF00, 0x00B000A0, 0x00000100)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function &
vector shift\_bytes\_up\textless n\textgreater(vector)\newline
vector shift\_bytes\_down\textless n\textgreater(vector)
 \\ \hline
\bfseries Defined for & Vec16c, Vec32c, Vec64c \\ \hline
\bfseries Description & shifts the bytes of a vector up or down and inserts zeroes at the vacant places \\ \hline
\bfseries Efficiency &
Vec16c: Good for SSSE3, medium otherwise \newline
Vec32c: Good for AVX2, medium otherwise \newline
Vec64c: Good for AVX512BW, medium otherwise \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec16c a(10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25);
Vec16c b = shift_bytes_up<5>(a);
// b = (0,0,0,0,0,10,11,12,13,14,15,16,17,18,19,20)
\end{lstlisting}

\section{Floating point simple functions}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & horizontal\_add \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & calculates the sum of all vector elements \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.0f, 1.1f, 1.2f, 1.3f);
float b = horizontal_add(a);  // b = 4.6
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & max \newline min \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & returns the biggest/smallest of two values \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}

\codei{max(a,b)} is equivalent to \codei{a > b ? a : b }\\
\codei{min(a,b)} is equivalent to \codei{a < b ? a : b }\\

These functions will not return a NAN if the first parameter is NAN.\\
These functions make no distinction between 0 and -0.
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.0f, 1.1f, 1.2f, 1.3f);
Vec4f b(1.4f, 1.3f, 1.2f, 1.1f);
Vec4f c = max(a, b);         // c = (1.4f, 1.3f, 1.2f, 1.3f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & maximum \newline minimum \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & returns the biggest/smallest of two values \\ \hline
\bfseries Efficiency & good, but slower than max / min \\ \hline
\end{tabular}

These functions are similar to max and min, but sure to propagate NAN values.\\
The sign of zero is ignored unless SIGNED\_ZERO is defined.

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & horizontal\_min, horizontal\_max \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & Returns the lowest or highest element in a vector.\newline
NANs are propagated. The sign of zero is ignored. \newline
VCL version 2.00 or later \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4i a(1, 8, -5, 3);
int   b = horizontal_min(a);  // b = -5
int   c = horizontal_max(a);  // c =  8
\end{lstlisting}

\vspacebig
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & abs \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & gets the absolute value \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(-1.0f, 0.0f, 1.0f, 2.0f);
Vec4f b = abs(a);  // b = (1.0f, 0.0f, 1.0f, 2.0f)
\end{lstlisting}
\vspacesmall

\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & change\_sign\textless i0, i1, ...\textgreater(vector) \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & changes sign of selected vector elements.\newline
Each template parameter is 1 for changing sign of the corresponding element, and 0 for no change. \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(10.0f, 11.0f, -12.0f, 13.0f);
Vec4f b = change_sign<0,1,1,0>(a); // b = (10.f, -11.f, 12.f, 13.f)
\end{lstlisting}
\vspacesmall

\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & sign\_combine(vector a, vector b) \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & Returns the value of a, with the sign inverted if b has its sign bit set.\newline
Corresponds to select(sign\_bit(b), -a, a) \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f  a(-2.0f, -1.0f,  0.0f,  1.0f);
Vec4f  b(-10.f,  0.0f, -20.f,  30.f);
Vec4f  c = sign_combine(a, b);  // c = (2.0f, -1.0f, -0.0f, 1.0f)
\end{lstlisting}
\vspacesmall

\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & sign\_bit \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & returns a boolean vector with true for elements that have the sign bit set, including -0.0, -INF, and -NAN \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f  a(-1.0f, 0.0f, 1.0f, 2.0f);
Vec4fb b = sign_bit(a);  // b = (true, false, false, false)
\end{lstlisting}
\vspacesmall

\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & sqrt \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & calculates the square root \\ \hline
\bfseries Efficiency & poor \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(0.0f, 1.0f, 2.0f, 3.0f);
Vec4f b = sqrt(a);  // b = (0.000f, 1.000f, 1.414f, 1.732f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & square \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & calculates the square \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(0.0f, 1.0f, 2.0f, 3.0f);
Vec4f b = square(a);  // b = (0.0f, 1.0f, 4.0f, 9.0f)
\end{lstlisting}

\label{powVectorInt}
\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & pow(vector x, int n) \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & raises all vector elements to the same integer power.
Will generate a compiler error if n is floating point and vectormath\_exp.h is not included, or in general if n is not of type int.
See page \pageref{ExpLogFunctions} for pow with floating point exponent.
 \\ \hline
\bfseries Precision & slightly imprecise for high values of n due to accumulation of rounding errors \\ \hline
\bfseries Efficiency & medium \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(0.0f, 1.0f, 2.0f, 3.0f);
int   b = 3;
Vec4f c = pow(a, b);  // c = (0.0f, 1.0f, 8.0f, 27.0f)
\end{lstlisting}

\label{powConstVectorInt}
\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & pow\_const(vector x, const int n) \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & raises all vector elements to the same integer power n, where n is a compile-time constant \\ \hline
\bfseries Precision & slightly imprecise for high values of n due to accumulation of rounding errors \\ \hline
\bfseries Efficiency & medium, often better than pow(vector, int) \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(0.0f, 1.0f, 2.0f, 3.0f);
Vec4f c = pow_const(a, 3);  // c = (0.0f, 1.0f, 8.0f, 27.0f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & round \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & round to nearest integer (even value if two values are equally near). The value is returned as a floating point vector.\newline
See also roundi and round\_to\_int32 on page \pageref{roundToInt}. \\ \hline
\bfseries Efficiency & good if SSE4.1 or higher instruction set \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.0f, 1.4f, 1.5f, 1.6f)
Vec4f b = round(a);   // b = (1.0f, 1.0f, 2.0f, 2.0f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & truncate \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & truncates number towards zero. The value is returned as a floating point vector. \newline
See also truncatei and truncate\_to\_int32 on page \pageref{truncateToInt}. \\ \hline
\bfseries Efficiency & good if SSE4.1 or higher instruction set \\ \hline
\bfseries Note & may be slightly inaccurate for x \textgreater{} $10^7$ if instruction set is less than SSE4.1 \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.0f, 1.5f, 1.9f, 2.0f)
Vec4f b = truncate(a);   // b = (1.0f, 1.0f, 1.0f, 2.0f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & floor \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & rounds number towards $-\infty$. The value is returned as a floating point vector \\ \hline
\bfseries Efficiency & good if SSE4.1 or higher instruction set \\ \hline
\bfseries Note & may be slightly inaccurate for x \textgreater{} $10^7$ if instruction set is less than SSE4.1 \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(-0.5f, 1.5f, 1.9f, 2.0f)
Vec4f b = floor(a);   // b = (-1.0f, 1.0f, 1.0f, 2.0f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & ceil \\ \hline
\bfseries Defined for & all floating point vector classes \\ \hline
\bfseries Description & rounds number towards $+\infty$. The value is returned as a floating point vector \\ \hline
\bfseries Efficiency & good if SSE4.1 or higher instruction set \\ \hline
\bfseries Note & may be slightly inaccurate for x \textgreater{} $10^7$ if instruction set is less than SSE4.1 \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(-0.5f, 1.1f, 1.9f, 2.0f)
Vec4f b = ceil(a);   // b = (0.0f, 2.0f, 2.0f, 2.0f)
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & approx\_recipr \\ \hline
\bfseries Defined for & Vec4f, Vec8f, Vec16f \\ \hline
\bfseries Description & fast approximate calculation of reciprocal  \\ \hline
\bfseries Precision & the relative accuracy depends on the instruction set:\newline
Default: $2^{-11}$\newline
AVX512F: $2^{-14}$\newline
AVX512ER: full precision \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.5f, 2.0f, 3.0f, 4.0f)
Vec4f b(0.5f, 1.0f, 0.5f, 1.0f)
Vec4f c = a * approx_recipr(b);  // c approximates a/b
\end{lstlisting}

\vspacesmall
\begin{tabular}{|p{25mm}|p{100mm}|}
\hline
\bfseries Function & approx\_rsqrt \\ \hline
\bfseries Defined for & Vec4f, Vec8f, Vec16f \\ \hline
\bfseries Description & reciprocal square root. Fast approximate calculation of value to the power of -0.5 \\ \hline
\bfseries Precision & the relative accuracy depends on the instruction set:\newline
Default: $2^{-11}$\newline
AVX512F: $2^{-14}$\newline
AVX512ER: full precision \\ \hline
\bfseries Efficiency & good \\ \hline
\end{tabular}
\begin{lstlisting}[frame=none]
// Example:
Vec4f a(1.0f, 2.0f, 3.0f, 4.0f)
Vec4f b = approx_rsqrt(a) * a;  // b approximates sqrt(a)
\end{lstlisting}
\vspacesmall

\end{document}


\documentclass[12pt]{article}

\usepackage{amsmath}
\usepackage[margin=0.75in]{geometry}
\usepackage[numbers]{natbib}
\usepackage{physics}
\usepackage[hyphens]{url}

\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}
\rhead{Creative Destruction Lab}
\lhead{Week 1: Trapped ions}
\rfoot{Page \thepage}

\usepackage{graphicx}
\graphicspath{
	{images}
}

\usepackage[hidelinks]{hyperref}

\renewcommand{\phi}{\varphi}

\title{Week 1: Simulating quantum advantage with trapped ions}
\author{}
\date{}

\begin{document}

\maketitle

\thispagestyle{empty}

\section*{Introduction}

In 2019, the Martinis research group at Google ran an experiment on their Sycamore quantum computer, and they claimed it would take a classical supercomputer 10,000 years to simulate the same experiment~\cite{arute2019quantum}.
Thus, they concluded that this was the world's first example of quantum computational advantage: a quantum computer has drastically outperformed a classical one at a specific task, and the disparity will grow exponentially as the task is made more difficult.
Although different approaches have since been suggested to drastically improve on the classical bound of 10,000 years~\cite{pednault2019leveraging,pan2021simulating}, this remains a landmark feat of engineering on the road to general purpose quantum computation.

The task that was chosen for Google's demonstration is sampling from random circuits composed of 1- and 2-qubit gates.
While this sampling task was initially believed to provide no ``real-world'' applications, potential use cases are beginning to appear~\cite{aaronson2018certified}.
It's important to keep in mind that the current state-of-the-art gate-based quantum computers are limited by errors in the individual gates, which compound to produce unreliable results.
Indeed, the current generation of quantum computers is often referred to as ``noisy intermediate-scale quantum'' (NISQ) to emphasize their lack of error correction.
Using quantum computers for truly useful tasks (such as Shor's algorithm to factor integers out of reach of classical factoring techniques) is estimated to still be a long way into the future.

However, in a clever twist, Ref.~\citenum{arute2019quantum} actually takes advantage of the noisy nature of their quantum computer.
Their main result is the experimental determination of the linear cross-entropy benchmarking (XEB) fidelity~\cite{neill2018blueprint,boixo2018characterizing}:
\begin{align}
	\mathcal{F}_\mathrm{XEB}
	&= 2^N \langle P \rangle - 1
	= \frac{2^N}{S} \sum_{i=1}^S P(x_i) - 1,
\end{align}
where $N$ is the number of qubits, $P(x)$ is the exact probability of observing the bit-string $x$, and the average in angle brackets is performed over $S$ samples.
Ideally, $\mathcal{F}_\mathrm{XEB}$ should be 1, as would be the case if the samples $\{ x_i \}_{i=1}^S$ were drawn from the true distribution $P$; for example, if their quantum computer had no errors.
In practice, $\mathcal{F}_\mathrm{XEB} \ll 1$, due to imperfections in the realizations of the circuits.
Crucially, the authors were able to extrapolate $\mathcal{F}_\mathrm{XEB}$ based on their knowledge of the error rates of their quantum computer!

Superconducting qubits, such as those found in Sycamore are not the only possible foundation for a gate-based quantum computer.
Numerous other experimental implementations exist, but this week we will focus on ion trap quantum computers.
We can model 1-qubit gates as
\begin{align}
	R(\theta, \phi)
	&= \begin{pmatrix}
			\cos{\frac{\theta}{2}} & -i e^{-i \phi} \sin{\frac{\theta}{2}} \\
			-i e^{i \phi} \sin{\frac{\theta}{2}} & \cos{\frac{\theta}{2}} \\
		\end{pmatrix},
\end{align}
and 2-qubit gates as
\begin{align}
	M(\Theta)
	&= \begin{pmatrix}
			\cos{\Theta} & 0 & 0 & -i \sin{\Theta} \\
			0 & \cos{\Theta} & -i \sin{\Theta} & 0 \\
			0 & -i \sin{\Theta} & \cos{\Theta} & 0 \\
			-i \sin{\Theta} & 0 & 0 & \cos{\Theta} \\
		\end{pmatrix},
\end{align}
which can be combined in various ways to create circuits for an ion trap quantum computer~\cite{sorensen1999quantum,pogorelov2021compact}.

The tasks this week will involve applying these gates to a quantum state on a classical computer, with additional gates to simulate errors.
You will see how chaos can arise in individual measurements of random circuits, but also that it can be tamed by averaging over many measurements.

\section*{Suggested weekly tasks}

This section will guide you through several aspects of simulating an ion trap quantum computer using your classical computer.
The starting points provided for these tasks make use of Julia (\url{https://julialang.org/}), PastaQ (\url{https://github.com/GTorlai/PastaQ.jl/}), and ITensor (\url{https://itensor.github.io/ITensors.jl/v0.1/ITensorType.html}) but teams are encouraged to use the environments and libraries they prefer.

\subsection*{Task 1}

The output states of deep random circuits are chaotic, in the sense that slight perturbations in the circuits can lead to very different sampling probabilities.
Ref.~\citenum{arute2019quantum} makes an analogy between the visual patterns produced by a laser and samples produced by a quantum computer:
\begin{quote}
Owing to quantum interference, the probability distribution of the bitstrings resembles a speckled intensity pattern produced by light interference in laser scatter, such that some bitstrings are much more likely to occur than others.
\end{quote}
You will use this analogy to draw ``speckle patterns'' in order to visualize the states generated by perturbed random circuits.

The example script \texttt{run\_random\_circuit.jl} creates and runs a random circuit using the ion trap $R$ and $M$ gates, resulting in a random matrix product state (MPS), which represents a quantum state $\ket{\psi}$.
Extend this script to \textbf{extract the coefficients $\ip{x}{\psi}$ for each bit-string $x$ from the MPS}.
Please note that if you are using ITensor and PastaQ that PastaQ requires ITensor \texttt{v0.1.41}.
Unfortunately, there are functionalities in ITensor \texttt{v0.2.2} that would make this task very fast to complete, but they simply do not work in conjunction with PastaQ.
That being said, there are still many ways to do this Task!

The squared magnitude of each coefficient,
\begin{align}
	P(x)
	&= \abs{\ip{x}{\psi}}^2,
\end{align}
gives the probability of sampling the bit-string $x$ from $\ket{\psi}$.
\textbf{Plot the probability of each $x$ using a dot whose area is proportional to $P(x)$, like in Fig.~\ref{fig:speckle}, for several circuit widths and depths.}

\begin{figure}
	\centering
	\includegraphics{images/speckle_N=004,depth=032}
	\caption{
		A ``speckle pattern'' displaying the probabilities of obtaining each of the 16 possible outcomes when sampling a 4-qubit state.
	}
	\label{fig:speckle}
\end{figure}

\medskip \noindent \textit{Bonus:}
Examine the change in the bond dimension of the generated MPS as the random circuits are made deeper.
Discuss the connection to entanglement entropy.

\subsection*{Task 2}

The outputs of sufficiently deep random circuits are very sensitive to slight perturbations in the circuit parameters, which can be seen by inserting errors.
For example, quantum computers are susceptible to bit-flip errors, modelled using
\begin{align}
	\sigma_x
	&= \begin{pmatrix}
			0 & 1 \\
			1 & 0 \\
		\end{pmatrix}.
\end{align}
Modify \texttt{run\_random\_circuit.jl} to \textbf{run one random circuit multiple times, but with a single bit-flip error at a random location in the circuit each time}.
The resulting speckle patterns should all be quite different; collect them into a collage.

\subsection*{Task 3}

As the depth of the random circuits is increased, the distribution of the probabilities $p = P(x)$ for a fixed output bit-string $x$ tends to the exponential distribution\footnote{
	In this context, it is sometimes referred to as the ``Porter--Thomas distribution''.
}:
\begin{align}
	p \sim 2^N e^{-2^N p},
\end{align}
where $N$ is the number of qubits.
For example, Fig.~\ref{fig:dists} shows that for random circuits on 8 qubits, those of depth 512 result in a cumulative distribution quite close to the expected one,
\begin{align}
	1 - e^{-2^N p},
\end{align}
while those of depth 1 do not.
\textbf{Demonstrate the convergence of the empirical cumulative distribution function of $p$ to the exact CDF of the exponential distribution with increasing circuit depth.}

\begin{figure}
	\centering
	\includegraphics{images/dists_N=008}
	\caption{
		Empirical cumulative distribution functions of the probabilities $p$ for 8-qubit circuits of depth 1 and 512.
	}
	\label{fig:dists}
\end{figure}

\subsection*{Task 4}

One source of error in experimental realizations of quantum circuits is the inability to perfectly implement gates.
This could cause the observed distribution of $p$ to differ from the expected distribution, but visual comparison of entire distributions can be tedious and inexact.
A more quantitative approach to determine the difference between distributions is the linear XEB fidelity, $\mathcal{F}_\mathrm{XEB}$.
This is a single number that encodes the quality of the observed results.

Starting from a sufficiently deep random circuit, \textbf{perturb the angle of each 2-qubit gate by a fixed amount $\Delta \Theta$ to simulate a systematic error}.
Plot $\mathcal{F}_\mathrm{XEB}$ as a function of $\Delta \Theta$.

\subsection*{Business Application}

As apparent from your simulations, random circuits can be implemented on non-fault-tolerant NISQ hardware without error correction.
In the long term, people expect quantum computing to become feasible on universal, gate-based quantum computers with error correction,
which would benefit many applications in industry.
Even with current NISQ hardware, methods exist to perform useful computations, such as the variational quantum eigensolver (VQE)~\cite{peruzzo2014variational},
which you will learn about in Week 3.
However, sampling from random circuits does not naively lend itself to such an obvious use case.
\textbf{Devise a potential business that could be built around sampling-based quantum computing with random circuits in the NISQ era.}
Integrate your idea into this week's \href{https://github.com/CDL-Quantum/CohortProject_2021/blob/main/Week1_Trapped_Ions/Business_Application.md}{Business Application}.

\section*{Additional Challenges}

The following optional tasks are of a broader scope, and might require additional research on your part.

\begin{enumerate}

\item Combine your speckle patterns from Task 2 into an animation that shows the changes in state probabilities as a single bit-flip error is moved around in a deep random circuit.

\item Download some samples and circuits from the data repository for Ref.~\citenum{arute2019quantum} at \url{https://datadryad.org/stash/dataset/doi:10.5061/dryad.k6t1rj8}.
Use these to reproduce $\mathcal{F}_\mathrm{XEB}$ values from the paper.

\item Run your quantum circuits on a trapped ion quantum computer, for example IonQ's quantum computers via Google Cloud Marketplace: \url{https://ionq.com/news/june-17-2021-ionq-quantum-computers-now-available-on-google-cloud/}.

\end{enumerate}

\bibliography{refs}
\bibliographystyle{unsrturl}

\end{document}