\subsection{Burn}
\label{sec:20Burn}

We continue with the notation and indices from the prior sections.\\
\\
Suppose Bob is the owner of the token commitment $Z_e$ which represents a value of $e$ (denominated in the currency of a particular ERC-20 token).\\
\\
Recall that whilst the token commitment $Z_e$ exists (read: ``is spendable'') within the Shield contract, the Shield contract holds an equivalent value of $e$ `public' ERC-20 tokens; effectively `locked up' in escrow.\\
\\
Suppose Bob (now the owner of $Z_e$ because he knows the secret key $sk_B$) wishes to `release' a value of $e$ ERC-20 tokens from escrow.
Then he will need to effectively `reveal' the contents of his token commitment $Z_e$ in order to convince the Shield contract that he is indeed entitled to withdraw $e$ from escrow.
We call this act of converting from a `private' token commitment back to its `public' counterpart a `\textbf{burn}'.
\\
Note that by burning a token commitment, Bob is revealing information which was previously private; namely, the value $e$. Bob could continue to use an anonymous Ethereum address when calling the `burn' transaction, but analytics of public ERC-20 transactions thereafer will likely eventually reveal that it was Bob who burned $e$. We'll have Bob use his public Ethereum address `burn', for simplicity.\\
\\

\noindent
For Bob to burn $Z_e$ within the Shield contract, under zero knowledge, he follows the steps in Figure~\ref{fig:fBurnAlgorithm}.

\begin{figure}[htp]
  \ContinuedFloat*
	\begin{center}
		\begin{framed}
      \begin{tabular}{p{16cm}}
        \textbf{Fungible burn algorithm} \\
        \\
        \midrule
        \textbf{Bob's steps:}\\
        \begin{enumerate}
          \setcounter{enumi}{\value{ongoingEnumCounter}}
          \item Compute $N_e := h(\;\sigma_e\;|\;sk^Z_B\;)$, the nullifier of Bob's commitment $Z_e$.
          \item Get $\psi_{Z_e}$ -- the sister-path of $Z_e$ -- from the Shield contract (see Details below).
          \item Get the latest Merkle root from the Shield contract: $\roott_{n+m+k+l}$ (see Details below).
          \item Set public inputs $x = (\;e,\;N_e,\;\roott_{n+m+k+l})$
          \item Set private inputs $\omega = (\psi_{Z_e},\;sk_B,\;\sigma_e)$
          \item Select $C_{ft-burn}(\;\omega,\;x\;)$ -- the set of constraints which are satisfied if and only if:
          \begin{enumerate}
            \item $pk_B$ equals $h(\;sk_B\;)$; (Proof of knowledge of the secret key to $pk_B$) (see Details for why $pk_B$ isn't an input to $C$)
            \item $Z_e$ equals $h(\;e\;|\;pk_B\;|\;\sigma_e\;)$ (Proof of the constituent values of $Z_c$)
            (See Details for why $Z_e$ isn't an input to $C$)
            \item $\roott_{n+m+k+l}$ equals $h\br*{\psi_{Z_e}(1)\;|...|\;h\br*{\psi_{Z_e}(d-2)\;|\;h\br*{\psi_{Z_e}(d-1)\;|\;Z_e}\;}...}$ (Proof that $Z_e$ belongs to the on-chain Merkle Tree)
            \item $N_e$ equals $h(\;\sigma_e\;|\;sk^Z_B\;)$ (Proof that $N_e$ is indeed the nullifier of $Z_e$)
          \end{enumerate}
          \item Generate $\pi := P(\;p_C\;,\;x,\;\omega\;)$; a proof of knowledge of satisfying arguments $(\omega, x)\;s.t.\;C(\omega, x) = 1$. Recall: $p_C$ -- the proving key for $C$ -- will be stored on Alice's computer.

          The pair $(\pi, x)$ is the zk-SNARK which attests to knowledge of private inputs $\omega$ without revealing them.
          \item Send $(\pi, x)$ to the Shield contract for verification.

          Using web3: \texttt{fTokenShield.burn(payTo, proof, inputs, vkId)}

          where \texttt{payTo} is an Ethereum address, specified by Bob, into which he wishes for $e$ to be transferred (denominated in the currency of the linked ERC-20 contract).
          %remember where the count (enumi) is up to and store it in ongoingEnumCounter:
          \setcounter{ongoingEnumCounter}{\value{enumi}}
        \end{enumerate}
        \ \\
        \midrule
        \textbf{Shield contract's steps:}\\
        \begin{enumerate}
          %resume counter
          \setcounter{enumi}{\value{ongoingEnumCounter}}
          \item Verify the proof as correct: call a Verifier contract to verify the \texttt{(proof, inputs)} pair against the verification key represented by \texttt{vkId}.
          \setcounter{ongoingEnumCounter}{\value{enumi}}
        \end{enumerate}
        \ \\
        \midrule
        ...
			\end{tabular}
		\end{framed}
	\end{center}
\caption{Fungible Burn Algorithm}
\label{fig:fBurnAlgorithm}
\end{figure}

%continue on next page
\begin{figure}[htp]
  \ContinuedFloat %to continue
	\begin{center}
		\begin{framed}
      \begin{tabular}{p{16cm}}
       \textbf{ Verifier contract's steps:}\\
        \begin{enumerate}
          \setcounter{enumi}{\value{ongoingEnumCounter}}
          \item Compute \texttt{result = verify(proof, inputs, vkId)}.

          I.e. Verify the \texttt{(proof, inputs)} pair against the verification key.
          \item Return \texttt{result}$\in$\texttt{\{false, true\}} to the Shield contract.
          \setcounter{ongoingEnumCounter}{\value{enumi}}
        \end{enumerate}
        \ \\
        \midrule
        \textbf{Shield contract's steps:}\\
        \begin{enumerate}
          \setcounter{enumi}{\value{ongoingEnumCounter}}
          \item If \texttt{result = false}, revert.
          \item Else:
          \begin{enumerate}
            \item Check $\roott_{n+m+k+l}$ is in $\rootsList$. (Revert if not).
            \item Check $N_e$ is not already in its list of `spent' nullifiers. (Revert if not).
            \item Transfer ERC-20 tokens of value $e$ from the Shield contract (which has been holding the value in escrow) to Bob's \texttt{payTo} Ethereum address.
            \item Append the nullifier $N_{e}$ to the ever-increasing array $\bm N$.
          \end{enumerate}
          \setcounter{ongoingEnumCounter}{\value{enumi}}
        \end{enumerate}
        \ \\
        \midrule
        \textbf{Bob's steps:}\\
        \begin{enumerate}
          \setcounter{enumi}{\value{ongoingEnumCounter}}
          \item Check the ERC-20 contract to ensure his balance has increased by $e$.
          \item Store any relevant data in his local database.
          \setcounter{ongoingEnumCounter}{0} %reset for next figure
        \end{enumerate}
			\end{tabular}
		\end{framed}
	\end{center}
\caption{Fungible Burn Algorithm} %same caption as the first part of this figure
%\label{fig:nfTransferAlgorithm} - no label in this second part of the figure
\end{figure}

\newpage
\subsubsection{Details}
\label{sec:20BurnDetails}

We refer to the numbered steps of Figure~\ref{fig:fBurnAlgorithm}.\\
\\

\textbf{Step $1$}
\ \\
This is handled within \hyperref[sec:f-token-controller]{\texttt{f-token-controller.js}}.\\
\\

\textbf{Steps $2 - 3$}
\ \\
These calls to the Shield contract are handled within \hyperref[sec:f-token-zkp]{\texttt{f-token-zkp.js}}.\\
\\
\noindent
It is important at this stage to note that there are an unknown number of other parties utilising the Shield smart contract.
Hence, the dynamic array of tokens $\bm{Z}$ might have grown since Alice appended Bob's $Z_e$ and Alice's $Z_f$ as the $(n+m)^{th}$ and $(n+m+1)^{th}$ leaves of $M$.
Suppose there have been $l-1$ additional tokens added to $\bm{Z}$ since then.
That is,\\
\begin{align*}
  \bm{Z}_{n+m+k-1} = (Z_0, Z_1,...,Z_{n-1}, Z_c, ..., Z_{n+m-1}, Z_d,..., Z_{n+m+k-1}, Z_e, Z_f, Z_{n+m+k+2}, ... Z_{n+m+k+l})
\end{align*}

\noindent
We denote the corresponding Merkle Tree which holds tokens $\bm{Z}_{n+m+k+l}$ by $M_{n+m+k+l}$. We denote its root by $\roott_{n+m+k+l}$; an element of $\rootsList$.

\begin{align*}
  \scalebox{0.85}{
    \begin{forest}
      [{$\roott_{n+m+k+l}:= h\br*{
                          h\br*{
                            h\br*{
                              h\br*{
                                Z_0,Z_1
                              },
                              ...
                            },
                            h\br*{
                              h\br*{
                                Z_{n-1},Z_c
                              },
                              h\br*{
                                ...,Z_{n+m-1}
                              }
                            }
                          },
                          h\br*{
                            h\br*{
                              h\br*{
                                Z_d, ...
                              },
                              h\br*{
                                Z_{n+m+k-1}, Z_e
                              }
                            },
                            h\br*{
                              h\br*{
                                Z_f, ...
                              },
                              h\br*{
                                Z_{n+m+k+l}, 0
                              }
                            }
                          }
                        }
                      $}
        [{$ h\br*{
              h\br*{
                h\br*{
                  Z_0,Z_1
                },
                ...
              },
              h\br*{
                h\br*{
                  Z_{n-1},Z_c
                },
                h\br*{
                  ...,Z_{n+m-1}
                }
              }
            }
          $}
          [{$ h\br*{
                h\br*{
                  Z_0,Z_1
                },
                ...
              }
            $}
            [{$ h\br*{
                  Z_0,Z_1
                }
              $}
              [{$Z_0$}][{$Z_1$}]
            ]
            [...
              [...][...]
            ]
          ]
          [{$ h\br*{
                h\br*{
                  Z_{n-1},Z_c
                },
                h\br*{
                  ...,Z_{n+m-1}
                }
              }
            $}
            [{$ h\br*{
                  Z_{n-1},Z_c
                }
              $}
              [{$Z_{n-1}$}][{$Z_c$}]
            ]
            [{$ h\br*{
                  ...,Z_{n+m-1}
                }
              $}
              [...][{$Z_{n+m-1}$}]
            ]
          ]
        ]
        [{$ h\br*{
              h\br*{
                h\br*{
                  Z_d, ...
                },
                h\br*{
                  Z_{n+m+k-1}, Z_e
                }
              },
              h\br*{
                h\br*{
                  Z_f, ...
                },
                h\br*{
                  Z_{n+m+k+l}, 0
                }
              }
            }
          $}
          [{$ h\br*{
                h\br*{
                  Z_d, ...
                },
                h\br*{
                  Z_{n+m+k-1}, Z_e
                }
              }
            $}
            [{$ h\br*{
                  Z_d, ...
                }
              $}
              [{$Z_d$}][...]
            ]
            [{$ h\br*{
                  Z_{n+m+k-1}, Z_e
                }
              $}
              [{$Z_{n+m+k-1}$}][{$Z_e$}]
            ]
          ]
          [{$ h\br*{
                h\br*{
                  Z_f, ...
                },
                h\br*{
                  Z_{n+m+k+l}, 0
                }
              }
            $}
            [{$ h\br*{
                  Z_f, ...
                }
              $}
              [{$Z_f$}][...]
            ]
            [{$ h\br*{
                  Z_{n+m+k+l}, 0
                }
              $}
              [{$Z_{n+m+k+l}$}][0]
            ]
          ]
        ]
      ]
    \end{forest}
  }
\end{align*}

\noindent
Bob retrieves the value of the current Merkle root, $\roott_{n+m+k+l}$, from the Shield contract.\\
\\
Since Bob knows that $Z_e$ is at leaf-index $n+m+k$ of $M_{n+m+k+l}$, Bob can also retrieve the path from the leaf $Z_{n+m+k}=Z_e$ to the root $\roott_{n+m+k+l}$. Path computations are done in \texttt{zkp/src/compute-vectors.js}.\\
\\
We denote this path
\begin{align*}
  \phi_{Z_e} = [\phi_{d-1}, \phi_{d-2},..., \phi_{1}, \phi_0]
\end{align*}
Note that $\phi_0 = \roott_{n+m+k+l}$.\\
\\
Bob also retrieve's the `sister-path' of this path:
\begin{align*}
  \psi_{Z_e} = [\psi_{d-1}, \psi_{d-2},..., \psi_{1}, \psi_0]
\end{align*}
where $\psi_0 = \phi_0 = \roott_{n+m+k+l}$.\\
\\
For ease of reading, let's focus only on the nodes of $M_{n+m+k+1}$ which Bob cares about for the purposes of burning his token commitment $Z_e$:

\begin{align*}
  \scalebox{0.85}{
    \begin{forest}
      [{$\roott_{n+m+k+l}:= \phi_{0} = \psi_{0}$}
        [{$\psi_{1}$}
          [...
            [...
              [...][...]
            ]
            [...
              [...][...]
            ]
          ]
          [...
            [...
              [...][...]
            ]
            [...
              [...][...]
            ]
          ]
        ]
        [{$\phi_{1}$}
          [{$\phi_{2}$}
            [{$\psi_{3}$}
              [...][...]
            ]
            [{$\phi_{3}$}
              [{$\psi_{4}$}][{$Z_e$}]
            ]
          ]
          [{$\psi_{2}$}
            [...
              [...][...]
            ]
            [...
              [...][0]
            ]
          ]
        ]
      ]
    \end{forest}
  }
\end{align*}

\noindent
Equipped with $\psi_{Z_e}$, Bob can prove that he owns a token commitment at one of the leaves of $M_{n+m+k+l}$, without revealing that it is "$Z_{n+m+k}$ located at leaf-index $n+m+k$".\\
\\

\textbf{Steps $4-5$}
\ \\
These steps are handled within \hyperref[sec:f-token-controller]{\texttt{f-token-controller.js}}.\\
\\
As a reminder, we let:
\begin{center}
  \begin{tabular}{l l}
    $x = (e,\
          N_{e},\
          \roott_{n+m+k+l})$ & Public Inputs used to generate the Proof\\
    $\omega = (\psi_{Z_e},\
              sk_B,\
              \sigma_e)$ & Private Inputs used to generate the Proof\\
  \end{tabular}
\end{center}
\ \\

\textbf{Steps $6 - 7$}
\ \\
These steps are handled within a \hyperref[sec:zokrates]{ZoKrates} container.\\
\\
Bob uses the $C_{ft-burn}$ (or $C$) -- the set of constraints for a fungible burn, located in \texttt{zkp/code/gm17/ft-burn} (see \hyperref[sec:trustedSetup]{Trusted Setup}). $C_{ft-burn}(\;\omega,\;x\;)$ returns a value of $true$ if Bob provides a set of valid `satisfying' arguments $(\omega, x)$ to $C$.\\
\\
Let's elaborate on each of the checks and calculations constraining the inputs to $C$ (we highlight public inputs in \textbf{bold} below):
\begin{enumerate}
  \item Calculate $h(sk_B) =: pk_B'$.\\
    Note that this newly calculated $pk_B'$ should equal $pk_B$ (Bob's public key), but we don't need to pass $pk_B$ as a private input and explicitly check that $pk_B'=pk_B$; a check on the correctness of $sk_B$ (and hence $pk_B'$) is implicitly achieved in the next two steps:
  \item Calculate $h(\bm{e}\;|\;pk_B'\;|\;\sigma_e) =: Z_e'$.\\
    Note again that this newly calculated $Z_e'$ should equal $Z_e$ (Bob's token commitment), but we don't need to pass $Z_e$ as a private input and explicitly check that $Z_e'=Z_e$; a check on the correctness of $Z_e$ (and hence $Z_e'$) is implicitly achieved in the next step:
  \item Check inputs $\psi_{Z_e}=[\psi_{d-1}, \psi_{d-2},..., \psi_{1}, \bm{\psi_{0}=\roott_{n+m+k+l}}]$ and the newly calculated $Z_e'$ satisfy:\\
    $h\br*{\psi_{1}\;|...|\;h\br*{\psi_{d-2}\;|\;h\br*{\psi_{d-1}\;|\;Z_B'}\;}...} = \roott_{n+m+k+l} ( =: \bm{\psi_{0}})$\\
    Given the one-way nature of our hashing function $h$, the only feasible way we could have arrived at the correct value of $\roott_{n+m+k+l}$ is if the sister-path $\psi_{Z_e}$ is correct, and if $Z_e'$ is correct, which (working backwards) must mean that $sk_B$ is correct.

    How does the circuit know the value of $\roott_{n+m+k+l}$ is correct? It doesn't; but it is a `public input', and we can rely upon the Shield smart contract to check the correctness of all public inputs.\\
  \\
  We've therefore shown in the steps so far, that:
  \begin{itemize}
    \item[--] Bob is the owner of a token commitment (because he knows its secret key)
    \item[--] Said token commitment is indeed a leaf of the on-chain Merkle Tree $M_{n+m+k+l}$.
    \item[--] The token commitment does indeed represent a value of $e$ ERC-20 tokens (remember that $e$ is a public input to a `burn' zk-SNARK).
  \end{itemize}

  Bob commits to burning his token $Z_e$ in the next step:
  \item Check inputs $\sigma_e, sk_B, \bm{N_e}$ satisfy:
    $h(\sigma_e\;|\;sk_B) = \bm{N_e}$\\
    $N_e$ is referred to as a `nullifier' because it is understood by all participants to be an indisputable commitment to spend (`nullify') a token commitment. Remember that the token commitment being spent isn't revealed; the earlier steps have allowed Bob to demonstrate hidden knowledge of the secret key $sk_B$ of a token commitment which does indeed exist. By including $sk_B$ in the nullifier's preimage, Bob is binding himself as the executor of this `burn'. By including $\sigma_e$, Bob is specifying a serial number which is unique to the token $Z_e$ (thereby distinguishing this nullifier from those which would nullify any other token commitments he may own).
\end{enumerate}
Notice how each stage is linked to the last, and that at each of the `Check' stages, private inputs are being reconciled against at least one public input (highlighted in \textbf{bold} to help you notice). By structuring the circuit $C$ in this way, we are able to share only the public inputs with the Shield contract (along with a `proof' $\pi_{C,x,\omega}$). We'll see shortly that the Shield contract checks the correctness of each of the public inputs against its current states.\\
\\

\noindent
If all of the above constraints are satisfied by the public and private inputs, ZoKrates will generate the proof $\pi_{C,x,\omega}$; a proof of knowledge of satisfying arguments $(\omega, x) \ s.t. \ C(\omega, x) = 1$.\\
\\

\textbf{Step $8$}
\ \\
This transaction is handled within \hyperref[sec:f-token-zkp]{\texttt{f-token-zkp.js}}.\\
\\
Having generated $\pi_{C,x,\omega}$, Bob then sends the following to the Shield contract from his Ethereum address $E_B$:
\begin{align*}
  &E_B\\
  &\pi_{C,x,\omega}\\
  &x = (e, N_{e}, \roott_{n+m+k+l})
\end{align*}
\\
Recall that everyone knows the checks and calculations which have been performed in the circuit $C_{ft-burn}$, because it is a public file in the Nightfall repository. Further, everyone knows the verification key $vk_C$ which uniquely represents this circuit, because it has been publicly stored in the Verifier Registry contract. Therefore, when Bob shares the pair $(x, \pi_{C,x,\omega})$, and the `unique id' of the relevant verification key $vk_C$; everyone will interpret this information as the Bob's intention to burn; and everyone will be convinced that he knows the secret key which permits him to transfer ownership of a token commitment; and everyone will be convinced that that token commitment represents a value of $e$ ERC-20 tokens.\\
\\

\textbf{Steps $9 - 11$}
\ \\
The Verifier Registry contract already has stored within it the verification key $vk_C$.
It runs a verification function $V(vk_C, \pi_{C,x,\omega}, x)$.
\begin{align*}
  V: (vk_C, \pi_{C,x,\omega}, x) \to \{0,1\}
\end{align*}
where:
\[
    V=
\begin{cases}
    1,& \text{if } \pi_{C,x,\omega} \text{ and } x \text{ satisfy } vk_C\\
    0,& \text{otherwise}
\end{cases}
\]
\ \\

\textbf{Steps $12 - 13$}
\ \\
If the Verifier contract returns $1$ ($true$) (verified) to the Shield contract, then the Shield contract will be satisfied that Bob's proof and public inputs represent his commitment to burning a token commitment, and to withdrawing its underlying ERC-721 token $=\alpha$. If the Verifier contract returns $0$, then the transaction will revert.\\
\\
Let's suppose Bob's $(x, \pi_{C,x,\omega})$ pair is verified.\\
\\
Following verification of the proof, the Shield contract will do the following:
\begin{enumerate}
  \item Check $\roott_{n+m+k+l}$ is in $\rootsList$.\\
    (If not, the burn will fail)
  \item Check $N_e$ is not already in the list of nullifiers, which we denote $\bm{N}$.\\
    (If $N_e$ is already in $\bm{N}$, the burn will fail)
  \item Transfer a value of $e$ ERC-20 tokens from the Shield contract (i.e. from escrow) to Bob's Ethereum address.
  \item Append the nullifier $N_e$ to the ever-increasing array $\bm N$.
\end{enumerate}
\ \\

\textbf{Steps $14 - 15$}
\ \\
Bob is now the owner of $e$ more ERC-20 tokens. The Nightfall UI queries the linked ERC-20 contract for tokens Bob owns.
If Bob ever wished to convert some or all of this value back into a token commitment, he would need to do a fungible `mint' (discussed earlier).


\section{Models for the Microconnectome}
In this section, we study the Random Graph models with regards to how well they capture the various properties of the Bio-M MC. We fit the parameters of the Random Graph models to the Bio-M MC.
\subsection{\ER Model}
\subsubsection{Construction}
As a starting point for the modelling of the MC, we first construct the \ER random graph model. To be consistent with the statistics of the Bio-M MC, we restricted this model to contain 31,346 neurons and approximately 8 million synaptic connections. To achieve this for the \ER random graph model, we set each potential connection between any pair of neurons to be ~0.8\%, that is;

\begin{equation}
    P(e) =\frac{|\textrm{E}|}{|\textrm{V}|^{2}} = \frac{7,822,274}{31,346^2} \approx 0.8\%
\end{equation}
where e is an edge, $|E|$ is the total number of connections and $|V|$ is the total number of neurons in the Bio-M MC. We typically let the vertex set of labelled neurons to be $V = \{0, 1, 2, \dots, |V|-1\}$

\begin{algorithm}[H]
\SetAlgoLined
\SetKwInOut{Input}{Input}
\SetKwInOut{Output}{Output}
\Input{Vertex Set V, $p \leftarrow 0.008$, random number generator \textit{r} $\in[0, 1)$}
\Output{Adjacency Matrix $M$}
\Init{}{
$M[i,j] \leftarrow 0~~\forall~ (i,j) \in V \times V$}
\ForEach{$i,j \in V \times V$}{\If{r $<$ p}{M[i,j] $\leftarrow$ 1}}
\caption{$\mathcal{G_{ER}} (V, p, r)$}
\end{algorithm}

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{ER/matrix_Erdos-Renyi.png}
\caption{Sample output from the \ER model based on the statistics of the Bio-M MC}
\end{center}
\end{figure}
\subsubsection{Block Layout}
Given that each neuron pairing has an equal probability of connecting, it is unsurprising that a sample from $\mathcal{G}_{ER}$, shown in Figure 10, gives a uniform distribution of connections contained within each block. To illustrate this fact further, in Figure 11, we see each block contains approximately $0.8\%$ of the total potential connections within that block. This type of illustration where we speak purely in terms of the number of potential connections in each block is dealt with for this model only. The subsequent models in later sections will deal with Block-wise Edge Densities with respect to the proportion of connections observed in the functional graph created by the Bio-M MC. We look at this for the \ER model now.
Now, given the distribution of edges in the blocks of the MC, it becomes clear that the block sizes are unequal. We can see this clearly from and 12(b), where we observe that each block contains a varying number of connections, ranging from around 900 to 1.2 million connections. Figure 12(a) gives the Block-wise Edge Densities. A breakdown of the TV distance of the Block-wise edge densities from the Bio-M MC can be found in section 6.4.
\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=9cm]{ER/heat_map_layer_Erdos-Renyi probability.png}
\caption{Density of edges in each block: $\frac{\text{Edges in block}}{\text{Total number of potential edges}}$}
\end{center}
\end{figure}

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Block-wise Edge Densities ]{{\includegraphics[width=7cm]{ER/heat_map_layer_er_test.png} }}%
    \qquad
    \subfloat[\centering Block-wise Edge Counts]{{\includegraphics[width=7cm]{ER/heat_map_layer_Erdos_Renyi.png} }}%
    \caption{Connectivity by block of a random graph $\mathcal{G}_{ER}$ given by the \ER model}%
    \label{fig:example}%
\end{figure}

\subsubsection{Distance distributions}
To get an idea of the distribution of distances between neurons under the \ER model, we superimposed it onto that of the functional graph of the Bio-M MC. We computed the pairwise distances of the indexed neurons and plotted the histogram to represent these connections against what it was for the Bio-M MC in Figure 13. A metric that we use to ascertain differences here, is that of the TV distance, described in mathematical preliminaries, between the \ER model and the Bio-M MC. Here, briefly, we can state that, over 100 realisations, the mean TV distance between the \ER model and the Bio-M MC is 0.7092. This is the highest distance between a model and the MC described here. Further details about this statistic are to be found in Section 6, Results.
\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=9cm]{ER/Erdos_Renyi_dist_distr.png}
\caption{Distance distribution of connected neurons for the random graph $\mathcal{G}_{ER}$ \\if they were superimposed onto functional graph of the Bio-M MC}
\end{center}
\end{figure}

\subsubsection{Signed Degree of Neurons}
One noteworthy difference between the \ER random graph model and all the other models, as can be seen from the cumulative signed degree graphs in Figure 14, is that each neuron does not maintain the same in-degree and out-degree as that of the Bio-M MC and therefore all of our other models that preserve the in-degree and out-degree of the Bio-M MC.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Realisation 1 ]{{\includegraphics[width=7cm]{ER/cumsum_degree_Erdos-Renyi.png} }}%
    \qquad
    \subfloat[\centering Realisation 2]{{\includegraphics[width=7cm]{ER/cumsum_degree_Erdos-Renyi1.png} }}%
    \qquad
    \subfloat[\centering Realisation 3]{{\includegraphics[width=7cm]{ER/cumsum_degree_Erdos-Renyi2.png}}}%
    \qquad
    \subfloat[\centering Realisation 4]{{\includegraphics[width=7cm]{ER/cumsum_degree_Erdos-Renyi3.png}}}
    \caption{Realisations of the Cumulative Signed Degree for \ER random graph model}%
    \label{fig:example}%
\end{figure}

\newpage

%--------------------------------------
%--------------------------------------
%--------------------------------------
\subsection{Configuration Model}
This model reconnects the Bio-M MC using the ``cut-permute-rewire'' algorithm proposed by Watts and Strogatz \cite{WattsStrogatz1998}.

\subsubsection{Construction}
We use the ``cut-permute-rewire'' algorithm to produce samples from $\mathcal{G}_{C}$, the Configuration random graph model. This model outputs the rewired neurons by a  resampling of the connected directed edges of the Bio-M MC. By restricting ourselves to the constraints of the algorithm, this model will be able to retain the same in-degree and out-degree for each vertex as the Bio-M MC. One difference to the Bio-M MC and the General Biological model (mentioned later) however, is that we exhibit multiple connections that occur between a pair of neurons that traverse in the same direction. We allow these connections to exist so as to ensure that each neuron does indeed maintain its in-degree and out-degree. This occurs for the subsequent three models as well, namely the Geometric Configuration model, the Block Configuration model and the Block Geometric Configuration model.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Before configuration of small network]{{\includegraphics[width=7cm]{configuration/config_before_rewire.png} }}%
    \qquad
    \subfloat[\centering After configuration of network]{{\includegraphics[width=7cm]{configuration/config_after_rewire.png} }}%
    \caption{Example of a configuration of a small version of the network}%
    \label{fig:example}%
\end{figure}

\begin{algorithm}[H]
\DontPrintSemicolon
\SetAlgoLined
\SetKwInOut{Input}{input}
\SetKwInOut{Output}{output}
\SetKwData{$E$}{$(u, v)$}
\Input{$u$, $v$}
\Output{Adjacency Matrix $M$}
\Init{}{$u \leftarrow$ Shuffle($u$)\\
$M[i,j] \leftarrow 0~\forall (i,j) \in [u][v]
$}

\ForEach{$(i,j) \in [u][v]$}
{\eIf{$i \neq j$}{$M[i,j] \leftarrow 1$}{$u \leftarrow$ Shuffle($u$)}}
\caption{$\mathcal{G_{C}}$(u, v)}
\end{algorithm}

For the ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm to run, we first take the ordered set of edges in E, where we assign, for each $e \in E$, $\tau_1(e) = v_1$ as the pre-synaptic neurons represented by $u$ in Algorithm 2, and assign $\tau_2(e) = v_2$ as the post-synaptic neurons, represented as $v$ in Algorithm 2. We then initialise the algorithm by shuffling the order of $u$ so as to obtain a permutation of $u$, the pre-synaptic neurons. We then attempt to connect each vertex pairing providing we do not have the same vertex, that is $i \neq j$, to avoid self-loops. If we happen upon an occurrence of this, then we reshuffle the remaining vertices in $u$ and continue. Upon completion, we acquire a new ordered set of vertices contained in $u^\prime$. With this new ordered set of vertices in $u^\prime$, and the vertices in $v$, we can then form the adjacency matrix M that represents a realisation of the random graph model $\mathcal{G}_{C}$.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{configuration/matrix_configuration.png}
\caption{Adjacency matrix representing a realisation of the random graph $\mathcal{G}_{C}$}
\end{center}
\end{figure}
\subsubsection{Block Layouts}
In Figure 17, we have a breakdown of the Block-wise Edge connections, both in terms of counts and in terms of density of connections within the functional graph. The density of connections concerning layer 1 amount to less than $1\%$ of all connections in a realisation of the random graph model $\mathcal{G}_{C}$ of the MC. Similarly, in relation to the structure of the Bio-M MC functional graph, the highest number of connections occur in the self-contained block of layer 6 to layer 6. Further statistics on the TV distance of the Block-wise Edge densities between the models can be found in Section 6, Results.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Block-wise Edge Densities]{{\includegraphics[width=7cm]{configuration/heat_map_layer_c_test.png} }}%
    \qquad
    \subfloat[\centering  Block-wise Edge Counts]{{\includegraphics[width=7cm]{configuration/heat_map_layer_configuration.png} }}%
    \caption{Connectivity by block of the random graph $\mathcal{G}_{C}$ given by the Configuration Model}%
    \label{fig:example}%
\end{figure}
\subsubsection{Distance Distributions}
In Figure 18, we can also see a similar distance distribution as to that of the \ER model. As mentioned for the \ER model, we have a TV distance to the Bio-M MC. For the Configuration model, this is 0.6595. This is an improvement on the TV distance given by the \ER model. Further details are given in the Results section.
\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{configuration/configuration_dist_distr.png}
\caption{Distance distribution of connected neurons for the random graph $\mathcal{G}_C$}
\end{center}
\end{figure}
\subsubsection{Signed Degree of Neurons}
From Figure 19, we see that the each neuron has maintained its in-degree and out-degree thereby following the constraints of the ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm.
\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Signed degree of each neuron ]{{\includegraphics[width=7cm]{configuration/configuration_sd.png} }}%
    \qquad
    \subfloat[\centering Cumulative sum of the Signed Degree of the neurons in a realisation of the random graph $\mathcal{G}_{C}$]{{\includegraphics[width=7cm]{configuration/cumsum_degree_configuration.png} }}%
    \caption{Neuron Statistics for a realisation of the random graph $\mathcal{G}_C$}%
    \label{fig:example}%
\end{figure}

%-------------------------------------
%-------------------------------------
%-------------------------------------
\newpage
\subsection{Geometric Configuration Model}
We introduce the Geometric Configuration (GC) model here. This model uses the distances between the connected neurons in the Bio-M MC. The GC model applies the ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm to the connected neurons in the Bio-M MC, whilst also considering a geometric constraint of their distances from one another.
\subsubsection{Construction}
The GC model is a variation of the Configuration model. This model has the added constraint that we must also take into account the locations of the neurons, in particular their pairwise distances, involved in the Bio-M MC. In Algorithm 3, we use a probability value p, that is determined by the distance distribution given in Figure 8.

\begin{algorithm}[H]
\SetAlgoLined
\SetKwInOut{Input}{input}
\SetKwInOut{Output}{output}
\SetKwData{$E$}{$(u, v)$}
\Input{$u$, $v$, $p$, random number generator $r$}
\Output{Adjacency Matrix $M$}
\Init{}{$u \leftarrow$ Shuffle($u$)\\
$M[i,j] \leftarrow 0~\forall (i,j) \in [u][v]
$}

\ForEach{$(i, j) \in [u][v]$}
{\eIf{$i \neq j$ \textbf{and} $r < p$}
{$M[i,j] \leftarrow 1$}
{$u \leftarrow$ Shuffle($u$)}}
\caption{$\mathcal{G}_{GC}$(u, v, p) using cut-permute-rewire}
\end{algorithm}

\begin{figure}[H]
\begin{center}
\includegraphics[width=12cm]{GC/gc_example.png}
\caption{Example of a collection of neurons and their varying probabilities of connection with neuron 2}
\end{center}
\end{figure}
As a note on the random graph model $\mathcal{G}_{GC}$, we compute the pairwise distance between each pair of vertices in E, whereby we obtain the distance distribution shown in Figure 8. This distribution shows the absolute counts of pairwise distances between neurons. This is then normalised to be used as the empirical probability distribution for connection probability between two neurons based on their pairwise distance.
There are occasions whereby a pair of neurons may contain multiple connections heading in the same direction and that these are included in order to make sure we maintain the same in-degree and out-degree for each neuron.
\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{GC/matrix_GC.png}
\caption{Adjacency matrix M of a realisation of the random graph $\mathcal{G}_{GC}$}
\end{center}
\end{figure}
\subsubsection{Block Layouts}
Figure 22 gives the breakdown of Block-wise Edge connections, again, both in terms of counts and in terms of densities of the functional graph. Once again, we can see a small proportion of edges are contained in layer 1 and that the vast majority of edges are within layer 6. The TV distance of the Block-wise Edge densities resulted in a similar distribution of values to the Configuration Model relatively speaking. However, the vast majority of blocks here observed smaller TV distances than the Configuration Model, by a factor of 10 or more. Further details can be found in Section 6, Results.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Block-wise Edge Densities]{{\includegraphics[width=7cm]{GC/heat_map_layer_gc_test.png} }}%
    \qquad
    \subfloat[\centering Block-wise Edge Counts]{{\includegraphics[width=7cm]{GC/heat_map_layer_GC.png} }}%
    \caption{Connectivity by block of the random graph $\mathcal{G}_{GC}$ given by the GC Model}%
    \label{fig:example}%
\end{figure}
\subsubsection{Distance Distribution}
We have a comparison of the distance distributions for a realisation of the Geometric Configuration model and the Bio-M MC in Figure 23. We see from this graph that the TV distance is much lower here than with the \ER model and the Configuration model, with a mean TV distance of 0.3169 after 100 realisations. This is to be expected given the construction of this model. More details of this statistic are found in section 6, Results.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{GC/GC_dist_distr.png}
\caption{Distance distribution of connected neurons for the random graph $\mathcal{G}_{GC}$}
\end{center}
\end{figure}

\subsubsection{Signed Degree of Neurons}
Figure 24 shows us that the in-degree and out-degree has been maintained, thereby showing that again the constraints of the  ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm have been followed and that the graph representing the network is indeed finite.
\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Signed degree for each neuron ]{{\includegraphics[width=7cm]{GC/GC_sd.png} }}%
    \qquad
    \subfloat[\centering Cumulative sum of the Signed Degree of the neurons in a realisation of the random graph $\mathcal{G}_{GC}$]{{\includegraphics[width=7cm]{GC/cumsum_degree_GC.png} }}%
    \caption{Neuron statistics for the random graph $\mathcal{G}_{GC}$}%
    \label{fig:example}%
\end{figure}

\newpage
\subsection{Block Configuration Model}
In this section, we describe the Block Configuration model. This model uses the biological constraint of splitting up the MC into blocks comprising pre-synaptic neurons in a layer, say $i$, to post-synaptic neurons in a layer, say $j$ and using the ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm in each block so that the layer-specific in-degrees and out-degrees for each neuron in each block is preserved, thereby seeing to it that this also remains the case for the entire random graph $\mathcal{G}_{BC}$.

\subsubsection{Construction}
The Block Configuration model is a hybrid of both the General Biological model (discussed later) and the Configuration model. This model divides up the connectome by layer rather than by morphological type, as was the case in the General Biological model and uses the ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm.

The construction process of the Block Configuration model begins with dividing up the MC into its 25 blocks, as shown in Figure 6. This means that we take a subset of vertices V and edges E from the Bio-M MC for each block. For each subset, we apply Algorithm 2. The resulting ordered sets $u^\prime$ and $v$ are then stored until the algorithm has been applied to all 25 blocks. On completion, these 25 blocks containing the ordered sets of vertices, are then used to construct a realisation of the random graph $\mathcal{G_{BC}}$.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{BC/matrix_Block_Configuration.png}
\caption{Adjacency Matrix M representing a realisation of the random graph $\mathcal{G}_{BC}$}
\end{center}
\end{figure}

\subsubsection{Block Layouts}
Given that we have subdivided the MC into 25 blocks on a layer by layer basis, the number of edges contained in each block will be precisely the same as the Bio-M MC. This is shown in Section 6, where we detail the TV distance for Block-wise Edge densities between this model and the Bio-M MC. Likewise with the Configuration Model and the Geometric Configuration Model previously, we observe pairwise neurons with multiple connections in the same direction.
\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Block-wise Edge Densities]{{\includegraphics[width=7cm]{BC/heat_map_layer_bc_test.png} }}%
    \qquad
    \subfloat[\centering Block-wise Edge Counts ]{{\includegraphics[width=7cm]{BC/heat_map_layer_Block.png} }}%
    \caption{Connectivity by block of the random graph $\mathcal{G}_{BC}$ given by the BC model}%
    \label{fig:example}%
\end{figure}
\subsubsection{Distance Distribution}
After 100 realisations of the Block Configuration model were observed, this yielded a mean TV distance of 0.3937. This is a large improvement on the \ER model and the Configuration model, however, weaker than the GC Model. Despite not allowing for a geometrical constraint here in terms of how a pair of neurons connect, it is clear that by dividing up the MC into these blocks plays a similar role in geometrically constraining the connections since we are only able to rearrange the connections in these specific blocks.
\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{BC/Block_dist_distr.png}
\caption{Distance distribution of connected neurons for the random graph $\mathcal{G}_{BC}$}
\end{center}
\end{figure}

\subsubsection{Signed Degree of Neurons}
As mentioned at the head of this subsection, we have the same in-degrees and out-degrees for each neuron in each block and thereby ensuring the case for the whole random graph. \begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering  Signed Degree of each Neuron]{{\includegraphics[width=7cm]{BC/Block_Configuration_sd.png} }}%
    \qquad
    \subfloat[\centering Cumulative sum of the Signed Degree of the neurons in a realisation of the random graph $\mathcal{G}_{BC}$ ]{{\includegraphics[width=7cm]{BC/cumsum_degree_Block_Configuration.png} }}%
    \caption{Neuron statistics for the random graph $\mathcal{G}_{BC}$}%
    \label{fig:example}%
\end{figure}

\newpage

\subsection{Block Geometric Configuration Model}
The Block Geometric Configuration model uses both the ``cut-permute-rewire'' \cite{WattsStrogatz1998} algorithm as well as the geometric constraint as mentioned in the GC model with a slight variation to it here.
\subsubsection{Construction}
The final model that we have is the Block Geometric Configuration model. The first part of the construction process, is to divide the MC into blocks, as was the case for the Block Configuration model. The second part of the process, is to then compute the pairwise distances of connected neurons in each block. That is, we take the subset of vertices and edges in each block, and compute the distances between these neurons. We then apply Algorithm 2 to each block and return the corresponding subsets $u^\prime$ and $v$. Upon completion of all 25 blocks, we can then use these ordered sets of vertices to construct a realisation of the random graph model $\mathcal{G_{BGC}}$. Thus, $\mathcal{G_{BGC}}$ not only preserves the in-degrees and out-degrees layer-specifically for each neuron but also the probability of connecting neurons based on the empirical pairwise distances of connected neurons.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{GBC/matrix_BGC.png}
\caption{Adjacency Matrix M representing a realisation of the random graph $\mathcal{G}_{BGC}$}
\end{center}
\end{figure}

\subsubsection{Block Layouts}
Just as we saw for the Block Configuration model, each Block-wise Edge density gives a TV distance of 0 to the Bio-M MC. As you will see from Figure 30, the values match that of the Bio-M MC. This, like the Block Configuration model has been achieved since all edge shuffling has occurred within these blocks that we are splitting the MC up into.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Proportion of connections in each block ]{{\includegraphics[width=7cm]{GBC/heat_map_layer_bgc_test.png} }}%
    \qquad
    \subfloat[\centering Total number of connections in each block ]{{\includegraphics[width=7cm]{GBC/heat_map_layer_Block.png} }}%
    \caption{Connectivity by block of the random graph $\mathcal{G}_{BGC}$ given by the BGC model}%
    \label{fig:example}%
\end{figure}

\subsubsection{Distance Distribution}

Figure 31 reveals a very similar distribution for the BGC model in comparison to the BC model. This, perhaps suggests that the geometric constraint has already been taken care of by splitting up the MC into these layer by layer blocks. Over 100 realisations of the BGC model yielded a mean TV distance of 0.3937. This is only marginally better than the BC model. Details of these differences are contained in Section 6, Results.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{GBC/Block_dist_distr.png}
\caption{Distance distribution of connected neurons for the random graph $\mathcal{G}_{BGC}$}
\end{center}
\end{figure}

\subsubsection{Signed Degree of Neurons}
Just as with all the other models, we have the same in-degree and out-degree for each neuron as described by the plots in Figure 32.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Signed Degree of each Neuron]{{\includegraphics[width=7cm]{GBC/BGC_sd.png} }}%
    \qquad
    \subfloat[\centering Cumulative sum of the Signed Degree of the neurons in a realisation of the random graph $\mathcal{G}_{BGC}$]{{\includegraphics[width=7cm]{GBC/cumsum_degree_BGC.png} }}%
    \caption{Neuron statistics for the random graph $\mathcal{G}_{BGC}$}%
    \label{fig:example}%
\end{figure}

\newpage
\subsection{General Biological Model}
\subsubsection{The Model}
The General Biological model is the model that is proposed in the Frontiers article \cite{Reimann_2017}.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{GB/matrix_general_biol.png}
\caption{Adjacency Matrix M representing a realisation of the random graph $\mathcal{G}_{GB}$}
\end{center}
\end{figure}

This model subdivides the MC into 3025 sub-matrices which represent each morphological neuron type from pre-synaptic to post-synaptic neurons. That is, we have 55 different morphological neuron types. Now, within these sub-matrices, we compute the distances between all pairwise neurons. These distances get binned, as mentioned in Section 4.1.3, into bin sizes of 75$\mu$m. Now, within these bins, we then shuffle the connections, so that a distance is preserved. We can see this diagrammatically in Figure 35. When the shuffling is completed, the sub-matrices are reassembled to form a complete matrix which now represents a realisation of the random graph $\mathcal{G}_{GB}$ given by the General Biological model.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Connections in each morphological block]{{\includegraphics[width=7cm]{GB/heat_map_morph_layer_general_biol.png} }}%
    \qquad
    \subfloat[\centering A closer look at the morphological block L1\_DAC ]{{\includegraphics[width=7cm]{GB/L1_DAC.png} }}%
    \caption{Connectivity of GB Model}%
    \label{fig:example}%
\end{figure}

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Sample of connected graph before shuffling]{{\includegraphics[width=7cm]{GB/before.png} }}%
    \qquad
    \subfloat[\centering The same sample after shuffling ]{{\includegraphics[width=7cm]{GB/after.png} }}%
    \caption{An example of a block before shuffling connections and after}%
    \label{fig:example}%
\end{figure}
Figure 34(a) represents the number of connections in each block. The blocks are split into morphological type. As we can see by the bar on the right hand side, darker shades show a block that is highly populated with connections and a lighter block representing a less populated block of connections.
Figure 34(b) gives a representation of an individual morphological block, in this case L1 DAC, Layer 1 - Descending Axonal Collaterals, where we see pairwise neuron distances computed and binned according to a bin size of 75$\mu$m. The leading diagonal is the brightest shade of yellow and represents the smallest bin, that is a distance of 0$\mu$m and therefore are discounted, since they represent self-loops which do not exist. This leaves the remaining shades to be shuffled in each respective group.
Figure 35(a) and 35(b) represent a sample shuffling of connections, whereby the connections and non-connections are shuffled within their respective bins as defined by the shades.
\subsubsection{Block Layouts}
Now, by restricting the connection shuffling to morphological neuron type blocks, which are subsets of the layer by layer blocks, we are able to maintain a Block-wise Edge density that is consistent with the Bio-M MC. Therefore, giving us a TV distance for Block-wise Edge Densities of 0.

\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Block-wise Edge Densities]{{\includegraphics[width=7cm]{GB/heat_map_layer_gb_test.png} }}%
    \qquad
    \subfloat[\centering  Block-wise Edge Counts ]{{\includegraphics[width=7cm]{GB/heat_map_layer_general_biol.png} }}%
    \caption{Connectivity by block of the random graph $\mathcal{G}_{GB}$ given by the GB model}%
    \label{fig:example}%
