\section[Unverified implementation]{Unverified implementation\implementation{TwoPassMerge.NoProofs}} \label{sec:no-proofs}
We begin by implementing the described algorithms without any proof of their correctness. We define \texttt{Heap} datatype as:

\begin{code}
data Heap : Set where
  empty : Heap
  node  : Priority → Rank → Heap → Heap → Heap
\end{code}
\noindent
According to this definition a heap is either empty or it is a node with priority, rank and two subheaps. Both \texttt{Priority} and \texttt{Rank} are aliases to \texttt{Nat}, which allows us to perform on them any operation that works on \texttt{Nat} type. Note that storing rank in a node is redundant: we could just compute size of a heap whenever necessary. I choose to store rank in the constructor because it will be instructive to show how it is converted into inductive type family index (see Section \ref{sec:rank-property}).

\subsection{Merging two heaps}\label{sec:twopass-merge}

Heaps \texttt{h1} and \texttt{h2} are merged using a recursive algorithm. We need to consider four cases:

\begin{enumerate}
 \item (base case) \texttt{h1} is empty: return \texttt{h2}.
 \item (base case) \texttt{h2} is empty: return \texttt{h1}.
 \item (inductive case) priority \texttt{p1} is higher than \texttt{p2}: \texttt{p1} becomes new root, \texttt{l1} becomes its one child and \texttt{r1}$\oplus$\texttt{h2} becomes the other.
 \item (inductive case) priority \texttt{p2} is higher than or equal to \texttt{p1}: \texttt{p2} becomes new root, \texttt{l2} becomes its one child and \texttt{r2}$\oplus$\texttt{h1} becomes the other.
\end{enumerate}
\noindent
There is no guarantee that \textit{r1}$\oplus$\textit{h2} (or \textit{r2}$\oplus$\textit{h1}) is smaller than \textit{l1} (or \textit{l2}). To ensure that rank invariant is maintained we use helper function \texttt{makeT}, as proposed by Okasaki \cite{Oka99}. We pass new children and the priority to \texttt{makeT}, which creates a new node with the given priority and swaps the children if necessary (see \Listing{lst:makeT-merge}). As Okasaki points out this algorithm can be view as having two passes: a top-down pass that performs merging and a bottom-up pass that restores the rank invariant.

\begin{listing}[htb!]
\begin{code}
makeT : Priority → Heap → Heap → Heap
makeT p l r with rank l ≥ rank r
makeT p l r | true  = node p (suc (rank l + rank r)) l r
makeT p l r | false = node p (suc (rank l + rank r)) r l

merge : Heap → Heap → Heap
merge empty h2 = h2
merge h1 empty = h1
merge (node p1 h1-r l1 r1) (node p2 h2-r l2 r2)
  with p1 < p2
merge (node p1 h1-r l1 r1) (node p2 h2-r l2 r2)
  | true  = makeT p1 l1 (merge r1 (node p2 h2-r l2 r2))
merge (node p1 h1-r l1 r1) (node p2 h2-r l2 r2)
  | false = makeT p2 l2 (merge (node p1 h1-r l1 r1) r2)
\end{code}
\caption{Implementation of \texttt{makeT} and \texttt{merge}. \texttt{rank} returns rank of a tree.}\label{lst:makeT-merge}
\end{listing}

\subsection{Inserting element into a heap}

Insert is defined by merging with a singleton heap as described in Section~\ref{sec:wblh}. See companion code for implementation.

\subsection{Finding and removing element with the highest priority}

To retrieve element with the highest priority we return value stored in the root of a heap:

\begin{code}
findMin : Heap → Priority
findMin empty          = \hilight{\{ \}?}
findMin (node p _ _ _) = p
\end{code}
\noindent
Here we encounter a problem: what should \texttt{findMin} return for an empty heap? If we were using a language like Haskell or ML one thing we could consider is raising an exception. This is the choice made by Okasaki in ``Purely Functional Data Structures''. But throwing an exception is precisely the thing that would make our implementation impure! Besides Agda is a total language, which means that every function must terminate with a result. Raising an exception is therefore not an option. Another alternative is to assume a default priority that will be returned for an empty heap. This priority would have to be some distinguished natural number. $0$ represents the highest priority so it is unreasonable to assume it as default. We could return $\infty$, which represents the lowest possible priority. This would require us to extend definition of \texttt{Nat} with $\infty$, which in turn would force us to modify all functions that pattern match on values of \texttt{Nat}. Redefining natural numbers for the sake of getting one function right also does not sound like a good option. Let's face it -- our types do not reflect the fact that \texttt{findMin} function is not defined for an empty heap! To solve this problem we need to be more specific about types. One solution would be to use \texttt{Maybe} datatype:

\begin{code}
data Maybe (A : Set) : Set where
  nothing : Maybe A
  just    : A → Maybe A

findMinM : Heap → Maybe Priority
findMinM empty          = nothing
findMinM (node p _ _ _) = just p
\end{code}

\noindent
Returning \texttt{nothing} is like saying ``no output exists for the given input data''. This allows us to express the fact that \texttt{findMin} is not defined for some input values. This solution works but it forces every caller of \texttt{findMinM} to inspect the result and be prepared for \texttt{nothing}, which means extra boilerplate in the code and checks during run time. Implementation of \texttt{deleteMin} based on description in Section~\ref{sec:wblh} faces the same problem.

The best solution to this issue is to ensure that \texttt{findMin} and \texttt{deleteMin} cannot be applied to an empty heap. We can achieve this by indexing \texttt{Heap} with its size. Doing so will also allow us to prove the rank property.

\section[Proving rank property]{Proving rank property\implementation{TwoPassMerge.RankProof}} \label{sec:rank-property}

We will now prove that our implementation maintains the rank property. The first step is to express \texttt{Rank} at the type level as an index of \texttt{Heap} datatype. Since rank of a heap is now part of its type we can ensure at compile time that rank of left subtree is not smaller than rank of the right subtree. We do this be requiring that \texttt{node} constructor is given a proof that rank invariant holds. To express such proof we use \texttt{≥} datatype:

\begin{code}
data _≥_ : Nat → Nat → Set where
  ge0 : \{y : Nat\} → y ≥ zero
  geS : \{x y : Nat\} → x ≥ y → suc x ≥ suc y
\end{code}
\noindent
Values of this type, which is indexed by two natural numbers, prove that: a) any natural number is greater than or equal to \texttt{0} (\texttt{ge0} constructor); b) if two numbers are in greater-equal relation then their successors are also in that relation (\texttt{geS} constructor). This type represents concept of data as evidence~\cite{AltMcBMcK05}. We use \texttt{order} function to compare two natural numbers and \texttt{Order} datatype to express the result. Implementation is located in \texttt{Basics.Ordering} module of the companion code.

Having defined ≥ we can now give new definition of \texttt{Heap}:

\begin{code}
data Heap : Rank → Set where
  empty : Heap zero
  node  : \{l r : Rank\} → Priority → l ≥ r →
          Heap l → Heap r → Heap (suc (l + r))
\end{code}

\noindent
Empty heap contains no elements and so \texttt{empty} returns \texttt{Heap} indexed with \texttt{0}. Non-empty node stores an element and two children of rank \textit{l} and \textit{r}. Therefore the size of the resulting heap is $1 + l + r$, which we express as $\suc(l + r)$. We must also supply a value of type \texttt{l ≥ r} to the constructor, ie. we must provide evidence that rank invariant holds.

Proving the rank invariant itself is surprisingly simple. We can obtain evidence that rank of left subtree is not smaller than rank of right subtree by replacing \texttt{≥} in \texttt{makeT} with \texttt{order}, which compares two \texttt{Nat}s and supplies evidence of the result. But there is another difficulty here. Recall that the merging algorithm is two pass: we use \texttt{merge} to actually do the merging and \texttt{makeT} to restore the rank invariant if necessary. Since we index heaps by their rank we now require that \texttt{makeT} and \texttt{merge} construct trees of correct rank. We must therefore prove that:\linebreak a) \texttt{makeT} creates a node with rank equal to sum of children nodes' ranks plus one;\linebreak b) \texttt{merge} creates a heap with rank equal to the sum of ranks of heaps being merged.

\subsection{Proving makeT}\label{sec:twopass-makeT-proof}

\begin{listing}[b!]
\begin{code}
makeT-lemma : (a b : Nat) → suc (a + b) ≡ suc (b + a)
makeT-lemma a b = cong suc (+comm a b)

makeT : \{l r : Rank\} → Priority → Heap l → Heap r → Heap (suc (l + r))
makeT \{l-rank\} \{r-rank\} p l r with order l-rank r-rank
makeT \{l-rank\} \{r-rank\} p l r | ge l≥r
  = node p l≥r l r
makeT \{l-rank\} \{r-rank\} p l r | le r≥l
  = subst Heap (makeT-lemma r-rank l-rank) (node p r≥l r l)
\end{code}
\caption{Implementation of \texttt{makeT} with verified rank property.}\label{lst:rank-proof-makeT-two-pass}
\end{listing}
\noindent
\texttt{makeT} takes subtrees of rank \textit{l} and \textit{r} and produces a new tree with rank $\suc(l + r)$, where $\suc$ follows from the fact that the node itself is storing one element. We must prove that each of two cases of \texttt{makeT} returns heap of correct rank:

\begin{enumerate}
 \item If \textit{l} is greater than or equal to \textit{r} then no extra proof is necessary as everything follows from the definition of + and type signature of \texttt{node}.
 \item If \textit{r} is greater than or equal to \textit{l} then we must swap \texttt{l} and \texttt{r} subtrees. This requires us to prove that:

\begin{equation*}
suc (r + l) ≡ suc (l + r)
\end{equation*}

That proof is done using congruence on $\suc$ function and commutativity of addition. We will define that proof as \texttt{makeT-lemma}.
\end{enumerate}
\noindent
\Listing{lst:rank-proof-makeT-two-pass} shows new code of \texttt{makeT}. Notice how \texttt{subst} applies the proof to the \texttt{Heap} type constructor and converts the type produced by \texttt{(node p r≥l r l)} expression into the type given in \texttt{makeT} type signature.

\subsection{Proving merge}

We now verify that all four cases of \texttt{merge} shown in \Listing{lst:makeT-merge} produce heap of required rank.

\subsubsection{base cases}

In the first base case we have $h1 ≡ 0$. Therefore:

\begin{equation*}
h1 + h2 ≡ 0 + h2 \stackrel{+, (1)}{≡} h2
\end{equation*}
\noindent
Which ends the first proof -- everything follows from definition of $+$\footnote{The $\stackrel{+, (1)}{≡}$ notation means that equality follows from the first defining equation of $+$.}. In the second base case $h2 ≡ 0$ and things are slightly more difficult: the definition of $+$ only says that $0$ is the left identity but it does not say that it is also the right identity. We must therefore construct a proof that:

\begin{equation*}
h1 + 0 \stackrel{?}{≡} h1
\end{equation*}
\noindent
Luckily for us, we already have that proof defined in the \texttt{Basics.Reasoning} module as \texttt{+0}. Since that proof is in the opposite direction -- it proves $a ≡ a + 0$, not $a + 0 ≡ a$ -- we have to use symmetry of $≡$ .

\subsubsection{inductive cases}\label{sec:twopass-merge-inductive}

In an inductive case we know that neither \texttt{h1} nor \texttt{h2} is empty, ie. their ranks are given as $\suc (l1 + r1)$ and $\suc (l2 + r2)$ respectively. This means that Agda sees expected rank of the merged heap as:

\begin{equation*}
\suc (l1 + r1) + \suc (l2 + r2) \stackrel{+, (2)}{≡} \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}
\noindent
This will be our goal in both proofs of inductive cases.

In the first inductive case we construct the result by calling\footnote{Note that \texttt{node} constructor in the unverified implementation show in \Listing{lst:makeT-merge} takes slightly different parameters. This is because we changed the definition of \texttt{Heap} datatype to take the proof of rank property instead of storing the rank in the constructor.}:

\begin{code}
makeT p1 l1 (merge r1 (node p2 l2≥r2 l2 r2))
\end{code}
\noindent
Call to \texttt{node} with \texttt{l2} and \texttt{r2} as parameters produces node of rank $\suc(l2 + r2)$. Passing it to \texttt{merge} together with \texttt{r1} gives a tree of rank $r1 + \suc(l2 + r2)$ (by the type signature of \texttt{merge}). Passing result of \texttt{merge} to \texttt{makeT} produces tree of rank $\suc (l1 + (r1 + \suc (l2 + r2)))$ by the type signature of \texttt{makeT}. We must therefore construct a proof that:

\begin{equation*}
\suc (l1 + (r1 + \suc (l2 + r2))) ≡ \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}
\noindent
Appealing to congruence on $\suc$ leaves us with a proof of:

\begin{equation*}
l1 + (r1 + \suc (l2 + r2)) ≡ (l1 + r1) + \suc (l2 + r2)
\end{equation*}
\noindent
Substituting $a = l1$, $b = r1$ and $c = \suc (l2 + r2)$ gives:

\begin{equation*}
a + (b + c) ≡ (a + b) + c
\end{equation*}
\noindent
This is associativity of addition that we have already proved in \texttt{Basics.Reasoning}.

The proof of second inductive case is much more interesting. This time we construct the result by calling:

\begin{code}
makeT p2 l2 (merge r2 (node p1 l1≥r1 l1 r1))
\end{code}
\noindent
and therefore have to prove:

\begin{equation*}
\suc (l2 + (r2 + \suc (l1 + r1))) ≡ \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}
\noindent
Again we use congruence to deal with the outer calls to $\suc$ and substitute $a = l2$, $b = r2$ and $c = l1 + r1$. This leaves us with a proof of lemma A:

\begin{equation*}
a + (b + \suc c) ≡ c + \suc (a + b)
\end{equation*}
\noindent
From associativity we know that:

\begin{equation*}
a + (b + \suc c) ≡ (a + b) + \suc c
\end{equation*}
\noindent
If we prove lemma B:

\begin{equation*}
(a + b) + \suc c ≡ c + \suc (a + b)
\end{equation*}
\noindent
then we can combine lemmas A and B using transitivity to get the final proof. We substitute $n = a + b$, $m = c$ and rewrite lemma B as:

\begin{equation*}
n + \suc m ≡ m + \suc n
\end{equation*}
\noindent
From symmetry of \texttt{+suc} we know that:

\begin{equation*}
n + \suc m ≡ \suc (n + m)
\end{equation*}
\noindent
Using transitivity we combine it with congruence on commutativity of addition to prove:

\begin{equation*}
\suc (n + m) ≡ \suc (m + n)
\end{equation*}
\noindent
Again, using transitivity we combine it with \texttt{+suc} to show:

\begin{equation*}
\suc (m + n) ≡ m + \suc n
\end{equation*}
\noindent
Which proves lemma B and therefore the whole proof is complete (\Listing{lst:twopass-merge-2nd-proof}, see companion code for complete implementation).

\begin{listing}[thb!]
\begin{code}
lemma-B : (n m : Nat) → n + suc m ≡ m + suc n
lemma-B n m = trans (sym (+suc n m)) (trans (cong suc (+comm n m)) (+suc m n))

lemma-A : (a b c : Nat) → a + (b + suc c) ≡ c + suc (a + b)
lemma-A a b c = trans (+assoc a b (suc c)) (lemma-B (a + b) c)

proof-2 : (l1 r1 l2 r2 : Nat) → suc (l2 + (r2  + suc (l1 + r1)))
                              ≡ suc ((l1 + r1) + suc (l2 + r2))
proof-2 l1 r1 l2 r2 = cong suc (lemma-A l2 r2 (l1 + r1))
\end{code}
\caption{Proof of second inductive case of \texttt{merge}.}\label{lst:twopass-merge-2nd-proof}
\end{listing}

\subsection{insert}

Inserting new element into the heap increases its rank by one. Now that rank is encoded as a datatype index this fact must be reflected in the type signature of \texttt{insert}. As previously we define \texttt{insert} as \texttt{merge} with a singleton heap. Rank of singleton heap is 1 (ie. \texttt{suc zero}), while already existing heap has rank n. According to definition of merge the resulting heap will therefore have rank:

\begin{equation*}
(\suc \zero) + n \stackrel{+, (2)}{≡} \suc (\zero + n) \stackrel{+, (1)}{≡} \suc n
\end{equation*}
\noindent
Which is the size we require in the type signature of \texttt{insert}. This means we don't need any additional proof because expected result follows from definition.

\subsection{findMin, deleteMin}

Encoding rank at the type level allows us to write total versions of \texttt{findMin} and \texttt{deleteMin}. By requiring that input \texttt{Heap} has rank \texttt{suc n} we exclude the possibility of passing empty heap to any of these functions.

\section{Constructing equality proofs using transitivity}\label{sec:eq-proofs-using-trans}

Now that we have conducted an inductive proof of \texttt{merge} in Section \ref{sec:twopass-merge-inductive} we can focus on a general technique used in that proof. Let us rewrite \texttt{proof-2} in a different way to see closely what is happening at each step. Inlining lemmas A and B into \texttt{proof-2} gives:

\begin{code}
proof-2i : (l1 r1 l2 r2 : Nat) → suc (l2 + (r2  + suc (l1 + r1)))
                               ≡ suc ((l1 + r1) + suc (l2 + r2))
proof-2i l1 r1 l2 r2 =
  cong suc (trans (+assoc l2 r2 (suc (l1 + r1)))
           (trans (sym (+suc (l2 + r2) (l1 + r1)))
           (trans (cong suc (+comm (l2 + r2) (l1 + r1)))
                  (+suc (l1 + r1) (l2 + r2))))
\end{code}
\noindent
We see that \texttt{proof-2} is structured around proofs of elementary properties combined using transitivity. In general, if we have to prove $a ≡ e$ and we can prove $a ≡ b$ using $\prof 1$, $b ≡ c$ using $\prof 2$, $c ≡ d$ using $\prof 3$, $d ≡ e$ using $\prof 4$ then we can combine these proofs to get the final proof of $a ≡ e$:

\begin{equation*}
\trans\, (\prof 1)\, (\trans\, (\prof 2)\, (\trans\, (\prof 3)\, (\prof 4)))
\end{equation*}
\noindent
While simple to use, combining proofs using transitivity can be hard to comprehend. The intermediate terms are hidden from us and we have to reconstruct them every time we read our proof. Let us then replace usage of transitivity with the following notation, which explicitly shows intermediate proof steps together with their proofs:

\begin{align*}
a&\;{≡}\langle \prof 1 \rangle\\
b&\;{≡}\langle \prof 2 \rangle\\
c&\;{≡}\langle \prof 3 \rangle\\
d&\;{≡}\langle \prof 4 \rangle\\
e&
\end{align*}
\noindent
Rewriting \texttt{proof-2i} in this notation gives:

\begin{align*}
                                \suc (l2 + (r2 + \suc (l1 + r1)))&\;{≡}\langle \congr\;\suc \rangle\\
{\color{gray} \suc(} l2 + (r2 + \suc (l1 + r1))  {\color{gray})} &\;{≡}\langle\assoc\;l2\;r2\;(\suc (l1 + r1))\rangle\\
{\color{gray} \suc(} (l2 + r2) + \suc (l1 + r1)  {\color{gray})} &\;{≡}\langle \sym (\Psuc\;(l2 + r2)\;(l1 + r1))\rangle\\
{\color{gray} \suc(} \suc ((l2 + r2) + (l1 + r1)){\color{gray})} &\;{≡}\langle \congr\;\suc\;(\comm\;(l2 + r2)\;(l1 + r1)) \rangle\\
{\color{gray} \suc(} \suc ((l1 + r1) + (l2 + r2)){\color{gray})} &\;{≡}\langle\Psuc\;(l1 + r1)\;(l2 + r2) \rangle\\
{\color{gray} \suc(} (l1 + r1) + \suc (l2 + r2)  {\color{gray})} &
\end{align*}

\noindent
Grey ${\color{gray}\suc}$ denotes that everything happens under call to \texttt{suc} (thanks to using congruence on $\suc$ as the first proof). Comparing this notation to \texttt{proof-2i} on the previous page shows that proofs in angle brackets correspond to proofs combined using $\trans$, while series of expressions left of $≡$ parallels our reasoning from Section \ref{sec:twopass-merge-inductive}.

\section[Proving rank property for single pass merge by composing existing proofs]{Proving rank property for single pass merge by composing existing proofs\implementation{SinglePassMerge.RankProof}} \label{sec:single-pass-merge-proof-by-comp}

As mentioned in Section \ref{sec:twopass-merge} \texttt{merge} can be viewed as consisting of two passes. We can obtain a single pass version of the algorithm by inlining calls to \texttt{makeT} into \texttt{merge}. This new algorithm has two bases cases (as previously) and four inductive cases:

\begin{enumerate}
 \item (base case) \texttt{h1} is empty: return \texttt{h2}.
 \item (base case) \texttt{h2} is empty: return \texttt{h1}.
 \item (1st inductive case) priority \texttt{p1} is higher than \texttt{p2} and \textit{l1} is not smaller than  \textit{r1}$\oplus$\textit{h2}: \texttt{p1} becomes new root, \texttt{l1} becomes the left child and \texttt{r1}$\oplus$\texttt{h2} becomes the right child.
 \item (2nd inductive case) priority \texttt{p1} is higher than \texttt{p2} and \textit{r1}$\oplus$\textit{h2} is larger than \textit{l1}: \texttt{p1} becomes new root, \texttt{r1}$\oplus$\texttt{h2} becomes the left child and \texttt{l1} becomes the right child.
 \item (3rd inductive case) priority \texttt{p2} is higher than or equal to \texttt{p1} and \textit{l2} is not smaller than  \textit{r2}$\oplus$\textit{h1}: \texttt{p2} becomes new root, \texttt{l2} becomes the left child and \texttt{r2}$\oplus$\texttt{h1} becomes the right child.
 \item (4th inductive case) priority \texttt{p2} is higher than or equal to \texttt{p1} and \textit{r2}$\oplus$\textit{h1} is larger than  \textit{l2}: \texttt{p2} becomes new root, \texttt{r2}$\oplus$\texttt{h1} becomes the left child and \texttt{l2} becomes the right child.
\end{enumerate}

Now that we have inlined \texttt{makeT} we must construct proofs of new \texttt{merge}. Note that previously we made calls to \texttt{makeT} only in inductive cases. This means that implementation of base cases remains unchanged and so do the proofs. Let us take a closer look at proofs we need to supply for inductive cases:

\begin{itemize}
 \item (1st inductive case): call to \texttt{makeT} would not swap left and right children when creating a node from parameters passed to it. We must prove:

\begin{equation*}
\suc (l1 + (r1 + \suc (l2 + r2))) ≡ \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}

\item (2nd inductive case): call to \texttt{makeT} would swap left and right children when creating a node from parameters passed to it. We must prove:

\begin{equation*}
\suc ((r1 + \suc (l2 + r2)) + l1) ≡ \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}

\item (3rd inductive case): call to \texttt{makeT} would not swap left and right children when creating a node from parameters passed to it. We must prove:

\begin{equation*}
\suc (l2 + (r2  + \suc (l1 + r1))) ≡ \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}

\item (4th inductive case): call to \texttt{makeT} would swap left and right children when creating a node from parameters passed to it. We must prove:

\begin{equation*}
\suc ((r2 + \suc (l1 + r1)) + l2) ≡ \suc ((l1 + r1) + \suc (l2 + r2))
\end{equation*}
\end{itemize}

First thing to note is that inductive cases 1 and 3 require us to supply the same proofs as the ones we gave for inductive cases in two-pass merge. This means we can reuse old proofs. What about cases 2 and 4? One thing we could do is construct proofs of these properties from scratch using technique described in Section~\ref{sec:eq-proofs-using-trans}. This is left as an exercise to the reader. Here we will proceed in a different way.

Notice that properties we have to prove in cases 2 and 4 are very similar to properties 1 and 3. The only difference between 1 and 2 and between 3 and 4 is the order of parameters inside outer $\suc$ on the left hand side of equality. This is expected: in cases 2 and 4 we swap left and right subtree passed to \texttt{node} and this is directly reflected in the types.  Now, if we could prove that:

\begin{equation*}
\suc ((r1 + \suc (l2 + r2)) + l1) ≡ \suc (l1 + (r1 + \suc (l2 + r2)))
\end{equation*}
\noindent
and
\begin{equation*}
\suc ((r2 + \suc (l1 + r1)) + l2) ≡ \suc (l2 + (r2  + \suc (l1 + r1)))
\end{equation*}
\noindent
then we could use transitivity to combine these proofs with proofs of inductive cases 1 and 3. If we abstract the parameters in the above equalities we see that the property we need to prove in both cases is:

\begin{equation*}
\suc (a + b) ≡ \suc (b + a)
\end{equation*}
\noindent
And that happens to be \texttt{makeT-lemma} from Section~\ref{sec:twopass-makeT-proof}! New version of \texttt{merge} was created by inlining calls to \texttt{makeT} and now it turns out we can construct proofs of that implementation by composing proofs of \texttt{makeT} and \texttt{merge} using transitivity. This is exactly the same technique that we developed in Section~\ref{sec:eq-proofs-using-trans} only this time it is used on a slightly larger scale. It leads to a very elegant solution presented in module \texttt{SinglePassMerge.}\texttt{RankProof} of the companion code.

\section[Proving priority property]{Proving priority property\implementation{TwoPassMerge.PriorityProof}} \label{sec:priority-invariant}

