Having outlined a variety of models and metrics tracked for the
purposes of their objective comparison, we proceed to present and discuss our
results in the next sections.

\subsection{Results of Decoupled Sampling}
\label{sec:modelres}

We begin by comparing the performance of a diverse set of surrogate families on previously generated samples of the expensive MC TBR model.
Through the four experimental cases described
in~\cref{sec:experiment-methodology}, we aim to study properties of the
considered models in terms of regression performance, training and prediction
time.

\subsubsection{Hyperparameter Tuning}

The first two experiments perform Bayesian optimisation to maximise~$R^2$ in
a cross-validation setting as a function of model hyperparameters. While in the
first experiment we limit training and test sets to the scope of four selected
slices of the feature space, in the second experiment we lift this restriction
to examine surrogate capability to model a more complex domain.

The results displayed in~\cref{fig:exp1-time-vs-reg} (and listed
in~\cref{tbl:exp1-detailed-results} in the Appendix) indicate that in the first
experiment, GBTs clearly appear to be the most accurate as
well as the fastest surrogate family in terms of mean prediction time. Following
that, we note that ERTs, SVMs and ANNs also achieved satisfactory results with respect to both examined metrics.
While the remainder of tested surrogate families does not exhibit problems in
complexity, its regression performance falls below average.

\begin{figure}[h]
	\centering
	\begin{subfigure}[b]{0.333\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp1_slice0}
		\caption{Run 2, batches 0-2}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.333\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp1_slice1}
		\caption{Run 2, batches 100-102}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.333\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp1_slice2}
		\caption{Run 2, batches 200-202}
	\end{subfigure}
	\caption{20~best-performing surrogates per each considered family, plotted in
		terms of complexity (as~$\overline{t}_{\text{pred.}}$) and regression
		performance (as~$R^2$) on selected slices of run~2, evaluated in
	experiment~1. Here, batches refer to subsets of training and test datasets that
	may be matched to slices using~\cref{tbl:slices}.}
	\label{fig:exp1-time-vs-reg}
\end{figure}

The results of the second experiment, shown in~\cref{fig:exp2-time-vs-reg} (and listed
in~\cref{tbl:exp2-detailed-results} in the Appendix),
seem to confirm our expectations. Compared to the previous case, we observe
that many surrogate families consistently achieved worse regression
performance and prediction times. The least
affected models appear to be GBTs, ANNs and ERTs, which are known to be capable of capturing relationships
involving mixed feature types that were deliberately withheld in the first
experiment. With only negligible differences, the first two of these families
appear to be tied for the best performance as well as the shortest prediction
time. We observe that ERTs and RBFs also
demonstrated satisfactory results, relatively outperforming the remaining surrogates in
terms of regression performance, and in some cases also in prediction time.

\begin{wrapfigure}[10]{r}{0.333\textwidth}
	\centering
	\vspace{-2ex}
	\includegraphics[width=\linewidth]{exp2_time_vs_reg}
	\caption{Results of experiment~2, plotted analogously
	to~\cref{fig:exp1-time-vs-reg}.}
	\label{fig:exp2-time-vs-reg}
\end{wrapfigure}

Following both hyperparameter tuning experiments, we conclude that while domain
restrictions employed in the first case have proven effective in improving the
regression performance of some methods, this result has fluctuated considerably
depending on the selected slices. Furthermore, in all instances the best
results were achieved by families of surrogates that were nearly unaffected by
this modification.

\subsubsection{Scaling Benchmark}

In the third experiment we examine surrogate scaling properties by correlating
metrics of interest with training set size. Firstly, the results shown
in~\cref{fig:scaling-r2} (and listed in~\cref{tbl:exp3-detailed-results-r2} in
the Appendix) suggest that the most accurate families from the previous experiments
consistently maintain their relative advantage over others, even as we introduce
more training points. While such families achieve nearly comparable
performance on the largest dataset, in the opposite case tree-based approaches
clearly outperform ANNs. This can be observed
particularly on sets of sizes up to~\num{6000}.

\begin{figure}[h]
	\centering
	\begin{subfigure}[b]{0.333\textwidth}
		\centering
		\includegraphics[width=\linewidth]{scaling_metric_r2}
		\caption{Regression performance (as $R^2$)}
		\label{fig:scaling-r2}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.333\textwidth}
		\centering
		\includegraphics[width=\linewidth]{scaling_time_train}
		\caption{Complexity (as~$\overline{t}_{\text{trn.}}$)}
		\label{fig:scaling-trn}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.333\textwidth}
		\centering
		\includegraphics[width=\linewidth]{scaling_time_pred}
		\caption{Complexity (as~$\overline{t}_{\text{pred.}}$)}
		\label{fig:scaling-pred}
	\end{subfigure}
	\caption{Various metrics collected during experiment 3 (scaling
	benchmark) displayed as a function of training set size.}
	\label{fig:scaling}
\end{figure}

Next, we examine scaling behaviour in terms of the mean training time (displayed
in~\cref{fig:scaling-trn} and listed in~\cref{tbl:exp3-detailed-results-t-train} in
the Appendix). Consistent with our expectation, the shortest times
were achieved by instance-based learning methods (e.g. KNN, IDW) that
are trained trivially at the expense of increased lookup complexity later during prediction.
Furthermore, we observe that the majority of tree-based algorithms also perform
and scale well, unlike RBFs and GPR which appear to behave superlinearly. We note that ANNs,
which are the only family to utilise parallelisation during training, show an
inverse scaling characteristic. Our conjecture is that this effect may be caused
by a constant multi-threading overhead that possibly dominates the training process
on relatively small training sets.

Finally, we study scaling with respect to the mean prediction time (shown
in~\cref{fig:scaling-pred} and listed in~\cref{tbl:exp3-detailed-results-t-pred} in
the Appendix). Our initial observation is that all tested
families with the exception of previously mentioned instance-based
models offer desirable characteristics overall. Analogous to previous
experiments, GBTs, ABTs and ANNs appear to be tied, as they not only exhibit
comparable times but also similar scaling slopes. Following that, we notice a
clear hierarchy of ERTs, SVMs, GPR and RBFs, trailed by IDW and KNNs.

\subsubsection{Model Comparison}

In the fourth experiment proposed
in~\cref{sec:experiment-methodology}, we exploit previously collected information
to produce surrogates with desirable properties for practical use. We
aim to create models that yield: (a)~the best regression performance regardless
of other features, (b)~acceptable performance with the shortest mean
prediction time, or (c)~acceptable performance with the smallest training set.
To this end, we trained 8~surrogates that are presented in~\cref{fig:reg-performance}
and~\cref{tbl:exp4-detailed-results}.

\begin{figure}[h]
	\centering
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model6}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model7}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model1}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model3}
	\end{subfigure}

	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model4}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model5}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model2}
	\end{subfigure}\hfill%
	\begin{subfigure}[b]{0.25\textwidth}
		\centering
		\includegraphics[width=\linewidth]{exp4_model8}
	\end{subfigure}
	\caption{Regression performance of models 1-4 (row 1, from the left) and 5-8
		(row 2) trained in experiment~4 (model comparison), viewed
		as true vs.~predicted TBR on a test set of a selected cross-validation
		fold. Points are coloured by density.}
	\label{fig:reg-performance}
\end{figure}

Having selected ANNs, GBTs, ERTs, RBFs and SVMs based on the results of
experiments~2-3, we utilised the best-performing hyperparameters.
In pursuit of goal~(a), the best approximator (no.~1,
ANN) achieved~$R^2=\num{0.998}$ and mean prediction
time~$\overline{t}_{\text{pred.}}=\SI{1.124}{\micro\second}$. These correspond
to a standard error~$S=\num{0.013}$ and a relative speedup~$\omega=\num{6916416} \times$
with respect to the MC TBR evaluation baseline measured during run~1
(see~\cref{tbl:sampling-runs} for details). Satisfying
goal~(b), the fastest model (no.~2, ANN) achieved~$R^2=\num{0.985}$,
$\overline{t}_{\text{pred.}}=\SI{0.898}{\micro\second}$, $S=\num{0.033}$
and~$\omega=\num{8659251} \times$.
While these surrogates
were trained on the entire available set of~\num{500000} datapoints, to satisfy
goal~(c) we also trained a more simplified model (no.~4, GBT)
that achieved~$R^2=\num{0.913}$,
$\overline{t}_{\text{pred.}}=\SI{6.125}{\micro\second}$, $S=\num{0.072}$ and $\omega=\num{1269777} \times$
with a set of size only~\num{10000}.