\end{figure}

\subsubsection{Distance Distributions}
Figure 37 shows that with distance-dependence taken into account in the form of keeping bin sizes to a maximum size of $75\mu$m, we are able to maintain the exact same distribution as that of the Bio-M MC. In fact, we get a mean TV distance over 100 realisations, to be $\epsilon$. That is to say that the difference is statistically insignificant as a non-zero value occurred but once and was of the order $\epsilon < 1\times10^{-7}$. The details of the exact value is given in Section 6, Results.

\begin{figure}[H]
\begin{center}
\captionsetup{justification=centering}
\includegraphics[width=12cm]{GB/general_biol_dist_distr.png}
\caption{Distance distribution of connected neurons for the random graph $\mathcal{G}_{GB}$}
\end{center}
\end{figure}

\subsubsection{Signed Degree of Neurons}
One curiosity that occurred when constructing the random graph for the General Biological model was the directionality upon computing the cumulative sum. This exhibited a different path to that of all other models, and hence why it is shown in Figure 38(b). The underlying reason for this will be that whilst the construction process restricted the MC into blocks of morphological type and shuffled connections here, the shuffling wasn't based on the pre-existing connections in the MC, but rather the distances between all neurons within each block and therefore creating entirely new sets of pre-synaptic and post-synaptic neurons. This therefore, does not preserve the in-degree and out-degree of each neuron.
\begin{figure}[H]%
    \centering
    \captionsetup{justification=centering}
    \subfloat[\centering Cumulative Signed Degree]{{\includegraphics[width=7cm]{GB/cumsum_degree_general_biol.png} }}%
    \qquad
    \subfloat[\centering Directionality]{{\includegraphics[width=7cm]{GB/overall_degree_general_biol_sd_2.png} }}%
    \caption{a sample of the cumulative signed degree and the directionality of the GB model}%
    \label{fig:example}%
\end{figure}


\problemname{Debugging}