To prove priority property I will index \texttt{Heap} with \texttt{Priority} and use technique demonstrated by Altenkirch, McBride and McKinna in Section 5.2 of ``Why Dependent Types Matter'' \cite{AltMcBMcK05}\footnote{To keep things simple let's forget about rank proof we conducted earlier -- in this section we once again store rank explicitly in the \texttt{node} constructor.}. Index of value n says that ``this heap can store elements with priorities n or lower''. In other words \texttt{Heap} indexed with 0 can store any priority, while \texttt{Heap} indexed with 3 can store priorities 3, 4 and lower, but can't store 0, 1 and 2. The new definition of \texttt{Heap} looks like this\footnote{Actual implementation in the companion code is slightly different. It uses sized types \cite{Abe08} to guide the termination checker in the \texttt{merge} function. This issue is orthogonal to the conducted proofs, hence I avoid sized types here for the sake of simplicity.}:

\begin{code}
data Heap : Priority → Set where
  empty : \{n : Priority\} → Heap n
  node  : \{n : Priority\} → (p : Priority) → Rank → p ≥ n →
          Heap p → Heap p → Heap n
\end{code}
\noindent
As always \texttt{Heap} has two constructors. The \texttt{empty} constructor returns \texttt{Heap n}, where index n is not constrained in any way. This means that empty heap can be given any restriction on priorities of stored elements. The \texttt{node} constructor also creates \texttt{Heap n} but this time \texttt{n} is constrained. If we store priority \texttt{p} in a node then:

\begin{enumerate}
 \item the resulting heap can only be restricted to store priorities at least as high as \texttt{p}. For example, if we create a node that stores priority 3 we cannot restrict the resulting heap to store priorities 4 and lower, because the fact that we store 3 in that node violates the restriction. This restriction is expressed by the \texttt{p ≥ n} parameter: if we can construct a value of type \texttt{p ≥ n} then it becomes a proof that priority \texttt{p} is lower than or equal to \texttt{n}.
 \item children of a node can only be restricted to store priorities that are not higher than \texttt{p}. Example: if we restrict a node to store priorities 4 and lower we cannot restrict its children to store priorities 3 or higher. This restriction is expressed by index \texttt{p} in the subheaps passed to node constructor.
\end{enumerate}

Altenkirch, McKinna and McBride \cite{AltMcBMcK05} used this technique to prove correctness of merge sort for lists. In a weight biased leftist heap every path from root to a leaf is a sorted list so extending their technique to heap case is straightforward. I elide discussion of \texttt{merge} as I offer nothing new compared to Altenkirch's paper. I instead focus on issue of creating singleton heaps and inserting elements into a heap as these cases now become interesting.

When creating a singleton heap we have to answer a question: "what priorities can we later store in a singleton heap that we just created?". "Any" seems to be a reasonable answer, which means the resulting heap will be indexed with 0 meaning: "Priorities lower than or equal to 0 -- ie. any priorities -- can be stored in this Heap". With such a liberal definition of singleton heap it is easy to write definition of \texttt{insert} by requiring that both input and output heap can store any priorities:

\begin{code}
singleton : (p : Priority) → Heap zero
singleton p = node p (suc zero) ge0 empty empty

insert : Priority → Heap zero → Heap zero
insert p h = merge (singleton p) h
\end{code}

But what if we want to insert into a heap that is not indexed with 0? One solution is to be liberal and ``promote'' that heap so that after insertion it can store elements with any priorities. Priority restriction can always be loosened but it cannot be tightened easily. However such a liberal approach might not always be satisfactory. We might actually want to keep priority bounds as tight as possible. Let us explore that possibility.

We begin by rewriting the \texttt{singleton} function:

\begin{code}
singletonB' : \{b : Priority\} → (p : Priority) → p ≥ b → Heap b
singletonB' p p≥b = node p one p≥b empty empty
\end{code}
\noindent
Now \texttt{singletonB'} allows to construct a heap containing a single element with priority \texttt{p} but the whole heap is bounded by some \texttt{b}. To construct such a heap we must supply a proof that \texttt{p} can actually be stored in \texttt{Heap b}. We can now implement new insertion function:

\begin{small}
\begin{code}
insertB' : \{b : Priority\} → (p : Priority) → p ≥ b → Heap p → Heap b
insertB' p p≥b h = merge (singletonB' p p≥b) (liftBound p≥b h)
\end{code}
\end{small}
\noindent
where \texttt{liftBound} is a function that loosens the priority bound of a heap given evidence that it is possible to do so (ie. that the new bound is less restrictive than the old one). But if we try to construct a heap using \texttt{insertB'} we quickly discover that it is useless:

\begin{code}
example-heap : Heap zero
example-heap = (insertB' (suc zero) ge0
               (insertB' zero \hilight{\{ \}?} empty))
\end{code}
\noindent
In the second call to \texttt{insertB'} we are required to supply a proof that $0 \ge 1$, which of course is not possible. The problem is that using the new \texttt{insertB'} function we can only lower the bound on the heap and thus insert the elements into the heap in decreasing order:

\begin{code}
example-heap : Heap zero
example-heap = (insertB' zero ge0
               (insertB' (suc zero) ge0 empty))
\end{code}
\noindent
This is a direct consequence of our requirement that the heap we are inserting into is restricted exactly by the priority of element we are inserting.

The bottom line is: one has to carefully consider implications of a proof on the design of functions that manipulate the data structure.


% !TEX encoding = UTF-8 Unicode
% !TEX spellcheck = en-US
\documentclass[
    aps,
    prl,
    showkeys,
    nofootinbib,
    %twocolumn,
    floatfix
]{revtex4-1}

\usepackage[utf8]{inputenc} % UTF-8
\usepackage{braket}

\usepackage{amsmath}
\usepackage{amssymb}

\usepackage{graphicx}

\renewcommand{\vec}[1]{\boldsymbol{#1}}

\newcommand{\fm}{\,\mathrm{fm}}
\newcommand{\ifm}{\,\mathrm{fm}^{-1}}
\newcommand{\MeV}{\,\mathrm{MeV}}

\begin{document}

\title{Discretization}

\author{C.~Körber}

\date{\today}

\begin{abstract}%
	How does the contact interaction depend on discretization effects?
\end{abstract}

\maketitle

\section{No discretization}
\subsection{1-d}
\subsubsection{Positive energies}

The momentum space Schrödinger equation
\begin{equation}
	\frac{p^2}{2 \mu} \psi(p) + \int \frac{d p}{2\pi} \braket{p | \hat V | p'} \psi(p') = E \psi(p')
\end{equation}
for contact interactions this becomes
\begin{equation}
	\frac{p^2}{2 \mu} \psi(p) +  c I_0 = E \psi(p') \, , \qquad I_0 = \int \frac{d p'}{2\pi} \psi(p') \, .
\end{equation}
Thus
\begin{equation}
	\psi(p) = \frac{c I_0}{E - \frac{p^2}{2\mu}}
\end{equation}
For scattering solutions we need $i\epsilon$ prescription
\begin{align}
	I_0 &= \int \frac{d p}{2\pi}  \frac{c I_0}{E - \frac{p^2}{2\mu} + i \epsilon} \\
	&= I_0 \times \frac{\mu c }{\pi} \int\limits_{ - \infty}^{\infty} \frac{d p}{\gamma^2 - {p^2} + i \tilde\epsilon} \, , \quad \gamma^2 = 2 \mu E > 0\,.
\end{align}
The remaining integral can be solved by the residual theorem: the zeros of the denominator are
\begin{align}
	\gamma^2 - {p^2} + i \tilde\epsilon &= (\gamma + i \tilde\epsilon - p)(\gamma + i \tilde\epsilon + p) \, .
\end{align}
Note that the zeros are independent on the sign of $\epsilon$ (one root in upper and one root in lower plane).
Completing the integral in the upper plane selects the residual $p_0 = \gamma + i \tilde \epsilon$ and thus
\begin{equation}
	\int\limits_{ - \infty}^{\infty} \frac{d p}{\gamma^2 - {p^2} + i \tilde\epsilon}
	=
	 \frac{2 \pi i}{2 \gamma} \, .
\end{equation}
and therefore
\begin{equation}
	1 = \frac{\mu c}{\pi} \times \frac{\pi i}{\gamma} \, ,
\end{equation}
or
\begin{equation}
	\gamma = i \mu c \, \Rightarrow  E = - \frac{\mu c^2}{2}
\end{equation}
In other words, you do not get positive energies for $c \in \mathbb{R}$.

It seems like, you only get positive energies once you are in a box...

\clearpage
\section{Understanding the unitary limit}

From my understanding, the unitary limit appears when the total cross section is independent of microscopic parameters.
The cross section is given by
\begin{equation}
	\frac{d \sigma}{d \Omega} = | f(\Omega, p) | ^ 2 \, ,
\end{equation}
where
\begin{align}
	f(\Omega, p) &= \sum_{l=0}^{\infty} f_l(\Omega, p) \, , \\
	f_l(\Omega, p) &\sim g_l(\Omega) \times \left[\exp( 2 i \delta_l (p)) - 1\right]
\end{align}
This is generally true for all $d = 1, 2, 3$ cases modulo not important factors.

In our system, for a simple contact interaction of strength $c_0$, we only find contributions to $l=0$.
Regarding your eq. (7), one finds that
\begin{equation}
	\cot \delta_0 (p) = \begin{cases}
		a_0 p &, \, d = 1 \\
		2 / \pi \log(a_0 p) &, \, d = 2 \\
		- 1/(a_0 p) &, \, d = 3
	\end{cases}
\end{equation}

In other words, we are at the unitary limit if $\cot \delta_0$ is independent of $a_0$.
This can only happen if $a_0 \rightarrow \infty$ or $a_0 \rightarrow \pm 0$ because $a_0$ must be independent of $p$.

\textbf{Does this make sense?}

To discriminate between infinite volume and lattice, I will label the momentum points which are extracted from lattice (as in continuum but finite volume) as $\gamma_i$.
Here, $\gamma_i^2 = 2 \mu E_i$, $\mu$ being the reduced two-particle mass and $E_i$ being the lattice energy spectrum.

Using your equations (35-37) and combining this with your eq. (7), one finds
\begin{equation}\label{def:a0}
	a_0 = \begin{cases}
		\frac{L}{2\pi^2}S_1(x_i) & \, , d =1 \\
		\frac{L}{2\pi} \exp \left\{ S_2(x_i) / (2\pi) \right\} & \, , d =2 \\
		\frac{ \pi L}{ S_3(x_i) } & \, , d =3
	\end{cases}
	\qquad \forall_i \, ,
\end{equation}
with $S_j(x_i)$ being the Lüscher Zeta function in $j$ dimensions and $ x_i = \mu E_i L ^2 / (2 \pi^2) $.
In other words, if your computation does the right thing, you fix your contact interaction strength $c_0$, which will give you a set of energy levels $E_i(c_0)$.
For all of the eigenstates $E_i$, all points $S_j(x_i)$ lay on a line because, because $a_0$ is independent of the energy level and eq.~\eqref{def:a0} tells us that there is a one-to-one relation between $S_j(x_i)$ and $a_0$.

So in which cases do we find that $a_0 \to 0, \pm \infty$?

\begin{itemize}
	\item For $d = 1$ find $c_0$ such that $S_1(x_i(c_0)) \to 0, \pm \infty$ $\forall_i$.
		Regarding your plots,
		\begin{itemize}
			\item $S_1(x_i(c_0)) = 0$ is not possible $\forall_i$ (ground state only approaches zero).
			\item $S_1(x_i(c_0)) \to - \infty$ is not possible $\forall_i$ (ground state $>0$).
			\item $S_1(x_i(c_0)) \to + \infty$ is possible $\forall_i$ if $c_0 \to 0^-$.
		\end{itemize}
	\item For $d = 2$ find $c_0$ such that $S_2(x_i(c_0)) \to + \infty$ $\forall_i$.
		Regarding your plots,
		\begin{itemize}
			\item $S_2(x_i(c_0)) \to + \infty$ is possible for $c_0 \to 0^-$.
		\end{itemize}
	\item For $d = 3$ find $c_0$ such that $S_3(x_i(c_0)) \to 0, \pm \infty$ $\forall_i$.
		Regarding your plots,
		\begin{itemize}
			\item $S_3(x_i(c_0)) = 0$ is possible $\forall_i$.
			\item $S_3(x_i(c_0)) \to \pm \infty$ is possible for $c_0 \to 0^\mp$.
		\end{itemize}
\end{itemize}

Obviously, the cases for $c_0 \to 0^\pm$ make sense --- if there is no interaction, than there is only the mass scale.
However this solution is not of interest.
This leaves $d=3$ as the only interesting case.

\newpage
\section{Momentum Space confusion}
This is a non complete description!
It should serve as a summary.

As we figured out most recently, it is interesting to look at Lüschers equation in a discrete finite volume if you want to connect discrete finite energy levels with continuum infinite volume phase shifts.
If you don't do so, you find that the discretization (in a finite volume) apparently induces an effective range (see figure \ref{fig-cont-lusch}).
\begin{figure*}[!htb]
\includegraphics[width=0.9\textwidth]{figs/eff-range-cont-lusch.pdf}
\caption{
    \label{fig-cont-lusch}Phase shifts extracted from continuum Lüscher equation for discrete finite volume eigenvalues of contact interaction Hamiltonian.
    The contact interactions was chosen such that the ground state matches the first zero of the zeta function.
    $\epsilon$ is the lattice spacing in [fm] for a box of size $L = 1$ [fm].
    $n_{\mathrm{step}}$ describes the implementation of the Laplace derivative.
    E.g., $n_{\mathrm{step}} = 1$ corresponds to an one step derivative where corrections are expected to scale with $\epsilon^2$.
    The variable $x$ is directly proportional to the eigenvalues of the Hamiltonian $x = 2 \mu E L^2 / (2 \pi)^2$.
    Even thought the interaction has no effective range (contact interaction), the effective range expansion for more precise implementations of the derivative, certainly is proportional to $x$.
 }
\end{figure*}

The trick you have used to get there was to replace the finite volume continuum Zeta function .
\begin{equation}
    S_3(x) = \sum\limits_{\vec n \in M(\Lambda)} \frac{1}{\vec n ^2 - x} - 4 \pi \Lambda
    \, , \qquad
    M(\Lambda) = \left\{ \vec n \in \mathbb N \middle\vert 0 \leq n_i \leq \Lambda \right\}
\end{equation}
with a "discretized version"
\begin{equation}
    \mapsto
    S_3^{\mathrm{lat}}(x) = \frac{4 \pi^2}{L^2} \sum\limits_{\vec k \in M^\epsilon(L)} \frac{1}{\vec k ^2 - 2 \mu E} - \mathcal L \pi^2 \frac{L}{\epsilon}
    \, , \qquad
    M^\epsilon(L) = \left\{ \vec k \in \frac{2 \pi}{L} \mathbb N \middle\vert - \frac{\pi}{\epsilon} \leq k_i < \frac{\pi}{\epsilon} \right\}
    \, ,
\end{equation}
where $\mathcal L = 0.777551 \cdots$ is the normalization of the momentum integral and the sum is limited but the momentum cutoff of the discrete spatial lattice.

This certainly improved the effective range expansion (see fig.~\ref{fig-cont-lusch}).
\begin{figure*}[!htb]
\includegraphics[width=0.9\textwidth]{figs/eff-range-discrete-lusch.pdf}
\caption{
    \label{fig-cont-lusch}Phase shifts extracted from discrete Lüscher equation for discrete finite volume eigenvalues of contact interaction Hamiltonian.
    $\epsilon$ is the lattice spacing in [fm] for a box of size $L = 1$ [fm].
 }
\end{figure*}

Even thought the utilization of the discrete Lüscher equation improves the description, e.g., reduces the size of the induced effective range, the results are not perfectly constant (e.g., equal to zero because of the choice of the contact interaction).
On top of that, we now see curvature in the effective range expansion.
This might be still the cause of further discretization effects.
Next, I describe how one can improve on that.

\subsection{Removing all discretization effects -- making ERE flat}
\textbf{The idea:} Implement an exact discrete derivative by transforming to momentum space, multiplying by the exact $p^2$, and transforming back to coordinate space.
Doing so, remove all derivative discretization approximations and hopefully recover a flat effective range expansion.

\textbf{The conclusion:} This is not possible.

\textbf{The next step:} Implementing the "actual" discrete Lüscher equation.

\subsubsection{The idea}
The idea is straight forward:

\begin{equation}
	\braket{ \vec r ' | \hat H_0 | \vec r}
	=
	\int d \vec q^3 \int d \vec k^3 \braket{ \vec k | \hat H_0 | \vec q} \braket{\vec r' | \vec k} \braket{\vec q | \vec r}
	=
	\int d \vec q^3 H_0(\vec q) \exp\left\{ i \vec q \cdot \left( \vec r - \vec r '\right)\right\}
\end{equation}
Discrete FFTs are already implemented in python, so the only remaining challenge is to multiply the transformed input times the expectation values of the kinetic Hamiltionian $H_0(\vec q)$.

But this turned out to be a major source of confusion.
As an example, suppose you have four spatial sites in a one dimensional discrete box with periodic boundary conditions.
This means, your momenta are discrete $\ket{\vec p} = \ket{2 \pi / L \vec n}$ with $\vec n \in \mathbb Z^3$ and periodic  $\ket{\vec p + 2 \pi / \epsilon} = \ket{\vec p}$.
A possible choice for momentum basis states are
\begin{equation}
	B_1(L = 4\epsilon, \epsilon)
	= \left\{ \frac{2\pi}{4\epsilon} \times n \middle \vert n \in \{-2, -1, 0, 1\} \right\}
	= \left\{ -\frac{\pi}{\epsilon}, -\frac{\pi}{2\epsilon}, 0, \frac{\pi}{2\epsilon} \right\} \, .
\end{equation}
The naive choice of eigenvalues are thus
\begin{equation}
    H(B_1) = \frac{1}{2\mu} \frac{\pi^2}{4 \epsilon^2} \left\{ 4, 1, 0, 1\right\} \, .
\end{equation}
But because of the periodicity of momenta $\ket{\vec p} = \ket{\vec p + 2\pi/\epsilon}$, the following basis is a valid choice as well:
\begin{equation}
	B_2(L = 4\epsilon, \epsilon)
	= \left\{ \frac{2\pi}{4\epsilon} \times n \middle \vert n \in \{0, 1, 2, 3\} \right\}
	= \left\{ 0, \frac{\pi}{2\epsilon}, \frac{\pi}{\epsilon}, \frac{3\pi}{2\epsilon} \right\} \, , \qquad
	H(B_2) = \frac{1}{2\mu} \frac{\pi^2}{4 \epsilon^2} \left\{ 0, 1, 4, 9\right\} \, .
\end{equation}
And since the discrete Fourier transformations are unitary transformations (and thus the eigenvalues of the Hamiltonian do not change through FTs), clearly the different implementations of the Hamiltonian return different answers.

Most interestingly, when actually implementing a 1-step derivative and running the FFTs in python, the first basis is actually preferred.

What's happening?

You have to manually take care of the periodicity!
Look at coordinate space.
Lüscher actually defines his finite volume periodic boundaries operators such that
\begin{equation}
    O_L(\vec r) = O_L(\vec r + \vec n L) = \frac{1}{\mathcal N} \sum _{\vec n \in \mathbb Z} O(\vec r + \vec n L)\, ,
\end{equation}
where $\mathcal N$ is a normalization and the infinite volume operator has a finite range such that $\lim\limits_{L\to \infty} O_L(\vec r) = O(\vec r)$.

So, how do we do the same thing for momenta.
The answer is basically the same.
Implement the expectation values of the operators such that
\begin{itemize}
    \item[(A)] The operators $O_\epsilon$ are periodic in $\frac{2\pi}{\epsilon}$ and
    \item[(B)] In the limit of $\epsilon \to 0$, you obtain  $O_\epsilon \to  O$.
\end{itemize}

So what's a valid choice?
\begin{equation}
	D^1( \vec p, \epsilon) = \sum_{i=1}^3 \frac{2 - 2 \cos(\epsilon p_i)}{\epsilon^2} \, .
\end{equation}
That's just the same thing you would do in coordinate space by introducing a finite step derivative.
In principal you can also do better and implement improved operators for faster convergence.

In other words: a naive infinite order improvement is not possible -- it does not matter where or how you implement your derivative.
If you take care of discretization and periodic boundary conditions, there is always a one to one correspondence of momentum and coordinate space.
At some point, it might be more efficient numerically though to run computations in one or the other space...

But here is the actual catch: since the momentum dispersion relation you have used $D^\infty(\vec p, \epsilon) = \vec p^2$ is actually not obtainable on a lattice (unless $n_{\mathrm{step}} \to \infty$), you should use the actual lattice dispersion relation (spectrum of $H_0$) to execute the Lüscher sum.

\subsection{New equations}

What I am suggesting is that the new equations are the following:
Instead of the infinitely improved dispersion relation $D^\infty(\vec p, \epsilon)$ (which is the continuum dispersion relation in a fixed interval), you should use the discrete lattice dispersion relation
\begin{equation}
    D^\infty(\vec p, \epsilon) = \vec p ^2
    \to
    D^{n_{\mathrm{s}}}(\vec p, \epsilon)
    =
    \frac{1}{\epsilon^2} \sum\limits_{i=1}^3 \sum\limits_{n_i=-n_{\mathrm{s}}}^{n_{\mathrm{s}}} c_{|n_i|}^{n_{\mathrm{s}}} \cos( p_i n_i \epsilon)
\end{equation}
Where the coefficients $c_i^{n_{\mathrm{s}}}$ are enforced by the constrained
\begin{equation}\label{def:lattice-dispersion}
    D^{n_{\mathrm{s}}}(\vec p, \epsilon)
    =
    p^2 + \mathcal O \left(\epsilon^{2 n_{\mathrm{s}}}\right)
    \, .
\end{equation}
A few coefficients are given in table \ref{tab-dispersion-coeff}.

\begin{table}[htb]
\centering
\begin{tabular}{r | ccccc}
$ c_{i}^{n_{\mathrm{s}}}$ & i = 0 & 1 & 2 & 3 & 4 \\ \hline
$n_{\mathrm{s}} = 1$ & 2 & -1 \\
2 & $\frac{5}{2}$ & $-\frac{4}{3}$ & $\frac{1}{12}$ \\
3 & $\frac{49}{18}$ & $-\frac{3}{2}$ & $\frac{3}{20}$ & $-\frac{1}{90}$ \\
4 & $\frac{205}{72}$ & $-\frac{8}{5}$ & $\frac{1}{5}$  & $-\frac{8}{315}$ & $\frac{1}{560}$
\end{tabular}
\caption{\label{tab-dispersion-coeff}Coefficients for discrete momentum dispersion relation.
    Note that this coefficients are minus the Laplace finite step coefficients (because $\partial_x^2 \leftrightarrow - p^2$).
}
\end{table}

Thus one has to update the counter term in the zeta function definition (your $m = 2\mu$) (do I get the factors right)
\begin{equation}
    \frac{\pi}{\epsilon}
    \mathcal L
    =
    \frac{4 \pi}{(2\pi)^3}
    \left(
    \prod \limits_{i=1}^3
    \int\limits_{-\pi /\epsilon}^{\pi / \epsilon}
    d q_i
    \right)
    \frac{1}{q_1^2 + q_2^2 + q_3^2}
    \to
    \frac{4 \pi}{(2\pi)^3}
    \left(
    \prod \limits_{i=1}^3
    \int\limits_{-\pi / \epsilon}^{\pi / \epsilon}
    d q_i
    \right)
    \frac{1}{D^{n_{\mathrm{s}}}(\vec p, \epsilon)}
\end{equation}
and adjust the zeta function
\begin{equation}
    S_3^{\mathrm{lat}}(x) = \frac{4 \pi^2}{L^2} \sum\limits_{\vec k \in M^\epsilon(L)} \frac{1}{\vec D^{n_{\mathrm{s}}}(\vec p, \epsilon) - 2 \mu E} - \mathcal L \pi^2 \frac{L}{\epsilon}
    \, , \qquad
    M^\epsilon(L) = \left\{ \vec k \in \frac{2 \pi}{L} \mathbb N \middle\vert - \frac{\pi}{\epsilon} \leq k_i < \frac{\pi}{\epsilon} \right\}
    \, ,
\end{equation}

Let me know what you think about that.

\newpage
\section{Long Range Forces}
Long range potentials defined by non-zero effective range and higher ERE parameters are the next step in the direction of realistic nuclear potentials.
Is it possible to improve the lattice finite volume effective range expansion for long range forces in the same manner as in the unitary case?
Particularly, if length scales like a non-zero scattering length and effective range are present, how do they mix with induced length scales?
Is there a power counting in terms of induced over physical quantities?

It is desirable to choose a potential where the infinite volume continuum results can be computed analytically, to answer the above questions in the most accurate way.
For this reason, I have choosen the following separable potential
\begin{align}
	V(\vec p', \vec p) &= - g^*(\vec p') g(\vec p) \, ,
	&
	g(\vec{p})=\overline{g} \sqrt{8 \pi} \frac{M^{3}}{\left(\vec{p}^{2}+M^{2}\right)^{2}}, \quad M, \overline{g} \in \mathbb{R}
	\, .
\end{align}
The factorization generally allows to extract numerical solutions for well defined functions $g(\vec p)$ (as in all integrals are convergent).
The specific choice of $g$ mimics a pion exchange, $V(r, r') \sim \exp(- M r - M r')$, converges against a delta function for $M\to \infty$ but is well behaved in its ultraviolet and infrared parts and thus does not need any regulator.

\subsection{Analytical derivation of ERE}

For this potential, the two-nucleon binding momentum $\gamma = \sqrt{-2 \mu E}$ (where $E < 0$ is the ground state energy and $\mu$ the reduced mass of the two-nucleon system) is related to the potential parameters by
\begin{equation}\label{def:g-lr-binding}
	\overline{g} = \frac{2M(\gamma+M)^{2}}{\sqrt{\mu M^{3}\left(\gamma^{2}+5 M^{2}+4 \gamma M\right)}} \, .
\end{equation}

To compute the phase shifts, one must know the $T$-matrix which is given by
\begin{align}
	T(\vec p', \vec p, E)
	&=
	V(\vec p'. \vec p) + \lim\limits_{\epsilon \to 0}\int \frac{d \vec k^3}{(2\pi)^3} V(\vec p', \vec k) G(\vec k, E + i \epsilon) T(\vec k, \vec p, E) \, ,
	&
	G(\vec k, E+ i \epsilon) = \frac{1}{E + i \epsilon - \frac{k^2}{2\mu}}
	\, .
\end{align}
Because of the separable potential, the equation factorizes to
\begin{align}
	T(\vec p', \vec p, E)
	&=
	- g^*(\vec p') \left[ g(\vec p) + \Gamma(\vec p, E) \right] \, ,
	&
	\Gamma(\vec p, E)
	&\equiv
	\lim\limits_{\epsilon \to 0}\int \frac{d \vec k^3}{(2\pi)^3} g(\vec k) G(\vec k, E + i \epsilon) T(\vec k, \vec p, E)
	\, .
\end{align}
Substituting $T$ back into the definition of $\Gamma$, one finds
\begin{align}
	\Gamma(\vec p, E)
	&= - \left[ g(\vec p) + \Gamma(\vec p, E) \right] I_0(E)
	\, , &
	I_0(E) &= \lim\limits_{\epsilon \to 0}\int \frac{d \vec k^3}{(2\pi)^3} g(\vec k) G(\vec k, E + i \epsilon) g^*(\vec k)
	\\&&&= - \lim\limits_{\epsilon \to 0}\int \frac{d \vec k^3}{(2\pi)^3}  G(\vec k, E + i \epsilon) V(\vec k, \vec k)
	\, ,
\end{align}
or equivalently
\begin{equation}
	\Gamma(\vec p, E) = - \frac{I_0(E)}{1 + I_0(E)}g(\vec p) \, .
\end{equation}
The $T$-matrix becomes
\begin{equation}
	T(\vec p', \vec p, E)
	=
	\frac{V(\vec p', \vec p)}{1 + I_0(E)}
	\, .
\end{equation}
The result for the integral is
\begin{equation}
	I_0\left(E = - \frac{\gamma^2}{2\mu}\right)
	=
	- |\bar g|^2 \mu  M \frac{\gamma ^2+5 M^2+4 \gamma  M}{4(\gamma +M)^4}
	\, , \qquad
	\gamma \in \mathbb R
\end{equation}
Indeed, for the binding energy and the choice of $\bar g$ as in eq.~\eqref{def:g-lr-binding}, $I_0(E = - \gamma^2/(2\mu)) = -1$ and therefore the $T$-matrix is singular.

In general, one has
\begin{equation}
	I_0\left(E = \frac{k^2}{2\mu}\right)
	=
	-|\bar g|^2 \mu  M \frac{
		-k^6-5 k^4 M^2+M^5 \left(5 M+16 i \sqrt{k^2}\right)-15 k^2 M^4 \sqrt{k^2}
	}{
		4\left(k^2+M^2\right)^4
	}
\end{equation}

And finally using
\begin{equation}
	\frac{2 \pi}{ \mu k } \frac{1}{\cot(\delta_0(k)) - i} = - T_0\left(\vec k, \vec k, \frac{k^2}{2 \mu} \right) \, ,
\end{equation}
one obtains the analytic effective range expansion
\begin{align}
	k \cot( \delta_0(k))
	&=
	-\frac{5 |\bar g|^2 \mu  M-4 M^2}{16 |\bar g|^2 \mu }
	+\frac{15 |\bar g|^2 \mu + 16 M}{16 |\bar g|^2 \mu M}k^2
	+\frac{5 |\bar g|^2 \mu + 24 M}{16 |\bar g|^2\mu  M^3}k^4
	+\frac{|\bar g|^2 \mu + 16 M}{16|\bar g|^2 \mu  M^5}k^6
	+\frac{1}{4 |\bar g|^2 \mu  M^6}k^8
	\\
	&=
	-\frac{16\gamma  M^4+29 \gamma ^2 M^3+20 \gamma ^3 M^2+5 \gamma ^4 M}{16 (\gamma +M)^4}
	+\frac{15 \gamma ^4+35 M^4+76\gamma  M^3+94 \gamma ^2 M^2+60 \gamma ^3 M}{16 M (\gamma +M)^4}k^2
	\\\nonumber&\qquad
	+\frac{5 \gamma ^4+35 M^4+44 \gamma  M^3+36 \gamma ^2 M^2+20\gamma ^3 M}{16 M^3 (\gamma +M)^4}k^4
	+\frac{\gamma ^4+21 M^4+20 \gamma  M^3+10 \gamma ^2 M^2+4 \gamma ^3 M}{16 M^5(\gamma +M)^4}k^6
	\\\nonumber&\qquad
	+ \frac{\gamma ^2+5 M^2+4 \gamma  M}{16 M^5 (\gamma +M)^4}k^8
	\\&\overset{M\to\infty}{\longrightarrow}-\gamma
\end{align}

The above quantities are computed in the \texttt{notebooks/long-range-ERE.nb} notebook.

\subsection{Long range forces in finite discrete volume}

\subsubsection{How are discretized finite volume quantities defined?}

The mandatory requirement is the convergence against continuum infinite volume counterparts.
For example, if we fix the finite volume lattice hamiltonian by the ground state energy (input), we expect that a second observable, e.g., the discrete finite volume phase shifts (output) converge against the continuum infinite volume phase shifts.
A finite volume lattice implementation of an observable is better than another if it converges faster against the physical observable.
An implementation is incorrect if no or even a wrong conversion pattern is apparent.

The kinetic hamiltonian, and in general all finite volume lattice momenta, fulfill the convergence criterium if they are implemented by their finite volume lattice dispersion (see eq.~\eqref{def:lattice-dispersion}).

\subsubsection{How to estimate finite volume lattice parameters?}
\begin{itemize}
	\item You can identify if the potential is sufficiently mapped out by the FV lattice grid points (fig.~\ref{fig:potential-component})
	\item You can verify that the expected continuum infinite volume ERE has well defined intersections with the zeta function (fig.~\ref{fig:pcotdelta-intersection})
	\item You can estimate the finite volume energy shifts by the intersections of the zeta function and the ERE (fig.~\ref{fig:finite-volume-energy-difference})
\end{itemize}

\begin{figure*}[!htb]
\includegraphics[width=0.7\textwidth]{figs/potential-component.pdf}
\caption{
	\label{fig:potential-component}
	Separable component $g(p)$ of the potential $V(p', p) = -g(p') g(p)$ for chosen lattice parameters agrees at available lattice momenta with continuum infinite volume counterpart.
	Ultra violet momenta part is covered up till $g(p) \sim 0.1$ fm.
}
\end{figure*}

\begin{figure*}[!htb]
\includegraphics[width=0.7\textwidth]{figs/pcotdelta-intersection.pdf}
\caption{
	\label{fig:pcotdelta-intersection}
	Continuum infinite volume effective range expansion has well defined intersection with zeta function for given parameters.
	E.g., only one intersection at negative energies is given and allows for an extraction of a unique ground state.
}
\end{figure*}

\begin{figure*}[!htb]
\includegraphics[width=0.7\textwidth]{figs/finite-volume-energy-difference.pdf}
\caption{
	\label{fig:finite-volume-energy-difference}
	Difference of continuum infinite volume energies and continuum finite volume energies times box length, extracted from the first intersection of the zeta function and the effective range expansion (see fig.~\ref{fig:pcotdelta-intersection}), decays exponentially.
	Numerical precision disturbs the result at $10^{-8}$.
}
\end{figure*}

For the chosen potential, solutions can be extracted reliably for the following parameters
\begin{itemize}
	\item Infinite volume continuum ground state energy $E_0 = - 2.225$ MeV.
	\item Finite volume box length $L = 10$ fm.
	\item Potential parameter $M = 20 m_\pi$ (this turns the potential more into a smeared delta function than into a pion exchange).
		This parameter is also fixed in discrete finite volume ("constant of nature") and only $\bar g$ will be adjusted.
\end{itemize}

\subsection{How to pin down finite volume lattice potential parameters?}
How does one implement the potential in a discrete finite volume?
Or more specifically, how to estimate the potential coefficients?
In the following content, I will present three different ideas which take different inputs and try to predict the effective range expansion.
Is there a well behaved way to solve the problem without knowing analytic relations between potential parameters and observables?

\begin{itemize}
	\item Use all known continuum infinite volume parameters to reproduce the result on the lattice.
		Technically this cannot be done for more complex potentials (see fig.~\ref{fig:long-range-ere-v-inf-cont}).
	\item Solve the discrete finite volume Schrödinger equation to fit $\bar g$ to the continuum infinite volume ground state for each lattice spacing and finite volume.
		Compute phase shifts for each fitted $\bar g$ and observe the convergence pattern against "experimental" results (see fig.~\ref{fig:long-range-ere-v-fit}).
	\item Use "experimental" phase shifts to compute continuum finite volume energies.
		Fit $\bar g$ to the continuum finite volume ground state.
		Compute phase shifts for each fitted $\bar g$ and observe the convergence pattern against "experimental" results (see fig.~\ref{fig:long-range-ere-v-lat}).
\end{itemize}

\begin{figure*}[!htb]
\includegraphics[width=0.7\textwidth]{figs/long-range-ere-v-inf-cont.pdf}
\caption{
	\label{fig:long-range-ere-v-inf-cont}
	Infinite volume continuum parameters were fed into the finite volume lattice potential from which the energy levels were used to compute the effective range expansion.
	The difference between the standard Lüscher phase shift extraction (red markers) and the modified dispersion Lüscher extraction (green markers) is only visible at large normalized scattering momenta $x$.
	For few lattice nodes (large lattice spacings), the extracted ERE does not agree well with the analytic result.
	But for more lattice nodes (finer discretizations), the extracted ERE seemingly converges against the analytic result and the difference between original and dispersion Lüscher shrinks as well.
}
\end{figure*}

\begin{figure*}[!htb]
\includegraphics[width=0.7\textwidth]{figs/long-range-ere-v-fit.pdf}
\caption{
	\label{fig:long-range-ere-v-fit}
	Infinite volume continuum energy was used to fit finite volume lattice potential.
	ERE was extracted after fit.
	The difference between the standard Lüscher phase shift extraction (red markers) and the modified dispersion Lüscher extraction (green markers) is small at small $x$ but increases more drastically for large $x$ as in the "known parameter case" (see fig~\ref{fig:long-range-ere-v-inf-cont}).
	For all discretizations, the original Lüscher results agree with themselves at the smallest $x$ because the fit requires each $x$ to be the same and original Lüscher does not provide different different zeta functions for different discretizations.
	This is different for dispersion Lüscher.
	The $y$-values are different because one uses dispersion dependent zeta functions.
	The standard Lüscher has a nice internal convergence pattern (the finer discretization, the smaller the changes of the ERE) but it seemingly converges against a completely wrong value.
	The dispersion Lüscher convergence pattern seems more random (big step, small step, big step in directions of smaller lattice spacing).
	It is not obvious if dispersion Lüscher and standard Lüscher will converge against the same dispersion relation, but it seems quite reasonable to assume that both approaches will not converge against the analytical result.
}
\end{figure*}

\begin{figure*}[!htb]
\includegraphics[width=0.7\textwidth]{figs/long-range-ere-v-lat.pdf}
\caption{
	\label{fig:long-range-ere-v-lat}
	First, the finite volume continuum energy was computed using the "experimental" ERE.
	Next the finite volume ground state used to fit the finite volume lattice potential.
	This means that discretization effects were correlated with the potential.
	The ERE was extracted after fit.
	The difference between the standard Lüscher phase shift extraction (red markers) and the modified dispersion Lüscher extraction (green markers) is drastic.
	For all discretizations, again the original Lüscher results agree with themselves at the smallest $x$.
	The standard Lüscher has again a nice internal convergence pattern but still it seemingly converges against a completely wrong value.
	In this case, the dispersion Lüscher results at small $x$ are on top of each other.
	The dispersion Lüscher convergence pattern seems well behaved such that the smaller the lattice spacing, the smaller the changes.
	Also, dispersion Lüscher results now seem to covnverge against the continuum infinite volume counterpart.
}
\end{figure*}

\subsubsection{Questions and conclusions}

\begin{itemize}
	\item Give me a night to sleep over the results.
	\item One big question I have is: assuming that things actually work, why do we still see a convergence pattern in fig.~\ref{fig:long-range-ere-v-lat}?
	\item It seems to me that the best way of fixing coefficients is mapping the ERE to coefficients and computing binding energies.
\end{itemize}

\end{document}


\section{Linear combinations}
\label{sec:linear-combinations-rn}

\begin{outcome}
  \begin{enumerate}
  \item Compute linear combinations of vectors algebraically and
    geometrically.
  \item Determine whether a vector is a linear combination of given
    vectors.
  \item Find the coefficients of one vector as a linear combination of
    other vectors.
  \end{enumerate}
\end{outcome}

Now that we have studied both vector addition and scalar
multiplication, we can combine the two operations. You may remember
that when we talked about the solutions to homogeneous systems of
equations in Section~\ref{sec:homogeneous-systems}, we briefly
mentioned that the general solution of a homogeneous system is a
linear combination of its basic solutions. We now return to the
concept of a linear combination.

\begin{definition}{Linear combination}{linear-combination}
  A vector $\vect{v}$ is said to be a \textbf{linear combination}%
  \index{linear combination!in Rn@in $\R^n$} of the vectors
  $\vect{u}_1,\ldots, \vect{u}_n$ if there exist scalars
  $a_1,\ldots,a_n$ such that
  \begin{equation*}
    \vect{v} = a_1 \vect{u}_1 + \ldots + a_n \vect{u}_n.
  \end{equation*}
  The numbers $a_1,\ldots,a_n$ are called the \textbf{coefficients}%
  \index{coefficient!of a linear combination}%
  \index{linear combination!coefficient} of the linear combination.
\end{definition}

\begin{example}{Linear combination}{linear-combination}
  We have
  \begin{equation*}
    3
    \begin{mymatrix}{r}
      -4 \\
      1 \\
      0
    \end{mymatrix}
    +
    2
    \begin{mymatrix}{r}
      -3 \\
      0 \\
      1
    \end{mymatrix}
    =
    \begin{mymatrix}{r}
      -18 \\
      3 \\
      2
    \end{mymatrix}.
  \end{equation*}
  Thus we can say that
  \begin{equation*}
    \vect{v}= \begin{mymatrix}{r}
      -18 \\
      3 \\
      2
    \end{mymatrix}
  \end{equation*}
  is a linear combination of the vectors
  \begin{equation*}
    \vect{u}_1 = \begin{mymatrix}{r}
      -4 \\
      1 \\
      0
    \end{mymatrix}
    \quad\mbox{and}\quad
    \vect{u}_2 =
    \begin{mymatrix}{r}
      -3 \\
      0 \\
      1
    \end{mymatrix}.
  \end{equation*}
\end{example}

For the specific case of $\R^3$, there are three special vectors which
we often use.  They are given by
\begin{equation*}
  \vect{i} =
  \begin{mymatrix}{c}
    1 \\ 0 \\ 0
  \end{mymatrix},
  \quad
  \vect{j} =
  \begin{mymatrix}{c}
    0 \\ 1 \\ 0
  \end{mymatrix},
  \quad\mbox{and}\quad
  \vect{k} =
  \begin{mymatrix}{c}
    0 \\ 0 \\ 1
  \end{mymatrix}.
\end{equation*}
We can write any vector $\vect{u} = \mat{a_1,a_2,a_3}^T$ as a linear
combination of these vectors, namely
\begin{equation*}
  \vect{u} = a_1 \vect{i} + a_2 \vect{j} + a_3 \vect{k}.
\end{equation*}
We will use this notation from time to time.

\begin{example}{Determining if linear combination}{determine-linear-comb}
  Can $\vect{v}=\mat{1, 3, 5}^T$ be written as a linear combination
  of $\vect{u}_1=\mat{2, 2, 6}^T$, $\vect{u}_2=\mat{1, 6, 8}^T$, and
  $\vect{u}_3=\mat{3, 8, 18}^T$? If yes, find the coefficients.
\end{example}

\begin{solution}
  This question can be rephrased as: can we find scalars $x,y,z$ such
  that
  \begin{equation*}
    x\vect{u}_1+y\vect{u}_2+z\vect{u}_3=\vect{v}?
  \end{equation*}
  Multiplying out produces the system of linear equations
  \begin{align*}
    2x+y+3z&=1 \\
    2x+6y+8z&=3 \\
    6x+8y+18z&=5.
  \end{align*}
  Now we row reduce the corresponding augmented matrix to solve.
  \begin{align*}
    &\begin{mymatrix}{rrr|r} 2 & 1 & 3 & 1 \\ 2 & 6 & 8 & 3 \\ 6 & 8 & 18 & 5 \end{mymatrix}
                                                                            \stackrel{R_1\rowop R_1-R_2}{\stackrel{R_3\rowop R_3-3R_1}{\roweq}}
                                                                            \begin{mymatrix}{rrr|r} 0 & -5 & -5 & -2 \\ 2 & 6 & 8 & 3 \\ 0 & 5 & 9 & 2 \end{mymatrix}
                                                                                \stackrel{R_1\rowop R_1+R_3}{\roweq}
                                                                                \begin{mymatrix}{rrr|r} 0 & 0 & 4 & 0 \\ 2 & 6 & 8 & 3 \\ 0 & 5 & 9 & 2 \end{mymatrix}
                                                                                \stackrel{R_2\rowswap R_1}{\roweq} \\
    &\begin{mymatrix}{rrr|r} 2 & 6 & 8 & 3 \\ 0 & 0 & 4 & 0 \\ 0 & 5 & 9 & 2 \end{mymatrix}
                                                                           \stackrel{\frac{1}{2}R_1}{\stackrel{R_2\rowswap R_3}{\roweq}}
                                                                           \begin{mymatrix}{rrr|r} 1 & 3 & 4 & \frac{3}{2} \\ 0 & 5 & 9 & 2 \\ 0 & 0 & 4 & 0\end{mymatrix}
                                                                                \stackrel{\frac{1}{4}R_3}{\roweq}
                                                                                \begin{mymatrix}{rrr|r} 1 & 3 & 4 & \frac{3}{2} \\ 0 & 5 & 9 & 2 \\ 0 & 0 & 1 & 0 \end{mymatrix}
                                                                                \stackrel{R_1\rowop R_1-4R_3}{\stackrel{R_2\rowop R_2-9R_3}{\roweq}} \\
    &\begin{mymatrix}{rrr|r} 1 & 3 & 0 & \frac{3}{2} \\ 0 & 5 & 0 & 2 \\ 0 & 0 & 1 & 0 \end{mymatrix}
                                                                                \stackrel{\frac{1}{5}R_2}{\roweq}
                                                                                \begin{mymatrix}{rrr|r} 1 & 3 & 0 & \frac{3}{2} \\ 0 & 1 & 0 & \frac{2}{5} \\ 0 & 0 & 1 & 0 \end{mymatrix}
                                                                                \stackrel{R_1\rowop R_1-3R_2}{\roweq}
                                                                                \begin{mymatrix}{rrr|r} 1 & 0 & 0 & \frac{3}{10} \\ 0 & 1 & 0 & \frac{2}{5} \\ 0 & 0 & 1 & 0 \end{mymatrix}.
  \end{align*}
  We are in the case where we have a unique solution:
  \begin{align*}
    x&=\frac{3}{10} \\
    y&=\frac{2}{5} \\
    z&=0.
  \end{align*}
  This means that $\vect{v}$ is a linear combination of $\vect{u}_1$,
  $\vect{u}_2$, and $\vect{u}_3$:
  \begin{equation*}
    \vect{v}=\frac{3}{10}\vect{u}_1+\frac{2}{5}\vect{u}_2+0\vect{u}_3.
  \end{equation*}
  The coefficients are $\frac{3}{10}$, $\frac{2}{5}$, and $0$.
  In fact, $\vect{v}$ is also a linear combination of just $\vect{u}_1$ and
  $\vect{u}_2$.
\end{solution}

In the following example, we examine the geometric meaning of linear combinations.

\begin{example}{Graphing a linear combination of vectors}{graphing-linear-combination}
  Consider the following picture of the vectors $\vect{u}$ and $\vect{v}$
  \begin{center}
    \begin{tikzpicture}[scale=2]
      \draw[->, thick, blue] (0,0) -- node[above,pos=0.45]{$\vect{u}$} (2,1);
      \draw[->, thick, red] (4,1) -- node[above]{$\vect{v}$} (5,0.5);
    \end{tikzpicture}
  \end{center}
  Sketch a picture of $\vect{u}+2\vect{v}$ and $\vect{u}-\frac{1}{2}\vect{v}$.
\end{example}

\begin{solution}
  Both vectors are shown below.
  \begin{center}
    \begin{tikzpicture}[scale=2]
      \fill (1.5,1.25) circle (0.9pt);
      \fill (4,0) circle (0.9pt);
      \draw[->, thick, red] (2,1) -- node[above]{$\vect{2v}$} (4,0);
      \draw[->, thick, red] (2,1) -- node[above right]{$-\frac{1}{2}\vect{v}$} (1.5, 1.25);
      \fill (2,1) circle (0.9pt);
      \draw[->, thick, blue] (0,0) -- node[below,pos=0.55]{$\vect{u}$} (2,1);
      \draw[->, thick, purple](0,0) -- node[below]{$\vect{u}+2\vect{v}$} (4,0);
      \draw[->, thick, purple](0,0) -- node[above left]{$\vect{u} - \frac{1}{2}\vect{v}$} (1.5,1.25);
      \fill (0,0) circle (0.9pt);
    \end{tikzpicture}
  \end{center}
\end{solution}

Given any two non-parallel vectors $\vect{u}$ and $\vect{v}$ in
$\R^2$, we can create a grid of their linear combinations. The integer
ones are pictured below. From this we can see that all vectors in
$\R^2$ can be written as a linear combination of $\vect{u}$ and
$\vect{v}$.

\begin{center}
  \begin{tikzpicture}[scale=1.5]
    \draw[->, thick, blue] (0,0) -- node[below]{$\vect{u}$} (1.5,0.5);
    \draw[->, thick, red] (0,0) -- node[left]{$\vect{v}$} (0.5,1);
    \draw[-, gray] (-2,-1.5)--(4,0.5);
    \draw[-, gray] (-1.5,-0.5)--(0,0);
    \draw[-, gray] (1.5,0.5)--(4.5,1.5);
    \draw[-, gray] (-1,0.5)--(5,2.5);
    \draw[-, gray] (-0.5,1.5)--(5.5,3.5);
    \draw[-, gray] (0,2.5)--(6,4.5);
    \draw[-, gray] (-2,-1.5)--(0,2.5);
    \draw[-, gray] (-0.5,-1)--(0,0);
    \draw[-, gray] (0.5,1)--(1.5,3);
    \draw[-, gray] (1,-0.5)--(3,3.5);
    \draw[-, gray] (2.5,0)--(4.5,4);
    \draw[-, gray] (4,0.5)--(6,4.5);
    \draw (-2.0,-1.5) node[left]{$-1\vect{u}-1\vect{v}$};
    \draw (-1.5,-0.5) node[left]{$-1\vect{u}+0\vect{v}$};
    \draw (-1.0,0.5) node[left]{$-1\vect{u}+1\vect{v}$};
    \draw (-0.5,1.5) node[left]{$-1\vect{u}+2\vect{v}$};
    \draw (0.0,2.5) node[left]{$-1\vect{u}+3\vect{v}$};
    \draw (1.5,3.0) node[above=0.75ex]{$0\vect{u}+3\vect{v}$};
    \draw (3.0,3.5) node[above=0.75ex]{$1\vect{u}+3\vect{v}$};
    \draw (4.5,4.0) node[above=0.75ex]{$1\vect{u}+3\vect{v}$};
    \draw (6.0,4.5) node[right]{$3\vect{u}+3\vect{v}$};
    \draw (5.5,3.5) node[right]{$3\vect{u}+2\vect{v}$};
    \draw (5.0,2.5) node[right]{$3\vect{u}+1\vect{v}$};
    \draw (4.5,1.5) node[right]{$3\vect{u}+0\vect{v}$};
    \draw (4.0,0.5) node[right]{$3\vect{u}-1\vect{v}$};
    \draw (2.5,0.0) node[below=0.75ex]{$2\vect{u}-1\vect{v}$};
    \draw (1.0,-0.5) node[below=0.75ex]{$1\vect{u}-1\vect{v}$};
    \draw (-0.5,-1.0) node[below=0.75ex]{$0\vect{u}-1\vect{v}$};
    \draw[fill] (0,0) circle [radius=1.2pt] node[below right]{$\vect{0}$};
  \end{tikzpicture}
\end{center}


\chapter{Algorithms} \label{chap:algorithms}

This chapter gives an overview over the available algorithms in {\ViennaCL}.
The focus of {\ViennaCL} is on iterative solvers, for which {\ViennaCL} provides a generic implementation that allows the use of the same code on the CPU (either using \ublas, Eigen, MTL4 or \OpenCL) and on the GPU (using \OpenCL).

\section{Direct Solvers} \label{sec:direct-solvers}
{\ViennaCLversion} provides triangular solvers and LU factorization without pivoting for the solution of dense linear systems. The interface is similar to that of {\ublas}

\begin{lstlisting}
  using namespace viennacl::linalg;  //to keep solver calls short
  viennacl::matrix<float>  vcl_matrix;
  viennacl::vector<float>  vcl_rhs;
  viennacl::vector<float>  vcl_result;

  /* Set up matrix and vectors here */

  //solution of an upper triangular system:
  vcl_result = solve(vcl_matrix, vcl_rhs, upper_tag());
  //solution of a lower triangular system:
  vcl_result = solve(vcl_matrix, vcl_rhs, lower_tag());

  //solution of a full system right into the load vector vcl_rhs:
  lu_factorize(vcl_matrix);
  lu_substitute(vcl_matrix, vcl_rhs);
\end{lstlisting}
In {\ViennaCLminorversion} there is no pivoting included in the LU factorization
process, hence the computation may break down or yield results with poor
accuracy. However, for certain classes of matrices (like diagonal dominant
matrices) good results can be obtained without pivoting.

It is also possible to solve for multiple right hand sides:
\begin{lstlisting}
  using namespace viennacl::linalg;  //to keep solver calls short
  viennacl::matrix<float>  vcl_matrix;
  viennacl::matrix<float>  vcl_rhs_matrix;
  viennacl::matrix<float>  vcl_result;

  /* Set up matrices here */

  //solution of an upper triangular system:
  vcl_result = solve(vcl_matrix, vcl_rhs_matrix, upper_tag());

  //solution of a lower triangular system:
  vcl_result = solve(vcl_matrix, vcl_rhs_matrix, lower_tag());
\end{lstlisting}

\section{Iterative Solvers} \label{sec:iterative-solvers}
{\ViennaCL} provides different iterative solvers for various classes of
matrices, listed in Tab.~\ref{tab:linear-solvers}. Unlike direct solvers, the
convergence of iterative solvers relies on certain properties of the system
matrix. Keep in mind that an iterative solver may fail to converge, especially
if the matrix is ill conditioned or a wrong solver is chosen.

\TIP{For full details on linear solver calls, refer to the reference
documentation located in \texttt{doc/doxygen/} and to the tutorials}

\TIP{The iterative solvers can directly be used for {\ublas}, Eigen and MTL4 objects! Please have a look at Chap.~\ref{chap:other-libs} and the respective tutorials in the examples/tutorials/ folder.}

\NOTE{In {\ViennaCLversion}, GMRES using ATI GPUs yields wrong results due to a bug in Stream SDK v2.1. Consider using newer versions of the Stream SDK.}

\begin{lstlisting}
viennacl::compressed_matrix<float>  vcl_matrix;
viennacl::vector<float>  vcl_rhs;
viennacl::vector<float>  vcl_result;

/* Set up matrix and vectors here */

//solution using conjugate gradient solver:
vcl_result = viennacl::linalg::solve(vcl_matrix,
				     vcl_rhs,
				     viennacl::linalg::cg_tag());

//solution using BiCGStab solver:
vcl_result = viennacl::linalg::solve(vcl_matrix,
				     vcl_rhs,
				     viennacl::linalg::bicgstab_tag());

//solution using GMRES solver:
vcl_result = viennacl::linalg::solve(vcl_matrix,
				     vcl_rhs,
				     viennacl::linalg::gmres_tag());
\end{lstlisting}

\begin{table}[tb]
\begin{center}
\renewcommand{\arraystretch}{1.2}
\begin{tabular}{p{4cm}|p{3cm}|p{7.5cm}}
Method & Matrix class & ViennaCL\\
\hline
Conjugate Gradient (CG) & symmetric positive definite & \texttt{y = solve(A, x, cg\_tag());} \\
Stabilized Bi-CG (BiCGStab) & non-symmetric & \texttt{y = solve(A, x, bicgstab\_tag());} \\
Generalized Minimum Residual (GMRES) & general & \texttt{y = solve(A, x, gmres\_tag());} \\
\hline
\end{tabular}
\caption{Linear solver routines in {\ViennaCL} for the computation of $y$ in the expression $Ay = x$ with given $A$, $x$.}
\label{tab:linear-solvers}
\end{center}
\end{table}

Customized error tolerances can be set in the solver tags. The convention is
that solver tags take the relative error tolerance as first argument and the
maximum number of iteration steps as second argument. Furthermore, after the
solver run the number of iterations and the estimated error can be obtained from
the solver tags as follows:
\begin{lstlisting}
// conjugate gradient solver with tolerance 1e10
// and at most 100 iterations:
viennacl::linalg::cg_tag custom_cg(1e-10, 100);
vcl_result = viennacl::linalg::solve(vcl_matrix, vcl_rhs, custom_cg);
//print number of iterations taken and estimated error:
std::cout << "No. of iters: " << custom_cg.iters() << std::endl;
std::cout << "Est. error: " << custom_cg.error() << std::endl;
\end{lstlisting}
The BiCGStab solver tag can be customized in exactly the same way. The GMRES
solver tag takes as third argument the dimension of the Krylov space. Thus, a
tag for GMRES(30) with tolerance $1\mathrm{E}\!-\!10$ and at most $100$ total
iterations
(hence, up to three restarts) can be set up by
\begin{lstlisting}
viennacl::linalg::gmres_tag custom_gmres(1e-10, 100, 30);
\end{lstlisting}

\section{Preconditioners} \label{sec:preconditioner}
{\ViennaCL} ships with a generic implementation of several preconditioners.
The preconditioner setup is expect for simple diagonal preconditioners always carried out on the CPU host due to the need for dynamically allocating memory.
Thus, one may not obtain an overall performance benefit if too much time is spent on the preconditioner setup.

\TIP{The preconditioner also works for {\ublas} types!}

An overview of preconditioners available for the various sparse matrix types is as follows:
\begin{center}
 \begin{tabular}{|l|c|c|c|c|c|c|}
  \hline
  Matrix Type & ICHOL & (Block-)ILU[0/T] & Jacobi & Row-scaling & AMG & SPAI \\
  \hline
  \lstinline|compressed_matrix| & yes & yes & yes & yes & yes & yes \\
  \lstinline|coordinate_matrix| & no & no & yes & yes & no & no \\
  \lstinline|ell_matrix| & no & no & no & no & no & no \\
  \lstinline|hyb_matrix| & no & no & no & no & no & no \\
  \hline
 \end{tabular}
\end{center}
Broader support of preconditioners particularly for \lstinline|ell_matrix| and \lstinline|hyb_matrix| is scheduled for future releases.
AMG and SPAI preconditioners are described in Chap.~\ref{chap:additional-algorithms}.

In the following it is assumed that the sparse linear system of equations is given as follows:
\begin{lstlisting}
typedef viennacl::compressed_matrix<float>   SparseMatrix;

SparseMatrix  vcl_matrix;
viennacl::vector<float>  vcl_rhs;
viennacl::vector<float>  vcl_result;

/* Set up matrix and vectors here */
\end{lstlisting}

% \begin{table}[tb]
% \begin{center}
% \renewcommand{\arraystretch}{1.2}
% \begin{tabular}{p{3cm}|p{4cm}|p{7cm}}
% Method & Brief description & Parameters\\
% \hline
% ILUT & incomplete LU factorization & First parameter: Maximum number of entries
% per row. Second parameter: Drop tolerance. \\
% Jacobi & Divide each row in $A$ by its diagonal entry & none \\
% Row Scaling & Divide each row in $A$ by its norm & First parameter specifies
% the norm (1: $l^1$-norm, 2: $l^2$-norm)\\
% \hline
% \end{tabular}
% \caption{Preconditioners for iterative solvers in {\ViennaCL}.}
% \label{tab:preconditioners}
% \end{center}
% \end{table}

\subsection{Incomplete LU Factorization with Threshold (ILUT)}
The incomplete LU factorization preconditioner aims at computing sparse matrices lower and upper triangular matrices $L$ and $U$ such that the sparse system
matrix is approximately given by $A \approx LU$. In order to control the sparsity pattern of $L$ and $U$, a threshold strategy is used (ILUT)
\cite{saad-iterative-solution}. Due to the serial nature of the preconditioner, the setup of ILUT is always computed on
the CPU using the respective ViennaCL backend.

\begin{lstlisting}
//compute ILUT preconditioner:
viennacl::linalg::ilut_tag ilut_config;
viennacl::linalg::ilut_precond< SparseMatrix > vcl_ilut(vcl_matrix,
                                                        ilut_config);

//solve (e.g. using conjugate gradient solver)
vcl_result = viennacl::linalg::solve(vcl_matrix,
                                     vcl_rhs,
                                     viennacl::linalg::bicgstab_tag(),
                                     vcl_ilut);   //preconditioner here
\end{lstlisting}
The triangular substitutions may be applied in parallel on GPUs by enabling \emph{level-scheduling} \cite{saad-iterative-solution} via the member function call \lstinline|use_level_scheduling(true)| in the \lstinline|ilut_config| object.

Three parameters can be passed to the constructor of \lstinline|ilut_tag|: The first specifies the maximum number of entries per row in $L$ and $U$, while the
second parameter specifies the drop tolerance. The third parameter is the boolean specifying whether level scheduling should be used.

\TIP{The performance of level scheduling depends strongly on the matrix pattern and is thus disabled by default.}

\subsection{Incomplete LU Factorization with Static Pattern (ILU0)}
Similar to ILUT, ILU0 computes an approximate LU factorization with sparse factors L and U.
While ILUT determines the location of nonzero entries on the fly, ILU0 uses the sparsity pattern of A for the sparsity pattern of L and U \cite{saad-iterative-solution}.
Due to the serial nature of the preconditioner, the setup of ILU0 is computed on the CPU.
\begin{lstlisting}
//compute ILU0 preconditioner:
viennacl::linalg::ilu0_tag ilu0_config;
viennacl::linalg::ilu0_precond< SparseMatrix > vcl_ilut(vcl_matrix,
                                                        ilu0_config);

//solve (e.g. using conjugate gradient solver)
vcl_result = viennacl::linalg::solve(vcl_matrix,
                                     vcl_rhs,
                                     viennacl::linalg::bicgstab_tag(),
                                     vcl_ilut);   //preconditioner here
\end{lstlisting}
The triangular substitutions may be applied in parallel on GPUs by enabling \emph{level-scheduling} \cite{saad-iterative-solution} via the member function call \lstinline|use_level_scheduling(true)| in the \lstinline|ilu0_config| object.

One parameter can be passed to the constructor of \lstinline|ilu0_tag|, being the boolean specifying whether level scheduling should be used.

\TIP{The performance of level scheduling depends strongly on the matrix pattern and is thus disabled by default.}

\subsection{Block-ILU}
To overcome the serial nature of ILUT and ILU0 applied to the full system matrix,
a parallel variant is to apply ILU to diagonal blocks of the system matrix.
This is accomplished by the \lstinline|block_ilu| preconditioner, which takes
the system matrix type as first template argument and the respective ILU-tag type as second template argument
(either \lstinline|ilut_tag| or \lstinline|ilu0_tag|). Support for accelerators using {\CUDA} or {\OpenCL} is provided.

\begin{lstlisting}
//compute block-ILU preconditioner using ILU0 for each block:
block_ilu_precond<SparseMatrix,
                  ilu0_tag> vcl_block_ilu0(vcl_matrix,
                                           ilu0_tag());

//solve
vcl_result = viennacl::linalg::solve(vcl_matrix,
                                     vcl_rhs,
                                     viennacl::linalg::bicgstab_tag(),
                                     vcl_block_ilu0);
\end{lstlisting}
A third argument can be passed to the constructor of \lstinline|block_ilu_precond|:
Either the number of blocks to be used (defaults to $8$), or an index vector with fine-grained control over the blocks. Refer to the Doxygen pages in doc/doxygen for details.

\TIP{The number of blocks is a design parameter for your sparse linear system at hand. Higher number of blocks leads to better memory bandwidth utilization on GPUs, but may increase the number of solver iterations.}

\subsection{Jacobi Preconditioner}
A Jacobi preconditioner is a simple diagonal preconditioner given by the reciprocals of the diagonal entries of the system matrix $A$.
Use the preconditioner as follows:
\begin{lstlisting}
//compute Jacobi preconditioner:
jacobi_precond< SparseMatrix > vcl_jacobi(vcl_matrix,
                                          viennacl::linalg::jacobi_tag());

//solve (e.g. using conjugate gradient solver)
vcl_result = viennacl::linalg::solve(vcl_matrix,
                                     vcl_rhs,
                                     viennacl::linalg::cg_tag(),
                                     vcl_jacobi);
\end{lstlisting}

\subsection{Row Scaling Preconditioner}
A row scaling preconditioner is a simple diagonal preconditioner given by the reciprocals of the norms of the rows of the system matrix $A$.
Use the preconditioner as follows:
\begin{lstlisting}
//compute row scaling preconditioner:
row_scaling< SparseMatrix > vcl_row_scaling(vcl_matrix,
                                      viennacl::linalg::row_scaling_tag());

//solve (e.g. using conjugate gradient solver)
vcl_result = viennacl::linalg::solve(vcl_matrix,
                                     vcl_rhs,
                                     viennacl::linalg::cg_tag(),
                                     vcl_row_scaling);
\end{lstlisting}
The tag \lstinline|viennacl::linalg::row_scaling_tag()| can be supplied with a parameter denoting the norm to be used. A value of \lstinline|1| specifies the
$l^1$-norm, while a value of $2$ selects the $l^2$-norm (default).

\section{Eigenvalue Computations}
%{\ViennaCL}
Two algorithms for the computations of the eigenvalues of a matrix $A$ are implemented in {\ViennaCL}:
\begin{itemize}
\item The Power Iteration \cite{golub:matrix-computations}
\item The Lanczos Algorithm \cite{simon:lanczos-pro}
\end{itemize}
Depending on the parameter \lstinline|tag| either one of them is called.
Both algorithms can be used for either {\ublas} or {\ViennaCL} compressed matrices.\\
In order to get the eigenvalue with the greatest absolut value the power iteration should be called. \\
The lanczos algorithm returns a vector of the largest eigenvalues with the same type as the entries of the matrix.

The algorithms are called for a matrix object \lstinline|A| by
\begin{lstlisting}
std::vector<double> largest_eigenvalues = viennacl::linalg::eig(A, ltag);
double largest_eigenvalue = viennacl::linalg::eig(A, ptag);
\end{lstlisting}

\subsection{Power Iteration}
The Power iteration aims at computing the eigenvalues of a matrix by calculating the product of the matrix and a vector for several times, where the resulting vector is used for the next product of the matrix and so on. The computation stops as soon as the norm of the vector converges. \\
The final vector is the eigenvector to the eigenvalue with the greatest absolut value.\\
To call this algorithm, \lstinline|piter_tag| must be used.
This tag has only one parameter: \\ \lstinline|terminationfactor| defines the accuracy of the computation, i.e. if the new norm of the eigenvector changes less than this parameter the computation stops and returns the corresponding eigenvalue (default: $1e-10$).\\
The call of the constructor may look like the following:
\begin{lstlisting}
viennacl::linalg::piter_tag ptag(1e-8);
\end{lstlisting}

\TIP{Example code can be found in \lstinline|examples/tutorial/power-iter.cpp|.}

\subsection{The Lanczos Algorithm}
In order to compute the eigenvalues of a sparse high-dimensional matrix the lanczos algorithm can be used to find these.
This algorithm reformulates the given high-dimensional matrix in a way such that the matrix can be rewritten in a tridiagonal matrix at much lower dimension. The eigenvalues of this tridiagonal matrix are equal to the largest eigenvalues of the original matrix. \\
The eigenvalues of the tridiagonal matrix are calculated by using the bisection method \cite{golub:matrix-computations}. \\
To call this lanczos algorithm, \lstinline|lanczos_tag| must be used.
This tag has several parameters that can be passed to the constructor:

\begin{itemize}
 \item The exponent of epsilon for the tolerance of the reorthogonalization, defined by the parameter \lstinline|factor| (default: $0.75$)
 \item The method of the lanczos algorithm: $0$ uses partial reorthogonalization, $1$ full reothogonalization and $2$ does not use reorthogonalization (default: $0$)
 \item The number of eigenvalues that are returned is specified by \lstinline|num_eigenvalues| (default: $10$)
 \item The size of the krylov space used for the computations can be set by the parameter \lstinline|krylov_size| (default: $100$). The maximum number of iterations can be equal or less this parameter
\end{itemize}
The call of the constructor may look like the following:
\begin{lstlisting}
viennacl::linalg::lanczos_tag ltag(0.85, 15, 0, 200);
\end{lstlisting}

\TIP{Example code can be found in \lstinline|examples/tutorial/lanczos.cpp|.}

\section{QR Factorization}

\NOTE{The current QR factorization implementation depends on {\ublas}.}

A matrix $A \in \mathbb{R}^{n\times m}$ can be factored into $A = Q R$, where $Q \in \mathbb{R}^{n\times n}$ is an
orthogonal matrix and $R \in \mathbb{R}^{n \times m}$ is upper triangular. This so-called QR-factorization is important for eigenvalue computations as well as
for the solution of least-squares problems \cite{golub:matrix-computations}. {\ViennaCL} provides a generic implementation of the QR-factorization using
Householder reflections in file \lstinline|viennacl/linalg/qr.hpp|. An example application can be found in \lstinline|examples/tutorial/qr.hpp|.

The Householder reflectors $v_i$ defining the Householder reflection $I - \beta_i v_i v_i^{\mathrm{T}}$ are stored in the
columns below the diagonal of the input matrix $A$ \cite{golub:matrix-computations}. The normalization coefficients $\beta_i$ are returned by the
worker function \lstinline|inplace_qr|. The upper triangular matrix $R$ is directly written to the upper triangular part of $A$.
\begin{lstlisting}
  std::vector<ScalarType> betas = viennacl::linalg::inplace_qr(A, 12);
\end{lstlisting}
If $A$ is a dense matrix from \ublas, the calculation is carried out on the CPU using a single thread. If $A$ is a
\lstinline|viennacl::matrix|, a hybrid implementation is used: The panel factorization is carried out using \ublas, while expensive BLAS level 3 operations
are computed on the OpenCL device using multiple threads.

Typically, the orthogonal matrix $Q$ is kept in inplicit form because of computational efficiency
However, if $Q$ and $R$ have to be computed explicitly, the function \lstinline|recoverQ| can be used:
\begin{lstlisting}
  viennacl::linalg::recoverQ(A, betas, Q, R);
\end{lstlisting}
Here, \lstinline|A| is the inplace QR-factored matrix, \lstinline|betas| are the coefficients of the Householder reflectors as returned by
\lstinline|inplace_qr|, while \lstinline|Q| and \lstinline|R| are the destination matrices. However, the explicit formation of $Q$ is expensive and is usually avoided.
For a number of applications of the QR factorization it is required to apply $Q^T$ to a vector $b$. This is accomplished by
\begin{lstlisting}
 viennacl::linalg::inplace_qr_apply_trans_Q(A, betas, b);
\end{lstlisting}
without setting up $Q$ (or $Q^T$) explicitly.

\TIP{Have a look at \lstinline|examples/tutorial/least-squares.cpp| for a least-squares computation using QR factorizations.}