\documentclass[11pt]{article}
\usepackage{geometry}
\geometry{letterpaper}
\usepackage[]{graphicx}
\usepackage{amssymb}
\usepackage{enumitem}
\usepackage{hyperref}
\usepackage{amsmath}
\usepackage{multicol}
\usepackage{braket}

\begin{document}

\begin{center}
    {\LARGE CircuitSimulator Documentation }
\vspace{2mm}
    {\large \\ Patrick Rall, Iskren Vankov, David Gosset \\ \vspace{1mm} \today}
\end{center}

%figure environment for multicols
\newenvironment{Figure}
  {\par\medskip\noindent\minipage{\linewidth}}
  {\endminipage\par\medskip}

Simulation of quantum circuits via the conventional matrix-multiplication approach suffers from an exponential blowup in the number of qubits.  Medium size quantum circuits with 20 qubits or more are nearly impossible to simulate this way. On the other hand the Gottesmann-Knill theorem gives a polynomial-time algorithm for simulation of quantum circuits composed entirely of the Clifford operations:

\begin{equation}
    H = \frac{1}{\sqrt{2}} \begin{bmatrix}1 & 1 \\ 1 & -1\end{bmatrix} \hspace{5mm}
    S = \begin{bmatrix}1 & 0 \\ 0 & i\end{bmatrix}
        \hspace{5mm}
        CNOT = \begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0\end{bmatrix}
\end{equation}

In January 2017, Sergei Bravyi and David Gosset augmented the algorithm from the Gottesmann-Knill theorem to also permit simulation of the $T$ gate:

\begin{equation}
    T = \begin{bmatrix}1 & 0 \\ 0 & e^{i\pi/4}\end{bmatrix}
\end{equation}

Their modification retains the polynomial scaling in both the number of qubits and the number of Clifford operations, allowing it to simulate large quantum circuits. The only exponential parameter is the total number of $T$ gates used. Clifford+$T$ is a well-studied universal set of gates, and many interesting quantum circuits are written in Clifford+$T$.