\illustration{0.5}{bug}{Picture in public domain via \href{https://en.wikipedia.org/wiki/File:H96566k.jpg}{Wikimedia Commons}}%
\noindent
Your fancy debugger will not help you in this matter. There are many
ways in which code can produce different behavior between debug and
release builds, and when this happens, one may have to resort to more
primitive forms of debugging.
% -- a real coder uses them all!

So you and your printf are now on your own in the search for a line of
code that causes the release build to crash. Still you are lucky:
adding printf statements to this program affects neither the bug (it
still crashes at the same original code line) nor the execution time
(at least not notably).  So even the naive approach of putting a
printf statement before each line, running the program until it
crashes, and checking the last printed line, would work.

However, it takes some time to add each printf statement to the code,
and the program may have a lot of lines. So perhaps a better plan would involve
putting a printf statement in the middle of the program, letting it run, seeing
whether it crashes before the added line, and then continuing the search in
either the first or second half of the code.

But then again, running the program may take a lot of time, so the
most time-efficient strategy might be something in between.  Write a
program that computes the minimum worst-case time to find the crashing
line (no matter where it is), assuming you choose an optimal strategy
for placing your printf statements.

We're releasing the new version in five hours, so this issue is escalated and needs to be fixed ASAP.
%Did I already mention this issue is escalated and needs to be fixed asap?

\section*{Input}

The input consists of one line with three integers:
\begin{itemize}
\item $n$ ($1 \le n \le 10^6$), the number of code lines;
\item $r$ ($1 \le r \le 10^9$), the amount of time it takes to compile and run the program until it crashes;
\item $p$ ($1 \le p \le 10^9$), the time it takes to add a single printf line.
\end{itemize}

You have already run the program once and therefore already know that it does crash somewhere.

\section*{Output}

Output the worst-case time to find the crashing line when using an
optimal strategy.


\section{Model Optimization}
\label{sec:optimizerStrategies}

When analyzing the range of values obtainable by a model, frequently a key question is ``what set of
parameters result in the best response value?''  To answer this question, RAVEN uses the \xmlNode{Optimizer},
a powerful sampler-like entity that searches the input space to find minimum or maximum values of a response.

In the remainder of this section, we will explore how to use the optimizer using a simple analytic problem,
with a two-dimensional input space and single response of interest.  After getting used to running with the
optimizer, we will add increasing complexity, including changing adaptive step sizes, initial conditions,
parallel trajectories, input space subdivision, input space constraints, and response constraints.

To demonstrate the operation of the Optimizer entities in RAVEN, the model we consider is the Beale function,
which is documented in the analytic tests for RAVEN and replicated here:

\begin{itemize}
  \item Function: $f(x,y) = (1.5-x+xy)^2+(2.25-x+xy^2)^2+(2.625-x+xy^3)^2$
  \item Domain: $-4.5 \leq x,y \leq 4.5$
  \item Global Minimum: $f(3,0.5)=0$
\end{itemize}

The two inputs are the variables $x$ and $y$, and the response is a value we'll assign to $ans$, short for
``answer''.  The model is an external model in RAVEN, and can be found at
\begin{verbatim}
  raven/tests/framework/AnalyticModes/optimizing/beale.py.
\end{verbatim}
The function's values are distributed as in Fig. \ref{fig:beale}.
\begin{figure}[h!]
  \centering
  \includegraphics[scale=0.7]{../../tests/framework/user_guide/optimizing/Beale_grid.png}
  \caption{Plot of Beale's function for Optimization}
  \label{fig:beale}
\end{figure}

Note that throughout this example we use the SPSA optimizer by way of demonstration, since it is the first
advanced algorithm for optimization included in RAVEN; many of the options and parameters apply to other
optimizers, and details can be found in the RAVEN user manual.

\subsection{Introduction: The Optimizer Input}
As with other entities, the Optimizer gets its own XML block in the RAVEN input.
Here's an example of an input for a SPSA optimizer named \xmlString{opter}:
\xmlExample{framework/user_guide/optimizing/simple.xml}{Optimizers}
This is the smallest amount of input needed to run an optimization problem, with the exception that we include
the \xmlNode{initialSeed} to maintain consistent results.  Note the required blocks included
to define the optimizer:
\begin{itemize}
  \item \xmlNode{TargetEvaluation}, which declares the DataObject that the optimization search evaluations are
    going to be placed in.  All of the optimal points found as part of the optimization, as well as any other
    points evaluated as part of the algorithm, are placed in this object so the optimizer can retrieve this
    information later.  When this data object is defined, it is critical that the objective variable is
    defined in the output space, and the input variables in the input space, so the optimizer can collect the
    results of its sampling.  The data object type should be ``PointSet'' for this data object.  In this
    example, we use the self-descriptive \emph{optOut} data object.
  \item \xmlNode{variable}, which is where you can define the input space variables, one for each of these
    nodes.  Declaring a variable here informs the optimizer that you want it to find the optimal value for
    this variable, along with the other variables declared in their own blocks.  Additionally, you define the
    upper and lower bounds of the variable, which will give the optimizer some general expectations for
    finding the optimal point; it will never try to sample a value smaller than the lower bound or larger than
    the upper bound.  In the example we define variables \emph{x} and \emph{y} as our input variables, and
    both of them coincidentally range between -4.5 and 4.5.  We set the initial values for both variables to 0
    through the \xmlNode{initial} block, which is required in most cases; the exception is when a
    preconditioner sets them in mulitlevel optimization, but we're not concerned with that feature at this
    point.
  \item \xmlNode{objectVar}, which is where you indicate the variable for which you want to find the minimum (or,
    if you change the default, maximum).  As listed here, we want to minimize the value of \emph{ans} given a
    range of possible values for {x} and {y}.
\end{itemize}
The other critical blocks in this input are as follows:

\subsubsection{Models}
\xmlExample{framework/user_guide/optimizing/simple.xml}{Models}
Note that we define the external model with the name \xmlString{beale} and provide a path to the analytic
model itself.  This model is set up with the \texttt{run} method that allows RAVEN to run the model.  We also
list all our input/output variables, \emph{x, y}, and \emph{ans}.

\subsubsection{Data Objects}
\xmlExample{framework/user_guide/optimizing/simple.xml}{DataObjects}
We have three data objects: \xmlString{dummyIN}, which is necessary to define the input space of our external
model in the Steps; \xmlString{optOut}, which will hold all of the samples taken by our optimizer; and
\xmlString{opt\_export}, which will hold the actual solution path taken by our optimizer.  Note that while
\xmlString{optOut} is a Point Set, \xmlString{opt\_export} is a History Set.  This is because we store the
path travelled by the optimization algorithm as a history, with \emph{varsUpdate} keeping track of the
optimization steps taken.  Note especially how the input of \xmlString{opt\_export} is set to \emph{trajID},
which is a special keyword for the Optimizer history tracking, as is the output variable \emph{varsUpdate}.
There are several other special keyword outputs that can be written to the Solution Export data object, that
can be found in the user manual.

\subsubsection{Out Streams}
\xmlExample{framework/user_guide/optimizing/simple.xml}{OutStreams}
Here we define the way to print the output of our optimization algorithm.  There's not much to note, except
that we'll be printing the optimization path as a History-based CSV.

\subsubsection{Steps}
\xmlExample{framework/user_guide/optimizing/simple.xml}{Steps}
Here we put it all together into a work flow that RAVEN can follow.  We only need two steps: one to optimize,
and one to print out the results.  To actually perform the optimization, we need a MultiRun step, which we
cleverly name \xmlString{optimize}.  For input we take the placeholder data object \emph{dummyIN}, which sets
up the input space of the model we defined, \emph{beal}.  Where a \xmlNode{Sampler} would normally go, we
include the \xmlNode{Optimizer} we defined earlier.  We output to the same data object we indicated in the
Optimizer's \xmlNode{TargetEvaluation} node.  Finally, we note specifically the use of the
\xmlNode{SolutionExport} node.  The data object defined in this node is where the Optimizer will write the
optimization path history, with the final entry being the last step taken by the optimizer.  The IOStep is
unremarkable, used simply to write out the optimization path history to file.

\subsubsection{Conclusion}
After reviewing the components (don't forget the RunInfo block!), you can run this example and see the
results.  In particular, we can view the history of the optimizer in \texttt{Simple/opt\_export\_0.csv}.  Note
that \texttt{opt\_export} is the name of the \xmlNode{Print} OutStream we defined in the input file, and the
\texttt{\_0} indicates this is the first optimization path followed (we'll cover multiple paths later in
section \ref{subsec:opt parallel traj}).

When we open the file (preferably in a CSV reader such a spreadsheet viewer), we see a CSV with four headers,
the outputs defined in the data object in the input
file: \emph{x}, \emph{y}, \emph{ans}, and \emph{varsUpdate} (not necessarily in that order).  \emph{x},
\emph{y}, and \emph{ans} are the values of the variable at each optimization iteration, while
\emph{varsUpdate} gives the sequential order of the optimization iteration.

If we look at the last line, we converged around $f(1.61, -0.189) = 1.67$, which is okay but still quite a
ways from the analytic optimal point $f(3, 0.5) = 0$.  If we look at the output from the run, we can look at
the last time RAVEN was ``Checking convergence for Trajectory 0''.  Below that statement, there are a series
of convergence criteria and their status.  We can see that the reason we converged at the end is the
\texttt{Relative Loss Diff}, which means the relative change in the response \emph{ans} was sufficiently
small between steps to cause convergence.  Clearly, we claimed convergence prematurely because of the default convergence
values used by the optimizer.  Because these convergence criteria are very problem-specific, the default
parameters will not work best for all problems.

We can improve this result by changing convergence
parameters as well as step size growth and shrink factors, all of which can be found in the user manual, and
many of which we'll discuss in the rest of this section.

\subsection{Initial Conditions and Parallel Trajectories} \label{subsec:opt parallel traj}
Notice we set the optimization search to start at $(0,0)$.
%By default, RAVEN chooses the center
%point of the input space as an initial value.
You can change this initial value through
the \xmlNode{initial} block within the \xmlNode{variable} definition node.

Furthermore, RAVEN offers the possibility to run multiple optimization paths in parallel.  Because many
(perhaps most) optimization techniques get stuck in local minima, using multiple paths (or \emph{trajectories} as
they are called in RAVEN) increases the likelihood that one of the trajectories will find the global minimum
point.  You can request multiple trajectories by providing a variety of initial conditions in the
\xmlNode{initial} block, as shown in this Optimizer example:
\xmlExample{framework/user_guide/optimizing/multiple_trajectories.xml}{Optimizers}
Note that the ordered pairs are split across the \xmlNode{initial} nodes, so that the first trajectory will
start as a point made up of all the first entries, the second trajectory starts at all the second entries, and
et cetera.  In this case, we've requested starting points at (-2,-2), (-2,2), (2,-2), and (2,2).  This (and
defining a new working directory in the \xmlNode{RunInfo} block) is the only input change between the original
file and this one.

When run, we can see the results in the working directory \texttt{MultipleTraj}.  There, we see the same files
as for the base case, plus \texttt{opt\_export} files 0-3 instead of just 0.  Each of these corresponds to the
path that one of the initial points started at, as you can see at the top of each of these CSV files.  We can
see that trajectory 3 (who started at (2,2)) ended close to the analytic optimal point, while trajectory 0
was far from it.

In order to see a summary of the end point of each trajectory, we can use the additional RAVEN step described
in \ref{subsec:opt summarizing results}.

\subsection{Summarizing Results} \label{subsec:opt summarizing results}
While seeing the histories of the optimization paths taken in the \xmlNode{SolutionExport} is informative,
sometimes we just want to see the final optimal point found by each trajectory.  In this case, we can use an
\emph{InterfacedPostProcessor} called {HistorySetSnapShot} to get the last point found by each optimizer.  The
postprocessor looks like this:
\xmlExample{framework/user_guide/optimizing/summary.xml}{Models.PostProcessor}
Note that we named the postprocessor \xmlString{snapshot}, and instructed it to look for the \xmlString{max}
value of \xmlString{varsUpdate} in each of the histories, and combine them into a single data set.  We add the
following Step to our \xmlNode{Steps} to run it:
\xmlExample{framework/user_guide/optimizing/summary.xml}{Steps.PostProcess}
Don't forget to add \xmlString{getOptPoint} to the \xmlNode{Sequence} in the \xmlNode{RunInfo} block, before
\xmlString{print} but after \xmlString{optimize}.  Note that this post-processing step takes the
\xmlNode{SolutionExport} data object from the optimizing step as input, runs the postprocessing model, then
places the results in a new data object, \xmlString{opt\_soln}, which we add to the \xmlNode{DataObjects}
list in the input file.

Note also that we added the printing of the \xmlString{opt\_soln} data object to the \xmlString{print}
\xmlNode{IOStep}; we only needed to write an \xmlNode{OutStream} for it, not a whole new step.

After running this input, you can open \texttt{Summary/opt\_soln.csv} to see the final results of each
optimization trajectory.  The variable \emph{trajID} gives the trajectory label, \emph{x} and \emph{y} give
the final location of the optimal point found by that trajectory, \emph{ans} gives the value of the response
at that location, and \emph{varsUpdate} shows how many iterations were necessary to find that optimal point.
The trajectory with the lowest value for \emph{ans} is the most optimal point found.

\subsection{Adjusting Adaptive Steps} \label{subsec:opt stepsize}
As we've seen, some of the optimization paths are struggling to converge to meaningful optimal solutions.
One way to improve this is to tinker with the convergence tolerances defined in the user manual.  Another is
to change the step size modifications used as part of the search process, which we discuss in this section.
First, we briefly discuss how the SPSA chooses its step size, so we can make informed choices about what
parameters to use.

Because SPSA is a gradient-based method, it operates by starting at a particular point, estimating the
gradient at that point, then taking a step in the opposite direction of the gradient in order to follow a
downhill path.  It adaptively chooses how long of a step to take based on its history.  If the gradient is in
the same direction twice in a row, the algorithm assumes there's further to travel, so increases its step size
multiplicatively by the \emph{grainGrowthFactor}, which by default is 2.0 in RAVEN.  If, on the other hand,
the gradient switches directions, then the step size is divided by the \emph{gainShrinkFactor}, which again is
2.0 by default in RAVEN.  This means that by default, if the gradient keeps going in the same direction, you
always double your step size, while if you're bouncing back and forth in a valley, the step size is halved at
each iteration.

By way of note, in higher dimensions, the actual growth or shrink multiplier is scaled by a dot product
between the two previous gradients, with a max of the grain growth factor when the dot product is 1 (exactly
aligned) and a minimum of grain shrink factor when the dot product is -1 (exactly opposite).  This means if
the gradient is at right angles with the past gradient, then the step size remains unchanged (dot product is
0).

There are some additional considerations for the step size change, as well.  If the algorithm takes a step,
then discovers the new point has a worse response value than the point it's at, it will reject the new point,
re-evaluate the gradient, and flag the step size to be divided by the gain shrink factor.  Because of this, if
the gain shrink factor is too large, false convergence can be obtained when the algorithm struggles to find a
new downhill point to move to.  As a result, in practice it is often beneficial to have a gain shrink factor
that is smaller than the gain growth factor.

For this particular example, we use gain growth factor of 1.5 (meaning when the gradient continues in the same
direction our step grows to 150\% of its old value) and a gain shrink factor of 1.25 (meaning when the
gradient flips directions our step size shrinks to 80\% of its old value).  We add this to the base case
(\texttt{simple.xml}) to get:
\xmlExample{framework/user_guide/optimizing/step_size.xml}{Optimizers}
Note the definition of the gain growth and shrink factors in the \xmlNode{convergence} block.  Reviewing the
output file \texttt{StepSize}, we can see more steps were taken than the case using default step sizes, but
the final solution was $f(2.65,0.403)=0.0286$, which is much closer to the analytical solution of $f(3,0.5)=0$
than the base case and within our convergence tolerances of the right solution.

It is often challenging to find the best gain growth and shrink factors, and these can have a very significant
impact on the speed and accuracy of the convergence process.  Too large a shrink factor results in poor
resolution of valleys, while too small a shrink factor results in many unnecessary evaluations of the model.

\subsection{Denoising Stochastic Problems}
While many of the models we see in optimization are deterministic (meaning running the same inputs into the
model yields the same results every time), there are quite a few stochastic models that we might desire to
optimize.  For example, a model that included Brownian motion or is solved using unseeded random numbers might
be considered stochastic.

The difficulty with optimizing noisy problems rests in the unreliability of a single sample.  If we send a
single set of inputs into a stochastic model, we can't trust the results to be consistent.  One way to measure
the consistency of the results is through a signal-to-noise ratio (SNR).  There are many ways to define this
value; for our purposes, we will use the ratio of the mean of the signal to the standard deviation of the
signal, $\mu/\sigma$.

To obtain an approximation of your SNR, you can use RAVEN to perform a Monte Carlo run on your model and then
use the BasicStatistics postprocessor to collect the mean (expectedValue) and standard deviation (sigma) of
your response.  It's important to make this sampling all at a single value in the input space, so replace your
variables with constants in the Sampler input.  Once you have the mean and sigma, you have an idea of how
noisy your model is.  A SNR of 1 means the signal is just as big as the noise, making it very difficult to
optimize.  A SNR of less than 1 means the noise dominates the signal, and will make optimization almost
impossible without introducing denoising.  A SNR of more than 1 indicates the signal is stronger than the
noise, and perhaps denoising is not necessary.  If your standard deviation is 0, then you don't have any
discernable noise!

To denoise a model in RAVEN SPSA optimization currently, we turn our attention to the \xmlNode{Optimizer}
subnode \xmlNode{parameter}, specifically the \xmlNode{numGradAvgIterations} node.  This parameter instructs
RAVEN to perform multiple gradient evaluations, including multiple evaluations of each optimal point, and use
the average to make decisions in optimization pathing.  By default, RAVEN takes one optimal point and one
neighboring point to evaluate a gradient.  Increasing the \xmlNode{numGradAvgIterations} will increase the
number of times the optimal point is sampled, and how many neighbor points are sampled.  This serves to
denoise the model.

However, this also raises the question, how many resamples do I need to denoise my model?  In a Wilks-like
approach, we want to reduce the size of the confidence interval for our mean to be less than the noise.  The
number of resamples required depends on the size of the confidence interval $z$ and the confidence-to-noise ratio
$\xi$ we want to ultimately have for the optimization algorithm.  We also assume the distribution of the
response is roughly Gaussian Normal, which may not be the case.  The approximate equation for assuring the
confidence interval is smaller than the noise is
\begin{equation}
  \frac{z\sigma}{\sqrt{n}} \leq \xi\sigma,
\end{equation}
\begin{equation}
  n \geq \left(\frac{z}{\xi}\right)^2.
\end{equation}
Thus, the number of resamples depends on the confidence level as well as the desired ratio of the confidence interval
to the noise.

A few values for varying ratios are given in Table \ref{tab:confidence levels} for the 99\% confidence level ($z=2.576$).
\begin{table}[htb]
  \centering
  \begin{tabular}{c c}
    Confidence-to-noise $\xi$ & Resamples necessary \\ \hline
    1.0 & 7 \\
    0.9 & 9 \\
    0.7 & 14 \\
    0.5 & 27 \\
    0.1 & 664 \\
    0.05 & 2655
  \end{tabular}
  \caption{Estimate of the number of samples necessary to denoise models to varying confidence levels}
  \label{tab:confidence levels}
\end{table}
That is, if you want the noise and confidence interval to have the same magnitude, only 7 resamples are
required.  If, on the other hand, you want the confidence interval to be half the level of the noise, 27
resamples are required.

Note these are only guidelines; individual models may behave differently and require more or less resamples to
provide a clear optimization path.

\subsection{Input Space Subdivision}
In higher-dimensional problems, sometimes the input space can be divided into characteristic subspaces.  For
example, potentially one set of inputs vary slowly with consistent gradient directions in the response, while
for another set of inputs the response fluctuates frequently with many local minima.  In this case, it might
be beneficial to optimize the subspaces in nested loops, slowly converging the smoothly-varying space while
often converging the undulating space.

For these cases, RAVEN provides \emph{multilevel} operation.  To transition our base case to a multilevel
case, we change the optimizer as follows:
\xmlExample{framework/user_guide/optimizing/multilevel.xml}{Optimizers}
Note the addition of the \xmlNode{multilevel} node.  In this node, we need to define the subspaces, then the
ordering of the subspaces in terms of convergence priority.  We intuitively name the subspace with \emph{x}
the \emph{xgroup} and similarly with \emph{y}.  Note that while in this example each subspace consists of only
one variable, in general many variables may exist in any given subspace.  Note also that it's a bad idea to
include a variable in multiple subspaces.

The \xmlNode{sequence} can be thought of as an order of nesting optimization, where the first subspace listed
is optimized most slowly (but only once) and the last is optimized frequently and swiftly.  Each time a new
optimal point is found, the innermost space (in our example \emph{yspace}) is converged completely, holding all
the variables in all other subspaces (e.g. \emph{xspace}) constant at their most recent value.  Once
\emph{yspace} is converged, we take a single step in the subspace \emph{xgroup}, then return to converging
\emph{yspace} again.  Every step in \emph{xspace} triggers a full convergence of \emph{yspace}.

In the results in \texttt{Multilevel/opt\_export\_0.csv}, you can observe how first one dimension then the
other is perturbed in the search for the optimal point.

It should be noted as well, using multilevel optimization does not necessarily improve the optimization path;
in fact, in many cases, the number of model evaluations increases significantly for little gain in final
optimal value.  Multilevel is most useful when clustered subspaces share a particular feature in optimization
that is useful to isolate from the rest of the optimization procedure, or if some subsets of inputs act
independently from others in affecting the response.

\subsection{Functional Constraints} \label{subsec:opt explicit constraint}
Sometimes an optimization problem has a constrained input space, possibly where there is a tradeoff between
two inputs.  In this event, RAVEN allows the user to define a \emph{constraint} function, which will cause
RAVEN to treat this constraint as it would a boundary condition.

For example, we will introduce a void in the input where we reject inputs.  This void is defined by rejecting
all samples within $(x-1)^2 + y^2 < 1$.  We'll also include the modified step growth and shrink parameters
discussed in section \ref{subsec:opt stepsize}.

To include a constraint function, we first have to define it in the RAVEN input as a \xmlNode{Function}
entity:
\xmlExample{framework/user_guide/optimizing/constrain.xml}{Functions}
Note that the file \texttt{./Constrain/constraint.py} is located relative to the working directory.  Currently,
external functions are always Python files.  In that file,
note that the only method is \texttt{constrain}, which is RAVEN's keyword to find the constraint function.
RAVEN will pass in a \texttt{self} object, which will have the function variables defined in the
\xmlNode{Functions} input available as members.  The method \texttt{constrain} then returns a boolean which is \texttt{True} if
the evaluation does not violate the constraint, or \texttt{False} if the constraint is violated.

To attach the constraint to the optimizer, simply add it as an assembled \xmlNode{Function}:
\xmlExample{framework/user_guide/optimizing/constrain.xml}{Optimizers}

After running, looking through the path followed by trajectory 0 shows that instead of following the path from
section \ref{subsec:opt stepsize}, the path moves to lower \emph{y} values before swinging back up toward the
optimal point.

%\subsection{Implicit Constraints (Penalties)}
% TODO come up with a working example


\documentclass[twoside]{MATH77}
\usepackage{multicol}
\usepackage[fleqn,reqno,centertags]{amsmath}
\DeclareRobustCommand{\us}{\rule{.2pt}{0pt}\rule[-.8pt]{.4em}{.5pt}\rule{.7pt}{0pt}}
\begin{document}
\begmath 4.7  Sparse Square Nonsingular Systems of Equations

\silentfootnote{$^\copyright$ \thisyear \ Math \`a la Carte, Inc.}

\subsection{Purpose}

For a sparse square nonsingular matrix, $A$, of order N, and an
optional vector or matrix B, this routine will factor A, solve $A X =
B, \ A^T X = B$, compute the reciprocal of the condition number, and
obtain the determinant and the inverse.  This code has similar
functionality to the dense codes described in Chapter 4-1.  The
program in Chapter 19-6 can be used together with the code here to
solve problems with the matrix given in Matrix Market format.

\subsection{Usage}
With minimal options, this simply solves $A \mathbf{x} = \mathbf{b}$
for a single vector $\mathbf{b}$, and does not preserve the
factorization.  Other features are available through the options in
ISPEC.

\paragraph{Program Prototype, Single Precision}

\begin{description}

\item[INTEGER] \ {\bf N, ISPEC(?), IA(?)}

\item[DOUBLE PRECISION] \ {\bf A(?), B(?), OPT(3)}

\end{description}

Assign values to N, ISPEC(), IA(),  A(), and B().

\begin{center}
\fbox{\begin{tabular}{@{\bf }c}
CALL DSPGE (N, ISPEC, IA, A, B, OPT)\\
\end{tabular}}
\end{center}

Computed quantities are returned in IA(), A(), B(), and ISPEC.

\paragraph{Argument Definitions}

\begin{description}

\item[N] [in] The order of the matrix $A$ and number of rows in the
  $B$ and $X$.

\item[ISPEC()] [inout] An array used to return a flag, specify
  dimensions and specify options.  Locations are used as follows.
  \begin{description}
  \item[1] [inout] Must be 0 if the matrix is not factored.  The value
    returned on the first call must be preserved on later calls when
    the matrix is already factored.  If the returned value is $<$ 0,
    then the matrix was not factored.  See Section~\ref{sec:errors} on
    page~\pageref{sec:errors} for details.
  \item[2] [in] Declared dimension of IA() (or at least all that you
    want this routine to know about.  This number must be at least the
    space required for storing the factors of the matrix + twice the
    space needed for the original matrix + 7N.
  \item[3] [in] Declared dimension of A(), this can have a dimension
    4N less than that for IA.
  \item[4] [out]  The total free space in A at the solution.  If there
    was insufficient free space this gives the negative of the number
    of columns left to be factored.
  \item[5] [in] Start of options, see the next Section.
  \end{description}

\item[IA()] [inout] IA(1) gives the number of nonzeros in the first
  column.  IA(2) to IA(1 + IA(1)) give the row indexes for rows in the
  first column which must be in increasing order.  IA(2+IA(1)) then
  gives the number of nonzeros in the second column, etc.  Locations
  after this input data are used internally.

\item[A()] [inout] For each row index given in IA, the corresponding
  location in A contains the coefficient corresponding to that row and
  column.  The remaining locations in A are used internally.

\item[B()] [inout] Used to hold the right hand side(s) on entry and to
  hold the solution on exit.

\item[OPT()] [out] Used only for some options..\\
  OPT(1) = reciprocal condition number if requested.\\
  OPT$(2) \times 10^{OPT[3]}$ = the determinant if requested.
\end{description}

\subsubsection{Options}

First, a summary of the options.\vspace{2pt}

\begin{tabular}{|l@{}r|l|}\hline
  \multicolumn{2}{|c|}{\rule{0pt}{12pt}Name \hfill Value}&
  \multicolumn{1}{|c|}{Brief Description}
  \\[2pt]\hline\rule{0pt}{12pt}%
  IPS & 0 & Solve $A \mathbf{x} = \mathbf{b}$\\
  IPST & 1 & Solve $A^T \mathbf{x} = \mathbf{b}$\\
  IPBDIM & 2 & Specifies dimensions on B\\
  IPRCON & 3 & Compute reciprocal condition number\\
  IPDET & 4 & Compute determinant\\
\hline
\end{tabular}\vspace{5pt}

Starting in ISPEC(5) there is an index for an action which we denote
here by $I_a$.  Each $I_a$ has associated with it a parameter name, a
value for that parameter, and a (possibly empty) list of arguments,
which follow immediately after $I_a$ in ISPEC.  After the last
argument for an $I_a$, the next location in ISPEC contains the next
$I_a$, with its associated arguments.  This continues until the last
$I_a$ has been specified.  An option index $\leq 1$ ends the option
list (other options must precede these).  Setting ISPEC(5) = 0, gives
the default action.

It is assumed that B is a one dimensional of length N if option
IPBDIM is not used.

All the above options except for IPBDIM, take no arguments, and the
above table should be self-explanatory.  IPBDIM uses 3 locations in
ISPEC, the 2 to indicate this option, next $I_2$ to indicate the
number of columns (default is 1), and then $J_2$ to indicate the
distance between successive columns of B.  In addition one can get the
inverse by setting $I_2 = -1$, and DSPGE will initialize B to the
identity matrix computing a solution.  If no backsolve is desired, set
$I_2$ to 0.  In the case of a B with 5 columns one might have
ISPEC(5)=2, ISPEC(6)=5, and ISPEC(7)=N.  Note that the code always
assumes that B is dense.

If you want to compute the inverse matrix and are not an expert,
chances are you should ask an expert who is likely to tell you ---
don't.  Given the ability to backsolve using a previous factorization
the inverse should very rarely be needed.

\paragraph{Program Prototype, Single Precision}

Usage is the same as for double precision, except the ``DOUBLE
PRECISION'' statement is changed to ``REAL'', and the name DSPGE is
changed to SSPGE.

\subsection{Examples and Remarks}

Program DRDSPGE illustrates the use of DSPGE to solve a system
of linear equations and compute the reciprocal condition number of the
matrix of the system. Output is shown in ODDSPGE. The data for this problem
were chosen so the exact solution has components 2, $-$5, and~3.

\subsection{Functional Description}

To factor the matrix, Gaussian elimination is used on columns to get a
factorization of the form $A = U L^{-1}$.  Pivot selection permutes
rows and columns independently balancing a desire to keep an upper
triangular form of the matrix without sacrificing stability.

Internal scaling first computes scale factors to make all the columns
have an $L_\infty$ norm of 1, and follows this by doing the same to
the rows.

\subsubsection{Estimating reciprocal condition number}

The condition number of an $n\times n$ nonsingular matrix, $A$, is defined
as $\kappa = \|A\|\times \|A^{-1}\|$, a quantity that is never less than
unity.  This is the largest factor by which the relative error in a
vector, ${\bf y}$, can be amplified as a result of multiplication by $A$
or by $A^{-1}$.  Roughly speaking, if $\kappa = 10^k$ and the components
of the vector ${\bf b}$ in the problem, $A{\bf x} = {\bf b}$, are known to
$d$ decimal digits, and the components of $A$ are known to more than $d$
decimal digits, and the problem is solved using precision greater than $d$
decimal digits, then the solution will be known to about $d-k$ decimal
digits.  In particular, if $k \geq d$, the solution may have no reliable
digits at all.

We use the procedure described in \cite[pp.\ 128--130]{Golub:1996:GVL}
(based on work in \cite{Dongarra:1979:LUG}), which requires on the
order of $3n^2$ additional operations.  In a test with 1250~cases
reported in \cite{Dongarra:1979:LUG}, the maximum value for the
condition number / estimated condition number was just slightly more
than 16.

\subsubsection{Computing the determinant of $A$}

We have $Det(A) = Det(U) Det(L^{-1})$.  Since all row and column
permutations are done on both $L$ and $U$, and the diagonal of $L$
contains 1's, the determinant is simply the product of the diagonals
of $U$ times $-1$ if the sum of the number of exchanges done on rows
and columns of A is odd.\normalsize

For a matrix of large order it is not uncommon for the determinant to
be of extremely large or small magnitude. Consequently we compute and
store the determinant as a pair of numbers, permitting a very large
exponent range.  The second number of the pair is always in integer.

\bibliography{math77}
\bibliographystyle{math77}

\subsection{Error Procedures and Restrictions}
\label{sec:errors}
Error messages are printed using the facility described in Chapter
19-03.  Options there give one some control over actions taken on
errors, and on where the debug print goes.  Error indexes $<-4$ stop
by default, those $>-4$ only return an error flag, and the $-4$ case
will return only if there was enough space to get started on the
factorization.  The error flags returned are

\begin{description}
\setlength{\parsep}{0pt} \setlength{\itemsep}{-3pt}
\item[$-1$] Matrix appears singular.  (Sets OPT(1) = 0.)
\item[$-2$] Matrix has an empty column.
\item[$-3$] Matrix has an empty row.
\item[$-4$] No more space.
\item[$-5$] N $\leq$ 0
\item[$-6$] An unknown option.
\item[$-7$] Problem with column size.
\item[$-8$] Problem with row indexes.
\end{description}

\subsection{Supporting Information}

The source language is ANSI Fortran~77.

Design and programming by Fred T. Krogh, Math \`a la Carte, Inc.
March 2006.  We hope to revisit this in the future and improve
performance.

\begin{tabular}{@{\bf}l@{\hspace{5pt}}l}
\bf Entry & \hspace{.35in} {\bf Required Files}\vspace{2pt} \\
DSPGE & \parbox[t]{2.7in}{\hyphenpenalty10000 \raggedright
DMESS, DSPGE, MESS\rule[-5pt]{0pt}{8pt}}\\
SSPGE & \parbox[t]{2.7in}{\hyphenpenalty10000 \raggedright
MESS, SMESS, SSPGE\rule[-5pt]{0pt}{8pt}}\\
\ & \ \\\end{tabular}

\begcodenp
\vspace {10pt}
\lstset{language=[77]Fortran,showstringspaces=false}
\lstset{xleftmargin=.8in}

\centerline{\bf \large DRDSPGE}\vspace{0pt}

\vspace{10pt}
\lstinputlisting{\codeloc{dspge}}

\vspace{10pt}\centerline{\bf \large ODDSPGE}

\lstset{language={}}
\lstinputlisting{\outputloc{dspge}}

\end{document}


\section{PDMPs and generators} \label{pdmpgenerator}
The main class of stochastic processes utilized in this thesis is the piecewise deterministic Markov Process, or PDMP, whose theory is presented in Davis \cite{dav84}.  For a PDMP, a Markov process is allowed deterministic drift along flow lines of a vector field before randomly jumping to a new state.  In addition to covering several examples from queueing theory, including the  M/G/1 queue, the GI/G/1 queue, the model also encapsulates Markov chains.  Our chief object of interest is the infinitesimal generator and martingale from Dynkin's formula associated with the PDMP.   In Chatpers 3 and 4 we plan to use these martingales to provide an approximation to limiting kinetic equations.

Our goal is to describe a generalized jump process that takes place on a disjoint union of  manifolds, and follows a deterministic drift between jumps. To characterize the state space, we let $\mathcal S$ be a countable set,   $d:\mathcal S\rightarrow \mathbb{N}$ , where for each $\mathbf s \in \mathcal S$,  $M_\mathbf s \subset \mathbb{R}^{d(\mathbf s)}$ is an open set.   The state space is then the disjoint union
\begin{equation}
E =\coprod_{\mathbf s \in \mathcal S} M_\mathbf s = \left\{(\mathbf s, \textbf x):\mathbf s \in \mathcal S,  \textbf x \in M_\mathbf s \subset \mathbb R^{d(\mathbf s)}\right\}. \end{equation}
To define the topology of $E$, let $\iota_\mathbf s:M_\mathbf s \rightarrow E$ be the canonical injection defined by $\iota_\mathbf s(\textbf{x}) = (\mathbf s, \textbf{x})$.  A set $A$ in $E$ is open if for every $\mathbf s$, $\iota_\mathbf s^{-1}(A)$ is open in $M_\mathbf s$. We then define $\mathcal E$ as the Borel sets of $E$. This makes $(E,\mathcal E)$ a Borel space.

We now define a stochastic process $X(t) = (\mathbf s(t),\zeta(t))$, with a law $(X(t))_{t  \ge 0}$ based on the following:

\begin{enumerate}
\item
Vector fields $\mathcal X_\mathbf s,\mathbf s \in \mathcal S.$ defined on $M_\textbf s$.
\item
A measurable function $\lambda:E \rightarrow \mathbb R^+$.
\item
A transition measure $Q: \mathcal E \times (E \cup \Gamma^*) \rightarrow [0,1]$.

\end{enumerate}

We will formally define $\Gamma^*$, the exit boundary of a PDMP, shortly. To see how this fits in with a generalized jump process, points in $M_{\textbf s}$ will travel according to flows defined by $\mathcal X_\mathbf s$ until either a Poisson clock with intensity $\lambda$ rings, or the point hits the boundary of $M_\mathbf s$. When such an event occurs, the point jumps to a new position in $E$, determined by $Q$.

The vector fields $\mathcal X_\mathbf s$ are chosen so that for every $z \in M_\mathbf s$, there is a unique integral curve $\phi_\mathbf s(t,z)$ satisfying
\begin{eqnarray}
 \frac d{dt}f(\phi_\mathbf s(t,z)) = \mathcal X _{\mathbf s}f(\phi_\mathbf s(t,z))\\
 \mathbf \phi_\mathbf s(0,z) =  z \nonumber
\end{eqnarray}
for any smooth function $f: \mathbb{R}^{d(\mathbf s)} \rightarrow \mathbb{R}$.  Here we also require that the vector fields are conservative, meaning that there exists a $t>0$ where $\phi_\mathbf s(r,z)$ is defined for $r \in [0,t]$.

 Now let $\partial^*M_\mathbf s$ be the exit boundary of $M_\mathbf s$, defined as
  \begin{equation}
 \partial^*M_\mathbf s =\left \{y \in \partial M_\mathbf s: \phi_\mathbf s(t^-, \textbf{x}) = y \quad \hbox{ for some } (t, \textbf{x}) \in \mathbb{R}_+ \times M_\mathbf s\right \}
\end{equation}
 $\Gamma^*$ is then defined as the exit boundary of our state space:
\begin{equation}
\Gamma^* = \coprod_{\mathbf s \in \mathcal S} \partial ^{*}M_\mathbf s
\end{equation}
At a given state $\mathbf x \in E$, we define the exit time as
\begin{equation}
t^*(\mathbf x) = \inf \{t >0: \phi_\mathbf s(t, \textbf{x}) \in \partial ^{*}M_\mathbf s\}.
\end{equation}
The stochastic process $(X(t))_{t \ge 0}$ with initial condition $X(0) =  (\mathbf s,z)$ is then defined as follows.  For $\mathbf x = (\mathbf s, z)$, define a survivor function $\mathcal F$ as
\begin{equation}
\mathcal F_{\mathbf x}(t) = \begin{cases} \exp\left(-\int_0^t \lambda(\mathbf s,\phi_\mathbf s(r,z))dr\right), & t<t^*(\textbf{x}), \\ 0, & t \ge t^*(\textbf{x}).
\end{cases}
\end{equation}
The rate \ $\lambda:E \rightarrow \mathbb R^+$ is a measurable function, where for every state $\textbf{x} = (\mathbf s,  \textbf{x}) \in E$ there exists $\varepsilon > 0$ where the function $s \rightarrow \lambda(\mathbf s, \phi_\mathbf s(s, \textbf{x}))$ is integrable for $s \in [0,\varepsilon)$.  We also define $Q(A;\textbf{x})$ to be a measurable function of $\textbf{x}$ for each fixed $A \in \mathcal E$ on $\textbf{x} \in E \cup \Gamma^*$, and a probability measure on $(E, \mathcal E)$ for each $X \in E \cup \Gamma^*$.

Now choose a random variable $T_1$ such that $\mathbb{P}[T_1>t] = \mathcal F_\mathbf x(t)$.  Now independently choose an $E$-valued random variable $(L,Z)$ with distribution $Q(\cdot ; \phi_\mathbf s(T_1,z))$.  The trajectory of $X(t)$ for $t \le T_1$ is then
\begin{equation}
X(t) = \begin{cases} (\mathbf s,\phi_\mathbf s(t,z)), & t<T_1 \\
(L,Z), & t = T_1.
\end{cases}
\end{equation}
From $X(T_1)$, we choose the next inter-jump time $T_2-T_1$ and $X(T_2)$ in a similar fashion. It can be shown that the process $X(t)$ is Markov, and in fact, strong Markov (Section 3 of \cite{dav84}).

As a Markov process, the PDMP has an associated infinitesimal generator $\mathcal A$, acting on a domain $\mathcal D(\mathcal A)$, defined as the set of functions $f:E\rightarrow \mathbb R$ where the limit
\begin{equation}
 (\mathcal Af)(\mathbf x)=  \lim_{t\rightarrow 0^+} \frac{\mathbb E^\mathbf x (f(X(t)))-f(\mathbf x)}{t}
\end{equation}
exists for all $\mathbf x \in E$. The infinitesimal generator then takes the form

\begin{equation}\label{generator}
\mathcal Af(\mathbf x) = \mathcal X(f(\mathbf x))   +\lambda(\mathbf x)\int_E (f(y)-f(\mathbf x))Q(dy;\mathbf x)), \quad f \in \mathcal D(\mathcal A).
\end{equation}
From here, we can use Dynkin's formula to derive the
martingale
\begin{equation}\label{martingale}
M_t^f := f(X(t)) - f(X(0))-\int_0^t \mathcal A f(X(s))ds,\quad f \in \mathcal D(\mathcal A).
\end{equation}

The following set of sufficient conditions for membership in $\mathcal D(\mathcal A)$ is given in Rolski et. al. \cite{rolski2009stochastic}
\begin{theorem}\label{fourcond} A function $f: E \rightarrow \mathbb{R}$ satisfies $f \in \mathcal D(\mathcal A)$ if the following hold:

\begin{enumerate}
\item
The function $t \rightarrow f(\phi(x,t))$ is absolutely continuous on $[0,s^*(x))$ for every $\mathbf x \in E$, where $s^*(x) = \inf_t\{t|\mathcal F(t) =0\}$. \item
$f(x)  = \lim_{t \rightarrow 0} f(\phi(x,t))$ exists for all $x \in  \Gamma^*$ \item
(Boundary condition):$f(x)= \int_E f(y) Q(dy,x)$ for $x \in \Gamma^*$\item
(Finite expectation of number of jumps): for all $t \in \mathbb{R}^+, x\in E$,
\begin{equation}
\mathbb{E}\left[\sum_{i = 1}^{m(t)} |f(X(T_i)-f(X(T_{i-1}))|\right]<\infty
\end{equation}
\end{enumerate}
\end{theorem}

\subsection{A note on Skorokhod topologies} \label{j1m1}

\begin{figure}
\begin{centering}
\includegraphics[width=.5\textwidth]{j1m1tops.png}
\caption{\textbf{Topologies for cadlag functions.} \textbf{Left:} Two functions that are ``close" in the J1 topology.  Note that the magnitude of their jumps are similar. \textbf{Right:} Two functions close in the M1 topology.  Jumps are not required to be close in this case, but rather the Hausdorff distances of each function's completed graph. }\label{j1m1}
\end{centering}
\end{figure}

Throughout this thesis, our focus will be on stochastic processes which are cadlag, or are right continuous with lefthand limits. Let $(\mathfrak M,d)$ denote a metric space with metric $d$.   In the following, we use the $J1$ Skorohod topology, denoted $\mathbb D([0,t],\mathfrak M)$. For our purposes, $\mathfrak M$ will either be $\mathbb{R}^+$ or  $\mathcal M(\mathbb{R}^+)$, the space of finite measures on $\mathbb{R}^+$ with the Prohorov metric \cite{billingsley2009convergence}.
The $J1$ topology  allows for convergence of functions that ``wiggle" in time as well as space, and has  the following characterization (see \cite{jac87}):

Let $\mathscr R$ be the set of continuous reparameterizations $r: [0,t]\rightarrow \mathbb{R}^+$: functions that are strictly increasing, where $r(0) = 0$ and $r(t)=t$.  A sequence of functions $\alpha_n \rightarrow \alpha$ in $\mathbb{D}([0,t],\mathfrak M)$ if and only if there is a sequence $r_n \in \mathscr R$ with

\begin{enumerate}
\item $\sup_s |r_n(s)-s| \rightarrow 0,$
\item $\sup_{s \le t} d(\alpha_n(r_n(s)), \alpha(s)) \rightarrow 0.$
\end{enumerate}
as $n \rightarrow \infty$. If $\alpha(t)$ is continuous, the functions actually converge in the local uniform topology. However, in general,  the local uniform topology is strictly stronger than the Skorohod J1 topology, but this fact won't be used, since limiting functions of our interest in this paper will have no jumps (see Remark \ref{unifremark}).