\begin{table}[h]
	\centering
	\sisetup{round-mode=places,round-precision=3,detect-weight=true,detect-family=true}
	\setlength\tabcolsep{2pt}
	{\scriptsize
		\begin{tabular}{lrrrrrrrr}
		\toprule
		{} & {} & \multicolumn{4}{c}{Regression performance} &
		\multicolumn{3}{c}{Complexity}\\
		\cmidrule(lr){3-6}
		\cmidrule(lr){7-9}
		Model & $|\mathcal{T}|$ & MAE [TBR] & $S$ [TBR] & $R^2$ [rel.] & $R^2_{\text{adj.}}$ [rel.]
						& $\overline{t}_{\text{trn.}}$ [\si{\milli\second}] &
		$\overline{t}_{\text{pred.}}$ [\si{\milli\second}] & $\omega$ [rel.]\\
		\midrule
		\input{tbl/table11}
		\bottomrule
		\end{tabular}
	}
	\caption{Results of experiment~4. Here, figures are reported over 5~cross-validation folds,
		$|\mathcal{T}|$~denotes cross-validation set size ($\times 10^3$)
		and $\omega$ is a relative speedup with respect to
		$\overline{t}_{\text{eval.}}=\SI{7.777049573054314}{\second}$
		measured in the MC TBR model during run~1 (see~\cref{tbl:sampling-runs}).
		The best-performing metrics are highlighted in bold.}
	\label{tbl:exp4-detailed-results}
\end{table}

Overall we found that due to their superior performance, boosted tree-based
approaches seem to be advantageous for fast surrogate modelling on relatively small training
sets (up to the order of~$10^4$). Conversely, while neural networks perform
poorly in such a setting, they dominate on larger training sets (at least of the
order of~$10^5$) both in terms of regression performance and mean prediction time.

\begin{wrapfigure}[10]{r}{0.4\textwidth}
	\centering
	\vspace{-16ex}
	\includegraphics[width=\linewidth]{fig5_sintoy}
	\caption{Sinusoidal toy TBR theory over two continuous parameters,
	$n=1$.}
	\label{fig:sintoy}
\end{wrapfigure}

\subsection{Results of Adaptive Sampling}
\label{sec:adaptiveres}
In order to test our QASS prototype, several functional toy theories for TBR were developed as alternatives to the expensive MC model. By far the most robust of these was the following sinusoidal theory with adjustable wavenumber parameter $n$:

\begin{equation}
	\text{TBR} = \frac{1}{|C|}\sum_{i \in C} \left[1 + \sin(2\pi n (x_i - 1/2)) \right]
\end{equation}

plotted in~\cref{fig:sintoy} for $n=1$ and two continuous parameters $C$.
ANNs trained on this model demonstrated similar performance to those on the expensive
MC model. QASS performance was verified by training a $\text{1h3f}(256)$ ANN on
the sinusoidal theory for varied quantities of initial, incremental, and MCMC
candidate samples. Although the scope of this project did not include thorough
searches of this hyperparameter domain, sufficient runs were made to identify
some likely trends.

An increase in initial samples with increment held constant had a strong impact
on final surrogate precision, an early confirmation of basic functionality. An
increase in MCMC candidate samples was seen to have a positive but very weak
effect on final surrogate precision, suggesting that the runtime of MCMC on each
iteration can be limited for increased efficiency. The most complex dynamics
arose with the adjustment of sample increment, shown in~\cref{fig:qassincr}. For
each tested initial sample quantity $N$, the optimal number of step samples was seen to be well-approximated by $\sqrt{N}$. The plotted error trends suggest that
incremental samples larger than this optimum give slower model improvement on both the training and evaluation sets, and a larger minimum error on the evaluation set. This performance distinction is predicted to be even more significant when trained on the expensive MC model, where the number of sample evaluations will serve as the primary bottleneck for computation time.
\begin{figure}[h!]
    \centering
    \vspace{-1ex}
    \begin{subfigure}[t]{0.5\textwidth}
        \centering
        \includegraphics[width=1.1\linewidth]{fig6a_qassincrsamp.pdf}
    \end{subfigure}%
    \hfill%
    \begin{subfigure}[t]{0.5\textwidth}
        \centering
        \includegraphics[width=1.1\linewidth]{fig6b_qassincrtime.pdf}
    \end{subfigure}
    \caption{QASS absolute training error over total sample quantity (left) and number of iterations (right). MAE represents surrogate error on the adaptively-sampled training/test set, and E\_MAE on the independent evaluation sets.}
    \label{fig:qassincr}
    \vspace{-1ex}
\end{figure}

The plateau effect in surrogate error on the evaluation set, seen
in~\cref{fig:qassincr}, was universal to all configurations and thought to
warrant further investigation. At first this was suspected to be a residual
effect of retraining the same ANN instance without adjustment to data
normalisation. A ``Goldilocks scheme'' for checking normalisation drift was
implemented and tested, but did not affect QASS performance. Schemes in which
the ANN is periodically retrained were also discarded, as the retention of
network weights from one iteration to the next was demonstrated to greatly
benefit QASS efficiency. Further insight came from direct comparison between
QASS and a baseline scheme with uniformly random incremental samples, shown
in~\cref{fig:qasssampling}.

\begin{figure}[h]
\centering
\begin{minipage}{.48\textwidth}
  \centering
  \includegraphics[width=1.1\linewidth]{fig7_qasssampling.pdf}
  \captionof{figure}{Absolute training error for QASS, baseline scheme, and mixed scheme.}
  \label{fig:qasssampling}
\end{minipage}%
\hfill%
\begin{minipage}{.48\textwidth}
  \centering
  \includegraphics[width=1.1\linewidth]{fig8_qasssampling100k.pdf}
  \captionof{figure}{Absolute training error for QASS and baseline scheme, with 100k initial samples.}
  \label{fig:qasssampling100k}
\end{minipage}
\end{figure}

Such tests revealed that while QASS has unmatched performance on its own
adaptively-sampled training set, it is outperformed by the baseline scheme on
uniformly-random evaluation sets. We suspected that while QASS excels in
learning the most strongly peaked regions of the TBR theory, this comes at the
expense of precision in broader, smoother regions where uniformly random
sampling suffices. Therefore a mixed scheme was implemented, with half MCMC
samples and half uniformly random samples incremented on each iteration, which
is also shown in~\cref{fig:qasssampling}. An increase in initial sample size was observed to also resolve precision in these smooth regions of the toy theory, as the initial samples were obtained from a uniform random distribution. As shown in ~\cref{fig:qasssampling100k}, with~\num{100000} initial samples it was possible to obtain a ${\sim}40\%$ decrease in error as compared to the baseline scheme, from 0.0025 to 0.0015 mean averaged error. Comparing at the point of termination for QASS, this corresponds to a ${\sim}6\%$ decrease in the number of total samples needed to train a surrogate with the same error.


\documentclass{standalone}
\begin{document}
	\subsection{Training}
	This script allows for estimating the set of centroids. It requires as input a path to the training dataset. Each training scan must be saved in a format supported by \textsc{SimpleITK}. This script will return as output the set of centroids in \textit{.npy} format.

	This script will read the training dataset, construct the multichannel image, create the subsamples and cluster them independently. Notice that during the clustering process the background must be removed. This script is summarized in \ref{alg:training}.

		\begin{algorithm}[h!]

		\SetAlgoLined
		\DontPrintSemicolon

		\KwData{CT scans with Extracted lung}
		\KwResult{Centroid matrix}\;

		\ForEach{$scan \in input\_scans$}{

			read the scan\;
			sample$\leftarrow$image\_array\;
		}\;
		\tcc{prepare subsamples}
		sample$\leftarrow$ build\_multichannel(sample)\;
		sample$\leftarrow$shuffle(sample)\;
		subsamples$\leftarrow$split(sample)\;

		\tcc{start the first clustering}
		\ForEach{$ Sub \in subsamples $}
		{
			center$\leftarrow$kmeans(sub, number of centroids)\;
			centroid\_vector, internal\_variance$\leftarrow$append(center)

		}\;

		\tcc{Refinement}
		centroid\_matrix$\leftarrow$centroid\_vactor($\min(internal\_variance$))\;

		\caption{training}\label{alg:training}

	\end{algorithm}

	The clustering process is managed by the \textsc{kmeans\_on\_subsamples} function, implemented as follows.
	\lstset{style=python}
	\begin{lstlisting}[language=python, caption=kmenas\_on\_subsamples, label=code:kmeans]

	import cv2
	import numpy as np
	from tqdm import tqdm

	def kmeans_on_subsamples(imgs,  n_centroids, stopping_criteria,
							 centr_init, weight = None) :

		if weight is not None :
			vector = np.asarray([ el[w != 0]
								for el, w in zip(imgs, weight)],
								dtype = np.ndarray)
		else :
			vector = np.asarray([el.reshape((-1, el[-1]))
									for el in imgs],
									dtype=np.ndarray)

		centroids = []
		ret = []
		for el in tqdm(vector) :

			r, _, centr = cv2.kmeans(el.astype(np.float32), n_centroids,
									None, stopping_criteria,
									10, centr_init)
			centroids.append(centr)
			ret.append(r)

		final_center = centroids[np.argmin(ret)]

		return np.asarray(final_center, dtype= np.float32)

	\end{lstlisting}
	This function takes as input the array containing the subsamples and apply k-means clustering on each of them, storing all the values.
	To remove the background, it uses a weight tensor. The values of this tensor must be $0$ for the voxel corresponding to the background, and $1$ otherwise.
	At the end of the procedure, the centroid set which provides the minim value of the sum of square error is selected.

\end{document}


\documentclass[reqno]{article}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage{blindtext}
\usepackage{amsmath}
\usepackage{relsize} %bigger math symbols
\usepackage{bm} %bolder text
\usepackage[a4paper, inner=1.7cm, outer=2.7cm, top=3cm, bottom=3cm, bindingoffset=1.2cm]{geometry}
\usepackage{tcolorbox}
\usepackage{graphicx}
\usepackage{wrapfig}
\usepackage{enumitem}
\newlist{terms}{description}{1}
\begin{document}
\title{\textbf{Scalable Reward Distribution with Compounding Stakes}}
\author{Richard Pardoe \thanks{rick@liquity.org}}
\date{December 2020\\v1.0}
\maketitle
\begin{abstract}
    Scalability of Ethereum dApps is constrained by the gas costs of writing to storage.
    In previous work, Batog $\cite{Batog}$ and Solmaz $\cite{Solmaz}$ solved the problem of scalable reward distribution in a staking pool, distributing rewards in proportion to a staker’s share of total stakes with a ``pull'' based approach. Only a single running sum need be updated at each reward, sidestepping the need for an expensive $O(n)$ storage update for n stakers. However, their work stopped short of solving the problem for a compounding stake.
    Here we derive formulas for a scalable implementation of a compounding, decreasing Stability Pool deposit and its corresponding ETH gain. Thus, Liquity tracks the deposits and rewards of every depositor with only $O(1)$ complexity for each liquidation.
\end{abstract}

\section{Introduction}
The Liquity protocol uses a Stability Pool as its primary mechanism to liquidate collateralized debt positions (called ``troves'') that fall below the minimum collateralization ratio of 110$\%$ $\cite{Whitepaper}$. Stability deposits (provided in LUSD) absorb and cancel the debt (in LUSD) from defaulted troves: an amount of LUSD in the Stability Pool corresponding to the debt of the liquidated trove is burned from the pool’s balance, offsetting the debt. In return, Stability Pool depositors are rewarded with the acquisition of collateral (in ETH) from liquidated positions at a significant discount. The proportion of a stability depositor’s current deposit to the total LUSD in the pool determines the collateral share it receives from the liquidation.

The fact that liquidated troves decrease all deposits in the Stability Pool leads to an implementation challenge: Due to Ethereum's block gas limit, it becomes impossible to iterate over all deposits in the Stability Pool for a large number of deposits. Such an operation has computational complexity of $O(n)$ and does not scale.

This paper presents a method to perform liquidations against the Stability Pool in a scalable manner with only $O(1)$ complexity. The method is ``pull-based": Instead of adjusting all stability deposits upon every liquidation, the update is deferred to the moment at which an owner withdraws or tops up their deposit.

The methods presented in this paper are generalizable and can be used for other dApps running on Ethereum.

\section{Derivation}
For a pull-based implementation in Liquity’s Stability Pool, we must factor out the initial deposit, and track reward terms that are independent from the individual deposit values. We derive formulas for a compounding LUSD deposit and corresponding ETH gain as functions of the initial deposit, and involving a product $P$ and a sum $S$: the former is a function of the LUSD losses, and the latter is a function of $P$, the ETH rewards, and the total deposits.

\bigskip
\raggedright %align to the left side

\textbf{Terms}
\begin{terms}
    \item $d_i:$ A given user’s LUSD deposit at liquidation event \textit{i}\\
    \item $Q_i:$ The LUSD debt absorbed by the Stability Pool from liquidation \textit{i}\\
    \item $E_i:$ The ETH sent to the Stability Pool from liquidation \textit{i}\\
    \item $D_i:$ Total LUSD deposits at liquidation \textit{i}
\end{terms}

\bigskip
Let $d_0$ represent the user’s initial Stability Pool deposit. After the first liquidation, their new
deposit $d_0$ is given by:\\
\begin{equation}
    d_1=d_0-LUSDLoss
\end{equation}

\bigskip
Liquidation assigns an LUSD loss to the deposit proportional to the prior share of total deposits:
\begin{equation} \label{eq:2}
    d_1=d_0-Q_1\frac{d_0}{D_0}
\end{equation}
\begin{equation}
    d_1=d_0\left(1-\frac{Q_1}{D_0}\right)
\end{equation}

\bigskip
Since the deposit compounds, the deposit value after liquidation 2 is a function of the previous deposit value:
\begin{equation}
    d_2=d_1\left(1-\frac{Q_2}{D_1}\right)
\end{equation}

\bigskip
and substituting equation (\ref{eq:2}):
\begin{equation}
    d_2=d_0 \left(1-\frac{Q_2}{D_1}\right) \left(1-\frac{Q_1}{D_o} \right)
\end{equation}

\bigskip
Similarly:
\begin{equation}
    d_3=d_2\left(1-\frac{Q_3}{D_2}\right)
\end{equation}
\begin{equation}
    d_3=d_0\left(1-\frac{Q_3}{D_2}\right)\left(1-\frac{Q_2}{D_1}\right)\left(1-\frac{Q_1}{D_0}\right)
\end{equation}

\bigskip
And the general case for a compounded deposit:
\begin{equation} \label{eq:8}
    d_n=d_0\prod^n_{i=1}{\left(1-\frac{Q_i}{D_{i-1}}\right)}
\end{equation}
\subsection{Compounded deposit for initial deposit made at $t>0$}
For a deposit made between liquidations $[t, t+1]$, which is withdrawn between liquidations $[s, s+1]$, rewards are earned from liquidations $t+1, t+2, \ldots, s$.

We take a snapshot of the product at liquidation $t$, and calculate the compounded stake at liquidation $n$, with $t < n \leq s$, as:

\begin{equation}
    d_n=d_t\prod^n_{i=t+1}{\left(1-\frac{Q_i}{D_{i-1}}\right)}=d_t\frac{\displaystyle\prod^n_{i=1}{\left(1-\frac{Q_i}{D_{i-1}}\right)}}{\displaystyle\prod^t_{i=1}\left(1-\frac{Q_i}{D_{i-1}}\right)}
\end{equation}
This assumes that every multiplicand is non-zero, i.e. that $Q_i < D_{i-1}$ for all $i$ (see section 3.1 for the case where $Q_i = D_{i-1}$ and the pool is emptied).

\bigskip
Labelling the product term $P_k$, i.e: $P_k = \displaystyle\prod^k_{i=1}{\left(1-\frac{Q_i}{D_{i-1}}\right)}$, yields:

\begin{equation} \label{eq:10}
d_n=d_t\frac{P_n}{P_t}
\end{equation}

\bigskip
Where $P_n$ is the product at liquidation $n$, and $P_t$ is the snapshot of the product at the time when the user made the deposit.

\bigskip
\subsection{Corresponding ETH Gain}

\bigskip
The LUSD deposit earns an ETH gain at each liquidation.
At each liquidation $i$, the user’s LUSD deposit effectively decreases. Thus we can write the
user’s cumulative ETH gain $e_{n}$, from a series of \textit{n} liquidations, as:
\begin{equation}
e_n=d_0\left(\frac{E_1}{D_0}\right)+d_1\left(\frac{E_2}{D_1}\right)+d_2\left(\frac{E_3}{D_2}\right)+...+d_{n-1}\left(\frac{E_n}{D_{n-1}}\right)
\end{equation}

\bigskip
Then, using our expression for the deposit from equation (\ref{eq:8}):
\begin{equation}
e_n=d_0\left(\frac{E_1}{D_0}\right)+d_0\left(\frac{E_2}{D_1}\right)\prod^1_{i=1}\left(1-\frac{Q_i}{D_{i-1}}\right)+d_0\left(\frac{E_3}{D_2}\right)\prod^2_{i=1}\left(1-\frac{Q_i}{D_{i-1}}\right)+...+d_0\left(\frac{E_n}{D_{n-1}}\right)\prod^{n-1}_{i=1}\left(1-\frac{Q_i}{D_{i-1}}\right)
\end{equation}

\bigskip
And factoring out the initial deposit, $d_0$:
\begin{equation} \label{eq:13}
    e_n=d_0\sum^n_{k=1}\left[\frac{E_k}{D_{k-1}}\prod^{k-1}_{i=1}\left(1-\frac{Q_i}{D_{i-1}}\right)\right] = d_0\sum^n_{k=1}\left[\frac{E_k}{D_{k-1}}P_{k-1}\right]
\end{equation}

\bigskip
Where the initial product term $\displaystyle\prod^0_{i=1}(...)=1$.

\bigskip
Thus, we have the depositor's cumulative ETH gain $e_n$ as a function of the initial deposit $d_0$, and the rewards and total deposits at each liquidation.\\
Let the summation $\displaystyle\sum^n_{k=1}[...]$ be denoted $S_n$.

\bigskip
\subsection{ETH gain for initial deposit made at $t>0$}

\bigskip
For a deposit made between liquidations $[t, t+1]$, which is withdrawn between liquidations $[s, s+1]$, rewards are earned from liquidations $t+1, t+2, \ldots, s$.

We take a snapshot of the product at liquidation $t$, and calculate the compounded stake at liquidation $n$, with $t < n \leq s$, as:

\bigskip
To account for the deposit entering after liquidations have already begun, we correct the product terms in (\ref{eq:13}) to $\frac{P_n}{P_t}$, as per (\ref{eq:10}):
\begin{equation}
    e_n = d_t\sum^n_{k=t+1}\left[\frac{E_k}{D_{k-1}}\frac{P_{k-1}}{P_t}\right]
\end{equation}

\bigskip
We take a snapshot of the sum at liquidation $t$, $S_t$. Then, the ETH gain earned by the deposit at liquidation $n$ is:
\begin{equation}
e_n=d_t\frac{S_n-S_t}{P_t}
\end{equation}

\bigskip
\section{Basic Implementation}
\underline{Making a deposit:}

Record deposit: deposit[user] = $d_t$\\
Update total deposits: $D = D + d_t$\\
Record product snapshot: $P_t = P$\\
Record sum snapshot: $S_t = S$

\bigskip
\underline{Upon each liquidation yielding LUSD debt ‘Q’ offset with the Stability Pool and ETH gain ‘E’:}

Update $S$: $S = S + \frac{E}{D}P$ (\textit{intuition: a deposit’s marginal ETH gain is equal to the deposit $\times$ ETH per unit staked $\times$ current correction factor)}\\
Update $P$: $P = P(1 - \frac{Q}{D})$\\
Update total deposits: $D = D - Q$

\bigskip
\underline{Withdrawing the deposit and ETH gain:}

Compute final compounded LUSD deposit $d$: $d = d_t\frac{P}{P_t}$\\
Compute final corresponding cumulative ETH gain $e$: $e = d_t\frac{S - S_t}{P_t}$\\
Send $d$ and $e$ to user\\
Update deposit: deposit[user] = 0\\
Update total deposits: $D = D - d$\\

\bigskip
\section{Practical Implementation in Liquity}
Two further considerations are needed for our implementation:
\begin{enumerate}
    \item Liquidations that completely empty the Stability Pool
    \item How to handle the eternally decreasing product $P$, without truncating to 0
\end{enumerate}

\bigskip
\subsection{Liquidations that completely empty the Pool}

\bigskip
\textbf{Problem}: Pool-emptying should reduce all deposits to 0, but we should not set $P$ to 0. Doing so would break deposit computations for all future deposits: as $P$ is a running product, all snapshots and future values would be 0.

\bigskip
\textbf{Solution}: Complete pool-emptying is handled by tracking a “current epoch” variable. The ETH gain reward sum $S$ for each epoch is stored in a mapping.

\bigskip
Upon a pool-emptying liquidation, $S$ is first updated as usual, for the current epoch. Then, the current epoch is incremented by 1, and $P$ and $S$ terms are reset for the new epoch. By definition, deposits that were made in past epochs will have been completely cancelled with liquidated debt, and so reduced to 0.

\bigskip
\underline{Making a deposit:}

Record a snapshot of the current epoch for the deposit

\bigskip
\underline{Liquidation that empties the Pool:}

Compute the latest value of $S$, and store it for the current epoch.
Increase the epoch by 1, and reset the product and sum ($P$ = 1, $S$ = 0).

\bigskip
\underline{Withdrawing Deposit:}

When users withdraw, check their epoch snapshot against the current epoch: If equal, deposit and ETH gain are computed as normal.

\bigskip
If the current epoch is greater than the deposit’s epoch snapshot, then the deposit was made before the pool-emptying liquidation. Therefore:
\begin{itemize}
    \item The \textbf{compounded deposit} is 0, as the deposit has been fully used to absorb debt.
    \item The user’s \textbf{ETH gain} is computed using the $S$ sum that corresponds to the epoch in which their deposit was made.
\end{itemize}

\bigskip
\subsection{Eternally decreasing the product $P$, without truncating to 0}

\bigskip
At liquidation $i$, $P$ is multiplied by some new term $0 < p_i <1$. Thus in theory, $P$ is always decreasing, but should never reach 0.

\bigskip
\textbf{Problem:} We cannot represent an arbitrarily small value in Solidity.  Eventually, division will truncate a small value to 0. If so, all future values of $P$ would be 0, and deposit computation would break.

\bigskip
\textbf{Solution:} use a “current scale” that allows $P$ to decrease indefinitely, but never reach 0. Each scale represents a division by 1e18.

\bigskip
Upon a liquidation that would otherwise truncate $P$ to 0, $S$ is first updated as usual, for the current scale. Then, the current scale is incremented by 1, and $P$ is updated and scaled by 1e18.

\bigskip
\underline{Making a deposit:}

Record a snapshot of the current scale for the deposit

\bigskip
\underline{Liquidation:}

Compute the latest value of $S$, and store it for the current scale.
Liquidation $L_i$ causes the product $P$ to be multiplied by some new product factor $p_i$.  If $P$ $\times$ $p_i$ would be truncated to 0, instead do: $P = (P \times p_i \times 1e18)$, and increment the current scale by 1.

\bigskip
\underline{Withdrawing a deposit:}

First, compute the number of scale changes made during the deposit’s lifetime, i.e. (currentScale - scaleSnapshot).

\bigskip
If the number of scale changes is 0, compute the deposit and ETH gain as normal.

\bigskip
Otherwise:

\bigskip
\textbf{Compounded deposit:} If a scale change in $P$ was made during the deposit's lifetime, account for it in the deposit computation. If the deposit has decreased by a factor of $<$ 1e-18 (i.e. if more than one scale change was made) just return 0.

\bigskip
\textbf{ETH Gain:} Since the deposit may span up to one scale change, so too does the reward. In this case, obtain the ETH gain using the $S$ sums from the two consecutive scales that the deposit spans. The reward from the second sum is scaled by 1e-18. The rewards from both scales are added to make the final ETH gain.

\bigskip
\section{Putting it all together}

\bigskip
The implementation relies on a nested mapping: epochToScaleToSum.

\bigskip
The inner mapping stores the sum $S$ at different scales, for a given epoch. The outer mapping stores the ($scale \Rightarrow sum$) mappings for each epoch.

\bigskip
This allows us to track the ETH reward terms at each scale and epoch.Thus we can correctly compute the ETH rewards for a compounding decreasing stake, taking account of periodic Pool-emptying, and getting around the limitations of Solidity arithmetic.

\bigskip
All implementation logic above is combined in PoolManager.sol, in the functions:

\bigskip
$\_getCompoundedLUSDDeposit()$

$\_getDepositorETHGain()$

$\_updateRewardSumAndProduct()$

\section{Acknowledgements}
We would like to thank Daniel Simon, Robert Lauko, Bingen Eguzkitza and Onur Solmaz for the helpful discussion on reward distributions and Bojan Peček for his help with preparing this paper.

\begin{thebibliography}{9}
\bibitem{Batog}
B. Batog, L. Boca, N. Johnson.
\textit{Scalable Reward Distribution on the Ethereum Blockchain, 2018}.
http://batog.info/papers/scalable-reward-distribution.pdf

\bibitem{Solmaz}
O. Solmaz.
\textit{Scalable Reward Distribution with Changing Stake Sizes”, 2019}.
https://solmaz.io/2019/02/24/scalable-reward-changing/

\bibitem{Whitepaper}
R. Lauko, R. Pardoe.
\textit{Liquity: Decentralized Borrowing Protocol (Whitepaper), 2020}.
https://docsend.com/view/bwiczmy

\end{thebibliography}

\end{document}


\documentclass{article}
\usepackage{amsmath,amssymb}
\newcommand{\stepthecounter}[2]{\stepcounter{#1} #2 \texttt{.}}
\begin{document}
\section{Seminaive Evaluation}
\subsection{Non-Distributed Algorithm}
\newcounter{mycounter}
\[
\begin{array}{ll}
\stepthecounter{mycounter}{\themycounter} & ARGUMENTS : (P, I) \\
\stepthecounter{mycounter}{\themycounter} & RETURN : P(I) \\
\stepthecounter{mycounter}{\themycounter} & P^{'} := \{ rule : rule \in rules(P) \land idb(P) \cap body(rule) = \emptyset \} \\
\stepthecounter{mycounter}{\themycounter} & \forall S \in idb(P) : S := \emptyset \\
\stepthecounter{mycounter}{\themycounter} & \forall S \in idb(P) : \Delta^{1}_{S} := P'(I)(S) \\
\stepthecounter{mycounter}{\themycounter} & i := 1 \\
\stepthecounter{mycounter}{\themycounter} & \texttt{DO} \\
\stepthecounter{mycounter}{\themycounter} & \quad \texttt{FOR } S \in idb(P) \\
\stepthecounter{mycounter}{\themycounter} & \quad \texttt{BEGIN} \\
\stepthecounter{mycounter}{\themycounter} & \quad \quad P_{S} := \{ rule : rule \in rules(P) \land S = head(rule) \} \\
\stepthecounter{mycounter}{\themycounter} & \quad \quad T := \bigcup_{rule \in P_{S}} body(rule) \\
\stepthecounter{mycounter}{\themycounter} & \quad \quad S^{i} := S^{i-1} \cup \Delta^{i}_{S} \\
\stepthecounter{mycounter}{\themycounter} & \quad \quad \Delta^{i+1}_{S} := P^{i}_{S}(I, T^{i-1}, T^{i}, \Delta^{i}_{T}) - S \\
\stepthecounter{mycounter}{\themycounter} & \quad \texttt{END} \\
\stepthecounter{mycounter}{\themycounter} & \quad i := i + 1 \\
\stepthecounter{mycounter}{\themycounter} & \texttt{UNTIL } \forall S \in idb(P) : \Delta^{i}_{S} = \emptyset \\
\end{array}
\]
\newline
% @@TODO: also do \subsection{Distributed Blocking Algorithm}
\subsection{Distributed Streaming Algorithm}
% @@TODO
\[
\begin{array}{l}
\texttt{REMOVE I AS ARGUMENT AND USE IO DIRECTIVES HERE} \\
ARGUMENTS : (P, I) \\
RETURN : P(I) \\
P^{'} := \{ rule : rule \in rules(P) \land idb(P) \cap body(rule) = \emptyset \} \\
\forall S \in idb(P) : S := \emptyset \\
\forall S \in idb(P) : \Delta^{1}_{S} := P'(I)(S) \\
\texttt{CONSUME AND MERGE ALL INPUT RELATIONS HERE} \\
i := 1 \\
\texttt{DO} \\
\quad \texttt{FOR } S \in idb(P) \\
\quad \texttt{BEGIN} \\
\quad \quad P_{S} := \{ rule : rule \in rules(P) \land S = head(rule) \} \\
\quad \quad T := \bigcup_{rule \in P_{S}} body(rule) \\
\quad \quad S^{i} := S^{i-1} \cup \Delta^{i}_{S} \\
\quad \quad \Delta^{i+1}_{S} := P^{i}_{S}(I, T^{i-1}, T^{i}, \Delta^{i}_{T}) - S \\
\quad \quad \texttt{PRODUCE DELTA i + 1 HERE} \\
\quad \quad \texttt{CONSUME AND MERGE WITH DELTA i + 1 HERE} \\
\quad \texttt{END} \\
\quad i := i + 1 \\
\texttt{UNTIL } \forall S \in idb(P) : \Delta^{i}_{S} = \emptyset \\
\end{array}
\]
\end{document}


\achapter{Polymorphic Universes}
\aauthor{Matthieu Sozeau}

\label{Universes-full}
\index{Universes!presentation}

\asection{General Presentation}

\begin{flushleft}
  \em The status of Universe Polymorphism is experimental.
\end{flushleft}

This section describes the universe polymorphic extension of Coq.
Universe polymorphism allows writing generic definitions making use of
universes and reuse them at different and sometimes incompatible levels.

A standard example of the difference between universe \emph{polymorphic} and
\emph{monomorphic} definitions is given by the identity function:

\begin{coq_example*}
Definition identity {A : Type} (a : A) := a.
\end{coq_example*}

By default, constant declarations are monomorphic, hence the identity
function declares a global universe (say \texttt{Top.1}) for its
domain. Subsequently, if we try to self-apply the identity, we will get
an error:

\begin{coq_eval}
Set Printing Universes.
\end{coq_eval}
\begin{coq_example}
Fail Definition selfid := identity (@identity).
\end{coq_example}

Indeed, the global level \texttt{Top.1} would have to be strictly smaller than itself
for this self-application to typecheck, as the type of \texttt{(@identity)} is
\texttt{forall (A : Type@{Top.1}), A -> A} whose type is itself \texttt{Type@{Top.1+1}}.

A universe polymorphic identity function binds its domain universe level
at the definition level instead of making it global.

\begin{coq_example}
Polymorphic Definition pidentity {A : Type} (a : A) := a.
About pidentity.
\end{coq_example}

It is then possible to reuse the constant at different levels, like so:

\begin{coq_example}
Definition selfpid := pidentity (@pidentity).
\end{coq_example}

Of course, the two instances of \texttt{pidentity} in this definition
are different. This can be seen when \texttt{Set Printing Universes} is
on:

\begin{coq_example}
Print selfpid.
\end{coq_example}

Now \texttt{pidentity} is used at two different levels: at the head of
the application it is instantiated at \texttt{Top.3} while in the
argument position it is instantiated at \texttt{Top.4}. This definition
is only valid as long as \texttt{Top.4} is strictly smaller than
\texttt{Top.3}, as show by the constraints. Note that this definition is
monomorphic (not universe polymorphic), so in turn the two universes are
actually global levels.

Inductive types can also be declared universes polymorphic, on universes
appearing in their parameters or fields. A typical example is given by
monoids:

\begin{coq_example}
Polymorphic Record Monoid := { mon_car :> Type; mon_unit : mon_car;
  mon_op : mon_car -> mon_car -> mon_car }.
Print Monoid.
\end{coq_example}

The \texttt{Monoid}'s carrier universe is polymorphic, hence it is
possible to instantiate it for example with \texttt{Monoid} itself.
First we build the trivial unit monoid, in \texttt{Set}:
\begin{coq_example}
Definition unit_monoid : Monoid :=
  {| mon_car := unit; mon_unit := tt; mon_op x y := tt |}.
\end{coq_example}

From this we can build a definition for the monoid of
\texttt{Set}-monoids (where multiplication would be given by the product
of monoids).

\begin{coq_example*}
Polymorphic Definition monoid_monoid : Monoid.
  refine (@Build_Monoid Monoid unit_monoid (fun x y => x)).
Defined.
\end{coq_example*}
\begin{coq_example}
Print monoid_monoid.
\end{coq_example}

As one can see from the constraints, this monoid is ``large'', it lives
in a universe strictly higher than \texttt{Set}.

\asection{\tt Polymorphic, Monomorphic}
\comindex{Polymorphic}
\comindex{Monomorphic}
\optindex{Universe Polymorphism}

As shown in the examples, polymorphic definitions and inductives can be
declared using the \texttt{Polymorphic} prefix. There also exists an
option \texttt{Set Universe Polymorphism} which will implicitly prepend
it to any definition of the user. In that case, to make a definition
producing global universe constraints, one can use the
\texttt{Monomorphic} prefix. Many other commands support the
\texttt{Polymorphic} flag, including:

\begin{itemize}
\item \texttt{Lemma}, \texttt{Axiom}, and all the other ``definition''
  keywords support polymorphism.
\item \texttt{Variables}, \texttt{Context}, \texttt{Universe} and
  \texttt{Constraint} in a section support polymorphism.  This means
  that the universe variables (and associated constraints) are
  discharged polymorphically over definitions that use them. In other
  words, two definitions in the section sharing a common variable will
  both get parameterized by the universes produced by the variable
  declaration. This is in contrast to a ``mononorphic'' variable which
  introduces global universes and constraints, making the two
  definitions depend on the \emph{same} global universes associated to
  the variable.
\item \texttt{Hint \{Resolve, Rewrite\}} will use the auto/rewrite hint
  polymorphically, not at a single instance.
\end{itemize}

\asection{Global and local universes}

Each universe is declared in a global or local environment before it can
be used. To ensure compatibility, every \emph{global} universe is set to
be strictly greater than \Set~when it is introduced, while every
\emph{local} (i.e. polymorphically quantified) universe is introduced as
greater or equal to \Set.

\asection{Conversion and unification}

The semantics of conversion and unification have to be modified a little
to account for the new universe instance arguments to polymorphic
references. The semantics respect the fact that definitions are
transparent, so indistinguishable from their bodies during conversion.

This is accomplished by changing one rule of unification, the
first-order approximation rule, which applies when two applicative terms
with the same head are compared. It tries to short-cut unfolding by
comparing the arguments directly. In case the constant is universe
polymorphic, we allow this rule to fire only when unifying the universes
results in instantiating a so-called flexible universe variables (not
given by the user). Similarly for conversion, if such an equation of
applicative terms fail due to a universe comparison not being satisfied,
the terms are unfolded. This change implies that conversion and
unification can have different unfolding behaviors on the same
development with universe polymorphism switched on or off.

\asection{Minimization}

Universe polymorphism with cumulativity tends to generate many useless
inclusion constraints in general. Typically at each application of a
polymorphic constant $f$, if an argument has expected type
\verb|Type@{i}| and is given a term of type \verb|Type@{j}|, a $j \le i$
constraint will be generated. It is however often the case that an
equation $j = i$ would be more appropriate, when $f$'s
universes are fresh for example. Consider the following example:

\begin{coq_eval}
Set Printing Universes.
\end{coq_eval}
\begin{coq_example}
Definition id0 := @pidentity nat 0.
Print id0.
\end{coq_example}

This definition is elaborated by minimizing the universe of id to level
\Set~while the more general definition would keep the fresh level i
generated at the application of id and a constraint that $\Set \le i$.
This minimization process is applied only to fresh universe
variables. It simply adds an equation between the variable and its lower
bound if it is an atomic universe (i.e. not an algebraic \texttt{max()}
universe).

The option \texttt{Unset Universe Minimization ToSet} disallows
minimization to the sort $\Set$ and only collapses floating universes
between themselves.

\asection{Explicit Universes}

The syntax has been extended to allow users to explicitly bind names to
universes and explicitly instantiate polymorphic definitions.

\subsection{\tt Universe {\ident}.
  \comindex{Universe}
  \label{UniverseCmd}}

In the monorphic case, this command declare a new global universe named
{\ident}. It supports the polymorphic flag only in sections, meaning the
universe quantification will be discharged on each section definition
independently.

\subsection{\tt Constraint {\ident} {\textit{ord}} {\ident}.
  \comindex{Constraint}
  \label{ConstraintCmd}}

This command declare a new constraint between named universes.
The order relation can be one of $<$, $\le$ or $=$. If consistent,
the constraint is then enforced in the global environment. Like
\texttt{Universe}, it can be used with the \texttt{Polymorphic} prefix
in sections only to declare constraints discharged at section closing time.

\begin{ErrMsgs}
\item \errindex{Undeclared universe {\ident}}.
\item \errindex{Universe inconsistency}
\end{ErrMsgs}

\subsection{Polymorphic definitions}
For polymorphic definitions, the declaration of (all) universe levels
introduced by a definition uses the following syntax:

\begin{coq_example*}
Polymorphic Definition le@{i j} (A : Type@{i}) : Type@{j} := A.
\end{coq_example*}
\begin{coq_example}
Print le.
\end{coq_example}

During refinement we find that $j$ must be larger or equal than $i$, as
we are using $A : Type@{i} <= Type@{j}$, hence the generated
constraint. At the end of a definition or proof, we check that the only
remaining universes are the ones declared. In the term and in general in
proof mode, introduced universe names can be referred to in
terms. Note that local universe names shadow global universe names.
During a proof, one can use \texttt{Show Universes} to display
the current context of universes.

Definitions can also be instantiated explicitly, giving their full instance:
\begin{coq_example}
Check (pidentity@{Set}).
Universes k l.
Check (le@{k l}).
\end{coq_example}

User-named universes are considered rigid for unification and are never
minimized.

\subsection{\tt Unset Strict Universe Declaration.
  \optindex{StrictUniverseDeclaration}
  \label{StrictUniverseDeclaration}}

The command \texttt{Unset Strict Universe Declaration} allows one to
freely use identifiers for universes without declaring them first, with
the semantics that the first use declares it. In this mode, the universe
names are not associated with the definition or proof once it has been
defined. This is meant mainly for debugging purposes.

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "Reference-Manual"
%%% End:


\chapter{Examples of figures, tables, equations and listings}
In the following a bunch of examples of figures and tables have been made. There are advantages to using \texttt{tikZ} diagrams over excel diagrams. 1) the font and font size perfectly matches the document 2) the styling and colours are pre-defined to follow the design guide 3) the plots uses vector graphics which reduces the file size, reduces the compile time and looks sharp when zooming in. The possibilities are endless, look at the \texttt{pgfplots} gallery for inspiration: \url{http://pgfplots.sourceforge.net/gallery.html}.
However there are still cases where I would recommend to insert a plot as a picture. For example if the plot contains a lot of data: a line graph with 1000 points takes a long time to compile.

Some tips if you want good looking diagrams or graphs which will be inserted as pictures (e.g. in a figure environment with \textbackslash includegraphics): The main font is Arial. Use DTU colours as described in \cref{sec:colours}. Use high quality pictures. Try to scale the diagram (picture) so the text size of the axis legends match the text size in this document.

Remember to change the label of your figures so there are no duplicate labels. A label should be placed below a caption or after a heading (fx after a \textbackslash chapter).

\section{Graphs and charts}

\pgfplotstableread{
x  {Name 1} {Name 2}    {Name 3}    {Name 4}
1  0.847    0.786       0.367       0.742
2  1.73     0.838       1.27        1.05
3  1.50     0.952       0           0
4  0.506    1.05        0.751       0.698
5  0.672    0.777       0           0
6  0.349    1.62        1.16        0.655
7  0.498    0.480       0.375       0.306
8  0.454    0.925       0.498       0.375
9  0.698    0.716       0.733       0.541
10 0.829    1.12        0.803       0.725
}\stackedColumnData

\begin{figure}[htb]
\centering
\begin{tikzpicture}
\begin{axis}[
    width=15cm, % You could use \linewidth instead
    height=6.6cm,
    ybar stacked,
    xtick = data,
    xticklabels={1,2,3,4,5,6,Var 1,Var 2,Var 3,Var 4},
    ylabel={Some text with a unit $\phi$ },
    ymajorgrids=true,
    legend style={at={(0.5,-0.1)}, anchor=north},
    cycle list name=DTU,
    every axis plot/.append style={fill,draw=none},
    ]
\addplot table[x=x,y={Name 1}]{\stackedColumnData};
\addplot table[x=x,y={Name 2}]{\stackedColumnData};
\addplot table[x=x,y={Name 3}]{\stackedColumnData};
\addplot table[x=x,y={Name 4}]{\stackedColumnData};
\legend{Heating,Ventilation,Lighting,Solar shading}
\end{axis}
\end{tikzpicture}
\caption{Stacked column chart}
\label{fig:stackedcolumn}
\end{figure}

\pgfplotstableread{
y {Name 1} {Name 2} {Name 3} {Name 4}
1 50        20      15       15
2 10        40      25       25
3 40        30      20       10
4 30        10      20       40
5 30        20      10       40
6 20        10      40       30
7 10        10      50       30
}\stackedBarData

\begin{figure}[H]%
\centering
\begin{tikzpicture}
\begin{axis}[
    width=15cm-10pt, % pgfplots widths are only approximate. You might have to fine tune the width of your figures to deal with overfull hbox warnings.
    height = 6.6cm,
    xbar stacked,
    xlabel=Write something here,
    ytick=data,
    yticklabels = {Text 1, Text 2, Text 3, Text 4, Text 5, Text 6, Text 7},
    xmin = 0,
    enlarge x limits=false,
    xmajorgrids=true,
    legend style={at={(0.5,-0.22)}},
    cycle list name=DTU,
    every axis plot/.append style={fill,draw=none},
    ]
\addplot table[x={Name 1},y=y]{\stackedBarData};
\addplot table[x={Name 2},y=y]{\stackedBarData};
\addplot table[x={Name 3},y=y]{\stackedBarData};
\addplot table[x={Name 4},y=y]{\stackedBarData};
\legend{Legend 1, Legend 2, Legend 3, Legend 4}
\end{axis}
\end{tikzpicture}
\caption{Stacked bar chart}
\label{fig:stackedbar}
\end{figure}

\pgfplotstableread{
x    {Far}  {Near}  {Here}
1930 50     38      15
1940 33     42      12
1950 40     43      13
1960 50     45      25
1970 70     65      35
}\groupedColumnData

\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
    width=15cm,
    height=6.6cm,
    ybar,
    xtick=data,
    x tick label style={ /pgf/number format/1000 sep=},
    ylabel=Population,
    ymin=0,
    ymajorgrids=true,
    legend style={at={(0.5,-0.15)},anchor=north,legend columns=-1},
    cycle list name=DTU,
    ]
\addplot table[x=x,y={Far}]{\groupedColumnData};
\addplot table[x=x,y={Near}]{\groupedColumnData};
\addplot table[x=x,y={Here}]{\groupedColumnData};
\addplot[red,sharp plot,update limits=false] coordinates {(1910,43) (1990,43)} node[above] at (axis cs:1950,43) {Houses};
\legend{Far,Near,Here,Annot}
\end{axis}
\end{tikzpicture}
\caption{Grouped column chart}
\label{fig:groupedcolumn}
\end{figure}

\pgfplotstableread{
x {Name 1} {Name 2} {Name 3} {Name 4}
1 0         10       58       10
2 30        20       48       40
3 10        60       45       10.5
4 50        18       55       60
5 40        30       8        20
}\lineGraphData

\begin{figure}[H]
\centering
\begin{tikzpicture}[spy using outlines = {circle, size=2cm, magnification=5, connect spies}]
\begin{axis}[
    width=15cm,
    height=6.6cm,
    ylabel = {Unit},
    ymin = 0,
    enlarge x limits = false,
    ymajorgrids = true,
    legend style = {at={(0.5,-0.1)}, anchor=north},
    cycle list name=DTU,
    every axis plot/.append style={fill opacity=0},
    ]
\addplot table[x=x,y={Name 1}]{\lineGraphData};
\addplot table[x=x,y={Name 2}]{\lineGraphData};
\addplot table[x=x,y={Name 3}]{\lineGraphData};
\addplot table[x=x,y={Name 4}]{\lineGraphData};
\legend{Legend 1, Legend 2, Legend 3, Legend 4}
\end{axis}
\end{tikzpicture}
\caption{Line graph}
\label{fig:linegraph}
\end{figure}

\pgfplotstableread{
x {Name 1} {Name 2} {Name 3} {Name 4}
1 0         10       58       10
2 30        20       48       40
3 10        60       45       10.5
4 50        18       55       60
5 40        30       8        20
}\lineGraphMagnifyData

\begin{figure}[H]
\centering
\begin{tikzpicture}[spy using outlines = {circle, size=2cm, magnification=5, connect spies}]
\begin{axis}[
    width=15cm,
    height=6.6cm,
    ylabel = {Unit},
    ymin = 0,
    enlarge x limits = false,
    ymajorgrids = true,
    legend style = {at={(0.5,-0.1)}, anchor=north},
    cycle list name=DTU,
    every axis plot/.append style={fill opacity=0},
    ]
\addplot table[x=x,y={Name 1}]{\lineGraphMagnifyData};
\addplot table[x=x,y={Name 2}]{\lineGraphMagnifyData};
\addplot table[x=x,y={Name 3}]{\lineGraphMagnifyData};
\addplot table[x=x,y={Name 4}]{\lineGraphMagnifyData};

\coordinate (spypoint) at (axis cs:3,10.5); % Delete this line to remove magnifying glass
\coordinate (magnifyglass) at (axis cs:3.6,12); % Delete this line to remove magnifying glass
\legend{Legend 1, Legend 2, Legend 3, Legend 4}
\end{axis}

\spy [black, size=2cm] on (spypoint) in node[fill=white] at (magnifyglass); % Delete this line to remove magnifying glass
\end{tikzpicture}
\caption{Line graph with magnifying glass}
\label{fig:linegraphmagnify}
\end{figure}

\pgfplotstableread{
x {Name 1} {Name 2} {Name 3} {Name 4}
1 30        10       2        10
2 20        20       5        5
3 25        20       5        8
4 15        20       5        5
5 30        10       8        2
}\areaGraphData

\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
    width=15cm,
    height=6.6cm,
    stack plots=y,
    area style,
    ylabel = {Unit},
    ymin = 0,
    enlarge x limits=false,
    ymajorgrids=true,
    legend style={at={(0.5,-0.1)}, anchor=north},
    cycle list name=DTU,
    ]
\addplot table[x=x,y={Name 1}]{\areaGraphData}\closedcycle;
\addplot table[x=x,y={Name 2}]{\areaGraphData}\closedcycle;
\addplot table[x=x,y={Name 3}]{\areaGraphData}\closedcycle;
\addplot table[x=x,y={Name 4}]{\areaGraphData}\closedcycle;
\legend{Legend 1, Legend 2, Legend 3, Legend 4}
\end{axis}
\end{tikzpicture}
\caption{Area graph}
\label{fig:areagraph}
\end{figure}

\pgfplotstableread{
x {Name 1} {Name 2} {Name 3} {Name 4}
1   11	15	38	41
2   33	22	25	31
3   22	25	11	21
4   44	14	17	51
5   13	42	25	33
6   14	52	36	34
}\scatterData

\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
    %enlarge x limits=true,
    ylabel = {Unit},
    ymin = 0,
    ymajorgrids=true,
    cycle list name=DTU,
]
\addplot+[only marks,mark=*]        table[x=x,y={Name 1}]{\scatterData};
\addplot+[only marks,mark=square*]  table[x=x,y={Name 2}]{\scatterData};
\addplot+[only marks,mark=triangle*]table[x=x,y={Name 3}]{\scatterData};
\addplot+[only marks,mark=+]        table[x=x,y={Name 4}]{\scatterData};
\legend{Legend 1, Legend 2, Legend 3, Legend 4}
\end{axis}
\end{tikzpicture}
\caption{Scatter plot}
\label{fig:scatter}
\end{figure}