For a full explanation of the algorithm please see the original paper by Bravyi and Gosset at \url{http://arxiv.org/abs/1601.07601}. The purpose of this document is to illustrate how to use the implementation of the algorithm available at \url{https://github.com/patrickrall/CircuitSimulator}. The goal is that a full understanding of the algorithm is not required to use the software.

\clearpage
\tableofcontents

\clearpage
\section{Installation}

The application is written in Python. Python is easy to read even for non-programmers and is available on all platforms. A full implementation of the algorithm in Python should be easy to install on all operating systems, and matches the pseudo-code in \url{http://arxiv.org/abs/1601.07601} almost line-by-line.

The most time consuming part of the algorithm is the calculation of inner products $|\Pi\ket{H^{\otimes t}}|^2$, where $\Pi$ is a projector that depends on the circuit, and $\ket{H^{\otimes t}}$ is a particular quantum state. This highly parallelizable task also has an implementation in C, designed to run on computer clusters using OpenMPI.

\subsection{Python Implementation}

The application was developed in Python 3, although tests showed that Python 2 worked also. Download and install the following, either using the links provided or your favorite package manager:

\begin{description}
    \item[Python 3:] \url{https://www.python.org/downloads/}
    \item[numpy:] \url{https://pypi.python.org/pypi/numpy}
    \item[matplotlib:] \url{http://matplotlib.org/users/installing.html}
\end{description}

Matplotlib is not strictly required for the algorithm itself, but several testing scripts use matplotlib to visualize results.

\subsection{OpenMPI Implementation}

OpenMPI is an implementation of Message Passing Interface, a tool that allows many processes to communicate on a cluster. Small numbers of $T$-gates can be simulated using Python, but for larger numbers the OpenMPI version of the algorithm will be required, either on a single machine or on several.

Download OpenMPI here: \url{https://www.open-mpi.org/}

\noindent Once OpenMPI is installed, C binaries can be compiled using \textit{mpicc} and executed using \textit{mpirun}. To compile the implementation simply change into the root directory and type \textit{make}.

\subsection{Usage}

\clearpage
\section{Performance}
\section{Approximations}

To achieve the fast scaling, the algorithm uses several complicated approximation tricks. You do not need to understand these in order to use the application. The default options make a reasonable compromise between accuracy and performance.

However, the approximations are fully configurable. If you have specific accuracy or performance requirements this section will be helpful.

\subsection{Algorithm background}

The most of the work in the algorithm is to calculate $|\Pi\ket{H^{\otimes t}}|^2$, where $\Pi$ is a projector that depends on the circuit. $\ket{H} = \cos(\pi/8)\ket{0} + \sin(\pi/8)\ket{1}$ is the eigenstate of the Hadamard gate, and is a `magic' state that is used to implement $T$-gates.

The CircuitSimulator application implements efficient manipulations of so-called stabilizer states. $\ket{H}$ is not a stabilizer state, but we can write $\ket{H^{\otimes 2}}$ as a linear combination of two stabilizer states. To write $\ket{H^{\otimes t}}$ we therefore require a linear combination of $\chi = 2^{\lceil t/2\rceil}$ stabilizer states: $\ket{H^{\otimes t}} \propto \sum_{i=1}^\chi \ket{\phi_i}$.  We don't need to worry about normalization since we are calculating the ratio of two such inner products. Expand $|\Pi\ket{H^{\otimes t}}|^2$:
$$\ket{H^{\otimes t}} = \sum^\chi_{i=1} \ket{\phi_i} \hspace{3mm} \to \hspace{3mm} |\Pi\ket{H^{\otimes t}}|^2 = |\bra{H^{\otimes t}}\Pi\ket{H^{\otimes t}}| \propto \left| \sum^\chi_{i=1} \sum^\chi_{j=1}\bra{\phi_i}\Pi\ket{\phi_j}\right|.\label{eq:decomp}$$

There are $O(\chi^2) = O(2^t)$ terms in this sum, so this algorithm runs in $O(2^t)$. For large $t$ this calculation is so slow that Bravyi and Gosset did not include it in their paper. Instead, they developed several approximate techniques that can calculate output probabilities to arbitrarily small error.

\subsection{Inner product approximation} \label{sec:ipa}

To calculate inner products in $O(\chi)$ time rather than $O(\chi^2)$, the algorithm samples $\bra{\theta}\Pi\ket{H^{\otimes t}}$, where $\ket{\theta}$ is a random stabilizer state. Define a random variable $\xi$ which is the average of $N$ samples from this distribution:

$$\xi = \frac{2^t}{N} \sum_{i=1}^N \left| \bra{\theta_i} \Pi \ket{H^{\otimes t}} \right|\hspace{4mm}\to\hspace{4mm} \mathbb{E}(\xi) = | \Pi \ket{H^{\otimes t}}|^2,\hspace{4mm} \sigma = \sqrt{\frac{2^t - 1}{2^t + 1}} \frac{1}{\sqrt{N}} | \Pi \ket{H^{\otimes t}}|^2 $$

\newcommand{\eps}{\varepsilon}
The Chebychev inequality guarantees a multiplicative error of at most $\eps$ with failure probability $p$, provided $N$ is large enough:
$$ N = \sqrt{\frac{2^t - 1}{2^t + 1}} \frac{1}{\eps p^2} \hspace{0.5cm}\to \hspace{0.5cm} \Big|\xi - |\Pi\ket{H^{\otimes t}}|^2 \Big| \leq \eps |\Pi\ket{H^{\otimes t}}|^2 $$

This can be further improved via the median-of-means trick. The software can take the median several bins, each a sample from $\xi$, lowering the failure probability $p$ without needing to increase $L$. Median-of-means can only decrease $p$ and not decrease $\eps$, and is only worth it for $p < 0.0076$. See the comment in \textit{libcirc/innerprod.py} for details.

The number of samples and bins can be set manually. However, you can also set $\eps$ and $p$ and have the software make the best choice for you.\\

\noindent \textbf{Configuration}
\begin{itemize}
    \item This approximation is done by default unless an exact calculation is faster. Force it off using the \textsc{-nosampling} flag (In the code, this switch is called \textit{noapprox}). Force it on using the $\textsc{-forceSample}$ option.
    \item Set the number of samples $L$ directly using the $\textsc{samples=}$ option. $L=2000$ is the default and guarantees $\eps = 0.2$ with $p = 5\%$ for large $t$.
    \item Set the number of bins directly using the $\textsc{bins=}$ option. Default is 1 bin.
    \item Set the multiplicative error $\eps$ with $\textsc{error=}$. Overrides $\textsc{samples=}$ and $\textsc{bins=}$.
    \item Set the failure probability $p$ with $\textsc{failprob=}$. Overrides $\textsc{samples=}$ and $\textsc{bins=}$.
\end{itemize}

\subsection{$\mathcal{L}$ approximation} \label{sec:msa}

The state $\ket{H^{\otimes t}}$ can be exactly decomposed into $2^{\lceil t/2\rceil}$ stabilizer states. It can also be approximately decomposed into  $2^{k}$ stabilizer states, where $k$ can be smaller than $t/2$. The trick is to replace $\ket{H^{\otimes t}}$ with a similar state $\ket{\mathcal{L}}$, which is a function of a $t \times k$ binary matrix $\mathcal{L}$ of rank $k$.

$\mathcal{L}$ is sampled at random. The approximation has fidelity $|\braket{H^{\otimes t}|\mathcal{L}}|^2 = 1-\delta$, where $\delta$ is a function of $\mathcal{L}$. $k$ can be set manually, or calculated for a given expected value of $\delta$. For fixed $\delta$ and large $t$, the scaling is $k \approx 0.23 t$. But for $t < 65$ or less and $\delta = 10^{-5}$, we have $k > t/2$ so this approximation is only worth it for large $t$.

The approximation incurs a constant error $\left|P_\text{out} - P_\text{correct}\right| < \sqrt{\delta}$. This is fine when sampling from the circuit output distribution, but may be unsuitable for calculating probabilities directly.

Calculating $\delta$ is expensive, so it is not done by default. Calculating the rank of $\mathcal{L}$ is expensive, so it is not done by default. A random binary matrix usually has full rank.\\

\noindent \textbf{Configuration}
\begin{itemize}
    \item This approximation is on by default when sampling from the circuit output distribution. It is off by default when calculating probabilities. Force it off using the \textsc{-exactstate} flag (In the code, this switch is called \textit{exact}). Force it on by setting $k$ as described below or with the \textsc{-forceL} option.
    \item Set $k$ directly using the $\textsc{k=}$ option. Software will not override if $k > t/2$, but will override if $k>t$ because then it is impossible for $\mathcal{L}$ to be full rank.
    \item Set expected $\delta$ using the $\textsc{fidbound=}$ option. Default is $\delta = 10^{-5}$. Overridden by $\textsc{k=}$. If the automatically chosen $k$ is larger than $t/2$, the approximation is disabled.
    \item Calculate and print $\delta$ with the $\textsc{-fidelity}$ flag. If $\textsc{fidbound=}$ is set, $\mathcal{L}$ is repeatedly sampled until $\delta$ is good enough.
    \item Calculate the rank of $\mathcal{L}$ with the $\textsc{-rank}$ flag. Will repeatedly sample $\mathcal{L}$ until it has rank $k$.
\end{itemize}

\section{Code Map}

Here is an outline of all files and functions in the code.

\subsection{Front end}
These functions are written in Python only.

\begin{description}
    \item[main] (main.py) Command line interface.\\ Compiles circuit from file using \textbf{compileCircuit} (libcirc/compile/compilecirc.py).\\ Parses arguments and feeds them to \textbf{probability} (libcirc/probability.py)\\ or \textbf{sampleQubits} (libcirc/sample.py).
    \item[sampleQubits] (libcirc/sample.py) Samples from a circuit's output distribution.\\
        Repeatedly calls \textbf{probability} (libcirc/probability.py).
\end{description}

\subsection{Compilation and Gadgetization}

Written in Python only. Together these functions take a circuit file as described in section~\ref{sec:lang}, and calculate projectors $\Pi'$. Then all that is left to do is calculate $|\Pi'\ket{H^{\otimes t}}|^2$.

\begin{description}
    \item[compileCircuit] (libcirc/compile/compilecirc.py) Compiles ``main'' in a given file.\\
        Calls \textbf{circuitSymbols} (same file) to extract ``main'' and all of its dependencies.
        Then calls \textbf{compile} (same file) to return a self-contained circuit.
    \item[circuitSymbols] (libcirc/compile/compilecirc.py) Extracts functions from a circuit file.\\
        Recursively iterates over included files. Yields a dictionary of functions, noting their dependencies. Dictionary is complete in the sense that no dependency is left out.
        Calls \textbf{commentParse} (same file) to remove comments.
    \item[compile] (libcirc/compile/compilecirc.py) Takes a dictionary of symbols as outputted by \textbf{circuitSymbols} (same file). Takes a symbol from that dictionary and compiles it to a completely self-contained circuit using only the gates in \textbf{gateset} (same file). Uses \textbf{standardGate} (same file) to help parse lines of code.
    \item[projectors] (libcirc/compile/projectors.py) Given bitstrings $x$ and $y$ and a circuit $C$, calculates the two projectors $\Pi_G = C(\ket{x}\bra{x} \otimes \ket{y}\bra{y})C^\dagger$ and $\Pi_H = C(\mathbb{I} \otimes \ket{y}\bra{y})C^\dagger$. Calls \textbf{standardGate} (libcirc/compile/compile.py) and \textbf{countY} (libcirc/compile/gadgetize.py) to count the number of bits needed for $x,y$. If $x,y$ are unspecified it chooses them at random. Calls \textbf{gadgetize} (libcirc/compile/gadgetize.py) to actually do the work.
    \item[gadgetize] (libcirc/compile/gadgetize.py) Given bitstrings $x$ and $y$ and a circuit $C$, calculates the projector $\Pi_{x,y} = C(\ket{x}\bra{x} \otimes \ket{y}\bra{y})C^\dagger$.
    \item[truncate] (libcirc/compile/projectors.py) Given a projector $\Pi$ with support on both $n$ circuit qubits and $t$ magic state qubits, truncates the circuit qubits by calculating $\Pi' = (\bra{0^{\otimes n}} \otimes \mathbb{I})\text{ } \Pi \text{ } (\ket{0^{\otimes n}} \otimes \mathbb{I})$. The output projector $\Pi'$ only has support on the magic state qubits.
\end{description}

\subsection{Back end}
These functions are written in Python and in C. File names and function names are identical. `.*' denotes `.c' or `.py', and sometimes `.h'.

\begin{description}
    \item[probability] (libcirc/probability.*) Calculates the probability of making a given measurement from a compiled circuit. Takes \textit{config} dictionary with many options.
    \begin{enumerate}
        \setlength{\itemsep}{1pt}
        \item The Python version calculates projectors $\Pi_G'$ and $\Pi_H'$ using \textbf{projectors} and \textbf{truncate} (libcirc/compile/projectors.py).
        \item Given the inner product approximation parameters (section~\ref{sec:ipa}), the number of samples and bins are calculated.
        \item If using the C back end, the Python version passes the projectors and options to the C executable via the \textit{subprocess} module. The C implementation parses the projectors and inputs. Now either the C implementation or the Python implementation proceeds.
        \item $\textbf{decompose}$ (same file) calculates $\mathcal{L}$ if needed. Depending on $\chi = 2^k$ or $2^{\lceil t/2 \rceil}$, inner product sampling (section~\ref{sec:ipa}) is disabled if an exact calculation is faster.
            \item $|\Pi_G'\ket{H^{\otimes t}}|^2$ and $|\Pi_H'\ket{H^{\otimes t}}|^2$ are calculated. If using the inner product approximation (section~\ref{sec:ipa}), it uses \textbf{multiSampledProjector} (libcirc/innerprod.*). Otherwise it uses \textbf{exactProjector} (libcirc/innerprod.*).
        \item Finally it outputs the probability $P = |\Pi_G'\ket{H^{\otimes t}}|^2 / |\Pi_H'\ket{H^{\otimes t}}|^2$, returning control to Python if necessary.
    \end{enumerate}
    \item[decompose] (libcirc/probability.*) Decomposes $\ket{H^{\otimes t}}$ into $\ket{\mathcal{L}}$ as needed in the $\mathcal{L}$ approximation (section~\ref{sec:msa}). Calculates $k$ given $\delta$ and $t$ if needed. Can also decide to disable the approximation if there is no benefit. Calculates the matrix $\mathcal{L}$ if needed and checks rank and $\delta$ if requested.
    \item[multiSampledProjector] (libcirc/innerprod.*) Given a projector $\Pi$, calculates $|\Pi\ket{H^{\otimes t}}|^2$ using the inner product approximation (section~\ref{sec:ipa}). Takes the median of several $\xi$ bins, using \textbf{sampledProjector} (same file) to calculate $\xi$.
    \item[sampledProjector] (libcirc/innerprod.*) Calculates $\xi$ (section~\ref{sec:ipa}), by averaging many samples of $|\bra{\phi}\Pi\ket{H^{\otimes t}}|$ where $\ket{\phi}$ is a random stabilizer state. Runs in parallel over the samples using \textbf{singleProjectorSample} (same file) to sample $|\bra{\phi}\Pi\ket{H^{\otimes t}}|$.
    \item[singleProjectorSample] (libcirc/innerprod.*) Samples $|\bra{\phi}\Pi\ket{H^{\otimes t}}|$ where $\ket{\phi}$ is a random stabilizer state. Uses the stabilizer library (libcirc/stabilizer/stabilizer.*). $\ket{H^{\otimes t}}$ is decomposed into $2^{t/2}$ stabilizer states, which are prepared using \textbf{prepH} (libcirc/stateprep.*).\\ If using the $\mathcal{L}$ approximation (section~\ref{sec:msa}), it calculates $|\bra{\phi}\Pi\ket{\mathcal{L}}|$. $\ket{L}$ is decomposed into $2^k$ stabilizer states, which are prepared using \textbf{prepL} (libcirc/stateprep.*).

    \item[exactProjector] (libcirc/innerprod.*) Given a projector $\Pi$, calculates $|\Pi\ket{H^{\otimes t}}|^2$ without sampling. Continuing from the equation in section~\ref{eq:decomp}, now using zero-indexing:
        $$ |\Pi\ket{H^{\otimes t}}|^2 = \left| \sum^{\chi-1}_{i=0} \sum^{\chi-1}_{j=0}\bra{\phi_i}\Pi\ket{\phi_j}\right| = \left| \sum^{\chi-1}_{i=0}\left( \bra{\phi_i}\Pi\ket{\phi_i} + \sum^{\chi-1}_{j=i+1}2\text{Re}( \bra{\phi_j}\Pi\ket{\phi_i})\right)\right| $$
        This is a sum of $\chi(\chi+1)/2$ terms. Runs in parallel over an index $0 \leq l < \chi(\chi+1)/2$, using \textbf{exactProjectorWork} to compute the individual inner products.

    \item[exactProjectorWork] (libcirc/innerprod.*) Given an index $l$, calculates a term in the sum above. If the $\mathcal{L}$ approximation (section~\ref{sec:msa}) is used, $\ket{\phi_{i/j}}$ are prepared using \textbf{prepL} (libcirc/stateprep.*). Otherwise \textbf{prepH} (libcirc/stateprep.*) is used.

    \item[prepH] (libcirc/stateprep.*) Given an index $0 \leq i < 2^{\lceil t/2\rceil}$, prepares a state $\ket{\phi_i}$ such that $\ket{H^{\otimes t}} \propto \sum_{i=0}^{2^{\lceil t/2 \rceil}-1} \ket{\phi_i} $. It achieves this using the decomposition $\ket{H^{\otimes 2}} \propto \ket{\alpha} + \ket{\beta}$ where $\ket{\alpha},\ket{\beta}$ are stabilizer states. $\ket{\phi_i}$ is a tensor product of several $\ket{\alpha}$ and $\ket{\beta}$.

    \item[prepL] (libcirc/stateprep.*) \\Given $\mathcal{L}$ and an index $0 \leq i < 2^{ k}$, prepares a state $\ket{\phi_i}$ such that $\ket{\mathcal{L}} \propto \sum_{i=0}^{2^{k}-1} \ket{\phi_i} $.

\end{description}

\subsection{Stabilizer library}

The files libcirc/stabilizer/stabilizer.* contain several functions for manipulating stabilizer states. These are explained in the appendix of \url{http://arxiv.org/abs/1601.07601}, but are listed here for completeness. Instead of using a tableau representation, it uses an affine subspace $\mathcal{K} \subset \mathbb{F}^{n}_2$ of dimension $k$ and a quadratic form $q$ such that $\ket{\phi} = |\mathcal{K}|^{-1/2}\sum_{x \in \mathcal{K}}e^{i \frac{\pi}{4}q(x)} \ket{x}$. In Python, a stabilizer state is a class. In C, a stabilizer state is a struct with a set of functions.

\begin{description}
    \item[printStabilizerState] (C function) and \textbf{display} (Python method) print Python code that initializes the state. Very useful for debugging.
    \item[unpack] (Python method only) prints a state vector representation of the state.
    \item[exponentialSum] $O(k^3)$. Calculates the sum $\sum_{x \in \mathbb{F}^k_2} e^{i\frac{\pi}{4}q(x)}$. Needed by \textbf{innerproduct}. Output is a complex number that can always be represented exactly by three integers $\eps, p, m$, so an exact version outputs these integers instead to avoid numerical error.
    \item[shrink] $O(kn)$. Given a vector $\xi$ and bit $\alpha$, shrinks the space $\mathcal{K}$ so $x \cdot \xi = \alpha$ for all $x \in \mathcal{K}$.
    \item[innerProduct] $O(n^3)$. Calculates the inner product between two stabilizer states. The complex output can also be written in terms of integers $\eps,p,m$.
    \item[randomStabilizerState] Average case $O(n^2)$, worst case $O(n^3)$. Samples a random stabilizer state by starting with $\mathcal{K} = \mathbb{F}^n_2$ and randomly calling \textbf{shrink}.
    \item[measurePauli] $O(n^2)$. Given a Pauli matrix $P = i^m X(\xi)Z(\zeta)$ in the form of an integer $m$ and two bit vectors $\xi,\zeta$, applies the projector onto the positive eigenspace $(1+P)/2$ to the state and returns the new state and its normalization. Uses a subroutine \textbf{extend} to add new vectors to $\mathcal{K}$.

\end{description}

\subsection{Utilities}

These files are written in C only.
\begin{itemize}
    \item libcirc/utils/matrix.h is a custom matrix library for manipulating bit vectors. \mbox{matrix.c} implements these by hand using bitwise operations, and \mbox{matrix-blas.c} implements them using the blas library.
    \item libcirc/utils/comms.h implements wrappers around MPI calls to pass data between threads. It also implements a struct for Pauli projectors.
\end{itemize}

comms.h includes matrix.h, and stabilizer.h includes comms.h. C files include \mbox{stabilizer.h} when stabilizer operations are needed, and include comms.h otherwise.

\section{Measurement}

\section{The Circuit Language} \label{sec:lang}
Lorem ipsum.

\end{document}


\section{Related Work}\label{sec:related}

Next, we situate \toolname with
existing Haskell verifiers.

\spara{Dependent Types} are the basis of many verifiers,
or more generally, proof assistants.
%
Verification of haskell code is possible with
``full'' dependently typed systems like Coq~\cite{coq-book},
Agda~\cite{norell07}, Idris~\cite{Brady13}, Omega~\cite{Sheard06}, and
 {$\lambda_\rightarrow$}~\cite{LohMS10}.
 %
 While these systems are highly expressive,
their expressiveness comes at the cost of making logical validity checking undecidable
thus rendering verification cumbersome.
 %
 Haskell itself can be considered a dependently-typed language,
 as type level computation is allowed via
 Type Families~\cite{McBride02},
 Singleton Types\cite{Weirich12},
 Generalized Algebraic  Datatypes (GADTs)~\cite{JonesVWW06, SchrijversJSV09},
 % more GADS ~\cite{Cheney02, GRDC03},
 and type-level functions~\cite{ChakravartyKJ05}.
 %
Again,
verification in haskell itself turns out to be quite painful~\cite{LindleyM13}.

\spara{Refinement Types} are a form of dependent types where
invariants are encoded via a combination of types and predicates
from a restricted \emph{SMT-decidable}
logic~\cite{Rushby98,pfenningxi98,Dunfield07,GordonTOPLAS2011}.
%
\toolname uses Liquid Types~\cite{LiquidPLDI09}
that restrict the invariants even more
to allow type inference, a crucial feature of a usable type system.
%
Even though the language of refinements is restricted,
as we presented, the combination of
Abstract Refinements~\cite{vazou13}
with sophisticated measure definitions
allows specification and verification of a wide variety
of program properties.

\spara{Static Contract Checkers}
like ESCJava~\cite{ESCJava} are a classical way of verifying
correctness through assertions and pre- and post-conditions.
%
%
%% One can view Refinement Types as a type-based
%% generalization of this approach.
%
%% Classical contract checkers check ``partial''
%% (as opposed to ``total'') correctness (\ie safety)
%% for \emph{eager}, typically first-order, languages
%% and need not worry about termination.
%% %
%% We have shown that in the lazy setting, even
%% ``partial'' correctness requires proving ``total''
%% correctness!
%
\cite{XuPOPL09} describes a static contract checker for
Haskell that uses symbolic execution to unroll procedures
upto some fixed depth, yielding weaker ``bounded'' soundness
guarantees.
%
%% The (checker's) termination requires that recursive
%% procedures only be unrolled up to some fixed depth.
%% While this approach removes inconsistencies, it yields
%% weaker, ``bounded'' soundness guarantees.
%
Similarly, Zeno~\cite{ZENO} is an automatic Haskell
prover that combines unrolling with heuristics for rewriting
and proof-search.
%%Based on rewriting, it is sound but
%%``Zeno might loop forever'' when faced with
%%non-termination.
%
Finally, the Halo~\cite{halo} contract checker encodes
Haskell programs into first-order logic by directly
modeling the code's denotational semantics,
again, requiring heuristics for instantiating axioms
describing functions' behavior.
%
%%Unlike any of the above, our type-based approach does
%%not rely on heuristics for unrolling recursive procedures,
%%or instantiating axioms.
%%%
%%Instead we are based on decidable SMT validity
%%checking and abstract interpretation~\cite{LiquidPLDI08}
%%which makes the tool predictable and the overall workflow
%%scale to the verification of large, real-world
%%code bases.
%%
%%
%%\spara{Tracking Divergent Computations}
%%The notion of type stratification to track potentially
%%diverging computations dates to at least~\citep{ConstableS87}
%%which uses %$\bar{\typ}$
%%to encode diverging terms, and types
%%%$\efix{}$ as $(\bar{\typ}\rightarrow\bar{\typ}) \rightarrow \bar{\typ}$).
%%%
%%More recently, \cite{Capretta05} tracks diverging
%%computations within a \emph{partiality monad}.
%%%
%%Unlike the above, we use refinements to
%%obtain terminating fixpoints %(\etfix{}),
%%which let us prove
%%the vast majority (of sub-expressions) in real world libraries
%%as non-diverging, avoiding the restructuring that would
%%be required by the partiality monad.
%%

\spara{Totality Checking}
is feasible by GHC itself, via an option flag that warns of any incomplete patterns.
%
Regrettably, GHC's warnings are local, \ie
GHC will raise a warning for @head@'s partial definition,
but not for its caller, as the programmer would desire.
%%(2)~ and preservative:
%%a warning will be raised for any incomplete pattern
%%without an attempt to reason if it is reachable or not.
%
Catch~\cite{catch},
a fully automated tool that tracks incomplete patterns,
addresses the above issue
%
by computing functions' pre- and post-conditions.
Moreover, catch statically analyses the code
to track reachable incomplete patterns.
%
\toolname allows more precise analysis than catch,
thus, by assigning the appropriate
types to $\star$Error functions (\S~\ref{sec:totality})
it tracks reachable incomplete patters
%we get catch analysis
as a side-effect of verification.

\spara{Termination Analysis}
is crucial for \toolname's soundness~\cite{LiquidICFP14}
and is implemented in a technique inspired by~\cite{XiTerminationLICS01},
%
Various other authors have proposed techniques to verify termination of
recursive functions, either using the ``size-change
principle''~\cite{JonesB04,Sereni05}, or by annotating types with size indices
and verifying that the arguments of recursive calls have smaller
indices~\cite{HughesParetoSabry96,BartheTermination}.
%
To our knowledge, none of the above analyses have been empirically
evaluated on large and complex real-world libraries.

AProVE~\cite{Giesl11} implements a powerful, fully-automatic
termination analysis for Haskell based on term-rewriting.
%
Compared to AProVE,
encoding the termination proof via
refinements provides advantages that are crucial in
large, real-world code bases.
Specifically, refinements
let us
%
(1) prove termination over a subset
    (not all) of inputs; many functions (\eg @fac@)
    terminate only on @Nat@ inputs and not all @Int@s,
%
(2) encode pre-conditions,
    post-conditions, and auxiliary invariants that
    are essential for proving termination, (\eg @qsort@),
%
(3) easily specify non-standard
    decreasing metrics and prove termination, (\eg @range@).
%
In each case, the code could be (significantly)
\emph{rewritten} to be amenable to AProVE but this defeats
the purpose of an automatic checker.
%

% Could use APROVE, but didn't
% 1. refinements let us reason about /partial functions/
% 2. refinements let us reason about /auxiliary invariants/
% 3. refinements let us specify witness expressions for termination

% Given the existence of such standalone termination provers, one might
% ask why we chose to prove termination ourselves. While certainly
%% We could use one such existing termination analysis; however, we found that
%% encoding the termination proof via refinements provided a synergy that
%% would have been impossible with an external oracle.
%% %
%% Specifically, we
%% found that
%% (1) refinements let us prove termination of \emph{partial functions},
%% (2) refinements let us reason about \emph{auxiliary invariants}, and
%% (3) refinements let us express termination metrics that require
%%     a \emph{witness} without editing the actual code.

% Given our the structure of our proof, with the Termination Oracle
% Hypothesis, one might ask why we chose not to use an existing
% termination prover for Haskell to discharge the termination
% requirement.
% While certainly possible, we found that encoding the
% termination proof via refinements provided a synergy that would have
% been impossible with an external tool like AProVe. Consider the
% following program:
% %
% \begin{code}
%   -- countDown :: Nat -> Int
%   countDown 0 = 0
%   countDown n = countDown (n - 1)
% \end{code}
% %
% We include the type as a comment to show the intended usage. A
% TRS-based oracle will (correctly) say that @countDown@ may not
% terminate, it could be called with a \emph{negative} input! Suppose,
% however, that @countDown@ is only called with @Nat@s. \toolname will
% then \emph{infer} the commented-out type, which will allow it to prove
% that @countDown@ does, in fact, terminate on all \emph{provided}
% inputs. The distinction between terminating on all possible vs.\ all
% actual inputs is crucial for us since we are only concerned with
% termination insofar as it allows us to prove safety properties.

%%\spara{Testing}
%%QuickCheck~\cite{quickcheck} is an automatic random testing tool
%%for Haskell programs.
%%%
%%Compared to numerous existing static contract checkers,
%%testing fails to provide a
%%complete correctness proof of a Haskell program,
%%but is tremendously easier to use.
%%%
%%The heavy usage of QuickCheck by the haskell programmers
%%shows that
%%users do care for verification of their code,
%%but are reluctant to spend much time
%%to get complete correctness proof.
%%%
%%Combining testing and proving
%%(as in~\cite{Dybjer03}) would be ideal.
%%%
%%%%In an attempt to simplify correctness proves ~\citep{Dybjer03}
%%%%leaves some lemmas to be tested only.
%%%
%%One can directly translate
%%a QuickCheck property
%%to a Haskell function that proves its correctness (\ref{sec:xmonad}).
%%%
%%We envision that \toolname
%%will be able to completely prove
%%a great number of QuickCheck properties
%%with a minimum effort from the user.
%%
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "main"
%%% End: