\documentclass{sigplanconf}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{fancyvrb}
\usepackage{url}
\usepackage[utf8]{inputenc}
\usepackage{balance}

\newtheorem*{lemma}{Lemma}
\newtheorem*{corollary}{Corollary}

\begin{document}
\toappear{}

\special{papersize=8.5in,11in}
\setlength{\pdfpageheight}{\paperheight}
\setlength{\pdfpagewidth}{\paperwidth}

% \conferenceinfo{Haskell Symposium 2015}{September, 2015, Vancouver, Canada}
% \copyrightyear{2015}
% \copyrightdata{978-1-nnnn-nnnn-n/yy/mm}
% \doi{nnnnnnn.nnnnnnn}

\title{Improving Haskell Types with SMT}

\authorinfo{Iavor S. Diatchki}
           {Galois Inc., USA}
           {iavor.diatchki@gmail.com}

\maketitle

\begin{abstract}
We present a technique for integrating GHC's type-checker with an SMT solver.
The technique was developed to add support for reasoning
about type-level functions on natural numbers, and so our implementation
uses the theory of linear arithmetic.  However, the approach is not
limited to this theory, and makes it possible to experiment with other
external decision procedures, such as reasoning about type-level booleans,
bit-vectors, or any other theory supported by SMT solvers.
\end{abstract}

\category{D.3.3}{Language Constructs and Features}{Constraints}
\keywords Type systems, SMT, constraint solving

\section{Introduction}

For a few years now, there has been a steady push in the Haskell
community to explore and extend the type system, slowly approximating
functionality available in dependently typed languages
\cite{Eisenberg2012,Lindley2013,Eisenberg2014}.  The additional
expressiveness enables Haskell programmers to maintain more
invariants at compile time, which makes it easier to develop
reliable software, and also makes Haskell a nice language
for embedding domain specific languages \cite{ivory-experience}.
The Haskell compiler is not just a translator from source code
to executable binaries, but it also serves as a tool that
analyzes the program and helps find common mistakes early
in the development cycle.

Unfortunately, the extra expressiveness comes at a cost:
Haskell's type system is by no means simple. Writing
programs that make use of invariants encoded in the
type system can be complex and time consuming.  For
example, often one spends a lot of time proving simple theorems
about arithmetic which, while important to convince the compiler
that various invariants are preserved, contribute little to
the clarity of the algorithm being implemented \cite{Lindley2013}.

Given that in many cases the proofs constructed by the programmers
tend to be fairly simple, we can't help but wonder if there might
be a away to automate them away, thus gaining the benefits of
static checking, but without cluttering the program with trivial
facts about, say, arithmetic.  This paper presents a technique
to help with this problem: we show one method of integrating
an SMT solver with GHC's type checker.  While we present
the technique in the context of Haskell and GHC, the technique
should be applicable to other programming languages and compilers too.

The approach presented in this paper uses similar tools---namely
SMT solvers---to Liquid Haskell \cite{liquid-haskell}. However,
the design and overall goals of the two techniques are somewhat
different and, indeed, it makes perfect sense to use both systems
in a single project.  Liquid Haskell enables Haskell programmers
to augment Haskell definitions with refinements of the types,
which may be used to verify various properties of the program.
The refinement language is separate from the language of Haskell
types---it is quite expressive, and is really aimed at formal
verification.  As such, a function will have its ordinary
type and, in addition, a refinement type, which serves to specify
some aspect of the behavior of the function.  The checks performed
by Liquid Haskell are entirely separate from the ones performed
by GHC's type checker.  This is quite different from the
technique described in this paper, which shows how to integrate
an SMT solver directly into GHC's type checker.  The benefit of
of extending GHC's type checker is that we don't need to
introduce a separate language for specifications, instead
we may reuse types directly.  Ultimately, however, the two
approaches are not at all mutually exclusive.  The next
section gives a brief flavor of what can be achieved using
the techniques from this paper.

\subsection{Examples}

We illustrate the utility of the functionality provided by our
algorithm with a few short examples.  A very common example in
this area is to define a family of singleton types that links
type-level natural numbers to run-time constants that represent
them:
\begin{Verbatim}
data UNat :: Nat -> * where
  Zero :: UNat 0
  Succ :: UNat n -> UNat (n + 1)
\end{Verbatim}
Here we've used a unary representation of the natural numbers,
and each member of the family, \Verb"UNat n", has exactly one
inhabitant, namely the natural number \Verb"n" represented in
unary form.  Because we are using a GADT, we can pattern match
on the constructors of the type and gradually learn additional
information about the value being examined.  The kind \Verb"Nat"
is inhabited by types corresponding to the natural number
(e.g., \Verb"0", \Verb"1", \dots), and \Verb"(+)" is a type-level
function for adding natural numbers.

Next, we define a function to add two such numbers:
\begin{Verbatim}
uAdd :: UNat m -> UNat n -> UNat (m + n)
uAdd Zero     y  = y
uAdd (Succ x) y  = Succ (uAdd x y)
\end{Verbatim}
While this is a simple definition, and we are unlikely
to have gotten it wrong, it is nice to know that GHC
is checking our work!  Had we made a mistake, for
example, by mis-typing the recursive call as \Verb"uAdd x x",
we would get a type error:
\begin{Verbatim}
  Could not deduce (((n1 + n1) + 1) ~ (m + n))
    from the context (m ~ (n1 + 1))
\end{Verbatim}
It is a small detail, but it is worth pointing out that our
GHC extension would have been just as happy had we defined the type
of \Verb"Succ" like this:
\begin{Verbatim}
  Succ :: UNat n -> UNat (1 + n)
\end{Verbatim}
The difference is in the return type, in the one case it is
\Verb"n + 1", and in the other it is \Verb"1 + n".  While
to a human this looks like an insignificant difference,
in many systems it is significantly easier to work
with the one definition, but not the other.

The unary natural numbers are handy if we are planning to
do iteration.  However, if we are working on some sort of
divide-and-conquer algorithm, we often need to split the
input in two.  In this situation, a different family of
singletons is more useful:
\begin{Verbatim}
data BNat :: Nat -> * where
  Empty :: BNat 0
  Even  :: (1 <= n) => BNat n -> BNat (2 * n)
  Odd   :: BNat n -> BNat (2 * n + 1)
\end{Verbatim}
This is another singleton family, where the type \Verb"BNat n"
is inhabited by a single member, \Verb"n".  However, in this
case we learn different information by pattern examining
the values:  an \Verb"Empty" value may not be split,
an \Verb"Even" value may be split into two equal non-empty
parts, while an \Verb"Odd" value may be split into two parts,
and there will be one element left over.

So, how do we add such numbers?  There are more cases to
consider:
\begin{Verbatim}
bAdd :: BNat m -> BNat n -> BNat (m + n)
bAdd Empty x            = x
bAdd x Empty            = x
bAdd (Even x) (Even y)  = Even (bAdd x y)
bAdd (Even x) (Odd y)   = Odd  (bAdd x y)
bAdd (Odd x)  (Even y)  = Odd  (bAdd x y)
bAdd (Odd x)  (Odd  y)  = Even (bSucc (bAdd x y))
\end{Verbatim}
The correctness of this definition is much less obvious,
and we did make a couple of mistakes before getting it
right!  In the last case, we use the auxiliary function
\Verb"bSucc", which increments a binary natural number
by one:
\begin{Verbatim}
bSucc :: BNat m -> BNat (m + 1)
bSucc Empty     = Odd Empty
bSucc (Even x)  = Odd x
bSucc (Odd x)   = Even (bSucc x)
\end{Verbatim}

Note that while these examples are somewhat simplistic,
they demonstrate the utility of the technology, and show that using
the extension feels quite natural to a Haskell programmer.

A more conventional example is the type of fixed-length vectors:
\begin{Verbatim}
data Vec :: Nat -> * -> * where
  Nil  :: Vec 0 a
  Cons :: a -> Vec n a -> Vec (n + 1) a
\end{Verbatim}
Note that this is very similar to \Verb"UNat", except that it also
stores a value in each \Verb"Cons" node.  The operation of appending
two vectors together follows exactly the same pattern as \Verb"uAdd".
An example of a function that is meaningful for vectors, bit no
so much for the unary natural numbers is reversing a vector, which
may be defined as follows using our extension:
\begin{Verbatim}
vecReverse = go Nil
  where
  go :: Vec m a -> Vec n a -> Vec (m + n) a
  go xs Nil = xs
  go xs (Cons y ys) = go (Cons y xs) ys
\end{Verbatim}
This example also illustrates that our extension does not change any type
signature requirements beyond what is already in GHC: the helper
function \Verb"go" needs a type signature, because it pattern-matches
using GADT constructors, however the type of \Verb"reverse" can be
inferred as usual:
\begin{Verbatim}
*Example> :type vecReverse
vecReverse :: Vec n a -> Vec n a
\end{Verbatim}

\subsection{Structure of the Paper}

The rest of the paper is organized as follows:
we start with a brief overview of SMT solvers from a user's perspective
(Section~\ref{smt}).  Then, in Section~\ref{GHC}, we introduce the
basic concepts of GHC's constraints
solver, which is necessary for putting the rest of the paper in context.
Section~\ref{algorithm} contains the details of the algorithm for
integrating an SMT solver with GHC, and Section~\ref{other} explains
other theories that could be added to GHC using the same technique.
Finally, Section~\ref{modular-typechecker} discusses the possibility
of using the ideas in this paper, and previous work on the
implementation of SMT solver, to engineer a modular constraint solver.

\section {SMT Solvers}
\label{smt}

This section contains an introduction to the core functionality
of a typical SMT solver, and may be skipped by readers who are already
familiar with similar tools.

\subsection{The Core Functionality}

SMT solvers, such as CVC4 \cite{cvc4}, Yices \cite{yices}, and Z3
\cite{z3}, implement a wide collection of decision procedures that
work together to solve a common problem.  They have proved to be a useful
tool in both software and hardware verification.
From a user's perspective, the core functionality of an SMT solver is fairly
simple: we may declare uninterpreted constants, assert formulas,
and check if the asserted formulas are {\em satisfiable}.  Checking
for satisfiability simply means that we are asking the
question: are there concrete values for the uninterpreted constants
that make all asserted formulas true. The solver may respond in
one of three ways:
\begin{itemize}
\item \Verb"sat", which means that a satisfying assignment exists,
\item \Verb"unsat", which means that a satisfying assignment does not exist,
\item \Verb"unknown", which means that the solver did not find an answer,
      often this is due to reaching some sort of limit (e.g, the solver
      used up too much time).
\end{itemize}

This example uses the notation of the SMTLIB standard \cite{smtlib2}:

\begin{Verbatim}
(declare-fun x () Int)
(assert (>= x 0))
(assert (= (+ 3 x) 8))
(check-sat)
\end{Verbatim}

The example declares an integer constant, $x$, asserts some formulas---%
using a prefix notation---%
about it, and then asks the solver if the asserted formulas are
satisfiable.  In this case, the answer is affirmative, as choosing
$5$ for $x$ will make all formulas true.  Indeed, if an
SMT solver reports that a set of formulas is satisfiable, typically
it will also provide a {\em satisfying assignment}, which maps
the uninterpreted constants to concrete values that make the
formulas true.

The same machinery may also be used to prove the validity of
a universally quantified formula. The idea is that we use the SMT solver
to look for a {\em counter-example} to the formula, and if no such
example exists, then we can conclude the formula is valid.
For example, if we want to prove that $\forall x. (3 + x = 8) \implies x = 5$,
then we can use the SMT solver to try to find some $x$ that contradicts it:

\break

\begin{Verbatim}
(declare-fun x () Int)
(assert (= (+ 3 x) 8))
(assert (not (= x 5)))
(check-sat)
\end{Verbatim}

To invalidate an implication, we need to assume the premise, and try to
invalidate the conclusion, which is why the second assertion is negated.
In this case the SMT solver tells us that the asserted formulas are not
satisfiable, which means that there are no counter examples to the original
formula and, therefore, it must be valid.

\subsection{Incremental Solvers}

Many SMT solvers have support for asserting formulas {\em incrementally}.
This means that the solver performs a little work every time a new formula
is asserted, rather than collecting all formulas and doing all the work
in batch mode, once we ask about satisfiability.  Furthermore, incremental
solvers have the ability to mark a particular solver state, and then revert
back to it, using a stack discipline.  Here is an example:

\begin{Verbatim}
(declare-fun x () Int)
(assert (= (+ 5 x) 3))
(push 1)
  (assert (>= x 0))
  (check-sat)
(pop 1)
(check-sat)
\end{Verbatim}

This example asks the solver two questions, and the answer to the first
one is \Verb"unsatisfiable", while the answer to the second one is
\Verb"satisfiable" and the solution is \Verb"x = -2".

The \Verb"push" command instructs the solver to save its state, then
proceed as normal.  When the solver encounters a \Verb"pop" command,
it reverts to the last saved state.

This functionality is extremely useful when we want to ask many questions
that are largely the same, and differ only in a few assertions:
we can perform the majority of the work once, and then use
\Verb"push" and \Verb"pop" to just assert the differences.
In our small example, the work for the first assertion is shared in
both calls to \Verb"check-sat".