\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
    boxplot/draw direction=y,
    xtick={1,2,3},
    xticklabels={Group A, Group B, Group C},
    x axis line style={opacity=0},
    enlarge y limits,
    ymajorgrids,
    cycle list name=DTU,
    every axis plot/.append style={semithick},
]
\addplot+[draw=black,
boxplot prepared={
lower whisker=42, lower quartile=45,
median=47,
upper quartile=47.5, upper whisker=48,
},
] coordinates {(0,40) (0,34) (0,56)};
\addplot+[draw=black,
boxplot prepared={
lower whisker=36, lower quartile=39,
median=40,
upper quartile=41, upper whisker=43,
},
] coordinates {};
\addplot+[draw=black,
boxplot prepared={
lower whisker=41, lower quartile=44,
median=45,
upper quartile=46, upper whisker=47,
},
] coordinates {(0,35) (0,55)};
\end{axis}
\end{tikzpicture}
\caption{Boxplot}
\label{fig:boxplot}
\end{figure}

\section{Tables and figures}

\begin{table}[H]
\centering
\caption{This is a \texttt{booktabs} table. Go to \url{http://www.tablesgenerator.com/} and use the booktabs table style}
\label{tab:tableExample}
\begin{tabular}{@{}llS@{}}
\toprule
\multicolumn{2}{c}{Item} &            \\ \cmidrule(r){1-2}
Animal     & Description & Price (\$) \\ \midrule
Gnat       & per gram    & 13.65      \\
           & each        & 0.01       \\
Gnu        & stuffed     & 92.50      \\
Emu        & stuffed     & 33.33      \\
Armadillo  & frozen      & 8.99       \\ \bottomrule
\end{tabular}
\end{table}
\texttt{Booktabs} tables don't use any vertical lines. Only horizontal lines are used. \Cref{tab:tableExample} begins with a \textbackslash \texttt{toprule}, ends with a \textbackslash \texttt{bottomrule} with \textbackslash \texttt{midrule} in between. The table has 3 columns formatted as \texttt{@\{\}llS@\{\}}. \texttt{@\{\}} is cropping the horizontal lines of the table to fit the content (removes column spacing at the left and right edges). \texttt{l} aligns the column to the left and \texttt{S} aligns the column according to the decimal point (\texttt{siunitx} package). You can of course also use \texttt{r} to align right or \texttt{c} to center the contents of the column.

\begin{table}[H]
\centering
\caption{Wrongly formatted table}
\label{tab:tableExampleWrong}
\begin{tabular}{llll}
\toprule
                    & Voltage & Current   & Power   \\
                    & V       & A         & W       \\ \midrule
Transformer input   & 234.4   & 0.50      & 117.4   \\ \midrule
Transformer output  & 25.86   & 2.72      & 70.3    \\ \midrule
Efficiency          &         &           & 60\%    \\ \bottomrule
\end{tabular}
\end{table}

\begin{table}[H]
\centering
\caption{Correctly formatted table}
\label{tab:tableExampleCorrect}
\begin{tabular}{@{}lSSS@{}}
\toprule
                    & {Voltage} & {Current} & {Power}       \\
                    & V         & A         & W             \\ \midrule
Transformer input   & 234.4     & 0.50      & 117.4         \\
Transformer output  & 25.86     & 2.72      & 70.3          \\ \midrule
Efficiency          &           &           & \SI{60}{\percent} \\ \bottomrule
\end{tabular}
\end{table}

\Cref{tab:tableExampleWrong} and \cref{tab:tableExampleCorrect} have the same comtents but there are some subtle differences in formatting which makes \cref{tab:tableExampleCorrect} the superior table of the two. The most obvious change is removing the midrule between the transformer input and output rows. The efficency row is the odd man out and a midrule has been used to emphasise the difference between the transformer rows and the efficiency row. The delimiters in the voltage, current and power columns are aligned. The horizontal lines (rules) fits to the content and instead of protruding. The spacing between 60 and the percentage sign is correctly adjusted.

\begin{figure}[H]
\centering
\includegraphics[width=0.3\textwidth]{Pictures/Logos/dtured_cmyk.pdf}
\caption{Just a normal figure}
\label{fig:figure}
\end{figure}

\begin{figure}[H]
\centering
\begin{subfigure}{.5\textwidth}
  \centering
  \includegraphics[width=.4\linewidth]{Pictures/Logos/dtured_cmyk.pdf}
  \caption{A subfigure}
  \label{fig:twosub1}
\end{subfigure}%
\begin{subfigure}{.5\textwidth}
  \centering
  \includegraphics[width=.4\linewidth]{Pictures/Logos/black_cmyk.pdf}
  \caption{A subfigure}
  \label{fig:twosub2}
\end{subfigure}
\caption{A figure with two subfigures}
\label{fig:twosubfigures}
\end{figure}

\begin{figure}[H]
\centering
\begin{subfigure}{.49\textwidth}
  \centering
  \includegraphics[width=.3\linewidth]{Pictures/Logos/dtured_cmyk.pdf}
  \caption{A subfigure}
  \label{fig:foursub1}
\end{subfigure}%
\begin{subfigure}{.49\textwidth}
  \centering
  \includegraphics[width=.3\linewidth]{Pictures/Logos/black_cmyk.pdf}
  \caption{A subfigure}
  \label{fig:foursub2}
\end{subfigure}
\begin{subfigure}{.49\textwidth}
  \centering
  \includegraphics[width=.3\linewidth]{Pictures/Logos/black_cmyk.pdf}
  \caption{A subfigure}
  \label{fig:foursub3}
\end{subfigure}
\begin{subfigure}{.49\textwidth}
  \centering
  \includegraphics[width=.3\linewidth]{Pictures/Logos/dtured_cmyk.pdf}
  \caption{A subfigure}
  \label{fig:foursub4}
\end{subfigure}
\caption{A figure with four subfigures}
\label{fig:foursubfigures}
\end{figure}

Referring to the figure as a whole \cref{fig:foursubfigures} or to an individual sub figure \cref{fig:foursub1} is done the normal way with \texttt{\textbackslash cref\{\}} commands.

\section{Equations}
In-line math is easy. Anything surrounded by dollar signs becomes a math field. Here is an example: $f(x)=2x-1$. Also anything inside the ``\textbackslash begin\{equation\}'' and  ``\textbackslash end\{equation\}'' environment is also a math field. Examples are shown below.

All equations use the default latex font. Some might say it looks weird with a serif font for equations and a sans-serif font for the body text. However, it is very unpractical to change the math font in latex which is the exactly the reason why this has not been done. One benefit of the serif style math font is the clear distinction between symbols (variables) and units.

On the subject of units, those are all taken care of by the \texttt{\textbackslash siunitx} package. Whenever there is a number followed by a unit one should write \textbackslash SI\{number\}\{unit\}. Note this command is case sensitive. If a unit should follow a variable use the command \textbackslash si\{unit\} (also case sensitive).

The ideal gas law is shown in \cref{eq:idealgaslaw}.
\begin{equation} \label{eq:idealgaslaw}
    p \cdot V = n \cdot R \cdot T
\end{equation}

\begin{equation} \label{eq:IME}
    \frac{\partial}{\partial t} \int_{0}^{\delta} U dy = - \delta \frac{1}{\rho}\frac{\partial P}{\partial x}-U_f(t)^2
\end{equation}

\begin{equation} \label{eq:penDepthStep}
d_{step} = \sqrt{\frac{\delta}{\frac{dw}{dp_v}} \cdot t} =
\sqrt{\frac{\SI{1.0e-11}{kg/(m.s.Pa)}}{\frac{\SI{5.4}{kg/m^3}}{\SI{233.82}{Pa}}} \cdot \SI{7200}{s}} =
\SI{0.001766}{m} = \SI{1.766}{mm}
\end{equation}

\begin{equation*} % Equation without number
    x = \mathtt{x}, \mathbf{x}, \mathit{x}, x_{1_{2_{3_{4}}}}^{1^{2^{3^{4}}}} \cdot hello * \text{hello world} \cdot \text{equation without number}
\end{equation*}

Notice how the \texttt{aligned} environment can be used to align the equilibrium arrows in \cref{eq:equilibrium}. Only one equation number is generated using this method. Alternatively if you want an equation number for each line see \crefrange{eq:align1}{eq:align2}.

\begin{equation} \label{eq:equilibrium}
\begin{aligned}
    CH_3COOH + OH^{-} &\rightleftharpoons CH_3COO^{-} + H_2O \\
    H_2O &\rightleftharpoons H^{+}_{(aq)} + OH^{-}_{(aq)}
\end{aligned}
\end{equation}

\begin{align}
    \label{eq:align1}
    f(x) &= 1 + x - 3 x^2 \\
    \label{eq:align2}
    g(x) + y &= 3x - \frac{1}{2} x^3
\end{align}

\section{Listings (code)}

\Cref{lst:montecarlo} is a nicely formatted block of code. A listing will automatically continue on the next page if it encounters a page break. Many different programming languages can be highlighted. Check the \texttt{listings} package documentation for a list of supported programming languages.

\begin{lstlisting}[language=Matlab, caption = Monte Carlo simulation to estimate the value of $\pi$, label=lst:montecarlo]
%% Monte Carlo simulation, estimation of pi
m=1E7;

x=rand(m,1);
y=rand(m,1);

g = x.^2+y.^2-1;

%dots outside
Pf = sum((g)<=0)/m

pi = 4*Pf
\end{lstlisting}