% !TeX root = ../main.tex
% Add the above to each chapter to make compiling the PDF easier in some editors.

\chapter{Imperative B-Trees in Isabelle}\label{chapter:imp-set}

In the previous chapter, we have seen
an abstract definition of B-trees and the reasoning
behind its correct implementation of the set interface.
However, the specification would not yield
efficiently executable code.
% main difference: specify allocation of data
The reason is that the abstract specification utilizes
the persistent data types node and list.
This way, trivially, no data is unknowingly
modified or corrupted,
however this is at the cost of computational efficiency.
A small change in a list or node
requires allocating complete copies of all objects that have to be updated,
recursively propagating through the whole data structure.

In order to obtain an efficient implementation
on ephemeral data structures common to imperative languages,
we specify imperative code and show that
it refines the abstract specification.
The imperative code can then be translated to
the languages Scala \parencite{OderskyScala} and SML \parencite{DBLP:books/daglib/0069232}
using the code generator
for Isabelle/HOL \parencite{Haftmann07acode}.
However, code extraction is not limited
to these specific languages
since the code generator is extensible.

\section{Refinement to Imperative/HOL}

The proofs of correct behavior for our imperative
code are stated in separation logic
an extension of Hoare Logic invented by Reynolds \parencite{DBLP:conf/lics/Reynolds02}.
It was formalized in Isabelle/HOL by Lammich \parencite{DBLP:journals/jar/Lammich19}
and comes with a framework that simplifies reasoning about
its expressions.

\subsection{Separation Logic}

Separation logic provides a way to reason about mutable resources
that lie in separated parts of an external heap,
an abstracted memory device.
The assumptions on the state of the heap are called \textit{assertions}.
They are stated as formulae that hold for specific heap states.
The basic assertions used in this work are the following:

\begin{itemize}
    \item \textit{emp} holds for the empty heap
    \item \textit{true} and \textit{false} hold for every and no heap respectively
    \item $\uparrow(P)$ holds if the heap is empty and predicate $P$ holds
    \item $a \mapsto_a as$ holds if the heap at position $a$ is reserved and contains
    an array representing $as$.
    \item $a \mapsto_r x$ holds if the heap at position $a$ is reserved and contains
    value $x$ where $x$ is of some type $'a::heap$
    \item $\exists_A x.\ P\ x$ holds if there exists some $x$ such that predicate P
    holds on the heap for given $x$.
    \item $P_1 * P_2$ holds if each assertion holds on its part of the heap
    and the areas of the heap described by each assertion are non-overlapping
\end{itemize}

The last assertion is key to enabling reasoning about local
parts of the heap.
With the tools provided by separation logic,
we will prove our imperative implementations functionally correct
by showing that they refine the abstract implementation in \Cref{chapter:abs-set}.

In general, refinement relates a concrete data structure
to an abstract structure via some refinement assertion.
Examples for such a refinement assertion are the id assertion and the
list assertion.
The latter relates lists, given a refinement
assertion between the elements of the first and second list.

\begin{lstlisting}[mathescape=true, language=Isabelle]
definition id_assn a b = $\uparrow$(a = b)

fun list_assn :: ('a $\Rightarrow$ 'c $\Rightarrow$ assn) $\Rightarrow$ 'a list $\Rightarrow$ 'c list $\Rightarrow$ assn where
  list_assn P [] [] = emp
| list_assn P (x#xs) (y#ys) = P x y * list_assn P xs ys
| list_assn _ _ _ = false
\end{lstlisting}

We can then specify Hoare Triples on assertions,
to encapsulate statements about imperative programs.

\begin{definition}{Hoare Triple}
    $\langle$ P $\rangle$ c $\langle \lambda r. $ Q r $\rangle$ holds iff \\
    if assertion $P$ holds on some heap before operation $c$
    is executed on the heap,
    and operation $c$ returns some $r$, then assertion $Q$ holds
    for $r$ and on the heap modified by $c$
\end{definition}

A simple example Hoare Triple is
$\langle$ id\_assn $a$ $b$ $\rangle$ return $b$ $\langle \lambda r.$ id\_assn $a$ $r$ $\rangle$.
In the refinement process, we will use more complex relationship assertions
between some abstract $b$ and some refined $bi$.
We then show that the value $r$ returned
by the imperative program \textit{imp\_op} satisfies the same relationship
to \textit{op} $b$ where \textit{op} is the refined abstract specification.
Further we use the notation $\langle\ P\ \rangle\ c\ \langle \lambda r.\ Q\ r\ \rangle_t$
as a shorthand for $\langle\ P\ \rangle\ c\ \langle \lambda r.\ Q\ r\ * true\ \rangle$.
Since $true$ holds for any heap, this part of the assertion
may be used to subsume all temporary and discarded variables.

Refining all set operations from \Cref{chapter:abs-set}
will yield imperative code that operates on the heap
with the  option to use efficient destructive updates.
We do not need to show that the operations themselves
satisfy the requirements of the set interface.
Instead we merely need to show that the imperative code
acts on a concretized version of the B-trees
the same way as the abstract operations on the abstract version.
The abstract idea of this approach is discussed in more detail
in the work of Lammich \parencite{DBLP:journals/jar/Lammich19}

% TODO note what to introduce here
% abstract idea: implementation that has same effect on concrete ds
% as abstract function on abstract ds
% TODO short intro hoare triples and notation here
% *  and \uparrow

\subsection{Refinement of abstract lists}

In the imperative collection framework by Lammich
\parencite{DBLP:journals/jar/Lammich19},
the abstract data type list is usually
refined to a dynamic array like data structure.
It comprises an array and a natural number,
where the latter denotes the current number of elements
stored in the array.
B-tree nodes do not always contain a constant number of elements,
which is why this property should be transferred to
the data structure refining key-value lists.

% TODO intended physical storing of B-tree on pages of memory
% --> partially filled array, non-dynamic!
However, dynamic arrays are designed to grow and shrink
as elements are inserted and deleted.
B-trees were invented to be stored on slow hard disks.
As one disk access loads as much data as fits into a page of main memory,
nodes of roughly this size make the most efficient use of an access
\parencite{DBLP:journals/acta/BayerM72}.
%TODO give clear reason
Therefore the data structure to store the node content
should reserve arrays of fixed size, independent
of the actual number of keys and children contained.

Based on the definition of dynamic arrays in the
imperative collection framework,
we introduce a simpler data structure,
the \textit{partially filled array},
that keeps count of currently inserted elements,
but does neither grow nor shrink.
A list $ls$ is represented by a partially filled array $(a,n)$
if the array $a$ represents a list $ls'$, of which the first $n$
elements form list $ls$.
Formally,

\begin{lstlisting}[mathescape=true, language=Isabelle]

datatype 'a pfarray = 'a array $\times$ nat

definition is_pfa :: nat $\Rightarrow$ 'a list $\Rightarrow$ 'a pfarray where
    is_pfa c ls (a,n) =
        $\exists_A$ ls'. a $\mapsto_a$ ls' *  $\uparrow$(c = length ls' $\wedge$ n $\le$ c $\wedge$ ls = (take n ls'))
\end{lstlisting}

where $c$ is the $capacity$ of the array,
the actually allocated size of the array on the heap.
All references to lists in the abstract data type $btree$
will in the imperative version be refined to partially filled arrays.

However one should note that
from the set operation specification in \Cref{chapter:abs-set} alone
it is not determined which operations are supposed to be conducted
in-place and which will require copying data.
To obtain the most efficient code we therefore manually
define the operations in \Cref{lst:pfarray-def} to replace complex composite
operations based on list construction and catenation.

% abstract function has length, insertion, take/drop
% --> concrete implementations
\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle,label={lst:pfarray-def},
    caption={Important Partially Filled Array functions for Insertion.}]
definition pfa_length $\equiv$ $\lambda$(a,n). return n

definition pfa_get $\equiv$ $\lambda$(a,n) i. Array.nth a i (* returns the nth element in array a *)

definition pfa_set $\equiv$ $\lambda$(a,n) i x. do {
    Array.upd i x a; (* sets the element at position i in a to value x *)
    return (a,n)
}

definition pfa_shrink k $\equiv$ $\lambda$(a,n). return (a,k)

definition pfa_shrink_cap  k $\equiv$ $\lambda$(a,n). do {
    a' $\leftarrow$ array_shrink a k; (* returns an array with the given actual size, potentially reallocated*)
    return (a',min k n)
}

definition pfa_drop $\equiv$ $\lambda$(src,sn) si (dst,dn). do {
    blit src si dst 0 (sn-si);
    return (dst,(sn-si))
}

definition pfa_insert $\equiv$ $\lambda$(a,n) i x. do {
  array_shr a i 1; (* shifts elements from index i on to the right by 1 *)
  Array.upd i x a;
  return (a,n+1)
}

definition pfa_ensure $\equiv$ $\lambda$(a,n) k. do {
  a' $\leftarrow$ array_ensure a k default; (* returns an array with given minimal size, potentially reallocated *)
  return (a',n)
}

definition pfa_insert_grow  $\equiv$ $\lambda$(a,n) i x. do {
  a' $\leftarrow$ pfa_ensure (a,n) (n+1);
  a'' $\leftarrow$ pfa_insert a' i x;
  return a''
}

$\dots$
\end{lstlisting}
\end{figure}

% TODO also include what the rule gives us?

During the splitting of nodes, a part of the overflowing
list is copied into another array.
The operation to copy data is based on the function $blit$,
that copies a slice of an array to a slice of another array.
The function already existed in the standard collection and could be reused
to define the \textit{pfa\_drop} function in \Cref{lst:pfarray-def}, which in this implementation copies data to a new array.

The $blit$ function is however not capable of correctly copying data
within the array, as required for efficient in-place insertion and deletion.
A suitable function, called $sblit$, was hence added in the course of this project.
The relevant addition is to differentiate between copying elements
from higher to lower indices or from lower to higher indices.
Depending on the direction of the copy, it is relevant
in which order to copy singleton elements so that in case
of overlapping ranges no elements are overwritten before being copied.

By adding a function that copies elements in reverse order
and conditionally calling either copy function,
loss-free in-place copying is achieved.
The resulting function is conveniently agnostic to the direction
of the copying, just as the respective implementations
in target languages for code extraction.\footnote{
    See for example \href{https://caml.inria.fr/pub/docs/manual-ocaml/libref/Array.html}{the specification of \texttt{Array.blit} in Ocaml} or
    the \href{https://smlfamily.github.io/Basis/array-slice.html\#SIG:ARRAY_SLICE.copy:VAL}{\texttt{ArraySlice.copy} specification in SML}.
}
The \textit{pfa\_insert} function in \Cref{lst:pfarray-def} makes
implicit use of in-place copying by calling a function to shift elements
to the right by one.
This is achieved by copying the slice of elements
from position $i$ to the end of the list
to the slice $i+1$ to the end of the list.
The element to be inserted is then placed in the remaining free spot.

For all functions in \Cref{lst:pfarray-def},
appropriate Hoare Triples were derived.
All triples are straightforward to derive but the reader is encouraged
to look them up in the proof documents.
To roughly sketch the obtained lemmas, the two examples
\textit{pfa\_drop} and \textit{pfa\_shrink} are investigated below.
The most important difference is whether
the operations are destructive (in-place) or not.
For most operations, the approach that required the least
memory allocations was chosen.\footnote{
    The only exception is node$_i$, which in the case of overflow
    currently requires temporary allocation of an array that holds more than $2k$ elements.
}

\begin{lemma}
    $k \le \length s \wedge (\length s - k) \le dn \Longrightarrow$ \\
    \begin{center}
    $\langle \pfarraycap$ sn s si * $\pfarraycap$ dn d di $\rangle$ \\
    $\pfadrop$ si k di \\
    $\langle\lambda di'. \pfarraycap$ sn s si * $\pfarraycap$ dn ($\drop$ k s) di' $\rangle$
    \end{center}
\end{lemma}

The array $si$ stays untouched.
This fact is expressed by the fact that the term about its relationship to $s$
is still available in the postcondition of the triple.
The only thing that changed is the content of $di$.\footnote{
    In the actual proof, where possible, we even show that the array itself has not changed
    (i.e. has not been reallocated).
    The correct notation does however not yield high readability
    and is hence abstracted here.
}
The $take$ function was refined differently.
The cheapest and in our context consistent way to
implement $take$ is to
reduce the number of elements knowingly stored in the array
from $n$ to $k$.
The result is that the original array gets modified and we loose any information
about the content that is written beyond given $k$.

\begin{lemma}
    $k \le \length s\Longrightarrow$ \\
    \begin{center}
    $\langle \pfarraycap$ sn s si$\rangle$
    $\pfashrink$ si k
    $\langle\lambda si'. \pfarraycap$ sn ($\take$ k s) si' $\rangle$
    \end{center}
\end{lemma}

With these operations and suitable Hoare-Triples on them,
we have all the tools required to refine the abstract set implementation.
% TODO more about sblit?

\section{Set-Operations}

Having covered the refinement for the list data type,
the B-tree data type itself can be refined.
Rather than actually storing nodes within lists,
the B-tree nodes are supposed to be stored in the heap,
and the node list will only contain pointers to the corresponding nodes.
Pointers are represented by the type \textit{ref} in Imperative/HOL.
Leaf nodes contain no information and consequently don't have to be stored
on the heap, therefore we refine them using null pointers.
Since Imperative/HOL does not support null pointers \parencite{DBLP:conf/tphol/BulwahnKHEM08},
and we do not want to explicitly store \textit{Leaf} objects on the heap,
B-tree nodes are refined by heap reference \textit{options} instead.
Thus \textit{None} represents leafs or empty trees,
while \textit{Some} heap reference points to refinements of internal nodes.

\begin{lstlisting}[mathescape=true, language=Isabelle]
datatype 'a btnode =
    Btnode (('a btnode ref option*'a) pfarray) ('a btnode ref option)
\end{lstlisting}

Note the similarity to the definition in \Cref{lst:btree-def},
only that \textit{btree} was replaced by \textit{btnode ref option},
\textit{list} was replaced by \textit{pfarray},
and there is no leaf case anymore.

An abstract B-tree is represented by such a physical node
if all references on subtrees represent the corresponding
abstract subtrees and all keys are the same.
The precise refinement assertion can be seen in \Cref{lst:imp-btree-refine}.

\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle, caption={The refinement assertion for B-trees},
    label={lst:imp-btree-refine}]
fun btree_assn :: nat $\Rightarrow$ 'a::heap btree $\Rightarrow$ 'a btnode ref option $\Rightarrow$ assn where
    btree_assn k Leaf None = emp |
    btree_assn k (Node ts t) (Some a) = ($\exists_A$ tsi ti tsi'.
        a $\mapsto_r$ Btnode tsi ti
        * btree_assn k t ti
        * is_pfa (2*k) tsi' tsi
        * list_assn ((btree_assn k) $\times_a$ id_assn) ts tsi'
        ) |
    btree_assn _ _ _ = false

abbreviation blist_assn k $\equiv$ list_assn ((btree_assn k) $\times_a$ id_assn)

\end{lstlisting}
\end{figure}

It seems a little bit awkward that the definition
includes two relationships regarding only the list of elements in the subtree.
The reason is that there are two steps of refinements going on.
First, all elements in the list are refined to their imperative counterparts.
This fact is expressed by the \textit{list\_assn} term in the assumption.
Second, the list itself is refined to an array.
This is expressed in \textit{is\_pfa} term.
Since the list assumption makes recursive use of the
B-tree assertion, we again cover up usage of the term
by an abbreviation.

Using the parameters of \textit{is\_pfa},
note that we can specify that every node of a B-tree should have
a capacity of $2k$.

\subsection{The split function}
\label{sec:imp-split}

To implement any set operations we again need a split operation.
However, what split function exactly will be used can be abstracted again.
The only important thing is that it refines an abstract split function.
However we have some freedom on how to specify this refinement relationship.

Imperative split functions should be efficient and as such should not actually
split the array in half.
The operation should rather return the index of the correct
subtree-separator pair.
The refinement condition derived from this relationship is as follows.

\begin{lstlisting}[mathescape=true, language=Isabelle]
definition split_relation xs (ls,rs) i = i $\le$ length xs $\wedge$ ls = take i xs $\wedge$ rs = drop i xs
\end{lstlisting}

A very useful alternative statement of the relationship follows automatically.
This allows us to simplify terms that only contain $xs$
to the two sublists when we obtain this relationship in proofs.

\begin{lemma}
    $\splitrelation xs\ (ls,rs)\ i = (xs = ls@rs \wedge i = \length ls)$
\end{lemma}

From this, we characterize the desired imperative
split function \textit{imp\_split} by its Hoare-Triple.

\begin{align*}
    \langle & \pfarraycap c\ xs\ (a,n) \rangle \\
            & \impsplit\ (a,n)\ p \\
\langle\lambda i. & \pfarraycap c\ xs\ (a,n)\\
& * \uparrow(\splitrelation xs\ (\splitfun xs\ p)\ i)\rangle_t
\end{align*}

Just as with the abstract implementation,
the imperative refinements can be built with this characterization alone.
However this time we are actually interested in finding an
efficient split and will spend some time finding
a good split function.
%TODO move to after the set operations?

In the imperative context, we prefer not to directly
refine the recursive function from \Cref{fig:linear_split}
but we embark on the exercise of using a while loop.
The implementation in \Cref{lst:imp-linear-split}
not more efficient than the functional linear search,
but suitable for getting to know
the usage of while loops in imperative HOL.
Every iteration, an index on the array is moved forward by one.
The main part is done in the loop head - if we
are within the array bounds,
we obtain the current separator and check if it is
smaller than the partitioning element.
We return the first index at which the separator is greater or equal.

\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle, caption={The imperative linear split},
    label={lst:imp-linear-split}]
definition lin_split :: ('a::heap $\times$ 'b::{heap,linorder}) pfarray $\Rightarrow$ 'b $\Rightarrow$ nat Heap where
    lin_split (a,n) p = do {
        i $\leftarrow$ while
            ($\lambda$i. if i<n then do {
                (_,s) $\leftarrow$ Array.nth a i;
                return (s<p)
            } else return False)
            ($\lambda$i. return (i+1))
            0;
        return i
    }
\end{lstlisting}
\end{figure}

As mentioned, the internal behavior of this function is
quite different to the abstract linear split from \Cref{fig:linear_split}.
Therefore, proving that it refines the abstract function requires a small detour.
We first express and show the most basic, non-trivial statement
we can make about the result of the function.
We then show that the result is the same as the result
of applying the abstract function,
that is that to an external observer, the functions behave the same.

We begin by stating a simple matching Hoare Triple
for the function.

\begin{lemma}
    \label{lem:lin-split-ht}
    \begin{align*}
        \langle &\pfarraycap c\ xs\ (a,n)\rangle \\
                  &\linsplit\ (a,n)\ p \\
        \langle \lambda i. & \pfarraycap c\ xs\ (a,n) \\
        * &\uparrow(i \leq n
            \wedge (\forall j < i.\ snd (xs!j) < p)
            \wedge (i<n \longrightarrow snd (xs!i) \geq p)) \rangle_t
    \end{align*}
\end{lemma}

It follows by supplying the following loop invariant:

\begin{itemize}
    \item $\forall j<i.\ \snd (xs!j) < p$: All elements up to the current $i$
        are smaller than the partitioning element,
    \item $\uparrow(i \leq n)$: $i$ does not exceed the length of the array and
    \item $\pfarraycap c\ xs\ (a,n)$: the array is not manipulated by the operation
\end{itemize}

In order to show that the loop also terminates,
we need to provide a measure that strictly decreases in each iteration.
The measure for the loop is the difference $n-i$ which
decrements by one in each iteration and stays positive.

For unexciting reasons, the post condition we have thus obtained
actually suffices to imply that the split relation
to the result of an abstract split function is satisfied.
Specifically, we use the abstract split function from
\Cref{fig:linear_split}. %TODO or explain why a different function was used
For the two cases of loop termination,
either $i = n$, or $i < n$, we find that
the abstract function will return the exact same split.

This is fortunate since the previous lemma
follows directly from the computation and is closely related
to the loop invariant.
This will simplify proofs for alternative imperative split functions.
\footnote{
    Another, albeit more theoretical,
    reason for excitement is that we can now specify imperative B-tree
    interfaces without any reference to the abstraction.
    We simply always use the abstract linear split function
    and only require that the imperative split function satisfies
    the hoare triple from \Cref{lem:lin-split-ht}.
}
With this reassurance we approach the binary split.

A detailed analysis of binary search algorithms
may be found in the work of Montague \parencite{DBLP:journals/csedu/Montague91},
which has served as an orientation
for the derived algorithm in \Cref{lst:imp-binary-split}.
Rather than walking through the array,
it narrows the range in which the desired element may lie
to a window that it bisected in every iteration.
This bisection is implemented by inspecting the middle element of the window.
If the desired element was not found, the algorithm
recurses into either the remaining subwindow to the left or right.
In the final iteration,
the window has narrowed down to a single element,
containing the correct separator and subtree.

\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle, caption={The imperative binary split},
    label={lst:imp-binary-split}]
definition bin_split :: ('a::heap $\times$ 'b::{heap,linorder}) pfarray $\Rightarrow$ 'b $\Rightarrow$ nat Heap
    where bin_split (a,n) p = do {
        (low',high') $\leftarrow$ while
            ($\lambda$(low,high). return (low < high))
            ($\lambda$(low,high).
            let mid = ((low  + high) div 2) in
            do {
                (_,s) $\leftarrow$ Array.nth a mid;
                if p < s then
                    return (low, mid)
                else if p > s then
                    return (mid+1, high)
                else
                    return (mid,mid)
            })
            (0::nat,n);
        return low'
    }
\end{lstlisting}
\end{figure}

Since pairs as list elements (i.e. pairs of trees and separators)
were expected to add another layer of complexity,
a binary split algorithm on normal lists has been derived first.
The split function for lists of pairs was then defined
and could be tackled using the same loop invariant.
Note that the binary split works on two indices
as states, the upper bound $h$ and the lower bound $l$.

\begin{itemize}
    \item $\forall j<l.\ \snd (xs!j) < p$: All elements up to the current $l$
        are smaller than the partitioning element,
    \item $h<n \rightarrow \snd (xs!h) < p$: If the upper bound $h$
    is strictly less than the length of the array,
    the element it points to is greater than the partioning element,
    \item $\uparrow(l \leq h)$: The lower bound is always less or equal to the upper bound,
    \item $\uparrow(h \leq n)$: the upper bound does not exceed the length of the array and
    \item $\pfarraycap c\ xs\ (a,n)$: again, the array is not manipulated by the operation
\end{itemize}

In this case the window that is considered by the binary split
provides the loop measure, as $h-l$ decreases by at least one in each step.
Proving that this is the case was not the main issue,
but rather finding a correct formulation of the algorithm
where this is actually true.

Overall obtaining the same Hoare Triple
as for the linear split required only
this slightly more complex loop invariant
and invocation of a number of algebraic lemmas.
This came to us somewhat of a surprise, since the functional
version of a binary split is much harder to
specify and analyse than a functional linear split.
The additional requirement for the binary split is
naturally that the list of separators must be sorted.

\begin{lemma} $\sorted (\separators xs) \Longrightarrow$ \\
    \label{lem:imp-bin-split-ht}
    \begin{align*}
        \langle &\pfarraycap c\ xs\ (a,n)\rangle \\
                  &\binsplit\ (a,n)\ p \\
        \langle \lambda i. & \pfarraycap c\ xs\ (a,n)\\
        &* \uparrow(i \leq n
            \wedge (\forall j < i. snd (xs!j) < p)
            \wedge (i<n \longrightarrow snd (xs!i) \geq p)) \rangle_t
    \end{align*}
\end{lemma}

Since we know that this implies equivalence to the abstract split function
and sortedness of the separators is guaranteed by the sortedness
invariant of the B-trees,
we can safely use this function for specifying
the set operations.

%TODO Note the choice of a while-loop for efficiency
%TODO The split function can be implemented linearly (easier, proof of concept)
% but due to abstraction of functionality may use binary split as well.

\subsection{The isin function}

In general, the formulation of the imperative set operations
do quite directly follow
from the refinement of the abstract operations.
The main difference is the usage of pointers,
that need to be dereferenced and updated.
Functions such as length need to be called and have their result
stored explicitly before use.
Other than that, the definition of the imperative isin in \Cref{lst:imp-isin-fun}
function should bare no surprises.
Note that it makes use of the function \textit{imp\_split}
which is an arbitrary split function that fulfills the Hoare Triple
of \Cref{lem:imp-bin-split-ht}.

\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle, label={lst:imp-isin-fun},
    caption={The imperative isin function}]
partial_function (heap) isin :: 'a btnode ref option $\Rightarrow$ 'a $\Rightarrow$  bool Heap
  where
    isin p x = (case p of
        None $\Rightarrow$ return False |
        (Some a) $\Rightarrow$ do {
        node $\leftarrow$ !a;
        i $\leftarrow$ imp_split (kvs node) x;
        tsl $\leftarrow$ pfa_length (kvs node);
        if i < tsl then do {
            s $\leftarrow$ pfa_get (kvs node) i;
            let (sub,sep) = s in
            if x = sep then
            return True
        else
            isin sub x
        } else
            isin (last node) x
    }
)
\end{lstlisting}
\end{figure}

The convention for variables that refer to refined data types
is that they have the same name as the abstract data type,
with the postfix \textit{i}.
For example below, the abstract \textit{btree} is referred to by $t$,
however the refined \textit{btnode ref option} is called $ti$.
To simplify notation, we simply assume that the set operations
such as \textit{isin} are overloaded and refer to abstract or
imperative implementations, depending on the parameter type.
The Hoare Triple to argue that the imperative \textit{isin}
refines the abstract \textit{isin} follows.

\begin{lemma} $\sorted (\inorder t) \Longrightarrow$ \\
\begin{align*}
   \langle &\btreeassn k\ t\ ti\rangle \\
           &\isinfun ti\ x \\
   \langle \lambda r. &\btreeassn k\ t\ ti\ * \uparrow(\isinfun t\ x = r)\rangle_t
\end{align*}
\end{lemma}

Note how, in contrast to the abstract specification,
we need to also show that the imperative function does not modify the tree
residing in the heap.
The proof follows by induction on the computation of the abstract isin function.

% TODO conclusion ?
Inside a structured proof skeleton of the induction,
proving the subgoals in apply style turned out to be the most
appropriate.
The separation automation tool only required help
for the instantiation of existential quantifiers,
especially after application of the inductive hypothesis.
% TODO more details?

\subsection{Insertion}
% TODO...
\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle, label={lst:imp-nodei-fun},
    caption={The imperative node$_i$ function}]
definition node$_i$
    :: nat $\Rightarrow$ ('a btnode ref option $\times$ 'a) pfarray $\Rightarrow$ 'a btnode ref option $\Rightarrow$ 'a btupi Heap
    where node$_i$ k a ti $\equiv$ do {
        n $\leftarrow$ pfa_length a;
        if n $\le$ 2*k then do {
            a' $\leftarrow$ pfa_shrink_cap (2*k) a;
            l $\leftarrow$ alloc (Btnode a' ti);
            return (T$_i$ (Some l))
        } else do {
            b $\leftarrow$ (pfa_empty (2*k) :: ('a btnode ref option $\times$ 'a) pfarray Heap);
            i $\leftarrow$ split_half a;
            m $\leftarrow$ pfa_get a i;
            b' $\leftarrow$ pfa_drop a (i+1) b;
            a' $\leftarrow$ pfa_shrink i a;
            a'' $\leftarrow$ pfa_shrink_cap (2*k) a';
            let (sub,sep) = m in do {
                l $\leftarrow$ alloc (Btnode a'' sub);
                r $\leftarrow$ alloc (Btnode b' ti);
                return (Up$_i$ (Some l) sep (Some r))
            }
        }
    }

\end{lstlisting}
\end{figure}

\begin{figure}
\begin{lstlisting}[mathescape=true, language=Isabelle, label={lst:imp-ins-fun},
    caption={Excerpt of the imperative insert function}]

partial_function (heap) ins :: nat $\Rightarrow$ 'a $\Rightarrow$ 'a btnode ref option $\Rightarrow$ 'a btupi Heap
    where ins k x apo = (case apo of
    None $\Rightarrow$ return (Up$_i$ None x None) |
    (Some ap) $\Rightarrow$ do { a $\leftarrow$ !ap; i $\leftarrow$ imp_split (kvs a) x; tsl $\leftarrow$ pfa_length (kvs a);
      if i < tsl then do {
        s $\leftarrow$ pfa_get (kvs a) i;
        let (sub,sep) = s in
        if sep = x then return (T$_i$ apo)
        else do {
          r $\leftarrow$ ins k x sub;
          case r of
            (T$_i$ lp) $\Rightarrow$ do { pfa_set (kvs a) i (lp,sep); return (T$_i$ apo)
            } |
            (Up$_i$ lp x' rp) $\Rightarrow$ do {
              pfa_set (kvs a) i (rp,sep);
              if tsl < 2*k then do {
                  ts' $\leftarrow$ pfa_insert (kvs a) i (lp,x');
                  ap := (Btnode ts' (last a));
                  return (T$_i$ apo)
              } else do {
                ts' $\leftarrow$ pfa_insert_grow (kvs a) i (lp,x');
                node$_i$ k ts' (last a)
        } } } } else $\dots$

definition insert :: nat $\Rightarrow$ ('a::{heap,default,linorder}) $\Rightarrow$ 'a btnode ref option $\Rightarrow$ 'a btnode ref option Heap
    where insert $\equiv$ $\lambda$ k x ti. do {
    ti' $\leftarrow$ ins k x ti;
    case ti' of
        T$_i$ sub $\Rightarrow$ return sub |
        Up$_i$ l a r $\Rightarrow$ do {
            ts' $\leftarrow$ pfa_init (2*k) (l,a) 1;
            t' $\leftarrow$ alloc (Btnode ts' r);
            return (Some t')
        }
    }

\end{lstlisting}
\end{figure}

%TODO Description of applying the refinement framework to the insert function
The imperative implementation and derived heap rule of the \textit{insert} function follow
the same pattern as the \textit{isin} function.
The only interesting part is whether and how often new memory is allocated.
An excerpt of the refinement of the \textit{ins} function
can be seen in \Cref{lst:imp-ins-fun}\footnote{
    In the imperative language in Isabelle, allocating heap memory
    is abbreviated by \textit{ref}.
    To clarify that this means allocation, it is named \textit{alloc} here.
}.
The function includes some simple optimizations, such as not calling
\textit{node$_i$} if the node is not overflowing.
This is an optimization as otherwise \textit{node$_i$} in
\Cref{lst:imp-nodei-fun} would always allocate a new B-tree node
rather than updating the current node in place.

To prove that this optimization is valid, the only obligation
is to show that the updated node itself is equivalent
to the node returned by \textit{node$_i$}.
Since we are in the branch where the node contains less than $2k$
elements, this is easy to show, provided some intermediate lemmas
that relate concrete node and abstract node in this context.

\begin{lemma}$\length ts \leq 2k \Longrightarrow
    \node_i k\ ts\ t = T_i (Node\ ts\ t)$
\end{lemma}

\begin{samepage}
By adding a lemma on the equivalence between abstract and imperative
\textit{node$_i$}, we obtain a lemma for \textit{ins}
by induction on the computation
of the abstract \textit{ins} function.

\begin{lemma} $\sorted (\inorder t) \Longrightarrow$ \\
    \begin{align*}
       \langle &\btreeassn k\ t\ ti\rangle \\
               &\insfun k ti\ x \\
       \langle \lambda r. &\btreeassn k\ (\insfun k\ t\ x) r\rangle_t
    \end{align*}
\end{lemma}
\end{samepage}

The proof of this lemma was done in a mixed structural and apply style manner.
It could have been done in a complete apply style manner.
However many subgoals are generated in the proof process that are
simply invalid due to the preconditions of the hoare triple.
Embedding the proof in the structural skeleton makes spotting
these void statements easier and allows to have a better
overview over the current state of the proof.

The insertion function incorporates the function \textit{tree}$_i$
in much the same way as \textit{ins} incorporated the small \textit{node}$_i$ optimizations.
Here the proof of equivalence followed automatically.
With the hoare triple for \textit{ins}, we obtain the final desired lemma
on the imperative insertion.

\begin{theorem} $k > 0 \wedge \sorted (\inorder t) \Longrightarrow$ \\
\begin{align*}
   \langle &\btreeassn k\ t\ ti\rangle \\
           &\insertfun k\ x\ ti \\
   \langle \lambda ri. &\btreeassn k\ (\insertfun k\ x\ t)\ ri\rangle_t
\end{align*}
\label{thm:imp-ins-rule}
\end{theorem}

% TODO say something about k?
Note how we have the additional assumption that $k$ is positive.
This was only required to show correct order in the abstract setting.
Here, the capacity of the root node needs to be specified at initialization.
And since the capacity has to be $2k$ and the node has to hold at least one element
a positive $k$ is required such that no contradiction appears.

Until now we have only shown that the concrete
implementations refine the abstract interpretations.
What does this mean concretely?
Do we have to resort to an informal argument to show that the result
satisfies the invariants and the set interface?
This is not the case.

The final theorem that proves functional correctness of the imperative
implementations with respect to the set interface follows.

\begin{corollary} $k > 0 \Longrightarrow$
\begin{align*}
   \langle &\btreeassn k\ t\ ti \wedge \btree_k t \rangle \\
           &\insertfun k\ x\ ti \\
   \langle \lambda ri. \exists_A r. &\btreeassn k\ r\ ri \wedge \btree_k r \wedge \inorder r = \inslist x\ (\inorder t)\rangle_t
\end{align*}
\end{corollary}

And indeed, this can be derived automatically with a single command invocation,
unfolding \Cref{def:btree-def} and using \Cref{thm:imp-ins-rule}, \Cref{thm:ins-set} and \Cref{thm:ins-invar}.\footnote{
    Technically we also need the fact that ins$_{list}$ preserves sortedness.
    This was already proven by Nipkow \parencite{DBLP:conf/itp/Nipkow16}
    and is not considered here.
}

\subsection{Deletion}

An imperative version of the deletion operation has been specified.
It required some additional operations on partially filled arrays but
posed no fundamental challenges.
Due to its length it is not shown here but may be looked up in the
actual proof documents.

However, the proof of its refining property was not conducted.
We assume that this proof would be structured similar to
the previous proofs.
The only benefit would be exploring usage of the new
heap rules introduced for the additional array operations.
The main difference to the verification of the
insertion function is that the refined functions
are undefined for many cases.
Hence it is highly important
to strongly tie the refined and imperative version
in order to discharge void cases.


\section*{Problem 2}

\begin{problem}{A.}
\vspace{2mm}

We have a hypothetical crystal, whose refractive index depends on both the polarisation and direction of propagation of an incoming EM wave.
\\
Let us choose a Cartesian reference frame, where the boundary between the medium we are investigating and vacuum is $x=0$ plane. The incident wave, lies in the xy plane, having a wave vector $\vec{k}_i$, making an angle $\theta_i$ with the $x-\mathrm{axis}$ (As shown in the  figure). Let us define two polarisations, S and P. Where S polarisation is when the wave is polarised perpendicular to the incident $xy$ plane and P is the polarisation when the electric field of the wave lies in the xy plane. Let us assume two real and positive refractive indices for S and P waves $\eta_S$ and $\eta_P$ repectively. Without loss of generality assume $\eta_P>\eta_S$.
\\
Say the incoming wave is linearly polarised confined in the $xy$ plane, with its electric field making an angle $\frac{\pi}{4}$ with the $z$ axis. This wave is a mixture of both $S$ and $P$ polarisation. It splits into two at different angles $\theta_{t\pm}=\theta_t \pm \alpha$, where $\vec{k}_{t+}$ corresponds to S, and $\vec{k}_{t-}$ corresponds to P.
\end{problem}
\begin{center}

\tikzset{every picture/.style={line width=0.75pt}} %set default line width to 0.75pt

\begin{tikzpicture}[x=0.75pt,y=0.75pt,yscale=-1,xscale=1]
%uncomment if require: \path (0,606); %set diagram left start at 0, and has height of 606

%Shape: Rectangle [id:dp41394729732408253]
\draw  [draw opacity=0][fill={rgb, 255:red, 155; green, 155; blue, 155 }  ,fill opacity=0.35 ] (251.13,82.37) -- (485.49,82.37) -- (485.49,289) -- (251.13,289) -- cycle ;
%Shape: Axis 2D [id:dp26172173283960065]
\draw [line width=1.5]  (153.17,162) -- (515.81,162)(250,15) -- (250,289) (508.81,157) -- (515.81,162) -- (508.81,167) (245,22) -- (250,15) -- (255,22)  ;
%Straight Lines [id:da8337450025284996]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (119.17,285.2) -- (247.17,163.2) ;
%Curve Lines [id:da1405822884062613]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (217.13,164) .. controls (212.3,164.95) and (226.77,183.09) .. (227.5,180.02) ;
%Straight Lines [id:da479198997901781]
\draw [line width=2.25]    (162.74,243.46) -- (197.17,211) ;
\draw [shift={(200.81,207.57)}, rotate = 136.68] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (11.43,-5.49) -- (0,0) -- (11.43,5.49) -- cycle    ;
%Straight Lines [id:da6299546920152124]
\draw [line width=0.75]  [dash pattern={on 4.5pt off 4.5pt}]  (248.32,161.72) -- (444.81,58.57) ;
%Straight Lines [id:da3883728648151408]
\draw [line width=0.75]  [dash pattern={on 4.5pt off 4.5pt}]  (247.17,163.2) -- (444.81,87.93) ;
%Straight Lines [id:da4998060156867363]
\draw [line width=0.75]  [dash pattern={on 4.5pt off 4.5pt}]  (248.32,161.72) -- (445.81,118.93) ;
%Curve Lines [id:da6470768122125261]
\draw [line width=1.5]  [dash pattern={on 5.63pt off 4.5pt}]  (379.8,92.91) .. controls (395.81,95.93) and (391.81,139.93) .. (390.81,127.93) ;
%Curve Lines [id:da8038047661899634]
\draw [line width=1.5]  [dash pattern={on 5.63pt off 4.5pt}]  (329.8,131.91) .. controls (338.32,133.52) and (339.19,144.75) .. (337.99,153.1) .. controls (336.93,160.44) and (334.27,165.54) .. (333.81,159.93) ;
%Straight Lines [id:da4217023866157301]
\draw [line width=2.25]    (345.56,110.14) -- (390.35,87.19) ;
\draw [shift={(394.8,84.91)}, rotate = 152.87] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10,-4.8) -- (0,0) -- (10,4.8) -- cycle    ;
%Straight Lines [id:da49843178394801124]
\draw [line width=2.25]    (352.81,139.93) -- (403.95,127.14) ;
\draw [shift={(408.81,125.93)}, rotate = 165.96] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10,-4.8) -- (0,0) -- (10,4.8) -- cycle    ;
%Shape: Circle [id:dp03983391745542253]
\draw  [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ,fill opacity=1 ] (244.51,161.93) .. controls (244.51,158.46) and (247.33,155.64) .. (250.81,155.64) .. controls (254.28,155.64) and (257.1,158.46) .. (257.1,161.93) .. controls (257.1,165.41) and (254.28,168.22) .. (250.81,168.22) .. controls (247.33,168.22) and (244.51,165.41) .. (244.51,161.93) -- cycle ;
%Shape: Cube [id:dp6684229072869232]
\draw  [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ,fill opacity=0.22 ] (244.28,398.8) -- (295.28,347.8) -- (511.28,347.8) -- (511.28,473.8) -- (460.28,524.8) -- (244.28,524.8) -- cycle ; \draw   (511.28,347.8) -- (460.28,398.8) -- (244.28,398.8) ; \draw   (460.28,398.8) -- (460.28,524.8) ;
%Straight Lines [id:da7498729323670823]
\draw    (123.68,487.8) -- (123.68,371.8) ;
\draw [shift={(123.68,368.8)}, rotate = 90] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
%Straight Lines [id:da8208999367418137]
\draw    (123.68,487.8) -- (290.88,487.8) ;
\draw [shift={(293.88,487.8)}, rotate = 180] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
%Straight Lines [id:da7174552504343465]
\draw    (123.68,487.8) -- (177.03,420.16) ;
\draw [shift={(178.88,417.8)}, rotate = 128.26] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
%Straight Lines [id:da21779076116998253]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (123.68,487.8) -- (279.98,447.55) ;
\draw [shift={(282.88,446.8)}, rotate = 165.56] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
%Straight Lines [id:da4538137858169531]
\draw    (175.88,474.8) -- (230,459.61) ;
\draw [shift={(232.88,458.8)}, rotate = 164.32] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
%Curve Lines [id:da5782358459753356]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (151.28,452.8) .. controls (164.88,452.8) and (169.88,484.8) .. (162.88,487.8) ;

%Straight Lines [id:da995607271595156]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (460.28,524.8) -- (459.96,555.61) -- (459.88,562.6) ;
%Straight Lines [id:da22758558142862872]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (511.28,473.8) -- (511.12,489.63) -- (510.97,503.6) -- (510.88,511.6) ;
%Straight Lines [id:da17388485750558225]
\draw  [dash pattern={on 4.5pt off 4.5pt}]  (462.41,541.68) -- (509.16,494.92) ;
\draw [shift={(511.28,492.8)}, rotate = 135] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
\draw [shift={(460.28,543.8)}, rotate = 315] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (10.72,-5.15) -- (0,0) -- (10.72,5.15) -- (7.12,0) -- cycle    ;
% Text Node
\draw (102.68,377.2) node [anchor=north west][inner sep=0.75pt]    {${y}$};
% Text Node
\draw (295.88,491.2) node [anchor=north west][inner sep=0.75pt]    {${z}$};
% Text Node
\draw (291.68,439.2) node [anchor=north west][inner sep=0.75pt]    {${x}$};
% Text Node
\draw (212.68,434.2) node [anchor=north west][inner sep=0.75pt]    {${k_{i}}$};
% Text Node
\draw (168.68,398.2) node [anchor=north west][inner sep=0.75pt]    {${E_{i}}$};
% Text Node
\draw (170.68,441.2) node [anchor=north west][inner sep=0.75pt]    {$\phi$};
% Text Node
\draw (487.78,521.7) node [anchor=north west][inner sep=0.75pt]    {${d}$};
% Text Node
\draw (516.8,169.31) node [anchor=north west][inner sep=0.75pt]    {${X}$};
% Text Node
\draw (226.8,19.31) node [anchor=north west][inner sep=0.75pt]    {${Y}$};
% Text Node
\draw (379.8,136.31) node [anchor=north west][inner sep=0.75pt]    {${k_{t-}}$};
% Text Node
\draw (403.8,106.31) node [anchor=north west][inner sep=0.75pt]    {$-\alpha $};
% Text Node
\draw (393.62,86.13) node [anchor=north west][inner sep=0.75pt]  [rotate=-338.35]  {$+\alpha $};
% Text Node
\draw (364.8,68.31) node [anchor=north west][inner sep=0.75pt]    {${k_{t+}}$};
% Text Node
\draw (349.06,143.73) node [anchor=north west][inner sep=0.75pt]    {${\theta }_{t}$};
% Text Node
\draw (191.8,167.4) node [anchor=north west][inner sep=0.75pt]    {${\theta _{i}}$};
% Text Node
\draw (181.7,234.84) node [anchor=north west][inner sep=0.75pt]  [rotate=-314.46]  {${k_{i}}$};
% Text Node
\draw (228.8,142.4) node [anchor=north west][inner sep=0.75pt]    {$Z$};

\end{tikzpicture}

\end{center}
\newpage
\begin{subpr}{A1. \hfill 1.5 pts.} Find $n_S$  and $n_P$ in terms of $\theta_t$, $\theta_i$, $\alpha$. Assume that $n_S=n_0+\Delta n$ and $n_P=n_0-\Delta n$, where $\Delta n/n_0 <<1$ and we only look for first-order terms in $\Delta n/n_0$.
\end{subpr}
\begin{problem}{}
 Now assume the incidence to be normal, and the electric field still makes an angle $\pi/4$ with the $z$-axis (As can be seen in the figure). The crystal has a thickness $t>>\lambda$.
\end{problem}
\begin{subpr}{A2. \hfill 1 pts.} Find the values of $t$ for which the light exiting crystal is either circularly polarised or it is linearly polarised, but rotated by and angle $\pi/2$ with respect to the incident polarisation. You may neglect the difference between Reflection coefficients for $S$ and $P$.
\end{subpr}

\begin{problem}{B.}
 Let us investigate a plane EM wave, of frequency $\omega$ travelling in a static uniform magnetic field $B_0 \hat{z}$, where $\hat{z}$ is the unit vector $z$ of the chosen Cartesian frame of reference. $B_0$ is much stronger than the field of the wave and the wave propagation is also along $\hat{z}$.
\\
 This medium contains $N_e$ bound electrons per unit volume, each obeying the classical equation of motion.
 \begin{equation}
e(\vec{E}+\frac{\vec{v}}{c}\times \vec{B}) +m_e \omega^2 r= -m_e \ddot{\vec{r}}, \vec{v}=\frac{d\vec{r}}
{dt}\end{equation}
Where $m_e$ and $-e$ are the mass and charge of electron respectively.
\end{problem}
\begin{subpr}{B1. \hfill 4.5 pts.} Prove that the wave propagation depends on polarisation, by calculating the refractive index for circular polarisation  (either left handed or right).
\end{subpr}
\begin{problem}{}
Now consider the propagation of a linearly polarised in the same wave. Asuume the field at $z=0$ to be given by $\vec{E}_i (z=0,t)=E_i e^{-i\omega t} \hat{x}$, and a relatively weak magnetic field such that $\omega >> \omega_c$ and higher order terms of $\omega_c/\omega$ can be neglected.
\end{problem}
\begin{subpr}{B2. \hfill 3 pts.} Calculate the electric field at $z=l$, and find the angle by which the polarization has rotated.
\end{subpr}
\clearpage


\chapter{Bidirectional \kl(tit){PCUIC}}
\label{chap:bidir-pcuic}

\margintoc

As we have seen in \cref{sec:tech-pcuic}, there is much more to the real \kl{Coq} than
\kl{CCω}.
The ideas exposed in the previous chapter nevertheless
scale very well to these extensions.
There are two areas, though, where some care needs to be taken.
The first is cumulativity, which in particular forces us to reconsider the statement
of the completeness and uniqueness properties, see \cref{sec:bidir-pcuic-cumulativity}.
But the main one is the introduction of inductive types. In particular, there is a subtle
interplay with cumulativity in the treatment of pattern-matching.
Working on the formalized proof of completeness in \kl{MetaCoq} led to the discovery of
an incompleteness bug in the kernel of \kl{Coq} linked to this.
In \cref{sec:bidir-pcuic-inductives} we show how the bidirectional setting adapts to
inductive types, and try and give an intuition of the origin of the completeness issue.

We do not give precise proofs in this chapter,
instead relying on the formalization in \kl{MetaCoq} described in \arefpart{metacoq}.

  % The first area of difference are the universes. While on paper those are simply integer, to handle typical ambiguity and polymorphic (co)-inductive types, PCUIC uses algebraic universes, containing level variables, algebraic $\vee$ and $+1$ operators, and a special level for the sort Prop. Moreover, those universes are cumulative, that is they behave as if smaller universes were included in larger ones. The precise handling of the algebraic universes is abstracted away in MetaCoq, and quite similar in the directed and undirected systems, so it did not prove too difficult to handle. Cumulativity, however, introduces some not-so-small differences with the previous presentation, so we spend some time on it in \cref{sec:pcuic-cumul}.

  % The second is the addition of new base type and term constructors. We describe the treatment of inductive types in \cref{sec:pcuic-indu}. Co-inductive types and records behave very similarly to inductive types at the level of typing, so we do not dwell on them. The difference lies mainly at the level of reduction/conversion, but as our type system treats those as black boxes the differences have a negligible impact.

\section{Cumulativity}
\label{sec:bidir-pcuic-cumulativity}

\begin{marginfigure}
  \begin{mathpar}
    \inferdef{CheckCum}
    {\inferty{\Gamma}{t}{T} \\ T \cum T'}{\checkty{\Gamma}{t}{T'}}
    \label{rule:bd-check-cum}
  \end{mathpar}
\end{marginfigure}
The introduction of the more liberal cumulativity rules in the undirected system
of course calls for an update to the computation rules.
The change to \ruleref{rule:bd-check} is direct: simply replace conversion with cumulativity,
as done in \ruleref{rule:bd-check-cum} opposite.
As for the constrained inference rules, they do not even need any modification.
Intuitively, this is because there is no reason to degrade a type to a larger one,
unless it is forced by a given target type in the checking judgment.

The statement of completeness also needs to account for cumulativity,
and becomes the following one.

\begin{theorem}[Completeness, with cumulativity]
  \label{thm:comp-cumul}
  If $\Gamma \vdash t \ty T$, then $\inferty{\Gamma}{t}{T'}$ is derivable
  for some $T'$ such that $T' \cum T$.
\end{theorem}

This also means that in the setting of \kl{PCUIC},
\kl{uniqueness of types} up to \kl{conversion} is not true any more.
For instance, we both have $\Gamma \vdash \uni[0] \ty \uni[1]$ and $\Gamma \vdash \uni[0] \ty \uni[2]$, but $\uni[1]$ and $\uni[2]$ are not convertible. In that context, however,
the type $\uni[1]$ still has a special property: it is minimal among all types, what
we call a \kl{principal type}.

\begin{definition}[Principal type]
  The type $T$ is a \intro{principal type} for term $t$ – in a context $\Gamma$ –
  if $\Gamma \vdash t \ty T$ and for any $T'$ such that $\Gamma \vdash t \ty T'$,
  we have $T \cum T'$.
\end{definition}

The existence of such a principal type is the same as \kl{uniqueness of types}
up to cumulativity. Moreover, even in the cumulative setting, \cref{thm:unique-inf}%
\sidenote{Uniqueness of inferred types up to joinability.}
stays true. Intuitively, this is because it only relies on properties of reduction, but not of
conversion. Thus, following the same proof as that of \cref{thm:unique-undir},%
\sidenote{Uniqueness of types for undirected typing.}
we obtain that inferred types are principal.

\begin{theorem}[Inferred types are principal]
  \label{thm:princ-types}
  If $\Gamma$ is well-formed and $\inferty{\Gamma}{t}{T}$,
  then $T$ is a \kl{principal type} for $t$ in $\Gamma$.
\end{theorem}

\begin{proof}
  If $\Gamma \vdash t \ty T'$, then by completeness there exists some $T''$ such that
  $\inferty{\Gamma}{t}{T''}$, and moreover $T'' \cum T'$.
  But by \cref{thm:unique-inf}, $T \conv T'' \cum T'$ and thus $T \cum T'$, and $T$ is thus indeed a principal type for $t$ in $\Gamma$.
\end{proof}

The existence of \kl{principal types} is not so easy to prove directly, as it more or less
amounts to showing correctness and completeness of the bidirectional system at once.
Nevertheless, it is useful, because it in particular means that any well-typed term $t$
has an unambiguous smallest universe, which can be obtained as the \kl{principal
type} of its \kl{principal type}. This means that there is a good separation between irrelevant
propositions – those terms whose smallest universe is $\Prop$ – and relevant terms
– those whose smallest universe is some $\uni[i]$ –, and that this stays true even in
presence of cumulativity, and even if $\Prop \cum \uni[i]$. If this were not the case,
the erasure of propositional content – which is one of the important use cases of $\Prop$ –
would not make sense.

\section{Inductive Types}
\label{sec:bidir-pcuic-inductives}

\subsection{An example: the pair type}[The pair type]

\begin{figure}

  \begin{mathpar}
    \inferdef{PairTy}{
      \pinferty{\uni}{\Gamma}{A}{\uni[i]} \\
      \pinferty{\uni}{\Gamma, x : A}{B}{\uni[j]}}
      {\inferty{\Gamma}{\Sb x : A .\ B}{\uni[\umax{i}{j}]}}
      \label{rule:pair-type-bd} \and
    \inferdef{Pair}{
      \pinferty{\uni}{\Gamma}{A}{\uni[i]} \\
      \pinferty{\uni}{\Gamma, x : A}{B}{\uni[j]} \\
      \checkty{\Gamma}{t}{A} \\
      \checkty{\Gamma}{u}{\subs{B}{x}{t}}}
      {\inferty{\Gamma}{\pair[A][x.B]{t}{u}}{\Sb x : A .\ B}}
      \label{rule:pair-bd} \and
    \inferdef{PairInd}{
      \pinferty{\Sb}{\Gamma}{s}{\Sb x : A .\ B} \\
      \pinferty{\uni}{\Gamma, z : \Sb x : A .\ B}{P}{\uni} \\
      \checkty{\Gamma, y_1 : A, y_2 : \subs{B}{x}{y_1}}{b}
        {\subs{P}{z}{\pair[A][x.B]{y_1}{y_2}}}}
      {\inferty{\Gamma}{\ind{\Sb}{s}{z.P}{y_1.y_2.b}}{\subs{P}{z}{s}}}
      \label{rule:pair-ind-bd} \and

    \inferdef{PairInf}{
      \inferty{\Gamma}{t}{T} \\ T \red \Sb x : A .\ B}
      {\pinferty{\Sb}{\Gamma}{t}{\Sb x : A .\ B}}
      \label{rule:sig-inf}
  \end{mathpar}

  \caption{Bidirectional pair type}
  \label{fig:bidir-pair}
\end{figure}

To set ideas straight, let us look at how we can adapt the dependent pair type of
\cref{fig:sig} to the bidirectional setting: see \cref{fig:bidir-pair}.
To obtain these rules, first notice that all undirected typing rules for the
pair type (\cref{fig:sig})
must become inference rules if we want the resulting system to be complete.
The question therefore is once again to choose modes for the premises.
Rules \nameref{rule:pair-type-bd} and \nameref{rule:sig-inf} are
very similar to the rule for Π-types, there is not much surprise there.

\ruleref{rule:pair-bd} shows why we insisted in the undirected system
on recording the types $A$ and $B$ in the pair. Indeed, they are needed to
know which type to infer for the pair. Without the annotation, one could infer a
type $A$ for $t$ and a type $B'$ for $u$, but there are potentially many incomparable types $B$ that would be correct for the whole pair, depending on which instances of $t$ in $B'$ are abstracted to $x$. We only know that $B'$ is $\subs{B}{x}{t}$,
but this is not enough to inambiguously determine $B$.
This impossibility to invert a substitution is a general source of need
for annotations, which is not specific to pair types!

Finally, \ruleref{rule:pair-ind-bd} is the most complex.
In presentations of \kl{recursors}, often the predicate appears first, then the branches,
and finally the scrutinee. But this is not possible here, as the parameters of the inductive
type are needed to construct the context in which the predicate is typed.
Instead, those parameters can be inferred from the scrutinee.
Thus, a type for the scrutinee is first obtained using a new constrained inference judgment,
forcing the inferred type to be a Σ-type, but leaving its parameters free.
Next, these parameters can be used to construct the context to type the predicate.
And finally, once the predicate is known to be well-formed,
it can be used to type-check the branch.

This same approach can be readily extended to the other inductive types of
\cref{sec:tech-cic}, with recursion or indices posing no specific problems.
%, see \cref{fig:bidir-indu-other}.

\subsection{Polymorphic inductive types}

The account of general inductive types in \kl{PCUIC} is slightly different from
the one we just gave. The reason for this is that giving a general account of rules
which infer type levels like our \ruleref{rule:pair-type-bd} is not easy.
Indeed, the parameters of an inductive type can
be of a type much more complex than simply $\uni$, and in that general setting deciding which
type variable can be inferred is a non-trivial problem.
Instead, the polymorphic inductive types as implemented in \kl{Coq} store explicit universe
levels on inductive types and constructors. The  pair type of \cref{fig:bidir-pair},
for instance, would contain universe levels $i,j$, so that both $A$ and $B$
would be checked rather than having their level inferred.
The rule for the type constructor in that context is given opposite.
\begin{marginfigure}
  \begin{mathpar}
  \inferrule{
    \checkty{\Gamma}{A}{\uni[i]} \\
    \checkty{\Gamma, x : A}{B}{\uni[j]}}
    {\inferty{\Gamma}{\Sb\ulev{i,j} x : A .\ B}{\uni[\umax{i}{j}]}}
  \end{mathpar}
\end{marginfigure}
This makes the treatment of complex inductive types possible by using checking uniformly –
rather than relying on constrained inference to infer universe levels –
at the cost of possibly needless annotations, as here with Σ-types.
This is mostly invisible for the end user though, as she does very seldom write universe
levels thanks to \kl{typical ambiguity} anyway.

In the same spirit, pattern-matching in \kl{Coq} – and its counterpart in \kl{PCUIC} –
also stores enough information to easily reconstruct the context
in which the predicate and branches are typed. This information consists in universe levels
– for polymorphic inductive types – and parameters of the inductive type.
Thus, the actual typing rule for pattern-matching in the case of Σ-types
is closer to the following one:

\begin{mathpar}
  \inferrule{
    \pinferty{\Sb}{\Gamma}{s}{\Sb\ulev{i,j} x : A .\ B} \\
    i \le i' \\ j \le j' \\ A \cum A' \\ B \cum B' \\
    \pinferty{\uni}{\Gamma, z : \Sb x : A' .\ B'}{P}{\uni} \\
    \checkty{\Gamma, y_1 : A', y_2 : \subs{B'}{x}{y_1}}{b}
      {\subs{P}{z}{\pair[A'][x.B']{y_1}{y_2}}}}
    {\inferty{\Gamma}{\match{\Sb}{i',j'}{A',B'}{s}{z.P}{y_1.y_2.b}}{\subs{P}{z}{s}}}
\end{mathpar}

Note that the domain and codomain are compared using \kl{cumulativity}. This is crucial
to retain \kl{subject reduction}. Indeed, reduction of the scrutinee might make its inferred
type decrease. For instance, suppose we have a polymorphic inductive $I\ulev{i}$ with a single
constructor $c$ such that $A : \uni[i] \vdash c\ulev{i}(A)$. Now consider
  \[ \left( \l y : I\ulev{1}.\ y \right)\ c\ulev{0}(\Nat)
    \ored c\ulev{0}(\Nat) \]
the redex infers type $I\ulev{1}$, while the reduct infers
$I\ulev{0}$. Thus, if such a term is plugged as scrutinee in a pattern-matching,
the whole term is still typeable after the reduction of
the scrutinee because we allow inequalities rather than equalities between levels.

But here lies a subtle issue: in pen-and-paper accounts of recursors,
the predicate and branches are often
represented respectively as Π-types and λ-abstractions. This is also how previous versions of
\kl{Coq} represented pattern-matching.%
\sidenote{Until version 8.14 to be precise.}
But recall that in \kl{PCUIC}, cumulativity is
equivariant on the domain of Π-types. This led to an implementation that wrongly compared
the universe levels using equality rather than inequality, leading to a completeness
bug that manifested as a failure of subject reduction in situations such as the one above.%
\sidenote{A precise description of the problem in the kernel and an example similar to the
  one above are given in issue \coqIssue{13495}.}
This prompted subsequent work, both on the theory of \kl{PCUIC} and on the implementation, to
remove the use of Π- and λ-abstractions completely from pattern-matching%
\sidenote{This was carried out by Pierre-Marie Pédrot starting with pull-request \coqPR{13563},
following ideas that had been laid down earlier by Hugo Herbelin in the
\href{https://github.com/coq/ceps/blob/master/text/inductive-branch-predicate-representation-and-reduction.md}{\kl{Coq} enhancement
proposal \#34}.},
making both the implementation less ad-hoc, and the theory cleaner.
A detailed summary has been given in \sidetextcite{Sozeau2022}.

Further investigations in that area might still be valuable though, in particular in order
to determine what kind of annotations are actually needed for pattern-matching, both
in theory and in practice. Can we give a presentation of polymorphic inductive types
that is as lightweight as pair types in \cref{fig:bidir-pair}?
The bidirectional presentation is valuable there, because now
it is clear what the specification of an alternative syntax is:
it should remain complete, in the sense of \cref{thm:comp-cumul}.


\documentclass[main.tex]{subfiles}
\begin{document}

\marginpar{Thursday\\ 2020-8-27, \\ compiled \\ \today}

We then expand the electron and photon energy distributions \emph{after} the scattering up to second order in \(\Delta \): using the fact that \(\epsilon' - \epsilon = \Delta \Theta \) (\(\Delta \) \emph{times} \(\Theta \), not the variation of \(\Theta \)) we find
%
\begin{align}
f(E') &= f(E - \Delta \Theta ) \approx \qty(1 + \Delta + \frac{\Delta^2}{2}) f(E)  \\
n(\epsilon ') &= n( \epsilon + \Delta \Theta ) \approx n(\epsilon ) + \pdv{n}{\epsilon } \Delta \Theta
+ \pdv[2]{n}{\epsilon } \frac{(\Delta \Theta )^2}{2 }
\,,
\end{align}
%
where we have used the explicit expression we have for the thermal distribution \(f(E) \sim e^{- E/ \Theta }\), which gives us a factor \(-1/\Theta\) each we differentiate with respect to \(E\).

If we define the usual rescaled energy \(x = h \nu / k_B T = \epsilon / \Theta \) we can express the latter expansion as
%
\begin{align}
n(x') \approx n(x) + \Delta \pdv{n}{x} + \frac{\Delta^2}{2} \pdv[2]{n}{x}
\,.
\end{align}

We will assume that the medium is \textbf{homogeneous}, \textbf{isotropic} and \textbf{infinite}, and that the photon distribution is \textbf{isotropic}. The latter point means that \(n\) is not a function of \(\Omega \).
This will be close to true as long as the optical depth is large, since then we will see many interactions which will spread the photons.

We can then take out of the Boltzmann integral all the terms depending only on \(n\), since they have no more angular dependence. This yields the following expression (up to second order in \(\Delta \)):
%
\begin{align}
\pdv{n}{t} = \qty[n' + n(n+1)]
\underbrace{\int \dd[3]{p} \dd{\Omega } \dv{\sigma }{\Omega } f(E) \Delta }_{I_1 }
+
\qty[\frac{n''}{2}
+ \qty(n' + \frac{n}{2})
\qty(n+1)]
\underbrace{\int \dd[3]{p} \dd{\Omega } \dv{\sigma }{\Omega }
f(E) \Delta^2 }_{I_2 }
\,.
\end{align}

Here we are denoting \(n' = \pdv*{n}{x}\) for simplicity.
Let us then try to evaluate the integrals \(I_1 \) and \(I_2 \), starting from the latter. It depends on \(\Delta^2\), which is given by
%
\begin{align}
\Delta^2 = x^2 \beta^2 (\vec{\Omega}' - \vec{\Omega})^2 \cos^2 \theta_v
\,,
\end{align}
%
so it evaluates to
%
\begin{align}
I_2 =
\int \dd[3]{p} \dd{\Omega } \dv{\sigma }{\Omega } f(E) \Delta^2
= x^2 \int f(E) p^2 \beta^2 \cos^2 \theta _v \dd{p} \sin \theta _v \dd{\theta _v} \dd{\phi _v} \int \dd{\Omega } \dv{\sigma }{\Omega } (\vec{\Omega}' - \vec{\Omega})^2
\,,
\end{align}
%
where \(\theta _v\) and \(\phi _v\) are the two angles defining the unit vector \(\hat{p}\), so that \(\dd[3]{p} = p^2 \sin \theta _v \dd{p } \dd{\theta _v} \dd{\phi _v}\). We choose them by placing the vector \(\vec{\Omega}' - \vec{\Omega}\) on the \(z\) axis, so that the angle \(\theta _v\) is also the one appearing in \((\vec{\Omega}' - \vec{\Omega}) \cdot \vec{p} = p \abs{\vec{\Omega}' - \vec{\Omega}} \cos \theta _v\).

The angular integrals in \(\dd{\phi _v}\) and \(\dd{\theta _v}\) are standard, while for the integral in the modulus of \(p\) we need to use the actual expression of the Maxwellian: substituting \(\beta = p / mc\) and then \(z= \beta / \sqrt{\Theta }\) we get
%
\begin{align}
I_2
&= 2 \pi x^2m^3 c^3 \frac{2}{3} (2 \pi m k_B T)^{-3/2} n_e
\int_0^{\infty } \dd{\beta } \beta^{4} \exp(- \frac{\beta^2}{2 \Theta })
\int \dd{\Omega } \dv{\sigma }{\Omega } \qty(\vec{\Omega}' - \vec{\Omega})^2 \\
&= 2 \pi x^2m^3 c^3 \frac{2}{3} \Theta^{5/2} (2 \pi m k_B T)^{-3/2} n_e
\underbrace{\int_0^{\infty } \dd{z } z^{4} \exp(- \frac{z^2}{2})}_{= 3 \sqrt{2 \pi } / 2}
\int \dd{\Omega } \dv{\sigma }{\Omega } \qty(\vec{\Omega}' - \vec{\Omega})^2   \\
&= x^2 \Theta n_e
\int \dd{\Omega } \dv{\sigma }{\Omega } \qty(\vec{\Omega}' - \vec{\Omega})^2
\,,
\end{align}
%
so we are left with only the integral in the photon space: in order to evaluate it we need to substitute the expression of the modulus of the difference of the unit vectors and the differential cross section:
%
\begin{align}
\qty(\vec{\Omega}' - \vec{\Omega})^2 = 2 (1 - \cos \theta )
\qquad \text{and} \qquad
\dv{\sigma }{\Omega } = \frac{r_0^2}{2} \qty(1 + \cos^2 \theta )
\,,
\end{align}
%
so, also substituting the explicit expression for the radius \(r_0 \) we get
%
\begin{align}
I_2 &= n_e x^2 \Theta \int \sin \theta \dd{\theta } \underbrace{\dd{\phi }}_{= 2 \pi } \frac{3 \sigma _T}{16 \pi } 2 (1 + \cos^2 \theta ) (1 - \cos \theta )  \\
&= 2 n_e x^2 \Theta \sigma _T \frac{3}{16 \pi } 2 \pi \underbrace{\int_{-1}^{1} (1+\mu^2) (1 - \mu ) \dd{\mu }}_{= 8/3} \\
&= 2 \sigma _T x^2 n_e \Theta
\,.
\end{align}

The integral \(I_1 \) looks similar, and one might try to evaluate it similarly. This turns out to be tricky, and there is a better indirect way to do it.

The photon number density in phase space is given by
%
\begin{align}
\frac{ \dd{N}}{ \dd{V} \dd[3]{p}} = \frac{2}{h^3} n
\,,
\end{align}
%
so, since the momentum of a photon is proportional to its energy and also to \(x = h \nu / k_B T\) we can write
%
\begin{align}
\dv{N}{V} \propto \int_0^{\infty } \dd{x} n x^2
\,.
\end{align}

\todo[inline]{If I'm interpreting this correctly, the slides use \(x\) with two different meanings in the same equation: one is position, and the other is the normalized energy. Really confusing if it is the case.}

Since the medium is assumed to be homogeneous and isotropic, the photon number \emph{density} is conserved: this means that
%
\begin{align}
\dv{}{t} \qty(\dv{N}{V}) = 0
\implies
\dv{}{t} \int_0^{\infty } \dd{x} n x^2 = \int_0^{\infty } \dd{x} \pdv{n}{t} x^2 = 0
\,.
\end{align}

Now, for reasons which will become clear in a moment, we make an assumption: suppose that there is a function \(j(x, t )\) such that the derivative of the photon density can be written as
%
\begin{align}
\pdv{n}{t} = - \frac{1}{x^2} \pdv{[x^2 j(x, t)]}{x}
\,.
\end{align}

If this is the case, then the integral which we have just seen shown to equal zero can be written as
%
\begin{align}
\int_0^{\infty } \dd{x} \pdv{n}{t} x^2  = -\int_0^{\infty } \pdv{[x^2 j(x, t)]}{x}  = \eval{- x^2 j(x, t) }_{0}^{\infty } = 0
\,.
\end{align}

This gives us the boundary conditions for \(j\), which will have to be well-behaved at zero (non diverging) and at infinity (going to zero at least as \(1/x^2\)).
Now, the Boltzmann equation's dependence on \(n\) and its derivatives is in the form
%
\begin{align}
\pdv{n}{t} = C_1 (x ) n'' + C_2 (n, x) n' + C_3 (n, x)
\,,
\end{align}
%
and if we compare this expression with the one which defines \(j\)\footnote{Seeing that
%
\begin{align}
\pdv{n}{t} = - \frac{1}{x^2}
\pdv{[x^2 j(x, t)]}{x}
= - \frac{2j}{x} - \pdv{j}{x}
\,.
\end{align}
%
} we can prove that its dependence on \(n\) and \(x\) looks like
%
\begin{align}
j = g(x) \qty[n' + h (n, x)]
\,,
\end{align}
%
for some functions \(g\) and \(h\). In general \(h\) is a function of both \(n\) and \(x\), but we will assume it only depends on \(n\).

\todo[inline]{Why though? Is there a physical reason for it?}

Now, we substitute this general expression for \(j\) back into the Boltzmann equation: this yields
%
\begin{align}
\begin{split}
&\frac{1}{2} I_2 n'' + \qty[(1+ n) I_2 + I_1 ]n' + \qty(I_1 + \frac{I_2}{2}) n (1+n) =
\\
&\phantom{=}\ = - g(x) n'' - \qty( \frac{2 g(x)}{x} + g(x) \pdv{h}{n} + \pdv{g}{x}) n' - \qty(h \frac{2 g(x)}{x} + g(x) \pdv{h}{x} + h \pdv{g}{x})
\end{split}
\,,
\end{align}
%
from which, identifying the terms, we can recover the expressions for \(g\), \(I_1 \) and \(h\):
%
\begin{align}
g &= - \frac{I_2}{2} = - x^2 n_e \sigma_T \Theta   \\
I_1 &= - 2 \frac{g}{x}  - \pdv{g}{x} - \frac{I_2}{2} = (4-x) x n_e \sigma_T \Theta  \\
h &= n (1 + n)
\,.
\end{align}

This means that the form of \(j\) is
%
\begin{align}
j= g(x) \qty[n' + h (n, x)] = - x^2 n_e \sigma_T \Theta (n' + n + n^2 )
\,,
\end{align}
%
which we can finally substitute into the Kompaneets equation:
%
\begin{align}
\pdv{n}{t} = - c \frac{1}{x^2} \pdv{[x^2 j]}{x}
&= n_e \sigma_T c \frac{\Theta }{x^2} \pdv{[x^{4} (n' +n + n^2)]}{x}  \\
\pdv{n}{t_s} &= \frac{\Theta}{x^2} \pdv{[x^{4} (n' + n + n^2)]}{x}
\,,
\end{align}
%
where we calculate time in units of the mean time between subsequent scatterings, \(T = \frac{1}{n_e \sigma _T c} \), so that \(t_s = t / T\).
\todo[inline]{There is now a \(c\) which was not there before\dots}

This is the \textbf{Kompaneets equation}.
In general this nonlinear equation must be solved numerically, it is an equation of the Fokker-Planck type, whose solution exhibit two main effects:
\begin{enumerate}
    \item drift of the photon distribution to higher energies, this is called the \textbf{secular change}, and is due to the fact that \(I_1 \sim 4 k_B T - h \nu \) (as long as the photons start out with energies lower than \(4 k_B T\));
    \item broadening of the photon distribution, due to random walk effects: this is related to the integral \(I_2 \).
\end{enumerate}

\subsection{Stationary solutions}

We expect that, after the photons have interacted with the medium for a long time, their variation in time will become ever smaller, approaching a stationary solution which will satisfy
%
\begin{align}
0= \pdv{[x^{4} (n' + n + n^2)]}{x}
\,,
\end{align}
%
meaning that
%
\begin{align}
n' + n + n^2 = \frac{A}{x^{4}}
\,.
\end{align}

The constant \(A\) must equal zero, since otherwise the solution will not be regular at zero: recall that \(x^2 j = x^{4 }( n' + n +n^2)\) must vanish at zero and infinity.
Then, we can separate variables in order to integrate \(n' + n + n^2 = 0\): this yields
%
\begin{align}
\log \frac{n}{1 + n} = - x - \mu
\,
\end{align}
%
for a constant \(\mu \),
meaning that
%
\begin{align}
n = \frac{1}{ \exp( x + \mu ) - 1}
\,,
\end{align}
%
which is nice!
We found a Bose-Einstein distribution with an arbitrary chemical potential \(\mu \): photons are at equilibrium with another chemical species.

The reason the photons do not achieve a Planck distribution (which is a Bose-Einstein distribution with \(\mu = 0\)) is that their number must be conserved under our assumptions.

\todo[inline]{To understand better: the chemical potential quantifies how much the (energy?) changes if we change the number of particles, right?}

The Kompaneets equation is a \textbf{parabolic} PDE, like the Fourier heat transport equation.
This means that we need to provide boundary conditions not only in the time domain, but also in the frequency domain for \(x \to 0\) and \(x \to \infty \). We must set the distribution to zero in both regions, in order to avoid photons escaping through the boundary.

If the number of photons we initially insert in the model is smaller than the number of photons which would be contained in a blackbody at that temperature, then the evolution works out smoothly towards the blackbody distribution.

On the other hand, if we insert \emph{more} photons than those which would be contained in the Planckian the numerical solution goes nuts.

\end{document}


\documentclass[Physics.tex]{subfiles}
\begin{document}
\chapter{Superposition}
Superposition is a property of linear systems where the net response at a given point and time caused by two or more stimuli is the sum of the responses which would have been caused by each stimulus individually.

When contextualised to waves, the \sldef{superposition principle} is as such: When two waves of the same kind meet at a point in space, the resultant displacement at that point is the vector sum of the displacements that the two waves would separately produce at that point.
\section{Interference}
\sldef{Interference} is the superposing of 2 or more waves of the same type, interacting according to the principle of superposition. \sldef{Observable interference} is the superposing of 2 or more coherent waves to produce regions of maxima and minima in space, according to the principle of superposition.

\sldef{Coherent sources} are sources with the same frequency and a constant phase difference.

For interference to be observable, the sources must be coherent; the waves must have approximately equal amplitudes, and they must be polarised in the same plane, or unpolarised.

\sldef{Constructive interference} occurs when two or more waves arrive at the screen in phase with each other, such that the amplitude of the resultant wave is the sum of the amplitudes of the resultant waves.

\sldef{Destructive interference} occurs when two or more waves arrive at the screen \(\pi\) out of phase with each other, such that the amplitude of the resultant wave is the minimum possible value.

Interfering waves produce interference patterns with alternating maxima and minima. The zero order maximum is the brightest maximum; if there are multiple maxima with the highest amplitude, the zero order can be chosen as any. Successive maxima away from the 0 order are numbered the 1st, 2nd, 3rd and so on. Minima have the same order as the adjacent maximum away from the 0 order. This means that there is no 0 order minimum.
\subsection{One-source interference i.e. diffraction}
\sldef{Diffraction} is the bending or spreading of waves when they travel through a small opening. It is a special case of interference, and it occurs due to the Huygens-Fresnel principle, where each point along a slit is considered a source of spherical waves.

In diffraction, waves from the Huygens sources interfere with each other and produce a pattern with alternating maxima and minima, with minima at angles \(\theta\) satisfying the equation \begin{equation}a\sin\theta = m\lambda\end{equation} where \(a\) is the slit width and \(m\in\mathbb{Z}^+\) is the order of the minimum.

Generally, diffraction can only be observed when the size of the opening is approximately the same order as the wavelength or smaller.
%
%The intensity \(I\) of a diffraction pattern at distance \(d \propto\sin\theta\) is \[I = I_0\left(\frac{\sin( \pi a\lambda^{-1}\sin\theta)}{\pi a\lambda^{-1}\sin\theta}\right)^2\] where \(a\) is the slit width.
\subsection{Two-source interference}
Two point sources of spherical waves can produce an interference pattern on a screen, with alternating maxima and minima. The zero order maximum occurs at the point on the screen that is equidistant from both sources (assuming the sources are in phase).

The separation between successive maxima is estimated by \begin{equation}\Delta x = \frac{\lambda D}{a}\end{equation} for \(D \gg a\), where \(D\) is the distance from the point sources to the screen, and \(a\) is the separation of the two point sources. If \(D \approx a\) or \(D < a\), then Pythagoras' theorem must be used.

This phenomenon is investigated in Young's double slit experiment, where the two point sources are replaced by a monochromatic source of light passing through a single slit that acts as a point source, followed by a double slit that acts as two coherent point sources and causes light to diffract so that they can overlap and interfere.

For such a setup to produce a visible pattern, the double slits must be small enough for diffraction to occur; the single slit must be small enough so the light reaching the double slits is coherent; and the slit-screen separation must be at least one order larger than the slit separation so that the diffracted waves can overlap and interfere.

The path difference \(\Delta x\) between the two waves reaching a maximum and minimum in two-source interference can be expressed in terms of the order of the maximum \(n\) or minimum \(n\). If the two sources are in phase, then for maxima \begin{align}\Delta x &= n\lambda\\\intertext{and for minima}\Delta x &= (n - \frac{1}{2})\lambda\end{align} and vice versa for sources in antiphase.
%
%The intensity \(I\) of a two-source interference pattern at distance \(d \propto \sin\theta\) is \[I = I_{0}\left(\frac{\pi a\sin\theta}{\lambda}\right)\] \(I_0\) can be expressed in terms of an unknown constant where required.

Two-source interference can be demonstrated with a ripple tank. Two dippers connected to a bar connected to a vibrator are set into vertical vibrations with the same amplitude and frequency and in phase. Each dipper produces circular waves that have the same frequency, which spread out and overlap, interfering constructively and destructively, and an interference pattern where there are points with water waves of maximum amplitude and points with minimum amplitude is formed.

Two-source interference can also be demonstrated with a microwave. Microwaves from a transmitter pass through two slits on an aluminium plate that act as coherent sources of microwaves. Microwaves emerging from the slits diffract and overlap, resulting in constructive and destructive interference. A microwave detector is moved along a line and the current registered will vary alternately from a maximum to a minimum, showing constructive and destructive interference. Since the wavelength of microwaves is about \SI{3}{\centi\metre}, the slit size should be about \SI{3}{\centi\metre}, and the slit separation should be about \SI{30}{\centi\metre}, about \(10\lambda\). The interference can be observed about \SI{1}{\metre} away.
\subsection{Many-source interference}
A \sldef{diffraction grating} is a plate with a large number of parallel, identically spaced slits of the same width. These multiple slits act as multiple coherent sources.

Multiple sources of waves can produce an interference pattern similar to the previous two, with alternating maxima and minima. The zero order beam is the one parallel to the original beam of light.

The angle \(\theta\) from the normal to the grating at which each maximum (or each beam) occurs satisfies the equation \begin{equation}d\sin\theta = m\lambda\end{equation} where \(d\) is the slit separation, and \(m\) is the order of the maximum.

The maximum observable order for a planar screen parallel to the grating occurs at \[0 < \theta < \SI{90}{\degree} \iff \sin\theta < 1\] From the equation above, it can be derived that \begin{equation}m < \frac{d}{\lambda}\end{equation}
\section{Standing waves}
When two waves of the same type, amplitude and frequency travel in opposite directions to each other and overlap, a standing wave will be formed due to superposition.

Standing waves have points where constructive and destructive interference always occurs; they are known as \sldef{antinodes} and \sldef{nodes} respectively. Nodes are halfway between antinodes, and vice versa. Nodes have the minimum amplitude and intensity, while antinodes have the maximum amplitude and intensity.

In stationary waves, each point between consecutive nodes are in phase with each other i.e. they will reach the amplitude and equilibrium at the same time. Points to the between a node and the next node to the left are in antiphase with points between that node and the node to the right.

The distance between consecutive nodes or consecutive antinodes is half the wavelength of the original waves.

Standing waves can be produced when a reflector reflects waves back in the direction they came from. In reality, however, reflected waves will not have the same amplitude, so perfect standing waves are not formed.
%
%The displacement-distance and time graph of a standing wave is given by \(y = 2y_0\sin kx\sin\omega t\), where \(k\) is the wavenumber and \(y_0\) is the amplitude of the original waves. From this equation it can be seen that the amplitude at any point is \(y\prime_0 = 2y_0\sin kx\), where \(x\) is the distance from any node.
\subsection{Harmonics}
A \sldef{harmonic} of a wave is a frequency that is an integer multiple of the fundamental frequency.

Standing waves can be produced with nodes at both ends of the wave. This occurs e.g. in a string fixed at both ends that is then plucked. The longest possible wavelength occurs when the two end nodes are consecutive nodes i.e. the distance \(L\) between the two nodes is half the wavelength. This mode is known as the 1st harmonic or the fundamental. The frequency, which is the fundamental frequency, is then \[f_1 = \frac{v}{2L}\] The next possible standing wave occurs when there is one node between the two end nodes i.e. the distance \(L\) is the wavelength. This mode is the 2nd harmonic or the 1st overtone and has frequency \[f_2 = \frac{v}{L} = 2f_1\] Therefore, the frequency and wavelength of the \(n\)th harmonic or \((n-1)\)th overtone are \begin{align*}f_n &= nf_1\\\lambda_n &= \frac{2L}{n}\end{align*}

Standing waves can be produced with a node at one end and an antinode at the other. This occurs in a sound wave that enters an air column with one end closed, for example. The longest possible wavelength occurs also when the end node and antinode are adjacent i.e. \[L = \frac{1}{4}\lambda\] Thus the 1st harmonic or fundamental \[f_1 = \frac{v}{4L}\] The next possible standing wave occurs when there is one node between the node and antinode i.e. \[L = \frac{3}{4}\lambda\] This is the \emph{3rd} harmonic (since \(f\) is thrice that of \(f_1\)) or 1st overtone; \[f_3 = 3\frac{v}{4L} = 3f_1\] Therefore, the frequency and wavelength of the \(n\)th harmonic or \(\frac{1}{2}(n-1)\)th overtone are \begin{align*}f_n &= nf_1\\\lambda_n &= \frac{4L}{n}\end{align*}

Standing waves can be produced with antinodes at both ends. This occurs in a sound wave that enters an air column open at both ends. The modes of operation for this are identical to standing waves with nodes as ends.

In general, closed ends are usually nodes as particles cannot vibrate there; conversely, open ends are antinodes as particles must vibrate there.

For sound waves, pressure nodes are displacement antinodes, and vice versa. At a pressure node, a microphone or ear will not detect sound as they sense pressure variations, not displacement.

The air at the end(s) of a pipe are generally free to move and so naturally vibrations will extend into the air outside the pipe i.e. the antinode is slightly beyond the open end. The extra length it extends is called the \sldef{end correction}, and it is added to the length of the pipe i.e. \[f_1 = \frac{v}{4(L+e)}\] for a pipe with one open end, and \[f_1 = \frac{v}{2(L+2e)}\] for a pipe open at both ends.
\end{document}


\documentclass[simplex.tex]{subfiles}
% NO NEED TO INPUT PREAMBLES HERE
% packages are inherited; you can compile this on its own

\onlyinsubfile{
\title{NeuroData SIMPLEX Report: Reduced Dimension Clustering}
}

\begin{document}
\onlyinsubfile{
\maketitle
\thispagestyle{empty}

The following report documents the progress made by the labs of Randal~Burns and Joshua~T.~Vogelstein at Johns Hopkins University towards goals set by the DARPA SIMPLEX grant.

%%%% Table of Contents
\tableofcontents

%%%% Publications
\bibliographystyle{IEEEtran}
\begin{spacing}{0.5}
\section*{Publications, Presentations, and Talks}
%\vspace{-20pt}
\nocite{*}
{\footnotesize	\bibliography{simplex}}
\end{spacing}
%%%% End Publications
}

\subsection{Reduced Dimension Clustering}

We develop a new statistical method, named ``automatic repulsive
clustering'' (ARC, to handle the clustering problem when the
dimensionality outgrows the number of the data points. The standard
dimension reduction tool such as principle component analysis (PCA) is
not optimal for finding the subspace best suitable for clustering.
Therefore, we seek the method to do dimension reduction and clustering
at the same time: we develop a regularization to encourage good
separation of the clusters, forcing the subspace to an angle so that
each point can belong to a cluster completely. The plots below shows the
different performances in clustering a equally proportioned 3
components: the subspace found by PCA leads to incorrect clustering of
the data, due to the orientation of the space; whereas ARC successfully
identifies the ideal clustering direction in one dimensional space,
hence generating satisfactory clustering result.

\begin{figure}[h!]
\begin{cframed}
\centering
\includegraphics[width=0.45\textwidth]{./figs/pcaBased.png}
\includegraphics[width=0.45\textwidth]{./figs/ARC.png}
\caption{PCA (left) versus Reduced Dimension Clustering (right).}
\label{fig:arc}
\end{cframed}
\end{figure}

\end{document}


\chapter{PLMath}

\paragraph{Motivation}
The PixelLight math component provides common required tools like vector and matrix classes and therefore implements features, which are especially useful when dealing this 3D graphics.

\paragraph{External Dependences}
PLMath only depends on the \textbf{PLCore} library and doesn't use any external third party libraries.

\section{Transforming 2D to 3D and Reversed}

\paragraph{Overview}
Sometimes it's required to project a 3D world position onto the screen to get the 2D x/y display position of it or you want to find out on which 3D world position a 2D position is on. This can be seen as the interface between the flat 2D screen and the 3D world.

\paragraph{3D to 2D}
\emph{Vector3::To2DCoordinate()} returns the 2D screen coordinate corresponding to a given 3D world coordinate using the given camera settings. This can be useful if you e.g. want to set the mouse cursor over a given 3D object.

\paragraph{2D to 3D}
\emph{Vector3::To3DCoordinate()} returns the 3D coordinate corresponding to a given 2D screen coordinate using the given camera settings. 2D to 3D transformation is extremely useful if you want to perform picking were the user is able to select a 3D object by using the mouse. Because picking is a collision task were we have to find the intersection point of the line (camera position to mouse position) and the meshes, this is not handled in this document. Have a look at the \emph{PixelLight \ac{API} documentation} for more information how to perform picking.

\section{Additional Tool Functions}
\emph{PlaneSet::CreateSelectionPlanes()} takes a 2D start and end point and will return a plane set with the \emph{selection planes}. This plane set can be seen as \emph{selection frustum} and you can test your objects against it to see what's selected and what's not.

% Include the other sections of the chapter
\input{PLMath/GraphsAndPaths}
\cleardoublepage


\section{Coin and Multi-Asset Token algebras}
\label{sec:coin-ma}

In this chapter we introduce the concept of a \emph{Token algebra},
which is an abstraction used to generalize this specification to two
different eras depending on the Token algebra chosen.

\begin{definition}[Token algebra]
  A \emph{Token algebra} is a partially ordered commutative monoid
  $T$, written additively, (i.e. a commutative monoid together with a
  partial order, such that addition is monotonic in both variables)
  together with the functions and properties as described in Figure
  \ref{fig:TokenAlgebra}.
\end{definition}

%%
%% Figure ValMonoid and its Functions
%%
\begin{figure}[htb]
  %
  \emph{Functions}
  %
  \begin{align*}
      & \fun{coin} ~\in~ T \to \Coin\\
      & \text{Return the Ada contained inside the $\mathsf{ValType}$ element}
      \nextdef
      %
      & \fun{inject} ~\in~ \Coin \to T\\
      & \text{Create a $\mathsf{ValType}$ element containing only this amount of Ada}
      \nextdef
      %
      & \fun{policies} ~\in~ T \to \powerset{\PolicyID} \\
      & \text{The set of policy IDs required for minting}
      \nextdef
      %
      & \fun{size} ~\in~ T \to \MemoryEstimate\\
      & \text{Return the size, in words, of a $\mathsf{ValType}$ element}
  \end{align*}
  %
  \emph{Properties}
  %
  \begin{align*}
      & \fun{coin} \circ \fun{inject} = \fun{id}_{\Coin}
  \end{align*}
  \caption{Additional functions and properties required for a Token algebra}
  \label{fig:TokenAlgebra}
\end{figure}

A Token algebra is precisely the structure required to generalize the
$\Coin$ type of the Shelley specification in transaction outputs for
this ledger. We can then describe the ShelleyMA
transaction processing rules without fixing a concrete Token algebra.

Depending on the Token algebra chosen, we obtain distinct ledgers. In
particular, we get

\begin{itemize}
  \item the Allegra ledger rules with $\Coin$, and
  \item the Mary ledger rules with $\Value$ (defined below).
\end{itemize}

When multi-asset support on the ledger is introduced, Ada ($\Coin$) will still be
the most common type of asset on the ledger, as the ledger rules enforce that
some quantity of it (specified via
the $\fun{coinsPerUTxOWord}$ protocol parameter) must
be contained in every UTxO on the ledger.
It is the only
type of asset used for all non-UTxO ledger accounting, including deposits,
fees, rewards, treasury, and the proof of stake protocol. For this reason, not
all occurrences of $\Coin$ inside a transaction or in the ledger state can or
should be replaced by the chosen Token algebra.

Below we give the definitions of all the functions that must be defined on
$\Coin$ and $\Value$ in order for them to have the structure of a Token algebra.
In Section \ref{sec:other-valmonoids} we give several other types which we can meaningfully
support the definition of the required functions (addition, size, etc.), including
an optimized representation that more accurately represents the implementation
used in the Haskell implementation of the multi-asset type.
These types are convertible to and from the $\Value$ type, and appear in other
parts of the system as a multi-asset representation which is more suitable in particular
use cases.

\subsection{$\Coin$ as a Token algebra}

This section defines the Token algebra structure for the $\Coin$ type,
see Figure \ref{fig:coin}. The structure of a partially ordered monoid
is inherited from the (additive) integers.

For $\Coin$, no policies are associated with $\Coin$, since minting of Ada is not allowed.

%%
%% Figure Coin Functions
%%
\begin{figure}[htb]
  \begin{align*}
      & \fun{coin} = \fun{id}_{\Coin}
      \nextdef
      %
      & \fun{inject} = \fun{id}_{\Coin}
      \nextdef
      %
      & \fun{policies}~v = \emptyset
      \nextdef
      %
      & \fun{size}~v = 0
  \end{align*}
  \caption{The Token algebra structure of $\Coin$}
  \label{fig:coin}
\end{figure}

\subsection{Multi-assets and the Token algebra $\Value$}

Elements of $\Value$ represent heterogeneous collections of assets,
both user-defined and Ada. The Mary era ledger uses $\Value$ as its Token algebra
in order to support multi-assets.
$\Value$ and its Token algebra structure are given in Figure \ref{fig:defs:value}.

\begin{figure*}[t!]
  \emph{Derived types}
  %
  \begin{equation*}
    \begin{array}{r@{~\in~}l@{\qquad=\qquad}lr}
      \var{aname} & \AssetName & \mathsf{ByteString} \\
      \var{pid} & \PolicyID & \ScriptHash \\
      \var{adaID} & \AdaIDType & \{~\mathsf{AdaID}~\} \\
      \var{aid} & \AssetID & \AdaIDType \uniondistinct (\PolicyID \times \AssetName) \\
      \var{quan} & \Quantity & \Z \\
      \var{v}, \var{w} & \Value & \AssetID \mapsto_0 \Quantity
    \end{array}
  \end{equation*}
  %
  \emph{Token algebra structure of $\Value$}
  %
  \begin{align*}
    & \fun{coin}~\var{v} = \var{v}~\mathsf{AdaID}
    \nextdef
    %
    & \fun{inject}~c  = \mathsf{AdaID}~\mapsto_0~\var{c}
    \nextdef
    %
    & \fun{policies}~v = \{~\var{pid}~\vert~(\var{pid,~\wcard}) \in \supp v~\}
    \nextdef
    %
    & \fun{size} ~~~ \text{see Section \ref{sec:value-size}}
  \end{align*}
  \caption{$\Value$ and its Token algebra structure}
  \label{fig:defs:value}
\end{figure*}

\begin{itemize}
  \item $\PolicyID$ identifies monetary policies. A policy ID $\var{pid}$ is associated with a script
    $s$ such that $\fun{hashScript}~s=pid$. When a transaction attempts to create or destroy assets
    that fall under the policy ID $\var{pid}$,
    $s$ verifies that the transaction
    respects the restrictions that are imposed by the monetary policy.
    See sections \ref{sec:transactions} and \ref{sec:utxo} for details.

  \item $\AssetName$ is a byte string used to distinguish different assets with the same $\PolicyID$.
    Each $aname$ identifies a particular kind of asset out of all the assets under the
    $\var{pid}$ policy (but not necessarily among assets under other policies).
    The maximum length of this
    byte string is 32 bytes (this is not explicitly enforced in this specification).

  \item $\AssetID$ is either $\mathsf{AdaID}$ or a pair of a policy ID and an asset name.
  It is a unique and permanent
  identifier of an asset. That is, there are is no mechanism to change it or
  any part of it for any assets.

  Mary MA assets are fungible with each other if and only if they have to the same $\AssetID$.
  The reason the unique identifier is a pair of two elements (except for the non-mintable Ada case) is to allow
  minting arbitrary collections of unique assets under a single policy.

  \item $\mathsf{AdaID}$ is a special asset ID for Ada, different than all other asset IDs.
  It is a term of the single-term type $\AdaIDType$.
  It does not include a policy, so instead, the validation outcome in the presence
  of Ada in the $\fun{mint}$ field of the transaction is specified in the UTXO
  ledger rule. The rule disallows the $\fun{mint}$ field to contain Ada.

  \item $\Quantity$ is an integer type that represents an amount of a specific $\AssetName$. We associate
    a $q\in\Quantity$ with a specific asset to track how much of that asset is contained in a given asset value.

  \item $\Value$ is the multi-asset type that is used to represent
    a collection of assets, including Ada. This type is a finitely supported map.

    If $\var{aid}$ is an $\AssetID$ and $v \in \Value$,
    the quantity of assets with that assed ID contained in $v$ is $v~\var{aid}$.
    Elements of $\Value$ are sometimes also referred to as
    \emph{asset bundles}.
\end{itemize}

To give $\Value$ the structure of a partially ordered monoid, we define the
required operations
pointwise, in accordance with the usual definitions of these operations on
finitely supported maps. See Figure \ref{fig:pointwise}.

\begin{figure*}[t!]
  \begin{align*}
    v + w    &= \{~ aid \mapsto v~\var{aid} + w~\var{aid} ~\vert~ \var{aid} \in \fun{dom}~v \cup \fun{dom}~w ~\} \\
    v \leq w &\Leftrightarrow \forall~\var{aid} \in \AssetID, v~\var{aid} \leq w~\var{aid}
  \end{align*}
  \caption{Pointwise operations on Value}
  \label{fig:pointwise}
\end{figure*}

\subsection{Special Ada representation}
Although all assets are native on the Cardano ledger (ie. the accounting and
transfer logic for them is done directly by the ledger), Ada is still treated in a
special way by the ledger rules, and is the most common type of asset on the ledger.
It can
be used for special purposes (such as fees) for which other assets cannot be used.
The underlying consensus algorithm relies on Ada in a way that
cannot be extended to user-defined assets.
Ada can also neither be minted nor burned.

Note that in the $\Value$ definition above, we pick a special asset ID for Ada, that
is not part of the type which represents the asset IDs for all other assets.
Combining the asset name and policy for Ada gives a type-level guarantee that there is exactly
one kind of asset that is associated with it in any way, rather than
deriving this guarantee as an emergent property of minting rules.

Additionally, not giving Ada an actual policy ID
(that could have a hash-associated policy) eliminates the possibility
certain cryptographic attacks.
We sometimes refer to Ada as the primary or principal currency. Ada does not,
for the purposes of the Mary ledger specification, have a $\PolicyID$ or an $\AssetName$.

\subsection{Fixing a Token algebra}

For the remainder of this specification, let $\ValMonoid$ be an
arbitrary but fixed Token algebra. As described above, choosing
$\Coin$ results in the Allegra ledger, and choosing $\Value$ results
in the Mary ledger.


% !TeX root = ../main.tex
% !TEX spellcheck = en_GB

\chapter{Design}
\label{ch:Design}

\section{Matlab models}
\subsection{Speaker}

\subsection{Drive unit}

\subsection{Closed Box}
This modelling is primarily based on \citetitle[chap.~2.6,~p.~49-52]{Elektroakustik}

\subsubsection{Physical parameters}
\begin{itemize}
	\item Volume of box $V_B$
	\item Density of air $\rho_0$ \footnote{\href{https://en.wikipedia.org/wiki/Density_of_air}{Wikipedia, Density of air}}
	\item Speed of sound $c$
\end{itemize}

\begin{equation}
	C_{AB} = \frac{V_B}{\rho c^2}
\end{equation}

\subsection{Crossover filter}

\FloatBarrier


\section{Function objects}
\subsection{Introduction}
\begin{frame}
  \frametitle{Function objects}
  \begin{itemize}
  \item defined in \texttt{<functional>}
  \item[]
  \item comparison criteria
  \item[]
  \item predicates (functions returning \texttt{bool})
  \item[]
  \item arithmetic operations
  \end{itemize}
\end{frame}
\begin{frame}
  \frametitle{Predicates}
  \centering
  \includegraphics[width=0.8\textwidth]{img/predicates.png}
\end{frame}
\begin{frame}
  \frametitle{Arithmetic operations}
  \centering
  \includegraphics[width=0.8\textwidth]{img/arithmetic.png}
\end{frame}

\subsection{Examples}
\begin{frame}[fragile]
  \frametitle{Decreasing sort}
\begin{lstlisting}
#include <algorithm>
#include <vector>
#include <functional>

int main(){
  std::vector<double> v1;
  ...
  std::sort(v1.begin(), v1.end(),
            std::greater<double>{});
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{My comparison}
\begin{lstlisting}
#include <algorithm>
#include <vector>

template <typename num>
struct my_comparison{
  bool operator()(const num& a, const num& b) { return a > b;}
};

int main(){
  std::vector<double> v1;
  ...
  std::sort(v1.begin(), v1.end(),
            my_comparison<double>{});
}
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Lambda}
\begin{lstlisting}
#include <algorithm>
#include <vector>

int main(){
  std::vector<double> v1;
  ...
  std::sort(v1.begin(), v1.end(),
           [](const auto& a, const auto& b)
              { return a>b; } );
}
\end{lstlisting}
\end{frame}