\section{GHC's Constraint Solver}
\label{GHC}

In this section, we present relevant aspects of GHC's constraint solver.
The full details of the algorithm \cite{outsidein} are beyond the scope
of this paper.

\subsection{Implication Constraints}
During type inference, GHC uses {\em implication constraints}, which do
not appear in Haskell source code directly. An implication constraint is,
roughly, of the form $G\implies W$, where $W$ is a collection
of constraints that need to be discharged, and $G$ are assumptions that
may be used while discharging $W$.  In the GHC source code, the constraints
in $G$ are referred to as {\em given constraints}, while the ones in $W$ are
known as {\em wanted constraints}.  The intuition behind an implication
constraint is that $W$ contains the constraints that were collected
while checking a program fragment, while $G$ contains local assumptions
that are available only in this particular piece of code.  For example,
consider the following program fragment, which uses a GADT:
\begin{Verbatim}
data E :: * -> * where
  EInt :: Int -> E Int

isZero :: E a -> Bool
isZero (EInt x) = x == 0
\end{Verbatim}
When we check the definition of \Verb"isZero", we end up with an implication
constraint like this:
\begin{Verbatim}
(a ~ Int) => (Num a, Eq a)
\end{Verbatim}
Here, \Verb"a" is the type of the pattern variable \Verb"x", the wanted
constraints arise from the use of \Verb"0" and \Verb"(==)" respectively,
and the given constraint is obtained by pattern matching with \Verb"EInt"
because we know that the type parameter of \Verb"E" must be \Verb"Int".

\subsection{The Constraint Solver State}
Implication constraints are solved by two calls to the constraint solver:
the first call processes (i.e., assumes) the given constraints, and the
second one processes the wanted constraints.

The constraint solver has two central pieces of state: the {\em work queue},
and the {\em inert set}.  The work queue contains constraints that need to be
processed, while the inert set contains constraints that have already
been processed.  Constraints are removed---one at a time---from the work queue,
and {\em interacted} with the solver's state.  In the process of interaction
we may solve constraints, generate new work, or report impossible constraints.
If nothing interesting happens, then we relocate the constraint to the
inert set.  It is also possible that during interaction a previously
inert constraint may be reactivated in a rewritten form and re-inserted
in the work queue.  A single invocation of the constraint solver keeps
interacting constraints until the work queue is empty and all constraints
become inert.

\subsection{Type-Checker Plugins}
In this paper we describe a fairly general extension to the constraint
solver, but other researchers are interested in different extensions,
for example, to add support for units of measure \cite{units-of-measure}.

Instead of having many ad-hoc extensions directly in GHC's constraint solver,
we collaborated to define and implement an API for extending GHC's
functionality via {\em type-checker plug-ins}.  At present, we are aware
of three users of this API---our work, a related plug-in that can
solve numerical constraints using custom rewrite rules
\cite{typelits-normalise},
and the work on units of measure \cite{units-of-measure}.

While this infrastructure is still brand new, and not yet stable,
we hope that this mechanism may be useful to other researchers too,
as it makes it fairly easy to experiment with various extensions to
GHC's constraint solver.  Since the framework is aimed at GHC developers,
and is not intended for use in everyday Haskell programming, the plug-ins
have a lot of power.  Indeed, it is not difficult to write a plug-in
that would violate type-safety, in much the same way one could do this
by modifying GHC's constraint solver directly.  The full details of
the type-checker plug-ins API may be found in the GHC User's Guide
\cite{ghc-manual}. Here we discuss only some
of the design choices that we considered, as they have a direct
bearing on the workings of our plug-in.

An interesting question about type-checker plug-ins is: at what point in
GHC's type checker should we invoke them?  The answer to this question
affects their functionality, and the interface that a plug-in would have
to implement.  We considered a few alternatives:
\begin{enumerate}
\item Add a pass to the solver's pipeline, meaning that plug-ins process
constraints one at a time, the way GHC does.
\item Add a call to the plug-ins after the constraints solver has reached
an inert state.
\item Hand off implication constraints directly to the plug-ins,
before invoking GHC's constraint solver.
\end{enumerate}

Option 1 has the closest integration with GHC, but since plug-ins need
to process constraints one at a time, then they often ended up needing
some state, which than has to be stored and managed somewhere,
which became rather complicated.

Option 3 is the most general, as it
would allow for the plug-in to completely override GHC's behavior.  However,
we were more interested in {\em extending} GHC's capabilities rather than
{\em replacing} them, so we opted against it.

We chose option 2 as a nice middle ground. It allows a plug-in to
work with all constraints at once, but it has the benefit that standard work
done by GHC has already happened. So, after the constraint
solver reaches an inert state, it calls into the plug-ins, which examine
the inert state and attempt to make progress.  If they do, then the
constraint solver is restarted and process repeats.

\subsection{Improvement and Derived Constraints}
An improving substitution \cite{improvement} allows us to instantiate variables
in the constraints with types, potentially enabling further constraint
simplification.  Of course, we should only do so, as long
as we preserve soundness and completeness.  In this context, preserving
soundness means that the improved constraints should imply the original
constraints (i.e., we didn't just drop some constraints),
while completeness means that the original constraints imply the improved ones
(i.e., we didn't loose generality by making arbitrary assumptions).

In GHC, improvement happens by rewriting with {\em equality constraints}.
There are three sources of equality constraints:
\begin{itemize}
\item {\em given equalities} are implied by the given constraints,
\item {\em wanted equalities} arise when solving wanted constraints,
\item {\em derived equalities} are implied by the given and wanted constraints,
together.
\end{itemize}

The provenance of an equality constraint determines the kinds of
improvements that we can use it for.  Given equalities have solid proof,
and so we may use congruence to rewrite any other constraint.
On the other hand, wanted constraints are goals that need to be proved,
so they {\em cannot} be used to rewrite given constraints.  We may still
use them to rewrite other wanted or derived constraints though.
Finally, derived equalities are implied by the given and wanted constraints
jointly, so they may not be used in proofs directly,
as doing so may lead to circular reasoning.

Instead, derived equalities help with type inference, by {\em guiding} the
instantiation of {\em unification variables}. In general,
it is always sound to instantiate a unification variable with whatever
type we want: doing so may reject valid programs, but it will not accept
invalid ones, because we still need to solve all necessary constraints.
Of course, we don't want to reject valid programs, and this is where derived
equalities help us: since they are implied by the goals and assumptions
together, we know that we are not loosing any generality when instantiating
as suggested by a derived constraint.  So, for example, if we compute a
derived constraint \Verb"x ~ Int", and we have a wanted constraint
\Verb"Eq x", and \Verb"x" is a unification variable, then we may
rewrite \Verb"Eq x" to \Verb"Eq Int", which we would proceed to solve
as usual.  This is bit subtle:  a derived equality is never used directly
in a proof---instead it allows us to {\em change what we are trying to prove}
by instantiating unification variables, which may help discharge all
constraints that need solving.

\section{Integrating GHC with an SMT Solver}
\label{algorithm}

We describe the algorithm in the context of the theory of linear arithmetic
over the natural numbers, as having a concrete theory makes it easier to explain
the process and illustrate it with examples.  In the next section,
we discuss how, and why, we might want to consider other theories also.

\paragraph{Input.} Currently, the algorithm is implemented as a type-checker
plug-in, and so the input to the algorithm is a collection of constraints
that GHC has determined to be inert. This means that GHC simplified everything
as much as it could, improved using equalities, and cannot see
anything else to do.  The inert constraints are presented to the plug-in
in three collections based on the constraints' provenance: one group contains
the given constraints (i.e., assumptions), one group contains derived
constraints (see Section~\ref{GHC} for details), and one group contains
the wanted constraints, which are the goals that need solving.

\paragraph{Output.} The desired output of the algorithm is as follows:
\begin{itemize}
  \item Solve as many wanted constraints as possible.
  \item Notice if the wanted constraints are inconsistent.
  \item Compute new given and derived equalities to help solve constraints
        that are outside this decision procedure's scope.
\end{itemize}
The first task is the most obvious purpose of the algorithm, but the other
two are quite important also.

Noticing inconsistencies avoids the inference of types with unsatisfiable
constraints.  Consider, for example, a single wanted constraint,
\Verb"(x + 5) ~ 2".  Since we are working with natural numbers,
this constraint has no solution, so we cannot solve it.
As a result, we may end up inferring a type like this:
\begin{Verbatim}
someFun :: forall x. (x + 5) ~ 2 => ...
\end{Verbatim}
While, technically, this is not wrong, it is undesirable because the type
error is clearly in the definition of \Verb"someFun", but we would delay
reporting the error until the function is called.  So, we'd like to
notice constraints that are impossible to solve (i.e., they are logically
equivalent to $\bot$), so that we can report type-errors that are closer
to their true location.  Note that the source of a contradiction may
be a combination of constraints, and not just a single one.  For example,
the constraints \Verb"x >= 5" and \Verb"3 >= x" are inconsistent together,
but have solutions when considered individually.

Computing new equations is also very important, as it enables collaboration
between the plug-in and the rest of GHC (i.e., the main constraint solver,
and other plug-ins).  For example, consider an implication constraint
of the form:
\begin{Verbatim}
forall x. (x + 5) ~ 8  =>  KnownNat x
\end{Verbatim}
In this case, we'd like to use the SMT solver to compute a new given
equality, \Verb"x ~ 3".  Then, this equality can be used by GHC to
rewrite the wanted constraint \Verb"KnownNat x" to \Verb"KnownNat 3"
which, in turn, can be discharged by the custom solver for the \Verb"KnownNat"
class\footnote{The class \Verb"KnownNat" is defined in module
\Verb"GHC.TypeLits".  It is used to implement singleton types linking
type-level literals to their run-time representations as \Verb"Integer".}.
Such collaboration between different solvers is quite common.
Interestingly, this looks a lot like the collaboration between decision
procedures in an SMT solver!  We discuss this observation further
in Section~\ref{modular-typechecker}.

% \subsection{Communicating With The Solver}
% Our implementation uses the \Verb"simple-smt" library \cite{simple-smt}
% to communicate with external SMT solvers.

\subsection{The Language of Constraints}
Our first task is to identify constraints that are relevant to our solver.
In the current implementation, we consider equalities and inequalities
between a subset of the type-expressions of kind \Verb"Nat".
The kind \Verb"Nat" is
inhabited by an infinite family of type-constants:
\begin{Verbatim}
0, 1, 2, .. :: Nat
\end{Verbatim}
These constants may be combined and compared using the following
type-level functions:
\begin{Verbatim}
type family (+)   :: Nat -> Nat -> Nat
type family (*)   :: Nat -> Nat -> Nat
type family (<=?) :: Nat -> Nat -> Bool
\end{Verbatim}
These functions have no user-specified definitions: instead, we extended
the core GHC simplifier with support for forward evaluation on concrete
values, so it will evaluate concrete expressions, such as \Verb"2 + 3".
This simple forward evaluation cleans up the constraints, leaving the more
complex reasoning---involving variables---to the algorithm being presently
described.  Technically, the clean-up is not necessary because the
plug-in will perform as much evaluation as it needs to solve the constraints,
but it is a lot more efficient to simply evaluate known constants without
consulting the external solver.  Also, at present there is no standard
way to declare that these type function are handled by a special solver---%
we could use a closed type family with no equations to prohibit user
defined instances, but this is a bit of an abuse of an unrelated feature
of the type system.

The declaration for \Verb"(<=?)" refers to the kind \Verb"Bool", which
is simply the lifted \Verb"Bool" type.  As expected, it is inhabited by the
empty types \Verb"True" and \Verb"False".   Having \Verb"(<=?)" be a function
that returns a boolean is a little more convenient for programmers than having
a constraint. In this form, a programmer may inspect the result of the
inequality and make a decision based on it.  We can use a simple
abbreviation to implement the corresponding inequality constraint:
\begin{Verbatim}
type (<=) a b  = (a <=? b) ~ True
\end{Verbatim}

The constraints supported by the external solver are summarized by the
following grammar:
\begin{align*}
c & = e \overset {\mathbb{N}} \sim e ~|~  e \overset {\mathbb{B}} \sim e \\
e^\mathbb{N} & = \alpha ~|~ n ~|~ e + e ~|~ n * e \\
e^\mathbb{B} & = \alpha ~|~ \mathrm{False} ~|~ \mathrm{True} ~|~ e \leq^? ~e \\
n          & = 0 ~|~ 1 ~|~ \dots
\end{align*}

\subsection{Importing Constraints}

Of course, general constraints may be more complex.  In particular,
programmers are free to define their own type functions that return
results of kind \Verb"Nat", so it is entirely possible to encounter
constraints like \Verb"(F 3 + 4) ~ 7", where \Verb"F" is some programmer-defined
type-family.  It is also possible to encounter non-linear constraints such
as \Verb"x * y".

The process of identifying relevant constraints is as follows:
\begin{enumerate}
\item Set aside constraints that do not have a relevant top-level predicate
symbol.
\item Import the parameters to the predicates guided by the kind.
\item If we encounter a type outside of our theory, then we name it and replace
      it with a variable.
\item We remember the names assigned to various types, so that we may reuse
      the same name if a type appears multiple times.
\end{enumerate}

For example, the constraint \Verb"(F 3 + 4) ~ 7" will be imported as
\Verb"(x + 4) ~ 7", and we will remember that \Verb"x" stands for \Verb"F 3".
Later on, if we need to return results to the core GHC solver that mention
\Verb"x", we replace it by the original expression, \Verb"F 3".

The process of abstracting foreign constraints makes sense in our context,
because it {\em generalizes} the constraint.  Consider a constraint $C(t)$, and
its generalized form $C(x)$, where the sub-term $t$ is replaced by
the variable $x$, which does not occur in $C(t)$.

\begin{lemma}
If $C(t)$ is satisfiable, then $C(x)$ is also satisfiable.
\begin{proof} This follows because, by definition,
$C(t) \iff C(x) \wedge x = t$. Therefore, if $\sigma$ is satisfying
assignment for $C(t)$, then $\sigma \cup \{ x = \sigma t \}$ is satisfying
assignment for $C(x)$.
\end{proof}
\end{lemma}

\begin{corollary} If $C(x)$ is not satisfiable, then neither is $C(t)$.
This is simply the contrapositive form of the previous Lemma.
\end{corollary}

Recall from Section~\ref{smt}, that to prove something, we make sure
that there are no counter examples.  The Corollary states that if there
are no counter examples to the abstracted constraint, then there will
be no counter-examples to the original constraint as well, and so our
proof is sound.  From a logical stand-point, naming away sub-terms
amounts to trying to prove a more general fact, and so if we can complete
the proof in the more general setting, then the proof will work for
the special case of the original constraint.

\paragraph{Aside.}
The step of naming foreign types is similar to the flattening step performed
by GHC's constraint solver\footnote{GHC's ``flattening'' pass names the
results of all type functions.  This is done before passing constraints
to GHC's internal solver, but the process is reverted before passing the
constraints to the external plug-ins. }.
The main difference being that GHC names every
call to a type-function, while we name only terms outside of the theory.
Still, this duplication of work is somewhat unsatisfactory, and it would
be nice to extend GHC's flattening pass so that it can be reused by
external plug-ins.

\paragraph{Natural Numbers.}
We are interested in working with natural numbers, however, the SMT
decision procedure works with integers.  To work around this mismatch,
we are careful that whenever we declare an SMT variable corresponding
to a type of kind \Verb"Nat", we also add a formula asserting that
the variable is not negative.

\subsection{Communication with the Solver}

Different SMT solvers support different mechanisms for interacting
with other programs.  The most efficient way to interact with a solver
is to link it with the program, and call into the various methods,
using whatever API is exported by the solver.  Unfortunately, this
approach requires commitment to a specific solver as the low-level
API of the solvers differ.

In our work, we wanted to have the flexibility to experiment with
different solvers, so we opted for a slightly less optimal but
considerably more portable approach.  The multitude of SMT languages
has been recognized as a problem by the SMT community, and the
SMT-LIB standard \cite{smtlib2} was developed to address the issue.
A fair number of solvers have support for the standard, so
to communicate with the solver we developed a Haskell library
\cite{simple-smt}, which can interact with an SMT solver process
by using the SMTLIB language.  The library manages the connection
to the solver, and also provides combinators to create terms
in the common SMT theories.  In the future, we may add support for
direct integration with an SMT solver, and the only impact
should be improved performance.

The code samples in the rest of this section use the following
API for interaction with the solver:
\begin{Verbatim}
data Solver :: *
data Expr   :: *
data Result = Sat | Unsat

solverAssert :: Solver -> Expr -> IO ()
solverCheck  :: Solver -> IO Result
solverPush   :: Solver -> IO ()
solverPop    :: Solver -> IO ()
\end{Verbatim}
These correspond directly to the commands used in the examples in
Section~\ref{smt}.

\subsection{Checking for Consistency}

Given some constraints in our theory, we would like to know if a
solution exists.  If the constraints are inconsistent, then we can
terminate the constraint solving problem early, and report an error,
as discussed previously.

To check for consistency, we assert all constraints, and ask the SMT
solver if the result is satisfiable.  If this is not the case, then
we report an error, otherwise we proceed with the algorithm.
\begin{Verbatim}
checkConsistent :: Solver -> [Expr] -> IO Bool
checkConsistent s cs =
  do mapM_ (solverAssert s) cs
     res <- solverCheck s
     return (res == Sat)
\end{Verbatim}

Note that since we are working with generalized constraints, if we find an
inconsistency, then we are sure that we've detected a problem.  However,
if the SMT solver says that the constraints are satisfiable, then
we now that this is the case from the point of view of our theory,
however the constraints might still be unsatisfiable if one took a global
view of the problem.  Consider, for example, \Verb"(F a + 4) ~ 7".
This will get imported into our plug-in as \Verb"(x + 4) ~ 7", which is
satisfiable by \Verb"x = 3".  Now, some other theory might know that
\Verb"F a ~ 3" is not actually possible, but we won't detect this problem
at this stage.

\subsection{Minimizing Conflicts}
If we detect a contradiction, then
we know that there is no possible solution to the constraints.  However,
often only a few of the constraints are involved in the actual problem,
and it is much nicer if we report only them as the cause of the error,
rather than getting a huge error involving all constraints.  If an SMT
solver detects that a collection of assertions is inconsistent, it may
be able to compute an {\em unsatisfiability core}, which is the sub-set
of the assertions that lead to the conflict---exactly what we want!

Unfortunately, not all SMT solvers support this feature and CVC4---%
the SMT solver that we used during the development of this work---%
does not have this ability.  To work around this, we implemented
a custom reduction algorithm which work as follows:
\begin{Verbatim}
reduce :: Solver ->
            [Expr] -> -- part of conflict
            [Expr] -> -- search for conflict
            IO [Expr]
reduce s yes [] = return yes
reduce s yes mb =
  do solverPush s
     search s yes [] mb

search :: Solver ->
          [Expr] -> -- part of conflict
          [Expr] -> -- currently asserted
          [Expr] -> -- search for conflict
          IO [Expr]

search s yes mb (c : cs) =
  do solverAssert s c
     res <- solverCheck s
     case res of
       Unsat ->
         do solverPop s
            solverAssert s c
            reduce s (c : yes) mb

       _ -> search s yes (c : mb) cs

search s yes mb [] = error "Impossible!"
\end{Verbatim}
The algorithm keeps track of constraints that we are certain are part
of the conflict in the variable \Verb"yes".  In addition, the algorithm
has the invariant that the constraints in \Verb"yes" are always asserted
in the solver's state, represented by the variable \Verb"s".
Initially, \Verb"yes" starts off empty.

We search for conflicts in the function \Verb"search", which asserts
constraints one at a time, until a conflict is discovered.  The constraint
that caused the conflict is added to the \Verb"yes" set, and then we
examine the previously asserted constraint, to check if they are necessary
for the conflict.

The reduction process performs in $O(n^2)$ time, where $n$ is the
number of constraints.  This has not been a big problem,
as this reduction happens only when we report errors and, typically,
the number of constraints is fairly low.

Also note that the reduction algorithm may not produce the {\em smallest}
collection of constraints to cause a contradiction.  For example, consider
the constraints $A,B,C$, and suppose that $A,B$ lead to a contradiction
together, and also $C$ causes a contradiction on its own.  Now, depending
on the order in which we process the constraints, we may either compute
$C$ as the result of the reduction, or $A,B$.  This is OK---in this
case the context happens to contain multiple errors, so the reduction
algorithm will simply pick one of them to report.  Of course, a program
would have to eventually fix both errors before the program is accepted.
The important property of the algorithm is that the reduced set does
not contain redundant constraints, in the sense that if we removed
some of the constraints the resulting constraint set would be satisfiable.

\subsection{Improvement}

If all constraint are consistent (i.e., have at least one solution),
then we check for computed equality constraints.  As discussed previously,
these help other parts of the constraint solver to make progress.

It is convenient to compute the improvements right after the consistency
check because at this point we already have all constraints asserted
in the solver's state.  If all constraints in scope are given constraints,
then we also generate given equalities, otherwise we generate derived
equalities.

The current implementation considers three forms of improvement,
two of which are completely generic, and one of which is specific to
linear arithmetic.

\paragraph{Improve to Constant.} As we know that the constraints are
consistent, we can ask the SMT solver for a satisfying assignment.
This assignment contains one possible solution to constraints, but
we should not emit an improving equality unless we are sure that
this is the {\em the only} possible solution.  So, if $x = v$ is
in the satisfying assumption, then we try to prove that the currently
asserted constraints imply this fact.  We do this by temporarily asserting
$x \neq v$, and checking for satisfiability.  If the resulting is unsatisfiable,
then we know that $v$ is the only possible value for $x$,
and we can emit the corresponding improving equation.
\begin{Verbatim}
solverProve :: Solver -> Expr -> IO Bool
solverProve s p =
  do solverPush s
     solverAssert s (SMT.not p)
     res <- solverCheck s
     solverPop s
     return (res == Unsat)

mustBeK :: Solver -> Name -> Value -> IO Bool
mustBeK s x v =
  solverProve s (eq (SMT.const x) (value v))
\end{Verbatim}
This process takes $O(n)$ time, where $n$ is the number of variables.
Note that here we are making use of the incremental capabilities of the
solver, and reusing all asserted constraints, just doing one
additional \Verb"assert" per variable. To see the process in action,
consider the constraint \Verb"(2 * x) ~ 16".  The steps that we'd perform
are:

\break

\begin{Verbatim}
(assert (= (* 2 x) 16))
(check-sat)
; SMT response: SAT
(get-value (x))
; SMT response: (8)
(push 1)
(assert (not (= x 8)))
(check-sat)
; SMT response: UNSAT
(pop 1)
; We generate a computed improvement: x ~ 8
\end{Verbatim}

\paragraph{Improve to Variable.}
We may also use the satisfying assignment to look for improvements of
the form $x = y$, where $x$ and $y$ are both variables.
We look at the satisfying assignment, ignoring variables
that were already improved to constants, and consider pairs of variables
that happen to have the same value in this assignment. If $x$ and $y$
are two such variables, then we try to prove that $x = y$ must hold
under the current assumptions:
\begin{Verbatim}
mustEqual :: Solver -> Name -> Name -> IO Bool
mustEqual s x y =
  solverProve s (eq (SMT.const x) (SMT.const y))
\end{Verbatim}
This process take $O(n^2)$ time, where $n$ is the number of variables,
but we only need to call the solver for pairs of variables that have the same
value---if they do not, then the current assignment provides a counter
example indicating that the variables do not need to be equal in general.

\paragraph{Improve Using a Linear Relation.}
This improvement is a generalization of the previous example, that
is specific to linear arithmetic.  The idea is to try to discover
improving equations of the form $y = A * x + B$.  This type of
improvement is a little different from the others, in that the right-hand
side of the equation contains terms that are in the theory that we are solving.
In general, such constraints are not very useful for the rest of GHC,
as other parts of the constraint solver do not know about our theory
(i.e., the functions \Verb"*" or \Verb"+") and, if we can prove it, then
we must already know about this improvement!  This sort of improvement, is
useful in one very common case, however:  if $y$ is a unification variable,
then having this type of improving equation enables GHC to instantiate
the variable, which leads to better type inference and simpler constraints,
so we attempt this improvement only when the previous two have failed,
and only for the unification variables in the constraints.

We can compute the values for $A$ and $B$, if we have two examples for
$x$ and two examples for $y$.  It is quite standard to ask the SMT
solver for additional examples: this is done by adding additional constraints
that force the models to differ.  In our setting we know that we can
always get another such examples---if this was not the case, a variable
would have exactly one possible values, and we would have improved
it to a constant, as describe previously.  Furthermore, since we do the linear
relation improvement last, we usually can avoid extra calls to the solver
because by this point we typically already have two models where
the variables differ.  It is also
important that the $x$ values be different, but we can always find such
examples: if we cannot find such an example, then $x$ would have only
one possible value, and it would have been improved already.

Once we compute candidate values for $A$ and $B$, we still need to
invoke the solver to validate that the computed relation holds in all
instances of the constraints, and not just the two that we happened to pick.

\break
To see when this improvement is needed, consider the following program
fragment:
\begin{Verbatim}
f :: Proxy (a + 1)
f = Proxy

g :: Proxy (b + 2)
g = f
\end{Verbatim}
To check this program, GHC needs to solve the constraint \\
\Verb"(?a + 1) ~ (b + 2)". The question mark in \Verb"?a" emphasizes that
this is a unification variable, standing-in for a type that needs to be
inferred. We cannot discharge this constraint immediately, because it
does not hold {\em for all} possible values of \Verb"?a" and \Verb"b".
However, since \Verb"?a" is a unification variable, we have the option
of instantiating it to change the constraint.  Of course, we have to
be careful that in doing so we do not loose any generality and, in this
case, the safe instantiation is \Verb"?a := b + 1".  The purpose of the
linear-relation improvement is to discover these kinds of
instantiations.

At first sight, this example may appear artificial, however it is an
abstraction of a very common pattern: namely when one function calls
another, and the type of the provided argument does not match
syntactically the type of the expected argument.  As another example,
consider the function \Verb"vecHead", which requires that its parameter
has at least one element:
\begin{Verbatim}
vecHead :: Vec (n + 1) a -> a
vecHead (Cons x _) = x
\end{Verbatim}
Now, if we tried to call \Verb"vecHead" with an expression of type
\Verb"Vec (b + 2) a", we'd end up in exactly the same situation as the
previous example, where we'd have to infer that \Verb"?n = b + 1".

Our current implementation only considers linear relations between pairs
of variables as we were concerned about the performance penalty if
we tried combinations of more variables: the math will work out, but
the algorithm might become too slow to be practical, and alternative
solutions based on rewriting might be more suitable.

We admit that this improvement is somewhat ad-hoc, but as the previous
examples illustrate, it helps in situations that are quite common in
practice.  It was also fairly simple to implement using the solver.

\paragraph{Custom Improving Rewrites.}
All the improvements that we've defined so far work by {\em only} using
the solver---note that we were just looking at satisfying assignments,
and did not have any special rules about the shapes of the constraints.
It also makes sense to extend the system with custom rewrite rules,
which has the potential of speeding up performance, and also adding
support for features that go beyond the solver's capabilities.
We have experimented with various custom rules, but it is as yet
unclear what constitutes a good set of rewrites.  Concrete custom
rules that would help are various normalization rules, for example
applying distributivity repeatedly, and also rules that rewrite
equations so that there is just a unification variable on the one
side of the equation, which would help it get instantiated.

\subsection{Solving Constraints}

The process of solving constraints is a straight-forward call to the
solver.  The only thing we need to do before solving constraints is
to remove the assertions that were added during the consistency and
improvement stages.  Recall that GHC solves implication constraints
with two calls to the constraint solver: the first one asserts
the given constraints, while the second one actually solves goals.

While we are asserting the assumption, we just check for consistency
and improvement (to generate new given equalities), but we perform
no solving as there is nothing to solve.  During the solving stage,
we mark the solver's state after we've asserted the givens,
then we assert the new goals, check for consistency, and improvement,
and then, before solving, revert back to the state where only
the givens are asserted.
\begin{Verbatim}
solverSimplify :: Solver ->
                  [Expr] -> IO ([Expr],[Expr])
solverSimplify s wanteds =
  solverPrepare s wanteds $ \others our_wanteds ->
  do res <- mapM tryToSolve our_wanteds
     let (unsolved, solved) = partitionEithers res
     return (solved, unsolved ++ others)
  where
  tryToSolve (ct,e) =
    do proved <- solverProve s e
       if proved
         then return (Right ct)
         else return (Left ct)
\end{Verbatim}
The call to \verb"solverPrepare" identifies the constraints that belong
to our theory and translates them the SMTLIB language, where \Verb"others"
are the constraints that are completely outside our theory, and
\Verb"out_wanteds" are the constraints that we know about. Then,
we invoke the solver for each goal, and see if we can prove it.

\paragraph{Evidence.} When we solve a constraint, GHC expects some
evidence to be produced, explaining why the constraint holds
\cite{fc-evidence}.  The same is expected when generating new given
constraints.  While this evidence is not used for code generation,
it is a very useful for sanity checking while working with the constraint
solver.  Unfortunately, at present, our plug-in does not produce any
meaningful evidence, beyond indicating that the fact was produced
by using the SMT solver. In principle, SMT solvers should be able to
produce a proof, when they have concluded that a set of assertions
is unsatisfiable.  Unfortunately, this is not a commonly used feature,
so many provers do not support it out of the box, and the format of the
proofs is not standardized.

\subsection{Our Implementation}
\label{implementation}

To demonstrate the feasibility of the ideas described in this section,
we implemented a GHC plug-in, available from GitHub \cite{type-nats-solver}.
The implementation is intended as a proof-of-concept, and is not
yet ``industrial strength''---more engineering work would be required
to make it more robust and easier to install and configure.

The majority of the effort so far has been focused on understanding how
to integrate an SMT solver with the type-checker, and we have not
conducted extensive testing and measurement of the performance of the plug-in.
It is clear that calling out to an external tool has a cost associated
with it.  However, the preliminary results are encouraging---the plug-in
functions quite well on small examples, but certainly more testing and
experience is needed to find out if the approach will scale to larger
projects.

If despite all the disclaimers, the reader is still interested in
experimenting with the plug-in, we provide the list of GHC options and
extensions that we used in the examples from this paper:

\begin{Verbatim}
{-# OPTIONS_GHC -fplugin=TypeNatSolver #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
\end{Verbatim}

The option \Verb"fplugin=TypeNatSolver" instructs GHC to load the SMT solver
plug-in.  The rest are Haskell extensions that are commonly used in this
setting:

\break
\begin{itemize}
\item \Verb"DataKinds" enables natural number literals at the type
level.
\item \Verb"TypeOperators" and \Verb"TypeFamilies" are need to work
with type-level functions such as \Verb"+".
\item \Verb"KindSignatures" is used to specify the kinds of type variables,
for example, to state that some type-variable is of kind \Verb"Nat".
\item \Verb"GADTs" enables Generalized Algebraic Data-types;  strictly
speaking, these are not required to experiment with the plug-in, however,
many of the more interesting uses of the plug-in end up using GADTs.
\end{itemize}

For the experiments in this paper, we used CVC4, version 1.4.  There was
no deep reason for using this particular solver, other that when we started
working on the project this was the solver with the least restrictive license.
To communicate with the solver, plug-in uses the SMTLIB format (version 2).
Many other SMT solvers support this format (e.g., Z3, Yices), so they
should work just as well.

\section{Other Theories}
\label{other}

In the previous section, we described the core working of a procedure
for integrating an SMT solver with GHC's constraint solver.  While
we concentrated on the theory of natural numbers and linear arithmetic,
little of the algorithm is specific to that theory.

In principle, it should be fairly easy to add support for other theories,
simply by declaring additional ``uninterpreted'' kinds and type-functions
in Haskell.  Of course---as is often the case---doing so is not completely
trivial, which is why we have not done so yet.  For example, while we
have presented a mechanism for working with the symbols of a new theory
in the type-checker, one still needs to make decisions about which symbols
to import, or what notation to use.  In the rest of this section we
explore some of these possibilities.

\subsection{A Theory for Booleans}
We already made use of the lifted \Verb"Bool" type, but so far Haskell
does not support any interesting operations beyond the \Verb"<=?" relation
that we described.  Programmers are already experimenting with defining
type functions. For example, with the current version of GHC we may
define a function for conjunction of type-level booleans:
\begin{Verbatim}
type family And a b where
  And False x = False
  And True x  = x
\end{Verbatim}

Definitions like this work for simple evaluation, but do not support
more sophisticated reasoning.  For example, if GHC encounters
the constraint \Verb"And x y ~ True", it will not be able to conclude
that the only way to solve this is if \Verb"x ~ True" and \Verb"y ~ True"
both hold.  Using the approach outlined in the previous section, we
gain the full power of a SAT solver in the type system---SMT solvers
can reason about booleans, indeed a SAT solver is usually an important
part of the implementation of an SMT solver.

A good starting point for the theory of booleans, would be the following
signature:
\begin{Verbatim}
type family And (a :: Bool) (b :: Bool) :: Bool
type family Or  (a :: Bool) (b :: Bool) :: Bool
type family Not (a :: Bool)             :: Bool
\end{Verbatim}

\subsection{A Theory for Integers}

So far, our work uses natural numbers, which are quite useful for
keeping track of the sizes of data-structures such as arrays, vectors,
lists, bit-vectors, etc.  The standard theory supported by the SMT solvers
is actually linear arithmetic over the integers---in our implementation
we have to do some extra work to assert that we are only interested
in non-negative solutions.

The main challenge for supporting both integers and natural numbers
at the type level is not the technology for solving the equations, but
the notation!  One possible signature for the theory of type-level
integers is:
\begin{Verbatim}
type family ToInt  (a :: Nat) :: Int
type family Negate (a :: Int) :: Int
type family Add    (a :: Int) (b :: Int) :: Int
type family Sub    (a :: Int) (b :: Int) :: Int
type family Mul    (a :: Int) (b :: Int) :: Int
\end{Verbatim}
While this notation is somewhat verbose, at least it has the benefit
of exposing the functionality to programmers, who may use a more suitable
notation depending on their needs.  For example, if a program works
mostly with integers, one could add the following declaration, to get
the more usual mathematical notation:
\begin{Verbatim}
type (+) a b = Add a b
\end{Verbatim}

\subsection{A Theory of Bit-Vectors}
SMT solvers also have good support for reasoning about fixed-length bit-vectors.
Unlike the theory of linear arithmetic, the theory of bit-vectors
supports arbitrary multiplication and division, as well as various bit-wise
operations, similar to the operations available in hardware.

\paragraph{Tracking Sizes.}
If we are interested in keeping track of the sizes of data-structures
in memory, using 64-bit bit-vectors is a reasonable compromise
which provides more expressive reasoning than linear arithmetic,
and accommodates virtually all data-structures that fit in a computer's memory.

\paragraph{Finite Sets.}
Another potential application for the theory of bit-vectors is
to implement finite sets of integers at the type level.
As is usual at the value level, each bit is used to indicating the presence
or absence of an element in the set, and the bitwise \Verb"and"
and \Verb"or" operations correspond to intersection and union.
Such functionality would be useful in the implementation of various effect
systems.

\section{A Modular Constraint Solver}
\label{modular-typechecker}

In Section~\ref{algorithm} we outlined an algorithm for using an SMT solver
to solver a certain class of constraints, and then
in Section~\ref{other} we observed that it is possible---and potentially
useful---to solve many other constraints.  This raises an interesting
question: is it possible to structure the entire constraint solver for
a complex programming language, such as Haskell or ML, using a modular
approach, similar to the structure of an SMT solver?

We do not know that answer to this question, but the rest of this section,
we present a little bit about the structure of SMT solvers, and point out
similarities with GHC's constraint solver, which suggests that this might
be a fruitful area for future research.

\subsection{The Nelson-Oppen Method}

An SMT solver uses a collection of independent decision procedures,
and orchestrates them to compute an answer to a given query.  A well-known
technique for combining decision procedures is due to Nelson and Oppen
\cite{NelsonOppen}.  Their algorithm starts with a collection of
orthogonal theories (i.e., the symbols in the theories do not overlap),
and shows how we may simplify terms in the combined language of the
theories using {\em equality propagation}.  The equality propagation procedure
has a lot of similarities to the algorithm presented in this paper,
and this is entirely by design on our part.

First, constraints that mention symbols from multiple theories are
rewritten so that each constraint mentions only symbols in a single theory.
This is done by naming ``foreign'' sub-terms, in the same way we described
earlier in the paper.

Each collection of constraints is sent to the appropriate decision
procedure to be checked for consistency.  If one of the procedures
detects an inconsistency, then we know that the whole collection of
constraints is inconsistent and we may stop.

If the constraints look consistent, then the decision procedures
are given a chance to ``communicate'' with each other via equality
constraints.  This is analogous to the improvement step in what we
described.  A key observation of Nelson and Oppen is that the only
constraints that need to be communicated are equalities between variables.
The intuition behind this observation is that other equalities would
feature symbols that are ``foreign'' to the other decision procedures,
and they would not know what to do with them.

So, if one decision procedure emits an equality constraint that was not
known by some of the others, we propagate this information, and again
check for consistency and further improvement.

Finally, the Nelson-Oppen technique also allows for a more general
form of communication between procedures---a decision procedure may
indicate that it can solve a problem in multiple ways, by emitting
a {\em disjunction} of equality constraints.  If this happens,
then the coordinating logic has to explore all possibilities, the problem being
satisfiable if any one of the options succeeds, and it is not satisfiable
otherwise.  Searching the options introduced by disjunctions is typically
implemented with the aid of a SAT solver, which is usually considerably
more efficient than simply trying all possibilities, as SAT solvers
propagate information to prune the search space.

To implement the backtracking search efficiently, the decision procedures
are typically incremental (i.e, they can revert back to a previous
known state).  Some techniques can improve this search process further,
by using decision procedures that also produce proofs, \cite{cvc4-lin-arith},
as these proofs can be used to identify dependencies between variables.

So, the overall setups is that we have a collection of independent
decision procedures---each specializing in a single theory---and
they communicate by disjunctions of equalities.  There are three cases,
depending on the shape of the disjunction:
\begin{itemize}
\item an empty disjunction indicates a conflict,
\item a singleton disjunction is a certain improvement, and we propagate
it across theories,
\item a proper disjunction results in search.
\end{itemize}

\subsection{Theories of Haskell}

While GHC's constraint solver currently is structured quite differently
from an SMT solver, the similarities---in particular, the use of equality
constraints to disseminate information---suggest that there may be
a more modular way to structuring the solver.

While GHC currently does not do any back-tracking search (i.e., decision
procedure may only report inconsistency, or certain knowledge), this
is also the case for Nelson-Open if all theories are convex \cite{NelsonOppen}.
In addition,
there are interesting cases where backtracking might be potentially useful
in Haskell too.  For example, when solving class constraints in the
context of overlapping instances, or instance chains \cite{instance-chains},
it is useful to consider the context of instances,
but back-track and try a different instance, if the context is found
to be unsatisfiable.

GHC's implementation of Haskell contains numerous extensions, and so
there are many candidates for potential ``theories'', that is, constraints
that are solved by a dedicated decision procedure.  Engineering a
constraint solver in this style would be very beneficial, both
as one could reason about the correctness of each decision procedure
separately, but also, because it would make it simpler to experiment
with new extensions to the system.

\section {Conclusion}

The paper introduces the basics of GHC's constraint solver, and shows
how to connect it with an external decision procedure that produces
satisfying assignments.  The initial motivation for this work was
to improve the type-level support for natural numbers, but the solution
turned out to be more general, and opens up the door for interesting
new extensions to Haskell's type system.  More generally, we have
identified similarities between the techniques used to implement SMT solvers,
and the implementation of GHC's constraint solver, which suggests
the possibility of a modular constraint solver design.

% \bibliographystyle{abbrvnat}
% \bibliography{refs}

% The bibliography should be embedded for final submission.

\begin{thebibliography}{}
\softraggedright

\providecommand{\natexlab}[1]{#1}
\providecommand{\url}[1]{\texttt{#1}}
\expandafter\ifx\csname urlstyle\endcsname\relax
  \providecommand{\doi}[1]{doi: #1}\else
  \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi

\bibitem[yic(2015)]{yices}
\emph{Yices Manual}, 2015.
\newblock URL \url{http://yices.csl.sri.com/papers/manual.pdf}.

\bibitem[{Adam Gundry}(2015)]{units-of-measure}
{Adam Gundry}.
\newblock A typechecker plugin for units of measure.
\newblock Submitted for publication., 2015.

\bibitem[{Christiaan Baaij}(2015)]{typelits-normalise}
{Christiaan Baaij}.
\newblock A plug-in for normalising type literals in ghc.
\newblock 2015.
\newblock URL \url{https://github.com/clash-lang/ghc-typelits-natnormalise}.

\bibitem[{Clark Barrett} et~al.(2010){Clark Barrett}, {Aaron Stump}, and
  {Cesare Tinelli}]{smtlib2}
{Clark Barrett}, {Aaron Stump}, and {Cesare Tinelli}.
\newblock The {SMT-LIB} standard: Version 2.0.
\newblock Technical report, Department of Computer Science, The University of
  Iowa, 2010.
\newblock URL
  \url{http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.0-r12.09.09.pdf}.

\bibitem[{Clark Barrett} et~al.(2011){Clark Barrett}, {Christopher L. Conway},
  {Morgan Deters}, {Liana Hadarean}, {Dejan Jovanovi\'{c}}, {Tim King}, {Andrew
  Reynolds}, and {Cesare Tinelli}]{cvc4}
{Clark Barrett}, {Christopher L. Conway}, {Morgan Deters}, {Liana Hadarean},
  {Dejan Jovanovi\'{c}}, {Tim King}, {Andrew Reynolds}, and {Cesare Tinelli}.
\newblock {CVC4}.
\newblock In \emph{Proceedings of the 23rd International Conference on Computer
  Aided Verification}, Snowbird, Utah, USA, 2011.
\newblock URL \url{http://dl.acm.org/citation.cfm?id=2032305.2032319}.

\bibitem[{Dimitrios Vytiniotis} and {Simon Peyton Jones}(2013)]{fc-evidence}
{Dimitrios Vytiniotis} and {Simon Peyton Jones}.
\newblock Evidence normalization in System FC.
\newblock In \emph{24th International Conference on Rewriting Techniques and
  Applications}, Eindhoven, Netherlands, 2013.
\newblock URL
  \url{http://research.microsoft.com/en-us/um/people/simonpj/papers/ext-f/fc-new-tyco.pdf}.

\balance

\bibitem[{Dimitrios Vytiniotis} et~al.(2011){Dimitrios Vytiniotis}, {Simon
  Peyton Jones}, {Tom Schrijvers}, and {Martin Sulzmann}]{outsidein}
{Dimitrios Vytiniotis}, {Simon Peyton Jones}, {Tom Schrijvers}, and {Martin
  Sulzmann}.
\newblock {OutsideIn(X)}: Modular type inference with local assumptions.
\newblock \emph{Journal of Functional Programming}, September 2011.
\newblock URL
  \url{http://research.microsoft.com/apps/pubs/default.aspx?id=162516}.

\bibitem[{Greg Nelson} and {Derek C. Oppen}(1979)]{NelsonOppen}
{Greg Nelson} and {Derek C. Oppen}.
\newblock Simplification by cooperating decision procedures.
\newblock \emph{ACM Transactions on Programming Languages and Systems},
  1\penalty0 (2), October 1979.
\newblock URL \url{http://doi.acm.org/10.1145/357073.357079}.

\bibitem[{Iavor S. Diatchki}(2015{\natexlab{a}})]{simple-smt}
{Iavor S. Diatchki}.
\newblock \emph{simple-smt: a {Haskell} library for working with SMT solvers},
  2015{\natexlab{a}}.
\newblock URL \url{http://hackage.haskell.org/package/simple-smt}.

\bibitem[{Iavor S. Diatchki}(2015{\natexlab{b}})]{type-nats-solver}
{Iavor S. Diatchki}.
\newblock A plug-in for solving linear constraints using an smt solver.
\newblock 2015{\natexlab{b}}.
\newblock URL \url{https://github.com/yav/type-nat-solver}.

\bibitem[{J. Garrett Morris} and {Mark P. Jones}(2010)]{instance-chains}
{J. Garrett Morris} and {Mark P. Jones}.
\newblock Instance chains: Type class programming without overlapping
  instances.
\newblock In \emph{Proceedings of the 15th ACM SIGPLAN International Conference
  on Functional Programming (ICFP '10)}, Baltimore, Maryland, USA, 2010.
\newblock URL \url{http://web.cecs.pdx.edu/~mpj/pubs/instancechains.pdf}.

\bibitem[{Leonardo de Moura} and {Nikolaj Bjørner}(2008)]{z3}
{Leonardo de Moura} and {Nikolaj Bjørner}.
\newblock Z3: An efficient smt solver.
\newblock In \emph{Tools and Algorithms for the Construction and Analysis of
  Systems, 14th International Conference}, Budapest, Hungary, 2008.
\newblock URL \url{http://research.microsoft.com/projects/z3/z3.pdf}.

\bibitem[{Mark P. Jones}(1995)]{improvement}
{Mark P. Jones}.
\newblock Simplifying and improving qualified types.
\newblock In \emph{FPCA '95: Conference on Functional Programming Languages and
  Computer Architecture}, La Jolla, California, USA, 1995.
\newblock URL \url{http://web.cecs.pdx.edu/~mpj/pubs/fpca95.pdf}.

\bibitem[{Niki Vazou} et~al.(2014){Niki Vazou}, {Eric L. Seidel}, {Ranjit
  Jhala}, {Dimitrios Vytiniotis}, and {Simon Peyton-jones}]{liquid-haskell}
{Niki Vazou}, {Eric L. Seidel}, {Ranjit Jhala}, {Dimitrios Vytiniotis}, and
  {Simon Peyton-jones}.
\newblock Refinment types for Haskell.
\newblock In \emph{Proceedings of the 19th ACM SIGPLAN International Conference
  on Functional Programming}, Gothenburg, Sweeden, 2014.
\newblock URL
  \url{http://goto.ucsd.edu/~rjhala/papers/refinement_types_for_haskell.pdf}.

\bibitem[{Patrick C. Hickey} et~al.(2014){Patrick C. Hickey}, {Lee Pike},
  {Trevor Elliott}, {James Bielman}, and {John Launchbury}]{ivory-experience}
{Patrick C. Hickey}, {Lee Pike}, {Trevor Elliott}, {James Bielman}, and {John
  Launchbury}.
\newblock Building embedded systems with embedded {DSLs} (experience report).
\newblock In \emph{Proceedings of the 2014 ACM SIGPLAN Conference on Functional
  Programming}, Gothenburg, Sweden, 2014.
\newblock URL
  \url{https://github.com/GaloisInc/smaccmpilot-experiencereport/blob/master/embedded-experience.pdf?raw=true}.

\bibitem[{Richard A. Eisenberg} and {Jan Stolarek}(2014)]{Eisenberg2014}
{Richard A. Eisenberg} and {Jan Stolarek}.
\newblock Promoting functions to type families in {Haskell}.
\newblock In \emph{Proceedings of the 2014 ACM SIGPLAN Symposium on {Haskell}},
  Gothenburg, Sweden, 2014.
\newblock URL
  \url{http://www.cis.upenn.edu/~eir/papers/2014/promotion/promotion.pdf}.

\bibitem[{Richard A. Eisenberg} and {Stephanie Weirich}(2012)]{Eisenberg2012}
{Richard A. Eisenberg} and {Stephanie Weirich}.
\newblock Dependently typed programming with singletons.
\newblock In \emph{Proceedings of the 2012 ACM SIGPLAN Symposium on {Haskell}},
  Copenhagen, Denmark, 2012.

\bibitem[{Sam Lindley} and {Conor McBride}(2013)]{Lindley2013}
{Sam Lindley} and {Conor McBride}.
\newblock Hasochism: The pleasure and pain of dependently typed {Haskell}
  programming.
\newblock In \emph{Proceedings of the 2013 ACM SIGPLAN Symposium on {Haskell}},
  Boston, Massachusetts, USA, 2013.
\newblock URL
  \url{https://personal.cis.strath.ac.uk/conor.mcbride/pub/hasochism.pdf}.

\bibitem[{Sergey Berezin} et~al.(2003){Sergey Berezin}, {Vijay Ganesh}, and
  {Daivd L. Dill}]{cvc4-lin-arith}
{Sergey Berezin}, {Vijay Ganesh}, and {Daivd L. Dill}.
\newblock An online proof-producing decision procedure for mixed-integer linear
  arithmetic.
\newblock In \emph{Proceedings of the 9th International Conference on Tools and
  Algorithms for the Construction and Analysis of Systems}, Warsaw, Poland,
  2003.
\newblock URL \url{http://hci.stanford.edu/cstr/reports/2007-07.pdf}.

\bibitem[{The GHC Team}(2015)]{ghc-manual}
{The GHC Team}.
\newblock \emph{The Glorious Glasgow Haskell Compilation System User's Guide,
  Version 7.10.1}, 2015.
\newblock URL
  \url{https://downloads.haskell.org/~ghc/7.10.1/docs/html/users_guide/index.html}.

\end{thebibliography}

\end{document}


\documentclass{article}
\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage[all]{xy}
\usetikzlibrary{positioning,chains,fit,shapes,calc}

\begin{document}

\title{Homework 8}
\author{Josh Cai}

\maketitle
\section*{Section 10.4}

\textbf{2a)} $f(1) = -6, f(2) = 12, f(3) = -24, f(4) = 48, f(5) = -96$

\noindent\textbf{2b)} $f(1) = 16, f(2) = 55, f(3) = 172, f(4) = 523, f(5) = 1576$

\noindent\textbf{2c)} $f(1) = 1, f(2) = -3, f(3) = 13, f(4) = 141, f(5) = 19597$
\\\\\noindent\textbf{4a)} $f(2) = 0, f(3) = -1, f(4) = -1, f(5) = 0$

\noindent\textbf{4b)} $f(2) = 1, f(3) = 1, f(4) = 1, f(5) = 1$

\noindent\textbf{4c)} $f(2) = 2, f(3) = 5, f(4) = 33, f(5) = 1214$
\\\\\noindent\textbf{6b)} $f(n) = 0$ if $n \equiv 1 \mod{3}$ and $f(n) = 2^{\lfloor (n+1)/3 \rfloor}$ otherwise
\\Basis step: $f(0) = 1, f(1) = 0, f(2) = 2$
\\Recursive step: $f(n) = 2f(n-3) = 2*0 = 0$ if $n \equiv 1 \mod{3}$
\\$f(n) = 2f(n-3) = 2*2^{\lfloor (n-2)/3 \rfloor} = 2^{\lfloor (n-2)/3 \rfloor+1} = 2^{\lfloor (n+1)/3 \rfloor}$ otherwise
\\\\\noindent\textbf{8a)} $f(1) = 2, f(n+1) = f(n)+4$

\noindent\textbf{8b)} $f(1) = 2, f(n+1) = f(n)+2(-1)^{n+1}$

\noindent\textbf{8c)} $f(1) = 2, f(n+1) = f(n)(n+2)/(n)$

\noindent\textbf{8d)} $f(1) = 1, f(n+1) = f(n)+2n+1$
\\\\\noindent\textbf{10)} $f_m(0)=m, f_m(n+1) = f_m(n)+1$
\\\\\noindent\textbf{24a)} $1\in S; n\in S \Rightarrow n-2\in S \wedge n+2 \in S$

\\\\\noindent\textbf{24b)} $1\in S; n\in S \Rightarrow 3n\in S$

\\\\\noindent\textbf{24c)} $x\in S \wedge 1 \in S; a\in S \wedge b\in S \Rightarrow a+b\in S \wedge a-b\in S \wedge ab\in S$
\\\\\noindent\textbf{32a)} $ones(\lambda) = 0; ones(s1) = ones(s)+1; ones(s0)=ones(s)$

\\\\\noindent\textbf{32b)} Basis step: $ones(x\lambda)=ones(x)=ones(x)+0=ones(x)+ones(\lambda)$, so $P(\lambda)$ is true.
\\Recursive step: Assume $P(y)$ true, need to show $ones(xy1)=ones(x)+ones(y1)$ and $ones(xy0)=ones(x)+ones(y0)$. Since $ones(xy1) = ones(xy)+1$, $ones(y1)=ones(y)+1$, and $ones(xy)=ones(x)+ones(y)$ by assumption, $ones(xy1)=ones(xy)+1=ones(x)+ones(y)+1=ones(x)+ones(y1)$. Since $ones(xy0) = ones(xy)$, $ones(y0)=ones(y)$, and $ones(xy)=ones(x)+ones(y)$ by assumption, $ones(xy0)=ones(xy)=ones(x)+ones(y)=ones(x)+ones(y0)$.
\\\\\noindent\textbf{38)}  $1\in S \wedge 0 \in S; s\in S \Rightarrow 1s1\in S \wedge 0s0\in S$
\\\\\noindent\textbf{40)} $0\in S; s\in S \Rightarrow 0s,s0,s10,s01,1s0,10s,0s1,01s\in S$

\end{document}


\documentclass[11pt, oneside]{article}

\usepackage{../mathz/shared/preamble}
\addbibresource{../mathz/shared/references.bib}

\usepackage{../mathz/articles/real-numbers/real-numbers}
\usepackage{../mathz/articles/vector-spaces/vector-spaces}
\usepackage{2-sphere-curvature}

\title{Proof that $\Stwo$ is curved}
\author{Arthur Ryman, {\tt arthur.ryman@gmail.com}}
\date{\today}

\begin{document}

\maketitle

\begin{abstract}
Leonard Susskind,  in Lecture 3 of his Stanford University course on General Relativity,
asks his class to prove, as an exercise, that $\Stwo$ is curved.
This article attempts to do so.
The approach taken here is to precisely formalize every concept involved in the proof.
\end{abstract}

\section{Introduction}

In Lecture 3 of his Stanford University course on General Relativity \cite{susskind-gr3},
Leonard Susskind asks his class to prove that $\Stwo$ is curved.
He does this before defining curvature.
The class is simply tasked to show that there is no coordinate system in which the components
of the metric tensor become those of flat space.
The goal of this article is to produce such a proof.

The 2-sphere, $\Stwo$, is an extremely ubiquitous and illuminating example of a Riemannian manifold.
It appears in many interesting contexts including complex analysis, special relativity, electromagnetism, and quantum mechanics.
It is a compact submanifold of $\Rthree$ and so, unlike its higher-dimensional versions, can be easily visualized.
These attributes make $\Stwo$ an ideal concrete example for illustrating the concepts of
abstract Riemannian geometry.

\section{Plan}

\begin{enumerate}

\item Define the usual topology on $\R^n$. - DONE

\item Refactor the definitions of continuous and smooth functions on $\R$ so that they align with mainstream notation. - DONE

\item Define the smooth functions on $\R^n$.

A function is smooth if it is infinitely differentiable.

A function is differentiable on a set if it is differentiable at each point of the set.

A function is differentiable at a point if it is approximately linear at that point.

A function is approximately linear at a point if the residual vanishes to second order.
This condition is normally phrased in terms of the difference quotient.

\item Define tangent vectors.

\item Define the metric tensor and how its components transform under coordinate change.

\item Set up the differential equations to solve.

\item Solve the equations modulo terms of $O(x)$, $O(x^2)$, and $O(x^3)$, showing that no solution exists
modulo $O(x^3)$.

\item Generalize to other submanifolds of $R^3$.

\item Generalize to submanifolds of $R^n$ for $n > 3$.

\end{enumerate}

\section{Proof Approaches}

Susskind takes a very concrete, coordinate system based approach to defining the objects of study in General Relativity.
He defines tensors as collections of real-valued functions defined for each coordinate system with the property that they
transform in prescribed ways under a change of coordinate system.
The primary object is the metric tensor.
The task is to show that there is no coordinate system on the sphere that makes its metric tensor the same as that of the flat plane.

\subsection{The Coordinate System Approach}

The most direct route is to attempt to construct a coordinate system that makes the metric flat.
This approach will lead to differential equations that the coordinate functions must satisfy.
I suspect that one can show that the differential equations have no solution, probably due to the failure of some
integrability condition.

For example, suppose one is given two smooth functions $f(x,y)$ and $g(x,y)$, and one is asked to find $F(x,y)$ such that
\begin{align}
	\frac{\partial F}{\partial x}	&= f \\
	\frac{\partial F}{\partial y}	&= g
\end{align}
If $F$ exists then $f$ and $g$ must satisfy the following integrability condition
\begin{equation}
\begin{split}
	\frac{\partial f}{\partial y} 	& = \frac{\partial}{\partial y} \left( \frac{\partial F}{\partial x} \right) \\
						& = \frac{\partial^2 F}{\partial y \partial x} \\
						& = \frac{\partial^2 F}{\partial x \partial y} \\
						& = \frac{\partial}{\partial x} \left( \frac{\partial F}{\partial y} \right) \\
						& = \frac{\partial g}{\partial x}
	\end{split}
\end{equation}

\subsection{The Curvature Tensor Approach}

The idea here is to define a tensor that vanishes on flat space but not on $\Stwo$.
The existence of such a tensor proves that $\Stwo$ is not flat.
Of course, the tensor in question is the Riemann curvature tensor but Susskind has not introduced it yet.

Geometrically, the curvature tensor arises when one considers the parallel transport of a tangent vector around a
small closed loop anchored at some point.
How hard would it be to define this tensor from first principles?
Let $M$ be a smooth manifold, let $p \in M$ be some point, and let $M_p$ denote the tangent space at $p$.
Let $V \in M_p$ be a tangent vector.
Let $X, Y$ be tangent vectors at $p$.
Consider the small path anchored at $p$ defined by moving along $X$, then $Y$, then $-X$, and then finally $-Y$.
Transport $V$ along this closed path.
The result is a new vector $W$ which is a linear transform of $V$ that depends linearly on $X$ and $Y$.
\begin{equation}
	W = R_p(X,Y)V
\end{equation}

One suspects that the amount of change of $V$ is proportional to the two-dimensional area spanned by $X$ and $Y$, hence $R$ depends
on the area element $X \wedge Y$, or
\begin{equation}
	R_p(X,Y) = -R_p(Y,X)
\end{equation}

The tricky bit here is to define parallel transport.
It probably boils down to geodesic movement.

Parallel transport has an intuitive, physical meaning.
Suppose we have a massive, rigid body at rest at the point $p$.
By this I mean that the centre of mass of the body coincides with $p$.
Such a body defines a frame of reference at $p$.
We take $p$ to be the origin and pick several reference points on the body such that their displacements from $p$ define a set of basis vectors.
We give the body a slight push in some direction $V$, being careful not induce any rotation.
We achieve this by apply the same force in the direction $V$ at several points on the body, balancing them about the body's centre of mass.
We then let the body move a small distance in the direction defined by $V$ to some new point $p'$.
The new positions of the reference points define a new set of basis vectors.
For small movements the new basis vector will be defined by a linear transformation of the old basis vectors.

We can determine the equations of motion by defining a Hamiltonian.
It is natural to use the metric tensor as defining the kinetic energy of the system.
Solving the Hamiltonian equations of motion should yield a geodesic through $p$ in the direction of $V$ and the linear transformation of
the frame of reference.

Dirac, in his book on General Relativity, defined parallel transport for submanifolds of  $\R^n$ as the projections onto the submanifold of
straight line motion in $\R^n$.

\subsection{The Algebraic Topology Approach}

Before proceeding with the coordinate approach, it is illuminating to discuss a purely topological one.
If $\Stwo$ is flat then its tangent bundle is trivial so it has a non-zero cross section.
But a cross section of the tangent bundle is a vector field on $\Stwo$.
A vector field on $\Stwo$ defines a diffeomorphism of $\Stwo$ that is homotopic to the identity map.
If the vector field never vanishes then this diffeomorphism has no fixed points.
The Lefschetz fixed-point theorem tells us that any space $M$ that has such a diffeomorphism must have a vanishing Euler characteristic
$\chi(M) = 0$. But $\chi(\Stwo) = 2$. Therefore $\Stwo$ cannot be flat.

While this proof answers the question, it doesn't provide much insight into curvature in general.
For example, the 3-sphere $\Sthree$ must surely also be curved, but $\chi(\Sthree) = 0$.
Curvature is a local, geometric property, not a global, topological one.
A coordinate proof for $\Stwo$ should generalize to all higher-dimensional spheres and to other submanifolds of $\R^n$.

\section{Smooth Functions}

Recall that $\smoothR(x)$ demotes the set of functions that are smooth at $x \in \R$, $\smoothPR(U)$ the set of functions that are smooth at
every point $x \in U \subseteq \R$, and $\derivF f$ is the derivative of the function $f \in \R \pfun \R$.

\section{Riemannian Manifolds}

An $n$-dimensional manifold is a topological space that is locally homeomorphic to $\R^n$.

\subsection{\zcmd{Rtwo} and \zcmd{Rthree}}

Let $\Rtwo$ and $\Rthree$ denote the vector spaces of 2-tuples and 3-tuples.
\begin{zed}
	\Rtwo == \Rtuples(2) \\
	\Rthree == \Rtuples(3)
\end{zed}

\section{The 2-sphere as a Riemannian Manifold}

Let $\Stwo$ denote the 2-sphere of unit vectors in $\Rthree$.
\begin{equation}
	\Stwo = \{~ v: \Rthree | \norm{v} = 1 ~\}
\end{equation}

\begin{axdef}
	\Stwo: \power \Rthree
\where
	\Stwo = \{~ v: \Rthree | \normR(v) = \oneR ~\}
\end{axdef}

\subsection{Coordinates on $\Rthree$}

Let $\langle e_1, e_2, e_3 \rangle$ denote the standard orthonormal basis of $\Rthree$.
\begin{align}
e_1 & = \langle1, 0, 0 \rangle \\
e_2 & = \langle 0, 1, 0 \rangle \\
e_3 & = \langle 0, 0, 1 \rangle
\end{align}
\begin{axdef}
	e_1, e_2, e_3: \Rthree
\where
	e_1 = \langle~ \oneR, \zeroR, \zeroR ~\rangle \\
	e_2 = \langle~ \zeroR, \oneR, \zeroR ~\rangle \\
	e_3 = \langle~ \zeroR, \zeroR, \oneR ~\rangle
\end{axdef}

Let $x, y, z$ denote the standard Cartesian coordinate functions on $\Rthree$.
\begin{equation}
\forall p : \Rthree @ p = \langle x(p), y(p), z(p) \rangle
\end{equation}
\begin{axdef}
	x, y, z: \Rthree \fun \R
\where
	x = (\lambda p: \Rthree @ e_1 \dotR p) \\
	y = (\lambda p: \Rthree @ e_2 \dotR p) \\
	z = (\lambda p: \Rthree @ e_3 \dotR p)
\end{axdef}
\begin{remark}
We have $p = x(p) e_1 + y(p) e_2 + z(p) e_3$.
\end{remark}

The Cartesian coordinate functions define the vector fields $\frac{\partial}{\partial x}, \frac{\partial}{\partial y}, \frac{\partial}{\partial z}$
on $\Rthree$ as follows.
For $p \in \Rthree$ and $f \in \smoothPR(\Rthree)$, we define
\begin{align}
\left(\frac{\partial}{\partial x}\right)_p f = \left. \frac{d}{dt} f(p + t e_1) \right|_{t = 0} \\
\left(\frac{\partial}{\partial y}\right)_p f = \left. \frac{d}{dt} f(p + t e_2) \right|_{t = 0} \\
\left(\frac{\partial}{\partial z}\right)_p f = \left. \frac{d}{dt} f(p + t e_3) \right|_{t = 0}
\end{align}

Let $\gamma$ be a smooth curve in $\Rthree$ and let $\gamma(0) = p$.
Let $\gamma'$ be the tangent vector at $p$ defined by $\gamma$.

Let $\gamma(p,v)$ denote the curve through the point $p \in \Rthree$ in the direction $v \in \Rthree$.
\begin{axdef}
	\gamma: \Rthree \cross \Rthree \fun (\R \fun \Rthree)
\where
	\forall p, v: \Rthree; t: \R @ \\
	\t1	\gamma(p,v)(t) = p \vaddR t \smulR v
\end{axdef}

Let $X, Y, Z$ denote the vector fields

\printbibliography

\end{document}


\documentclass{article}
	\title{\underline{CREATING EQUATIONS}}
	\usepackage{amsmath}
		\begin{document}
			\maketitle
			\section*{QUADRATIC EQUATION}
			\begin{equation*}
				f(y) = ax^2 + bx + c
			\end{equation*}
		\end{document}

CSC 101 - miracle - LaTEX/practice-8 equations.tex


\documentclass[11pt]{article}

\usepackage[margin=1in]{geometry}

\usepackage{mathpazo}

\newcommand{\gcc}{\mathrm{g~cm^{-3} }}
\newcommand{\castro}{{\sffamily{Castro}}}

\begin{document}

\begin{center}
  {\Large Notes on the Radiation-Driven Planet Convection Problem}
\end{center}

\section{\castro\ Solver Details}

We are using the gray radiation solver.  Weiqun suggests
\begin{itemize}
\item {\tt radiation.comoving = 1} ---should be more stable
\item {\tt radsolve.level\_solver\_flag = 1} ---should be faster than {\tt 0}
\item {\tt castro.cfl}: the value we were using by default is {\tt
  0.9}---this may be too high.
\end{itemize}

\section{Opacity}

YM10 suggest the form of the opacity as (Eq.\ 3):
\begin{equation}
  \tilde{\kappa} = \tilde{\kappa}_0 \left (\frac{P}{P_\mathrm{kb}} \right)
\end{equation}
with $\tilde{\kappa} = 0.18~\mathrm{cm^2~g^{-1}}$, and $P_\mathrm{kb}
= 1000~\mathrm{bar} = 10^9~\mathrm{erg~cm^{-3}}$.  Note that this form
of opacity has different units than what \castro\ uses.  For \castro\,
opacity has units of $\mathrm{cm^{-1}}$, so we have:
\begin{equation}
  \kappa = \rho \tilde{\kappa} = \tilde{\kappa}_0 \rho \left ( \frac{P}{P_\mathrm{kb}} \right )
\end{equation}

\castro\ takes the opacity as a simple power law of density and temperature (without any
reference values for scaling).  We replace the pressure using the EOS:
\begin{equation}
  P = \frac{\rho k T}{\mu m_p}
\end{equation}
where $\mu = 2.34$ as specified in YM10, and $T$ is understood to be
the gas temperature.  Substituting this in, we have:
\begin{equation}
  \kappa = \tilde{\kappa}_0 \rho^2 \frac{k T}{\mu m_p P_\mathrm{kb}}
\end{equation}

Since \castro\ wants $\kappa = \kappa_0 \rho^m T^{-n}$, we evaluate
this with $\rho = 1~\gcc$ and $T = 1~\mathrm{K}$:
\begin{equation}
  \kappa = 6.35 \times 10^{-3} \, \rho^2 T~\mathrm{cm^{-1}}
\end{equation}
This can be set in \castro\ as:
\begin{verbatim}
radiation.const_kappa_p = 6.35e-3
radiation.kappa_p.exp_m = 2
radiation.kappa_p_exp_n = -1
\end{verbatim}

\subsection{Boundary Conditions}

The upper boundary of the domain needs to specify the flux coming from
the parent star.  Weiqun suggested the Sanchez-Pomraning BC, which is
a Neumann-like BC that allows for an incoming and outgoing flux.

The form of the flux is $F = cE_r$, where $E_r$ is the radiation
energy density.  This flux has units of $\mathrm{erg~cm^{-2}~s^{-1}}$.
We evaluate it as
\begin{equation}
  F = cE_r = c a T_\star^4 = 4\sigma T_\star^4
\end{equation}
where $T_\star$ is the effective temperature of the stellar flux at
the planet---this is how the YM10 paper characterizes the radiation
flux.  Evaluating, we have:
\begin{equation}
  F = 3.6\times 10^9~\mathrm{erg~cm^{-2}~s^{-1}}
\end{equation}

Alternately, we can arrive at this value as:
\begin{equation}
  f = \frac{L_\star}{4\pi d^2}
\end{equation}
where $L_\star$ is the luminosity of the parent star and $d$ is the
orbital radius of the planet.  Using Kepler's third law,
\begin{equation}
  d^3 = \frac{GM_\star P^2}{4\pi^2}
\end{equation}
giving
\begin{equation}
  f = \frac{L_\star}{4\pi} \left ( \frac{4 \pi^2}{GM_\star P^2} \right )^{2/3}
\end{equation}
Picking $L_\star = L_\odot$ and $M_\star = M_\odot$, and taking $P =
1~\mathrm{day}$, we get the same value for $f$ as above, $f =
3.6\times 10^9~\mathrm{erg~cm^{-2}~s^{-1}}$.

For the lower boundary, there should be a flux coming from the
interior of the planet, but this will be very small compared to the
flux coming from the star.  For now, we use a standard homogeneous
Neumann boundary condition.

\end{document}


    \filetitle{plotneigh}{Plot local behaviour of objective function after estimation}{grfun/plotneigh}

	\paragraph{Syntax}\label{syntax}

\begin{verbatim}
H = grfun.plotneigh(D,...)
\end{verbatim}

\paragraph{Input arguments}\label{input-arguments}

\begin{itemize}
\itemsep1pt\parskip0pt\parsep0pt
\item
  \texttt{D} {[} struct {]} - Structure describing the local behaviour
  of the objective function returned by the
  \href{model/neighbourhood}{\texttt{neighbourhood}} function.
\end{itemize}

\paragraph{Output arguments}\label{output-arguments}

\begin{itemize}
\itemsep1pt\parskip0pt\parsep0pt
\item
  \texttt{H} {[} struct {]} - Struct with handles to the graphics
  objects plotted by \texttt{plotpp}; the struct has the following
  fields with vectors of handles: \texttt{figure}, \texttt{axes},
  \texttt{obj}, \texttt{est}, \texttt{lik}, \texttt{bounds}.
\end{itemize}

\paragraph{Options}\label{options}

\begin{itemize}
\item
  \texttt{'caption='} {[} \emph{empty} \textbar{} cellstr {]} -
  User-supplied graph titles; if empty, default captions will be
  automatically created.
\item
  \texttt{'model='} {[} model \textbar{} \emph{empty} {]} - Model object
  used to create graph captions if the option \texttt{'caption='} is
  \texttt{'descript'} or \texttt{'alias'}.
\item
  \texttt{'plotObj='} {[} \emph{\texttt{true}} \textbar{} \texttt{false}
  {]} - Plot the local behaviour of the overall objective function; a
  cell array can be specified to control graphics options.
\item
  \texttt{'plotLik='} {[} \emph{\texttt{true}} \textbar{} \texttt{false}
  \textbar{} cell {]} - Plot the local behaviour of the data likelihood
  component; a cell array can be specified to control graphics options.
\item
  \texttt{'plotEst='} {[} \emph{\texttt{true}} \textbar{} \texttt{false}
  \textbar{} cell {]} - Mark the actual parameter estimate; a cell array
  can be specified to control graphics options.
\item
  \texttt{'plotBounds='} {[} \emph{\texttt{true}} \textbar{}
  \texttt{false} \textbar{} cell {]} - Draw the lower and/or upper
  bounds if they fall within the graph range; a cell array can be
  specified to control graphics options.
\item
  \texttt{'subplot='} {[} \emph{\texttt{'auto'}} \textbar{} numeric {]}
  - Subplot division of the figure when plotting the results.
\item
  \texttt{'title='} {[} \texttt{\{'interpreter=','none'\}} \textbar{}
  cell {]} - Display graph titles, and specify graphics options for the
  titles.
\item
  \texttt{'linkAxes='} {[} \texttt{true} \textbar{}
  \emph{\texttt{false}} {]} - Make the vertical axes identical for all
  graphs.
\end{itemize}

\paragraph{Description}\label{description}

The data log-likelihood curves are shifted up or down by an arbitrary
constant to make them fit in the graph; their curvature is preserved.

\paragraph{Example}\label{example}


\subsection{Measuring treatment effects in leaves}