\index{HolQbfLib|(}
\index{QBF|see {HolQbfLib}}
\index{Squolem|see {HolQbfLib}}
\index{decision procedures!QBF}

\setcounter{sessioncount}{0}

\ml{HolQbfLib} provides a rudimentary platform for experimenting with
combinations of theorem proving and Quantified Boolean Formulae~(QBF)
solvers.  \ml{HolQbfLib} was developed as part of a research project
on {\it Expressive Multi-theory Reasoning for Interactive
  Verification} (EPSRC grant EP/F067909/1) from 2008 to~2011.  It is
loosely inspired by \ml{HolSatLib} (Section~\ref{sec:HolSatLib}), and
has been described in parts in the following publications:
\begin{itemize}
\item Tjark Weber: {\it Validating QBF Invalidity in HOL4}.  In Matt
  Kaufmann and Lawrence C.\ Paulson, editors, Interactive Theorem
  Proving, First International Conference, ITP 2010, Edinburgh, UK,
  July 11--14, 2010.  Proceedings, volume 6172 of Lecture Notes in
  Computer Science, pages 466--480.  Springer, 2010.
\item Ramana Kumar and Tjark Weber: {\it Validating QBF Validity in
  HOL4}.  In Marko C.\ J.\ D.\ van Eekelen, Herman Geuvers, Julien Schmaltz,
  and Freek Wiedijk, editors, Interactive Theorem Proving, Second International
  Conference, ITP 2011, Berg en Dal, The Netherlands, August 22--25, 2011.
  Proceedings, volue 6898 of Lecture Notes in Computer Science, pages 168--183.
  Springer, 2011.
\end{itemize}
\ml{HolQbfLib} uses an external QBF solver, Squolem, to decide
Quantified Boolean Formulae.

\subsection{Installing Squolem}

\ml{HolQbfLib} has been tested with (the x86 Linux version of) Squolem
2.02 (release date 2010-11-10).  This is Squolem's latest version at
the time of writing.  Squolem can be obtained from
\url{http://www.cprover.org/qbv/download.html}.  After installation,
you must make the executable available as {\tt squolem2}, \eg, by
placing it into a folder that is in your {\tt \$PATH}.  This name is
currently hard-coded: there is no configuration option to tell \HOL{}
about the location and name of the Squolem executable.

\subsection{Interface}
\label{qbf-interface}

The library provides four functions, each of type \ml{term -> thm}, to invoke
Squolem: \ml{decide}, \ml{decide\_prenex}, \ml{disprove}, and \ml{prove}.  These
are defined in the \ml{HolQbfLib} structure, which is the library's main entry
point.

Calling \ml{prove $\phi$} will invoke Squolem on the QBF~$\phi$ to
establish its validity.  If this succeeds, \ml{prove} will then
validate the certificate of validity generated by Squolem in \HOL{} to
return a theorem $\vdash \phi$.

Similarly, calling \ml{disprove $\phi$} will invoke Squolem to
establish that $\phi$ is invalid.  If this succeeds, \ml{disprove}
will then validate the certificate of invalidity generated by Squolem
in \HOL{} to return a theorem $\phi \vdash \bot$.

\ml{decide\_prenex $\phi$} combines the functionality of \ml{prove} and
\ml{disprove} into a single function.  It will invoke Squolem on
$\phi$ and return either $\vdash \phi$ or $\phi \vdash \bot$,
depending on Squolem's answer.

Finally, \ml{decide} does the same job as \ml{decide\_prenex} but accepts QBFs
in a less restricted form. Restrictions on $\phi$ are described below.

\begin{session}
\begin{verbatim}
- load "HolQbfLib";
metis: r[+0+3]#
r[+0+6]#
> val it = () : unit

- open HolQbfLib;
> val decide = fn: term -> thm
val decide_prenex = fn: term -> thm
val disprove = fn: term -> thm
val prove = fn: term -> thm

- show_assums := true;
> val it = () : unit

- decide ``?x. x``;
<<HOL message: HolQbfLib: calling external command
  'squolem2 -c /tmp/filedH1K2x >/dev/null 2>&1'>>
> val it =  [] |- ?x. x: thm

- decide ``(?y. x \/ y) ==> ~x``;
> val it = [!x. (?y. x \/ y) ==> ~x] |- F: thm

- decide ``~(?x. x ==> y) \/ (?x. y ==> x)``;
<<HOL message: HolQbfLib: calling external command
  'squolem2 -c /tmp/fileyap3oD >/dev/null 2>&1'>>
> val it = [] |- ~(?x. x ==> y) \/ ?x. y ==> x: thm

- decide_prenex ``!x. ?y. x /\ y``;
<<HOL message: HolQbfLib: calling external command
  'squolem2 -c /tmp/fileZAGj4m >/dev/null 2>&1'>>
> val it = [!x. ?y. x /\ y] |- F : thm

- disprove ``!x. ?y. x /\ y``;
<<HOL message: HolQbfLib: calling external command
  'squolem2 -c /tmp/file0Pw2Tg >/dev/null 2>&1'>>
> val it = [!x. ?y. x /\ y] |- F : thm

- prove ``?x. x``;
<<HOL message: HolQbfLib: calling external command
  'squolem2 -c /tmp/fileKi4Lkz >/dev/null 2>&1'>>
- val it =  [] |- ?x. x: thm
\end{verbatim}
\end{session}

\paragraph{Supported subset of higher-order logic}
The argument given to \ml{decide} must be a Boolean term built using only conjunction, disjunction, implication, negation, universal/existential quantification, and variables. Free variables are considered universally quantified. Every quantified variable must occur.

The argument given to the other functions must be a QBF in
prenex form, \ie, a term of the form $Q_1 x_1. \, Q_2 x_2. \, \ldots
\, Q_n x_n. \, \phi$, where
\begin{itemize}
\item $n \geq 0$,
\item each $Q_i$ is an (existential or universal) quantifier,
\item $Q_n$ is the existential quantifier,
\item each $x_i$ is a Boolean variable,
\item $\phi$ is a propositional formula in CNF, \ie, a conjunction of
  disjunctions of (possibly negated) Boolean variables,
\item $\phi$ must actually contain each $x_i$,
\item all $x_i$ must be distinct, and
\item $\phi$ does not contain variables other than $x_1$, \dots,
  $x_n$.
\end{itemize}
The behavior is undefined if any of these restrictions are violated.

\paragraph{Support for the QDIMACS file format}

The QDIMACS standard defines an input file format for QBF solvers.
\ml{HolQbfLib} provides a structure \ml{QDimacs} that implements
(parts of) the QDIMACS standard, version 1.1 (released on December~21,
2005), as described at \url{http://www.qbflib.org/qdimacs.html}.  The
\ml{QDimacs} structure does not require Squolem (or any other QBF
solver) to be installed.

\ml{QDimacs.write\_qdimacs\_file path $\phi$} creates a QDIMACS file
(with name \ml{path}) that encodes the QBF $\phi$, where $\phi$ must
meet the requirements detailed above.  The function returns a
dictionary that maps each variable in~$\phi$ to its corresponding
variable index (a positive integer) used in the QDIMACS file.

\ml{QDimacs.read\_qdimacs\_file f path} parses an existing QDIMACS
file (with name \ml{path}) and returns the encoded QBF as a \HOL{}
term.  Since variables are only given as integers in the QDIMACS
format, variables in \HOL{} are obtained by applying \ml{f} (which is
a function of type \ml{int -> term}) to each integer.  \ml{f} is
expected to return Boolean variables only, not arbitrary \HOL{} terms.

\paragraph{Tracing}

Tracing output can be controlled via \ml{Feedback.set\_trace
  "HolQbfLib"}.  See the source code in \ml{QbfTrace.sml} for possible
values.

Communication between \HOL{} and Squolem is via temporary files.
These files are located in the standard temporary directory, typically
{\tt /tmp} on Unix machines.  The actual file names are generated at
run-time, and can be shown by setting the above tracing variable to a
sufficiently high value.

The default behavior of \ml{HolQbfLib} is to delete temporary files
after successful invocation of Squolem.  This also can be changed via
the above tracing variable.  If there is an error, files are retained
in any case (but note that the operating system may delete temporary
files automatically, \eg, when \HOL{} exits).

\subsection{Wishlist}

The following features have not been implemented yet.
Please submit additional feature requests (or code contributions) via \url{http://github.com/HOL-Theorem-Prover/HOL}.

\paragraph{Support for other QBF solvers}

So far, Squolem is the only QBF solver that has been integrated with
\HOL.  Several other QBF solvers can produce proofs, and it would be
nice to offer \HOL{} users more choice (also because Squolem's
performance is not necessarily state-of-the-art anymore).

\paragraph{QBF solvers as a web service}

The need to install a QBF solver locally poses an entry barrier.  It
would be much more convenient to have a web server running one (or
several) QBF solvers, roughly similar to the ``System on TPTP''
interface that G.~Sutcliffe provides for first-order theorem provers
(\url{http://www.cs.miami.edu/~tptp/cgi-bin/SystemOnTPTP}).

\index{HolQbfLib|)}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "description"
%%% End:


\documentclass[a4paper]{article}
\usepackage[acronym]{glossaries}
\usepackage{hyperref}
\usepackage{array}
\usepackage{algorithm,algpseudocode,float}
\usepackage{chngcntr}
\usepackage{listings}

\counterwithin{table}{section}
\counterwithout{algorithm}{section}

\newacronym{dsa}{DSA}{Dynamic Staking Algorithm}
\newacronym{token}{tokens}{Smart Audit Token}
\newacronym{wbr}{\ensuremath{\mathit{WBR}}}{weighted block reward}
\makeglossaries

\algdef{SE}[VARIABLES]{Variables}{EndVariables}
   {\algorithmicvariables}
   {\algorithmicend\ \algorithmicvariables}
\algnewcommand{\algorithmicvariables}{\textbf{global variables}}

\begin{document}
%\pagestyle{headings}
\setlength{\parindent}{2ex}
\setlength{\parskip}{0.5em}
\section{\acrfull{dsa}}
\noindent
Multiple custodial and non-custodial staking solutions exist with their advantages and inconvenients, every methods can be susceptible to hacks or exploits; however, custodial solution represents a higher risk, rather than users being in control of their assets a small group or a single entity is in charge exposing all assets to higher attack surface.\par
\noindent
The main invonvenience of non-custodial solution such as autonomous smart-contract is the trade-off between gas consumption and the reward algorithm. Knowing that EVM is a state machine, implemting such algorithms will require saving every action done by a user (without using any array to optimize gas consumption) while taking into account other users actions to solve one of the major inconvenience of smart contract staking algorithms.\par
\noindent
Please note that from here on we assume that the staking purpose is to generate reward for the users, other's can exist but for the sake of simplicity we will use the most common ones (reward or dividend).\par
\noindent
The biggest chalenge to over come is that users actions are dependent to one another meaning that if a user \textit{A} stake, add to his stake or widthraw, the reward of user \textit{B} will be affected. The main goal is to achieve a linear reward computaion for each user as demonstrated in equation \ref{eq:reward_goal}.\par
\begin{flushleft}
We define $R_{K,N}^{j}$ as the reward of user \textit{j} between block \textit{K} and \textit{N}.
\end{flushleft}
\begin{equation} \label{eq:reward_goal}
R_{K,N}^{j}= R_{K,M}^{j}+R_{M,N}^{j}
\end{equation}
\begin{flushleft}
where $K < M < N$.
\end{flushleft}
\section{Mathematical Proof}
\subsection{Example Use Cases}
\noindent
The goal of this use case implementation of \acrshort{dsa} is to achieve a a reward distribution by block, where a reward is distributed every block between stakers following their stake value, it can be seen as an inflationary token with a monetary policy that requires users to stake if they want to get part of the newly minted tokens.\par
\noindent
Other use cases can be implemented like:
\begin{itemize}
  \setlength\itemsep{0.1em}
  \item Future PoS pools, where stakers can make multiple deposits, without need to use an array to save their actions to compute the reward later on.
  \item A lending platform that distibute dividends using the proposed optimized algorithm, etc ...
\end{itemize}\par
\noindent
More research are needed to implement a broader library. Refer to Table \ref{tab:table_reward_example} for more details, another example is the deployement of future PoS dynamic pool where the reward can be disributed fairly without usage or arrays.\par
\begin{table}[h!]
  \begin{center}
    \caption{Reward distribution example.}
    \label{tab:table_reward_example}
    \begin{tabular}{ c | c c c c c c || c }
      \hline \
  	  \textit{i} & 0 & 1 &  2 & 3 & 4 & 5 & $\mathit{R_{0,4}^j}$ \\
  	  \hline
      $R_{i,i}^0$ & 0 & 120 & 40 & 20 & 0 & 0 & 180 \\
      $R_{i,i}^1$ & 0 & 0 & 80 & 40 & 48 & 60 & 228 \\
      $R_{i,i}^2$ & 0 & 0 & 0 & 60 & 72 & 60 & 192 \\
      \hline
      \multicolumn{8}{l}{\footnotesize \textit{i} is the block number}\\
      \multicolumn{8}{l}{\footnotesize $R_{i,i}^j$ is the reward of user \textit{j} at block \textit{i}}\\
      \multicolumn{8}{l}{\footnotesize $R_{0,4}^j$ is the reward sum between block $i=0$ and $i=4$ of user \textit{j} }\\
    \end{tabular}
  \end{center}
\end{table}
\noindent
We suppose that at each block a reward is distributed, where $\mathit{BR}_i$ for $i=0,...,5$ is equal to $120$ (the value of the reward per block can be dynamic following a precise monetary policy, we used a fixed reward for simplification only) \acrshort{token} with a chronological order of events as follow:
\begin{itemize}
  \setlength\itemsep{0.1em}
  \item $user_0$ stake 100 \acrshort{token} at block $1$
  \item $user_1$ stake 200 \acrshort{token} at block $2$
  \item $user_2$ stake 300 \acrshort{token} at block $3$
  \item $user_0$ widthraw 100 \acrshort{token} at block $4$
  \item $user_1$ stake 100 \acrshort{token} at block $5$
\end{itemize}
\noindent
Obtaining the results presented in Table \ref{tab:table_reward_example} in a custodial or centralized solution is easy since there is no gas fee or gas block limit, however, when implementing the same algorithm in a smart contract the task is a way harder since it is nearly impossible to compute and save the reward for each user at every block due to high gas consumption when dealing with arrays (if a single user stake at a given block, the reward for all users will change).\par
\noindent
The following subsection shows how to solve this problem by removing the usage of arrays of user interacations when computing the reward.\par
\subsection{Demonstration}
\begin{flushleft}
We define $R_{K,N}^{j}$ as the reward of user \textit{j} between block \textit{K} and \textit{N}.
\end{flushleft}
\begin{equation} \label{eq:reward_formula}
R_{K,N}^{j}= \sum_{i=K}^{i=N} A_i^j * \frac{\mathit{BR}_i}{S_i}
\end{equation}
\begin{flushleft}
where:\
\end{flushleft}
\begin{itemize}
  \item $ \mathit{BR}_i $ is the staking reward at block \textit{i} to be devided between the stakers
  \item $ S_i$ is the total staked amount at block \textit{i} for the total number of user \textit{P}
  	\begin{equation} \label{eq:total_stake}
	    S_i= \sum_{j=0}^{j=P}A_i^j
	  \end{equation}
  \item $A_i^j$ is the amount staked by a user \textit{j} at block \textit{i}
\end{itemize}
\begin{flushleft}
If we suppose that no staking or withdrawing activity was done between block \textit{K} and \textit{M}, $A_i^j$ and $S_i$ will remain constant on every block \textit{i} where $i=K,K+1,...,M-1,M$.
\end{flushleft}
\begin{flushleft}
The new formulation of equation \ref{eq:reward_formula} will be as follow:
\end{flushleft}
\begin{equation} \label{eq:reward_formula_fixed}
R_{K,L}^{j}= \frac{A^j}{S} * \sum_{i=K}^{i=L} \mathit{BR}_i
\end{equation}
\begin{flushleft}
if we assume that any user \textit{x} started staking at block \textit{M}, the reward of user \textit{j} where $j\neq x$ will be:
\end{flushleft}
\begin{equation} \label{eq:reward_goal_example}
R_{K,N}^{j}= R_{K,M}^{j} + R_{M,N}^{j}
\end{equation}
% \begin{equation} \label{eq:reward_goal_example}
% R_{K,N}^{j}= \frac{A^j}{S_{K,M}} * \sum_{i=K}^{i=M} \mathit{BR}_i + \frac{A^j}{S_{M,N}} * \sum_{i=M}^{i=L} \mathit{BR}_i
% \end{equation}
\begin{equation} \label{eq:reward_goal_example_2}
R_{K,N}^{j}= A^j*(\frac{1}{S_{K,M}} * \sum_{i=K}^{i=M} \mathit{BR}_i + \frac{1}{S_{M,N}} * \sum_{i=M}^{i=L} \mathit{BR}_i)
\end{equation}
\begin{flushleft}
If we define the \acrfull{wbr} as follow:
\end{flushleft}
\begin{equation} \label{eq:weighted_block_reward}
\acrshort{wbr}_{K,M}= \frac{1}{S_{K,M}}*\sum_{i=K}^{i=L} \mathit{BR}_i
\end{equation}
\begin{flushleft}
Equation \ref{eq:reward_goal_example_2} will become:
\end{flushleft}
\begin{equation} \label{eq:reward_goal_example_3}
R_{K,N}^{j}= A^j*(\acrshort{wbr}_{K,M} + \acrshort{wbr}_{M,N})
\end{equation}
\subsection{Algorithm}
\noindent
As demonstrated in equation \ref{eq:reward_goal_example_3}, a user \textit{j} reward between two blocks \textit{(M,N)} is the sum of \acrshort{wbr} between the same blocks multiplied by the user stake.\par
\noindent
When a user start staking at block \textit{K} we save the total sum $\acrshort{wbr}_{0,K}$ for the specific user, once he claims, stake or withdraw at block N, we substruct the sum of $\acrshort{wbr}_{0,N}$ from the initial sum of $\acrshort{wbr}_{0,K}$. hence getting the reward of user j, $R^j=A^j*\acrshort{wbr}_{K,N}$ (for a detailed definition please refer to algorithm \ref{alg:algo_1}).\par
\section{Conclusion}
\noindent
A beta solidity implementation of this algorithm can be found \href{https://github.com/RideSolo/staking-library}{here}, all the conducted tests satisfied the expected results in Table \ref{tab:table_reward_example}, the mathematical demonstration was proved experimentaly.\par

\noindent To execute the tests please follow the steps described in the repository \href{https://github.com/RideSolo/staking-library/blob/master/README.md}{README}.
% \begin{lstlisting}
% $ git clone https://github.com/ridesolo/staking-library.git
% $ cd staking-library
% $ npm install
% \end{lstlisting}
% \noindent Once installed, you can start testing the solidity code contained in the contract folder by running:
% \begin{lstlisting}
% $ npm run test-report
% \end{lstlisting}

\begin{algorithm}[H]
\caption{\acrlong{dsa}}
\label{alg:algo_1}
\begin{algorithmic}
\Variables
	\State $R^j$, reward of user \textit{j}
	\State $A^j$, stake of user \textit{j}
	\State $S$, total staked amount
	\State $\acrshort{wbr}$, \acrlong{wbr}
	\State $\acrshort{wbr}^j$, last \acrlong{wbr} for user \textit{j}
	\State $\mathit{LB}$, last block number where any modification was performed
	\State $\mathit{BR}$, 120 tokens reward to distribute on each block
\EndVariables
\Procedure{stake}{$value$, $\mathit{i}$, $\mathit{j}$}
  \State $\mathit{BR}_{LB,i}$, sum of the reward between block \textit{LB} and \textit{i}
  \State $\mathit{BR}_{LB,i} = (i - \mathit{LB}) * BR$
  \If{$S \neq 0$}
    \State $\acrshort{wbr} = \acrshort{wbr} + \frac{\mathit{BR}_{LB,i}}{S}$
  \EndIf
  \State $R^j = R^j + A^j * (\acrshort{wbr} - \acrshort{wbr}^j)$
  \State $\acrshort{wbr}^j = \acrshort{wbr}$
  \State $A^j = A^j + \mathit{value}$
  \State $S = S + \mathit{value}$
  \State $\mathit{LB} = i$
\EndProcedure
\Procedure{withdraw}{$value$, $\mathit{i}$, $\mathit{j}$}
  \State $\mathit{BR}_{LB,i}$, sum of the reward between block \textit{LB} and \textit{i}
  \State $\mathit{BR}_{LB,i} = (i - \mathit{LB}) * BR$
  \If{$S \neq 0$}
    \State $\acrshort{wbr} = \acrshort{wbr} + \frac{\mathit{BR}_{LB,i}}{S}$
  \EndIf
  \State $R^j = R^j + A^j * (\acrshort{wbr} - \acrshort{wbr}^j)$
  \State $\acrshort{wbr}^j = \acrshort{wbr}$
  \State $A^j = A^j - \mathit{value}$
  \State $\mathit{transfer}(j,value)$
  \State $S = S - \mathit{value}$
  \State $\mathit{LB} = i$
\EndProcedure
\Procedure{claim}{$\mathit{i}$, $\mathit{j}$}
  \State $\mathit{BR}_{LB,i}$, sum of the reward between block \textit{LB} and \textit{i}
  \State $\mathit{BR}_{LB,i} = (i - \mathit{LB}) * BR$
  \If{$S \neq 0$}
    \State $\acrshort{wbr} = \acrshort{wbr} + \frac{\mathit{BR}_{LB,i}}{S}$
  \EndIf
  \State $R^j = R^j + A^j * (\acrshort{wbr} - \acrshort{wbr}^j)$
  \State $\acrshort{wbr}^j = \acrshort{wbr}$
  \State $\mathit{LB} = i$
	\State $\mathit{transfer}(j,R^j)$
	\State $R^j = 0$
\EndProcedure
\end{algorithmic}
\end{algorithm}
\clearpage
% \printglossary[type=\acronymtype]
\end{document}


While collections are a useful AG extension, they may be undesirable due to memory requirements; we can still consider DAGs where they are provided as input and therefore not require collections. The challenge is that we can no longer rewrite the grammar to propagate phantom attributes alongside references in order to schedule reads of non-local attributes. Our basic solution is to require \emph{all} instance of an attribute to be solved before \emph{any} are accessed.

In terms of our original rewrite, instead of propagating phantom attributes alongside reference values, we conservatively assume the propagation is universal. Our rewrite is now to \emph{gather} all phantom instances of an attributes and then \emph{broadcast} a joined phantom value. Consider our ongoing example, where we must gather all instances of attribute \code{width} of node \code{Cell} and broadcast when they are all ready to any dereference of any instance (i.e., in \code{Column}). We reuse primitives from before, but also introduce $\O(\cdot, \cdot)$ to join two dependencies:

\pagebreak
\begin{lstlisting}[mathescape]
//grammar schema
@Start Table $\rightarrow$ Row Column {
  phantom c_w_gather : int;
  phantom c_w_broadcast : int
}
Cell $\rightarrow$ $\epsilon$ {
  input width : int;
  phantom c_w_gather : int;
  phantom c_w_broadcast : int
}
Row $\rightarrow$ Cell {
  phantom c_w_gather : int;
  phantom c_w_broadcast : int
}
Column $\rightarrow$ $\epsilon$ {
  input CellAlias : ref Cell;
  var width : int;
  phantom c_w_gather : int;
  phantom c_w_broadcast : int
}

//attribute constraints
Table {
  Col.CellAlias := @(Row.Cell_ptr);
  c_w_gather := $\O$(Row.c_w_gather, Col.c_w_gather);
  c_w_broadcast := c_w_gather;
  Row.c_w_broadcast = c_w_broadcast;
  Col.c_w_broadcast = c_w_broadcast;
}
Column {
  width := $\rightarrow$(CellAlias.width, c_w_broadcast);
  c_w_gather := true;
}
Row {
  c_w_gather := $\O$(Row.c_w_gather, Col.c_w_gather);
  cell.c_w_broadcast = c_w_broadcast;
}
Cell {
  c_w_gather := width;
}
\end{lstlisting}

Our example has several important properties:

\begin{enumerate}
\item \textbf{Input graph}. Note that the schema of \text{Column} treats \code{myCellAlias} as an input. Our input is thus a minimum spanning tree (MST) augmented with non-local edges.
\item \textbf{Global propagation}. We add phantom attributes \code{c_w_gather} and \code{c_w_broadcast} to all nodes.
\item \textbf{Gathering.} The first step is to \emph{gather} all uses of an attribute into one dependency; we do this in a bottom-up flow on the MST. Phantom attribute \code{c_w_gather} is ready when all of the \code{width} attributes of its subtree (in the MST) is ready. Most nodes are propagation nodes, e.g., \code{Row}, which merges flows from its children. Leaves such as \code{Column} have nothing to gather. \code{Cell} provides a \code{width} value in the original grammar, so it adds a dependency from where.
\item \textbf{Broadcasting.} Phantom attribute \code{c_w_broadcast} is ready when all instances of \code{c_w_gather} are ready. \code{Table} is the root of any tree allowed by our grammar, so it is responsible for this transfer. The remaining types further broadcast to their children.
\item \textbf{Dependent dereferences.} The non-local attribute read in \code{Column} is dependent on the broadcast of the attribute; it occurs after all instances of the attribute have been gathered.
\end{enumerate}

Finally, as with our dynamically computed graph connections, we use phantom attributes and operations to track non-local dependencies while still using the appropriate pointer-based code generation. Phantom code is not emitted.

\subsection{Rewrite rules}

See Figure~\ref{fig:statrewrites}.
\input{rewritestatic}


\documentclass{acmsiggraph}

\usepackage{parskip}
\usepackage{graphicx}
\usepackage{courier}
\usepackage{footmisc}
\usepackage{listings}
\usepackage{amsmath}
\usepackage{url}
\usepackage{color}
\usepackage{xcolor}
\onlineid{0}

\title{Cinematic Particle Systems with OpenCL}

\author{Tim Horton\thanks{e-mail: hortot2@rpi.edu}\\Rensselaer Polytechnic Institute}

\begin{document}

\maketitle

\begin{figure}
    \includegraphics[width=84.5mm]{gravity.png}
    \caption{A simple gravity simulation with two emitters and three supermassive particles (approx. 45,000 particles)}
    \label{titlefig}
\end{figure}

\section*{Abstract}

High-particle-count simulations are becoming increasingly crucial in many different aspects of our world today: both in entertainment --- within video games, movies, and the like --- and in scientific fields, where particle systems are capable of simulating and visualizing many interesting phenomena.

This paper will explore the possibility of parallelizing the simulation of these large particle systems and offloading them to very-parallel\footnote{As opposed to {\it massively-}parallel, like the CCNI's Blue Gene/L, or the {\it slightly}-parallel CPU in most modern computers} hardware which is usually only used for {\it rendering}: the video card.

We will also touch briefly on ways to design a system for describing particle systems in a generalized way, though the majority of the work that is currently in a functional state centers around simulation and rendering.

\section{Introduction}

Simulation of large particle systems requires a large amount of computation --- each particle must be inspected and updated. For certain types of particle systems --- n-body gravity, for example --- each particle is affected by its neighbors, increasing the required calculation time drastically.

This is what we aim to address with this paper. While it's unlikely that we can contribute any improved simulation algorithms, we can instead work to parallelize these algorithms and implement them with OpenCL, which will allow them to run on the GPU contained within modern graphics cards. This paper will demonstrate both the parallelization of the application of forces on large numbers of particles and the significant performance gained by doing so.

We will also explore a simple parallelized particle renderer, as well as the potential for the integration of our simulator into the popular open-source 3D package, Blender.

It is important to understand that the system we've developed is purely for offline work --- it is not suitable for realtime simulation and rendering. Thus, {\it cinematic}. This is primarily because of the relatively poor performance of the renderer. However, as you'll notice in section \ref{performanceSection}, the speedup provided by our work {\it is} actually sufficient to make some simulations fast enough to run in real time, if one were to find a faster renderer.

\section{Prior Art}

\cite{1281670} discusses a system quite similar to ours --- they use the GPU to simulate large-particle-count systems, including computationally-intensive forces like n-body gravity --- however, they make one simplification which drastically improves performance: they assume that the particle data never needs to return to the CPU. This means that the extremely expensive copying to and from video memory which is done continually within our system is completely unnecessary, but also removes the ability to use the particle data in any flexible way (i.e. copying it to a file to be rendered later, etc.).

\section{Implementation}

The code for this paper is available under the two-clause BSD license at:

\url{http://github.com/hortont424/particles}

It consists of about 3000 lines\footnote{According to {\it sloccount}} of C and Objective C, which encompass the curve editor and other design tools, an abstraction layer on top of OpenCL\footnote{the Open Computing Language, a framework for creating programs using a language similar to GLSL and run on the GPU}, and all of the code to drive simulation, preview, and rendering. In addition, there are well over 300 lines of OpenCL Kernel Language, which includes the code to apply each of the forces as well as the renderer.

\subsection{Particle Systems}

A particle system is defined by a simple JSON\footnote{JavaScript Object Notation, a format often used today for information exchange in place of things like XML, due to its lightweight nature} file (figure \ref{curveListing} is a very simple example of such a file), which lays out all of the system's parameters: the number of particles to start out with, the location and properties of emitters, the location and properties of forces, and many other things. If {\it Interpolator} had been finished, this file would also contain the mappings between these properties and various curve files.

\begin{figure}

    \lstset{language=Python}
    \lstset{basicstyle=\footnotesize\ttfamily}
    \lstset{stringstyle=\color{blue}\ttfamily}
    \lstset{numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt}
    \begin{lstlisting}[frame=trbl]{}
{
    "initialParticles": {
        "count": 1
    },
    "forces": [
        {
            "kernel": "gravity",
            "strength": 1.0,
            "noise": 0.0,
            "mass": 100000000000.0,
            "particle": {
                "fixed": true,
                "x": 1.2,
                "y": 1.2,
                "z": 0.5
            }
        }
    ],
    "emitters": [
    {
        "birthRate": 20.0,
        "initialVelocity": 0.0,
        "particle": {
            "fixed": true,
            "x": -1.2,
            "y": 1.2,
            "z": 1.5
        }
    }],
    "integration": {
        "kernel": "verlet",
        "timestep": 0.005
    }
}
    \end{lstlisting}

    \caption{A simple sample curve file, with one emitter and one force}
    \label{curveListing}
\end{figure}

\subsection{Design}

\begin{figure}
    \includegraphics[width=84.5mm]{interpolator.png}
    \caption{A screenshot of the unfinished {\it Interpolator} particle system design tool}
    \label{fig:interpolator}
\end{figure}

The particle system design tools implemented during the course of this project are not entirely functional, as they took a backseat to the simulation, preview, and rendering components, mostly due to the fact that it's possible to design a system by hand.

The primary design tool, which can be seen in figure \ref{fig:interpolator}, is called {\it Interpolator}, as it is quite literally a tool to design interpolation curves. It's a Cocoa application which provides an interface to edit arbitrary B\'{e}zier splines and map them to properties of an element in the particle system. For example, one curve might dictate the $x$ position of an emitter, while another might be mapped to the lifetime that emitter's children.

Since this tool was not finished in time for this paper, it is not integrated into the simulation and rendering phases introduced here.

\subsection{Simulation}

The simulation phase is the heart of our project. Starting from a system description file (as shown in figure \ref{curveListing}), it eventually provides the position of each particle to either the previewing or rendering subsystems in a frame-by-frame manner. It involves various steps, which we'll outline below.

\subsubsection{Parsing the .psys}

The particle system description file, in JSON format, is parsed with Michael Clark's MIT-licensed {\bf json-c} library. All of the properties are read into internal data structures and validated, with reasonable defaults being filled in for missing values.

\subsubsection{Load necessary kernels}

There are quite a few OpenCL kernels included with this project; since the program now knows which ones it needs, it can now instantiate one kernel for each force, as well as one copy of the interpolator kernel.

This is done by making a copy of the appropriate master kernel, all of which are loaded into a kernel library and compiled at the beginning of the process.

\subsubsection{Randomly generate default particles}

Some particle systems have an initial set of particles --- some, because they don't include any emitters, others, because they simply want to start with some particles displayed. At the moment, the only parameter of the initial particles that can be controlled is the number; they are placed randomly in the unit cube with zero initial velocity. Eventually, it would be ideal to support manipulation of the range and location of random positions, as well as of the mass and initial velocity.

\subsubsection{Evaluate emitters}

\label{emitters}

Evaluation of emitters primarily involves adding new particles at the location of the particle and giving them an initial velocity (depending on the emitter's settings).

Emitters are evaluated on the CPU (instead of the GPU). This is done primarily because of a limitation in OpenCL where one cannot resize a buffer from inside a kernel --- so, there would be no way to allocate space from inside an emitter kernel.

One key performance consideration while evaluating emitters is how many new particles to allocate space for. If we're given a constant emitter, we don't want to allocate {\it just} enough space during each frame to fit the new particles, because then we'd have to allocate more space on each new frame. Instead, we allocate enough space for 10 frames of said emitter plus 1024\footnote{This is completely arbitrary, chosen by random dice roll!} extra particles, which seems to stave off the performance-crushing problem of constant buffer reallocation, at least for the systems we've tested.

\subsubsection{Evaluate forces}

At this point, all particle data is copied to the GPU. Each force's kernel is instantiated once for each particle, and many such kernels can operate on their respective particles in parallel.

Each instance of the force kernel computes its own contribution to the acceleration of the particle it affects, adding the result to that particle's global acceleration accumulator.

A sample force --- pushing outward on all particles from one direction, with falloff --- is included in figure \ref{forceCode}.

\begin{figure}

    \lstset{language=C}
    \lstset{basicstyle=\footnotesize\ttfamily}
    \lstset{stringstyle=\color{blue}\ttfamily}
    \lstset{numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt}
    \begin{lstlisting}[frame=trbl]{}
__kernel void force(
    __global PAPhysicsParticle * input,
    __global PAPhysicsParticle * output,
    __global PAPhysicsNewtonian * newtonIn,
    __global PAPhysicsNewtonian * newtonOut,
    __global PAPhysicsForce * force,
    const unsigned int count)
{
    float4 fpoint, loc, accel, uv;
    float dist;

    int id = get_global_id(0);

    if(id > count || input[id].lifetime == 0)
        return;

    // Load location of force and current point
    loc = (float4)(input[id].x, input[id].y,
                   input[id].z, 0.0f);
    fpoint = (float4)(force->particle.x,
                      force->particle.y,
                      force->particle.z, 0.0f);

    // Compute acceleration on particle
    uv = normalize(loc - fpoint);
    accel = force->data.normal.strength * uv;
    dist = distance(loc, fpoint);
    accel = accel * (1.0f / powr(dist + 1.0f,
        force->data.normal.falloff.strength));

    // Accumulate acceleration on particle
    newtonOut[id].ax += accel.x;
    newtonOut[id].ay += accel.y;
    newtonOut[id].az += accel.z;
}
    \end{lstlisting}

    \caption{A simplified version of our 'normal' force kernel, which pushes outward on particles from a point, with falloff}
    \label{forceCode}
\end{figure}

\subsubsection{Integrate positions}

Our simulation uses a form of Verlet integration from \cite{verlet}, which is theoretically much more stable than basic Euler integration (which was used during the project's inception) in order to apply the acceleration values to the particles positions. This works by keeping around the previous position of the particle, instead of a velocity value:

\begin{equation}
    p_{next}=(p-p_{last}) + (a_p * t^2),
\end{equation}

where $t$ is the timestep and $a_p$ is the acceleration due to all of the forces on the given particle.

\subsection{Preview}

\begin{figure}
    \includegraphics[width=84.5mm]{preview.png}
    \caption{Example frame of preview output (simple gravity system); approximately 15,000 particles}
    \label{fig:preview}
\end{figure}

The preview subsystem takes the output from the simulator and uses an OpenGL view to draw all of the particles as uniformly sized red dots, as you can see in figure \ref{fig:preview}. This rendering is very rough but also very quick --- fast enough to be real-time, in many cases.

Preview rendering should be used when designing particle systems, as it provides nearly instant --- though relatively unattractive --- feedback.

\subsection{Rendering}

Our renderer is currently very simple: it takes the particle data from the simulation phase and turns it into a greyscale image. It does this by iterating over each pixel of the output image, mapping the pixel's location into 'particle space', then searching through all of the particles, finding those which are within $\epsilon$ units of it, and updating the output image. Particles are orthographically projected onto the plane of the image, and --- at the moment --- depth information is completely ignored.

For the purposes of all of the systems contained in this paper, $\epsilon=0.1$.

There are two main rendering modes at the moment: {\bf smooth}, and {\bf cloudy}.

{\bf Cloudy} simply increments the luminance of the pixel for each particle it finds that's within $\epsilon$ units, leading to 'circles of influence' around each particle, as seen in figure \ref{titlefig}.

{\bf Smooth} weights the increase in luminance by the distance to the particle, according to $(0.1 - dist) \cdot k$, as seen in figure \ref{smoothfig}. $k$ is an 'exposure' constant, and is determined by the number of particles likely to be near each other at any given time.

We've asked numerous people which of the two rendering modes they prefer, and have come up almost completely split, so they're both included for the time being.

\begin{figure}
    \includegraphics[width=84.5mm]{soft.png}
    \caption{{\bf Smooth} rendering mode}
    \label{smoothfig}
\end{figure}

\section{Performance \& Results}

\label{performanceSection}

\begin{figure}
    \includegraphics[width=84.5mm]{basicSpeedPlot.pdf}
    \caption{Simulation frame-rate of various different systems on CPU vs. GPU; higher values are better; the horizontal line rests at 60 fps}
    \label{fig:basicSpeedPlot}
\end{figure}

\subsection{Hardware}

All benchmarks and performance tests were taken on a machine running Mac OS X with a Core 2 Duo E7200 at 2$\times$2.53GHz with 8GB of RAM and an ATI Radeon 4890 at 800$\times$850MHz with 1GB of VRAM.

\subsection{Benchmarks}

Figure \ref{fig:basicSpeedPlot} shows the relative frame-rates of three different particle systems which we've been using as sample systems on the CPU versus the GPU.

The {\bf n-body} system is a simulation of 16,384 particles all interacting with each other, simulating gravity. There are no emitters in this system, and only one force.

The {\bf simple gravity} system (also pictured in figure \ref{titlefig}) is a simulation with two emitters --- which emit 20 particles per frame each --- and three equal-strength gravity wells (in the top right, top left, and center). The gravity simulation in this system is much simpler than in {\bf n-body}, as the particles don't interact with each other, just with the three wells.

The {\bf two-forces} system is a simulation with 1,048,576 particles and two outward-acting normal forces placed equidistant from the center on a diagonal through the random cloud of particles.

You'll note that {\bf n-body} shows a drastic speedup when moved to the GPU --- almost 10x! This is primarily because the n-body force is perfect for parallelization, as it has a long per-particle runtime (each particle has to iterate over all of the other particles, since we lack a spatial hashing data structure).

Something similar is true for {\bf two-forces}: while it's not actually nearly as computationally intensive per-particle, there are such a sheer number of particles that the parallelism comes into play in a big way, providing a less-impressive-but-still-significant 4$\times$ speedup.

The {\bf simple gravity} system shows the weakness of our approach: since emitters are evaluated on the CPU no matter what (because of the infeasbility of resizing buffers on the GPU discussed in section \ref{emitters}), and incur an additional pair of copies to/from the GPU, the CPU is able to significantly outpace the GPU. This makes it clear that emitter-heavy systems with few expensive forces are {\it not} well suited for our approach.

\subsection{Video}

Both the preview and rendering subsystems have the ability to output a PNG file for each simulated frame. These can be recombined and encoded with most video editing tools into a usable format.

\section{Applications}

The most likely application for GPU-side particle systems is games; however, our approach isn't targeted at games --- primarily because we copy the particle data back to the CPU, something unnecessarily expensive for a live game. Instead, our approach would more likely be useful to augment the current particle system tools within Blender, Apple's Motion, or Adobe's After Effects, all of which are meant for semi-offline work where the particle data is at some point needed for more generic computation on the CPU.

All three of these tools currently have advanced particle systems, but it seems reasonable, given the speedup demonstrated within this paper, that they might benefit significantly by offloading at least some of their physical simulation to the GPU.

\section{Future Work}

\subsection{Spatial Hashing}

One improvement which would massively improve the performance of both the renderer and some of the forces would be the inclusion of a spatial hashing mechanism.

For example, the renderer currently iterates over all of the particles to find the few which are very close to the pixel currently being rendered --- this operation is currently implemented in the most na\"{i}ve way possible, which is $O(n^2)$. The implementation of a kd-tree would make this $O(n^{2/3})$ instead --- quite a significant improvement, though at the expense of a measurable increase in complexity.

Alternatively, \cite{1281670}'s "force splatting" approach might make even better use of the optimized hardware available, though it's unclear to me that the summing operation (which their approach improves) is actually the primary bottleneck.

\subsection{Design Tools}

The design tools need a significant amount of work before they're usable. Most importantly, a method for exporting curves to files which the simulator can import and use to manipulate properties must be implemented.

Additionally, there's no rulers on either axis in {\it Interpolator} --- these would be necessary before one could even imagine using it as a design tool.

Really, the time constraints on this project made the implementation of both {\it Interpolator} {\bf and} the remainder of the project very unlikely, and, as such, there's a lot left to do. We're actually planning on continuing work in our free time over the summer, as this has turned out to be an eye-opening project.

\subsection{Rendering Improvements}

In the future, the renderer could be improved visually through a few means. Firstly, it would be a significant advantage to be able to support color image buffers --- this way, various sorts of information could be represented. For example, depth data could be encoded in one of the color channels, providing an easier way to understand the data.

In addition, the ability to move the camera (and script the camera's movements with {\it Interpolator} curves) would make for much-improved visualizations, but would also require significant additional complication. However, we were planning on implementing raytracing through the particles in order to provide self-shadowing and other useful features, which would also imply the ability to move the camera.

\section{Conclusion}

After consuming quite a bit of processing power doing experiments, and after writing a few thousand lines of code, I think it's safe to say that we've introduced a feasible implementation of very-parallel particle simulation on the GPU. It's also quite clear that it's very possible to use this technology in order to speed up highly-physically-accurate simulations, especially ones with high algorithmic complexity, like the n-body problem.

It's also clear that our implementation is not the be-all-end-all of particle simulators. There are many missing cases, and a few conditions in which our simulation actually negatively impacts performance, but it seems that an intelligent algorithm could certainly switch between target devices depending on the nature of the system, massively improving performance for many cases.

We would have liked to have an extra month or two to work on this; it's likely that such time would have made for a much more interesting final result... alas, a semester is short, so we only had time for minor successes. There's always the summer...

\bibliographystyle{acmsiggraph}
\nocite{*}
\bibliography{report}

\end{document}