\documentclass[]{article}
\usepackage[margin=1.0in]{geometry}
\usepackage{amssymb}

%title material
\title{Astronomy 400B Lecture 5: Stellar Orbits}
\author{Brant Robertson}
\date{February, 2015}

%include latex definitions
\input{astro400B_definitions.tex}

%begin the document
\begin{document}

%make the title, goes after document begins
\maketitle

%first section
\section{Motion Under Gravity}

Newton's Law of Gravity point mass $M$ attracts another mass $m$ separated by
distance $\vr$, causing a change in momentum $m\vv$ of:

\begin{equation}
\frac{d}{dt}(m\vv) = -\frac{GmM}{r^{3}} \vr
\end{equation}
\noindent
where $G$ is Newton's gravitational constant. For an $N$-body system, we have
\begin{equation}
\frac{d}{dt}(m_{i}\vv_{i}) = -\sum_{j\ne i}\frac{G m_{i} m_{j}}{|\vx_i - \vx_j|^{3}} (\vx_i - \vx_j)
\end{equation}
\noindent
This equation can be re-written as
\begin{equation}
\frac{d}{dt}(m \vv_i) = - m \nabla\Phi(\vx_i)
\end{equation}
\noindent
where
\begin{equation}
\Phi(\vx_i) = - \sum_{i\ne j} \frac{G m_j}{|\vx_i - \vx_j|}
\end{equation}
\noindent
is the gravitational potential supplied by the point mass distribution at positions $\vx_i$.
Note we have chosen to define the potential such that $\Phi(x)\to0$ as $x\to\infty$ but
this is arbitrary. Note that
\begin{equation}
\nabla = \left[\frac{\partial}{\partial x},\frac{\partial}{\partial y},\frac{\partial}{\partial x}\right]
\end{equation}

\subsection{Continuous Matter Distributions}
Now consider a continuous distribution of matter density $\rho(\vx)$.  The
potential generated by $\rho(\vx)$ is given by
\begin{equation}
\label{eqn:potential}
\Phi(\vx) = - \int \frac{G\rho(\vx')}{|\vx - \vx'|}d^{3}\vx'
\end{equation}
\noindent
Note that the integral is performed over $\vx'$.  The force $\vF$ per unit mass
is
\begin{equation}
\vF(\vx) = - \nabla \Phi(\vx) = - \int \frac{G\rho(\vx')(\vx-\vx')}{|\vx-\vx'|^{3}}d^{3}\vx'
\end{equation}

\subsection{Poisson's Equation}

Take Equation \ref{eqn:potential} and apply the Laplacian operator
\begin{equation}
\nabla^{2} \equiv \nabla \cdot \nabla = \left[\frac{\partial^{2}}{\partial x^{2}}+\frac{\partial^{2}}{\partial y^{2}}+\frac{\partial^{2}}{\partial z^{2}}\right]
\end{equation}
\noindent
to both sides.  Remembering that the operator acts on $\vx$ and not $\vx'$, we have
\begin{equation}
\label{eqn:pois_init}
\nabla^{2} \Phi(\vx) = - \int G \rho(\vx') \nabla^{2} \left(\frac{1}{|\vx-\vx'|}\right)d^{3}\vx'.
\end{equation}
\noindent
We can evaluate this by noting that
\begin{equation}
\label{eqn:nabla}
\nabla\left(\frac{1}{|\vx - \vx'|}\right) = -\frac{\vx-\vx'}{|\vx-\vx'|^3}, \nabla^{2}\left(\frac{1}{|\vx - \vx'|}\right) = 0.
\end{equation}
\noindent
So we conclude that outside of a very small region around $\vx$, $\nabla^{2}\Phi(\vx)=0$.
Let's take a spherical region $S(\epsilon)$ of radius $\epsilon$ centered on $\vx$. In proceeding, let's
note that
\begin{equation}
\nabla^{2} f(|\vx-\vx'|) = \nabla_{\vx'}^{2} f(|\vx-\vx'|)
\end{equation}
\noindent
for any function $f(|\vx - \vx'|)$. If we take $\epsilon$ to be small enough such
that $\rho(\vx)\approx$ a constant, then we can write
\begin{eqnarray}
\label{eqn:pois_med}
\nabla^{2}\Phi(\vx) &\approx& - G\rho(\vx) \int_{S(\epsilon)} \nabla^2 \left( \frac{1}{|\vx - \vx'|} \right)d^{3}\vx' \nonumber \\
&=& - G \rho(\vx)  \int_{S(\epsilon)} \nabla_{\vx'}^2 \left( \frac{1}{|\vx - \vx'|} \right)d V'.
\end{eqnarray}
\noindent
Now we get to use the {\it divergence} theorem
\begin{equation}
\int \nabla^{2} f dV = \oint \nabla f \cdot dS,
\end{equation}
\noindent
which allows us to write Equation \ref{eqn:pois_med} as
\begin{equation}
- G \rho(\vx)  \int_{S(\epsilon)} \nabla_{\vx'}^2 \left( \frac{1}{|\vx - \vx'|} \right)d V' = - G \rho(\vx) \oint_{S(\epsilon)} \nabla_{\vx'}\left(\frac{1}{|\vx-\vx'|}\right) \cdot d\vS'
\end{equation}
\noindent
By applying Equation \ref{eqn:nabla} and the identity $\nabla_{\vx'} f = -\nabla f$, we have
\begin{eqnarray}
- G \rho(\vx) \oint_{S(\epsilon)} \nabla_{\vx'}\left(\frac{1}{|\vx-\vx'|}\right) \cdot d\vS' &=&
-G \rho(\vx) \oint_{S(\epsilon)} \left(\frac{\vx-\vx'}{|\vx-\vx'|^{3}}\right) \cdot d\vS' \nonumber \\
&=& 4 \pi G \rho(\vx)
\end{eqnarray}

\subsection{Inside a Uniform Shell}

The gravitational force inside a spherical shell of uniform density is zero.  The potential is a
constant.

{\bf See Figure 3.1 of Sparke and Gallagher.}

The opening angle OA is the same as OB, so the ratio of the enclosed mass is (SA/SB)$^{2}$.  Since
the ratio of the forces scale like the inverse of this ratio (from the inverse square law), the
force contributions of the A and B patches are equal and opposite.

\subsection{Gravitational Potential Outside a Uniform Spherical Shell}

{\bf See Figure 3.2 of Sparke and Gallagher}

We are calculating the potential a uniform spherical shell of mass $M$ and radius $a$.
Consider a point $P$ a distance $r$. The contribution of a narrow cone of opening
solid angle $\Delta\Omega$ around another point $Q'$ is
\begin{equation}
\Delta\Phi[\vx(P)] = -\frac{GM}{|\vx(P) - \vx(Q')|} \frac{\Delta\Omega}{4\pi}
\end{equation}
\noindent
Now consider the potential $\Phi'$ at point $P'$ at a radius $a$ away from the
center of a shell of the same mass $M$ but with a radius $r$.
The contribution $\Delta\Phi'$ from the material in the same cone of solid
angle $\Delta\Omega$ but at point $Q$ a distance $r$ away is
\begin{equation}
\Delta\Phi'[\vx(P')] = - \frac{GM}{|\vx(P') - \vx(Q)|}\frac{\Delta\Omega}{4\pi}
\end{equation}
\noindent
but since $PQ'=P'Q$, $\Delta\Phi[\vx(P)] = \Delta\Phi'[\vx(P')]$.
When we integrate over $4\pi$, we have
\begin{equation}
\Phi[\vx(P)] = \Phi'[\vx(P')]= \Phi'[\vx=0] = -\frac{GM}{r}
\end{equation}
\noindent
The force associated with this spherical shell is just $F(r) = \nabla \Phi[\vx(P)] = -\frac{GMm}{r}$.
So the force outside the shell is the same as for a point mass at distance $r$.

Inside a spherical mass distribution $\rho(r)$, the
centripetal acceleration that allows for a circular
orbit must be the radial gravitational force inwards.
On a circular orbit, in terms of the circular velocity
$V$ this acceleration is just
\begin{equation}
a = \frac{V^{2}(r)}{r} = -F(r) = \frac{GM(<r)}{r^2}.
\end{equation}
\noindent
For a point mass, $V(r)\propto r^{-1/2}$.  No extended
distribution can have a circular velocity curve that
declines more rapidly than $\propto r^{-1/2}$.

Note that the potential of a distributed mass density $\rho(\vx)$
is not the same as for a point mass.  Instead, we have
\begin{equation}
\Phi(r) = - \left[ \frac{GM(<r)}{r} + 4 \pi G \int_{r}^{\infty} \rho(r') r' dr'\right].
\end{equation}
\noindent
But as long as the spherical mass distribution has a finite size, eventually we
will have
\begin{equation}
\Phi(\vx) \to - \frac{G M_{\mathrm{tot}}}{|\vx|}
\end{equation}
\noindent
at large enough radius.

\subsection{Moving Through a Potential}

If we are moving through a background potential $\Phi(\vx)$ with
velocity $\vx$, the potential we experience changes
with time according to $d\Phi/dt = \vv\cdot\nabla\Phi(\vx)$.
We can re-write Newton's equation as
\begin{equation}
\vv \cdot \frac{d}{dt} ( m\vv) + m \vv\cdot\nabla \Phi(\vx) = 0 = \frac{d}{dt}\left[\frac{1}{2}m\vv^{2} + m \Phi(\vx)\right]
\end{equation}
\noindent
Therefore, the total energy
\begin{equation}
\label{eqn:total_energy}
E \equiv \frac{1}{2} m\vv^{2} + m\Phi(\vx) =~\mathrm{const}
\end{equation}
\noindent.
We can write of course that $E = KE + PE$, where $KE = \frac{1}{2}m\vv^{2}$ and $PE = m\Phi(\vx)$.
The kinetic energy cannot be negative, and we adopt $\Phi(\vx)\to0$ as $\vx\to\infty$.  At position
$\vx$, an orbit is unbound only if the total energy $E>0$. The speed at this place in the
orbit must exceed the escape speed, which is found by setting Equation \ref{eqn:total_energy} to zero.
We then have
\begin{equation}
v_{e}^{2} = - 2 \Phi(\vx).
\end{equation}

\subsection{Angular Momentum}

The angular momentum of an orbit is $L = \vx \times m\vv$. The time rate of change is
\begin{equation}
\frac{dL}{dt} = \vx \times \frac{d}{dt} (m \vv) = -m\vx \times \nabla \Phi.
\end{equation}
\noindent
For a spherically symmetric distribution, the force is central and $dL/dt = 0$ (angular
momentum is conserved).
In an axisymmetric distribution, on the component of $L$ parallel to the symmetry
axis is conserved.

\subsection{Individual Energy is Not Conserved in a Time-Dependent Potential}

In a many-body system, the total energy of each star is not individually conserved.
The time derivative of the kinetic energy of star $i$ is
\begin{equation}
\sum_{i} \vv_i \cdot \frac{d}{dt} (m_i \vv_i) = \frac{d}{dt} KE = -\sum_{i,j;i\ne j} \frac{Gm_i m_j}{|\vx_i - \vx_j|^{3}}(\vx_i - \vx_j) \cdot \vv_i
\end{equation}
\noindent
Doing the same calculation on star $j$ and taking the dot product with $\vv_j$ gives
\begin{equation}
\frac{1}{2}\sum_{j} \frac{d}{dt} (m_j \vv_j \cdot \vv_j) = - \sum_{i,j; i\ne j}\frac{Gm_i m_j}{|\vx_i - \vx_j|^{3}}(\vx_j - \vx_i)\cdot \vv_j
\end{equation}
\noindent
Adding the RHS of these two equations gives
\begin{equation}
- \sum_{i,j; i\ne j}\frac{Gm_i m_j}{|\vx_i - \vx_j|^{3}}(\vx_i - \vx_j)\cdot(\vv_i - \vv_j) = \sum_{i,j;i\ne j}\frac{d}{dt}\left(\frac{Gm_i m_j}{|\vx_i - \vx_j|}\right).
\end{equation}
The potential energy $PE$ is a sum of pairs of potentials from individual objects
\begin{equation}
PE = -\frac{1}{2} \sum_{i,j;i\ne j}\frac{Gm_i m_j}{|\vx_i - \vx_j|} = \frac{1}{2} \sum_i m_i \Phi(\vx_i) = \frac{1}{2} \int \rho(\vx)\Phi(\vx)dV.
\end{equation}
\noindent
We divided by two so every object contributes only once.

We can now see that, for the whole collection of objects
\begin{equation}
2 \frac{d}{dt} \left[ KE - \frac{1}{2} \sum_{i,j;i\ne j} \frac{G m_i m_j}{|\vx_i - \vx_j|}\right] = 0.
\end{equation}
\noindent
This means the total energy of the system is conserved.

\subsection{External Forces}

Consider the total force on an object $i$ in
a many body system under the influence of an external force $\vF_{\mathrm{ext}}$.
\begin{equation}
\sum_i \frac{d}{dt} (m_i \vv_i) \cdot \vx_i = -\sum_{i,j; i\ne j} \frac{Gm_i m_j}{|\vx_i - \vx_j|^{3}} (\vx_i - \vx_j) \cdot \vx_i + \sum_i \vF_{\mathrm{ext}}^{i} \cdot \vx_i.
\end{equation}
\noindent
The force on the $j$th object is
\begin{equation}
\sum_j \frac{d}{dt} (m_j \vv_j) \cdot \vx_j = - \sum_{i,j;i\ne j }\frac{G m_i m_j}{|\vx_i - \vx_j|^{3}}(\vx_j - \vx_i)\cdot\vx_j + \sum_j \vF_{\mathrm{ext}}^{j} \cdot \vx_j
\end{equation}
\noindent
The left hand sides of these equations are equal, and are equal to
\begin{equation}
\frac{1}{2} \sum_i \frac{d^2}{dt^2}(m_i\vx_i \cdot \vx_i) - \sum_i m_i \vv_i \cdot \vv_i = \frac{1}{2} \frac{d^2I}{dt^2} -2 KE
\end{equation}
\noindent
where the moment of inertia $I$ is
\begin{equation}
I \equiv \sum_i m_i \vx_i \cdot \vx_i.
\end{equation}
\noindent
By averaging the force on $i$ and $j$, we find
\begin{equation}
\frac{1}{2} \frac{d^2 I}{dt^2} - 2 KE = PE + \sum_i \vF_{\mathrm{ext}}^{i} \cdot \vx_i
\end{equation}
\noindent
and averaging this over a short time interval $0<t<\tau$ gives
\begin{equation}
\frac{1}{2\tau}\left[ \frac{dI}{dt}(\tau) - \frac{dI}{dt}(0)\right] = 2 \ave{KE} + \ave{PE} + \sum_i \ave{\vF_{\mathrm{ext}}^{i} \cdot \vx_i}
\end{equation}
\noindent
If all objects in the system are bound, then $|\vx_i \cdot \vv_i|$ and $dI/dt$ will be finite.  As $\tau\to\infty$, the LHS goes to zero.  Then we have
\begin{equation}
2\ave{KE} + \ave{PE} + \sum_i \ave{\vF_{\mathrm{ext}}^{i} \cdot \vx_i} = 0
\end{equation}

\section{Two-Body Relaxation}

A potential can be thought of as a combination of a smooth and steep potential wells.
We can calculate the average time between strong encounters with the steep
potential wells supplied near individual stars. Suppose that the
stars have mass $m$ and typical velocities $V$. If two stars come
within $r$ of one another, their kinetic energies increase to balance the
change in potential energy.  We say there is a {\it strong encounter}
if the change in potential energy is comparable to their starting
kinetic energy.  In other words
\begin{equation}
\frac{Gm^{2}}{r} \gtrsim \frac{mV^{2}}{2}
\end{equation}
\noindent
and the radius must be smaller than
\begin{equation}
r \lesssim r_{s} \equiv \frac{2Gm}{V^2}.
\end{equation}
\noindent
In the solar neighborhood, $V\approx30~\km~s^{-1}$, and taking $m\sim0.5\Msun$ we have $r_s \approx 1~$AU.
For the Sun, there has been no strong encounter for $\sim4.5~\Gyr$. Over a time $t$, the Sun
has an encounter with all stars in a cylinder with volume $\pi r_s^2 V t$. If there is a number
density of $n$, then we are interested in the time when $n\pi r_s^2 V t = 1$.  This time is
\begin{equation}
t_s = \frac{V^3}{4\pi G^2 m^3 n} \approx 4 \times 10^{12}~\yr~\left(\frac{V}{10~\km~s^{-1}}\right)^3\left(\frac{m}{\Msun}\right)^{-2}\left(\frac{n}{1~\pc^{-3}}\right)^{-1}.
\end{equation}
\noindent
For $n\approx0.1~\pc^{-3}$, then $t_s\sim10^{15}~\yr$.

\subsection{Weak Encounters}

Instead of strong encounters, we need to calculate the effects of weaker encounters
on indivudal stars.  We do this via the impulse approximation, that tells us how to
approximate the change in velocity from a weak encounter.  As one object passes
another, the perpendicular force between them is
\begin{equation}
\vF_{\perp} = \frac{GmMb}{(b^2 + V^2t^2)^{3/2}} = M \frac{dV_{\perp}}{dt}.
\end{equation}
\noindent
Integrating over time, we find that
\begin{equation}
\Delta V_{\perp} = \frac{1}{M} \int_{-\infty}^{\infty} \vF_{\perp}(t) dt =\frac{2 G m}{bV}.
\end{equation}
Slower approaches result in larger perpendicular velocity changes. The
path of $M$ is bent via
\begin{equation}
\alpha = \frac{\Delta V_{\perp}}{V} = \frac{2Gm}{bV^2}.
\end{equation}
\noindent
A weak encounter requires $b$ to be larger than $r_s$.

The number of stars with mass $m$ passing $M$ with
separations between $b$ and $b+\Delta b$ is the product of
the number density $n$ and the volume $V t \cdot 2 \pi b\Delta b$.
We multiply by $\Delta V_{\perp}^{2}$ and integrate over $b$ to find
\begin{equation}
\ave{\Delta V_{\perp}^{2}} = \int_{b_{min}}^{b_{max}} n V t\left(\frac{2Gm}{bV}\right)^2 2 \pi b db = \frac{8 \pi G^2 m^2 nt}{V} \ln \left(\frac{b_{max}}{b_{min}}\right).
\end{equation}
\noindent
After a time $t_{\mathrm{relax}}$ such that $\ave{\Delta V_{\perp}^2} = V^2$, the expected perpendicular
velocity becomes about equal to its original forward speed.  The initial path is forgotten!
Defining $\Lambda\equiv (b_{max}/b_{min})$, we find the relaxation time is much shorter than
the strong interaction time as
\begin{equation}
t_{\mathrm{relax}} = \frac{V^3}{8\pi G^2 m^2 n \ln \Lambda} = \frac{t_s}{2 \ln \Lambda}
\end{equation}
\begin{equation}
t_{\mathrm{relax}} \approx \frac{2\times10^9~\yr}{\ln \Lambda}\left(\frac{V}{10~\km~s^{-1}}\right)^3\left(\frac{m}{\Msun}\right)^{-2}\left(\frac{n}{10~\pc^{-3}}\right)^{-1}.
\end{equation}
\noindent
So what is $\Lambda$?  Well, if $b<r_s$ the method can't be correct and we usually take $b_{min} = r_s$.  We
can then take $b_{max}$ to be the size of the whole system.  For the Sun, $r_s = 1$~AU.  If we
take $300~\pc \leq b_{max} \leq 30~\kpc$, then $\Lambda\approx18-22$.  So the exact value of
$\Lambda$ doesn't matter, as $t_{\mathrm{relax}}\approx10^{13}~\yr$.

In a cluster consisting of $N$ stars with mass $m$ and typical $V$, the average separation is about
half the size of the system $R$.  We have
\begin{equation}
\frac{1}{2}NmV^2 \sim \frac{G(Nm)^2}{2R},~\Lambda = \frac{R}{r_s} \sim \frac{GmN}{V^2} \cdot \frac{V^2}{2Gm}\sim\frac{N}{2}.
\end{equation}
The crossing time of the system is $t_{cross} \sim R/V$.  Since $N=4n\pi R^3 /3$, we have
\begin{equation}
\frac{t_{relax}}{t_{cross}} \sim \frac{V^4 R^2}{6 N G^2 m^2 \ln \Lambda} \sim \frac{N}{6 \ln (N/2)}.
\end{equation}
\noindent
For $N\sim10^{11}$ stars, the relaxation will take $10^9$ crossing times.  For globulars with $10^6$ stars,
the relaxation time for the whole system is $t_{\mathrm{relax}} \sim 10^4 t_{cross}$.

\subsection{Effects of Two-Body Relaxation}

Consider a cluster of stars, each with mass $m$.
The {\it Maxwellian} distribution gives the fraction $f$ of stars with
velocities between $v$ and $v+\Delta v$ as
\begin{equation}
4\pi f_M(E) v^{2} \Delta v
\end{equation}
\noindent
where
\begin{equation}
f_M(E)\propto \exp\left(-\frac{E}{kT} \right) = \exp \left\{ -\left[ m\Phi(\vx) + \frac{mv^{2}}{2} \right]
 \Big/ kT \right\}.
\end{equation}
The temperature is related to the average kinetic energy as
\begin{equation}
\frac{1}{2}m\ave{\vv^{2}(\vx)} = \frac{3}{2}kT.
\end{equation}
\noindent
But there are stars at large energies, and these will evaporate. The kinetic
energy of stars that escape will typically be
\begin{equation}
\left\langle \frac{1}{2} m v_2^2(\vx) \right\rangle = - \frac{1}{N} \sum_i m_i \Phi(\vx_i) = -\frac{2}{N} PE = \frac{4}{N} KE = 6 kT
\end{equation}
The fraction of stars that escape will be
\begin{equation}
\int_{\sqrt{12kT/m}}^{\infty} f(E) v^2 dv \Big/ \int_0^{\infty} f(E) v^2 dv = 0.0074 \approx \frac{1}{136}
\end{equation}
\noindent
The evaporation time will be $t_{evap} \sim 136 t_{relax}$.  For globulars this is longer than
the age of the universe, but for open clusters it is a few gigayears.

\section{Orbits of Disk Stars and Epicycles}

Now we will treat orbits in axisymmetric potentials, and we will use cylindrical polar
coordinates $(R,\phi,z)$. In an axisymmetric potential, $\partial\Phi/\partial\phi = 0$, and
angular momentum about the $z$-axis is conserved.  We adopt $l_z$ at the angular
momentum per unit mass, we can write
\begin{equation}
\frac{d}{dt}(R^2 \dot{\phi}) = 0;~l_z \equiv R^2 \dot{\phi} =~\mathrm{constant}.
\end{equation}
\noindent
The radial equation of motion is
\begin{equation}
\label{eqn:radial_motion}
\ddot{R} = R \dot{\phi}^2 - \frac{\partial \Phi}{\partial R} = - \frac{\partial \Phi_{\mathrm{eff}}}{\partial R}
\end{equation}
\noindent
\begin{equation}
\Phieff \equiv \Phi(R,z) + \frac{l_z^2}{2R^2}.
\end{equation}
Multiplying \ref{eqn:radial_motion} by $\dot{R}$ and integrating informs us that
for a star in the midplane $z=0$
\begin{equation}
\frac{1}{2}\dot{R}^2 + \Phieff(R,z=0;l_z) = ~\mathrm{constant}.
\end{equation}
\noindent
If $l_z\ne0$, then there is an angular momentum barrier at the center of the galaxy that
limits $R$ to some minimum value.

The vertical equation of motion is
\begin{equation}
\ddot{z} = -\frac{\partial \Phi}{\partial z} (R,z) = -\frac{\partial \Phieff}{\partial z} (R,z)
\end{equation}
\noindent
If the potential is an even function about $z=0$ there is no vertical force in the midplane.

Let's expand the potential about the average radius $R_g$ of a star in a Taylor series and
truncate at the first term
\begin{equation}
\ddot{z} = -z \left[ \frac{\partial^2 \Phi}{\partial z^2}(R_g, z)\right]_{z=0} \equiv - \nu^2(R_g) z
\end{equation}
\noindent
where $\nu$ is an angular frequency.  The solution to this equation is
a harmonic oscillator
\begin{equation}
z(t) = Z \cos (\nu t + \theta)
\end{equation}
\noindent
where $Z$ and $\theta$ are constants.

Circular orbits with $\dot{R} = 0$ are only possible at a radius $R_g$ where $\Phieff =~\mathrm{constant}$.
At this radius
\begin{equation}
\frac{\partial \Phi}{\partial R}(R_g,z=0) = \frac{l_z^2}{R_g^3} = R_g \Omega^{2}(R_g)
\end{equation}
\noindent
where $\Omega(R)$ is the angular speed of a circular orbit in the disk plane.  If $\Phieff$ has a
minimum at $R_g$, then the circular orbit will have the lowest $l_z$.  Any larger $l_z$
will oscillate about the circular orbit, in an {\it epicycle} about a point that
moves with $\Omega(R_g)$ in a circular orbit of radius $R_g$.

Let's set $R = R_g+x$ in Equation \ref{eqn:radial_motion}, assume that $x\ll R$, and expand to
first order in $x/R$ and $z/R$.  We find that
\begin{equation}
\ddot{x} \approx - x\left[\frac{\partial^2 \Phieff}{\partial R^2}\right]_{R_g}\equiv - \kappa^2(R_g)x
\end{equation}
\noindent
and
\begin{equation}
x(t) \approx X \cos(\kappa t + \psi).
\end{equation}
\noindent
The constant $\kappa$ is called the epicyclic frequency when $\kappa^2>0$.  If $\kappa^2<0$,
the orbit is unstable.

Recalling that in a circular orbit
\begin{equation}
R \Omega^2(R) = \frac{\partial \Phi(R,z=0)}{\partial R}
\end{equation}
\noindent
we can write
\begin{equation}
\kappa^2(R) = \frac{d}{dR}[R\Omega^2(R)] + \frac{3 l_z^2}{R^4} = \frac{1}{R^3}\frac{d}{dR}[(R^2\Omega)^2] = -4B\Omega
\end{equation}
\noindent
where $B$ is Oort's constant.  In the solar neighborhood $B<0$ and $\kappa^2$ is positive and the Solar
orbit is stable.  If $R^2\Omega(R)$, the angular momentum of a circular orbit, increases with $R$ then
all larger circular orbits are stable.  Near a black hole this isn't the case, and the inner
most circular orbit is at $R=6GM/c^2$.

\subsection{Azimuthal Motion in Epicycles}

Since $R$ changes in an epicyclical orbit, the azimuthal velocity must change to
compensate to keep $l_z$ constant.  This means that
\begin{equation}
\dot(\phi) = \frac{l_z}{R^2} = \frac{\Omega(R_g)R_g^2}{(R_g + x)^2} \approx \Omega(R_g)\left(1 - \frac{2x}{R_g}\right).
\end{equation}
\noindent
We can integrate this equation to find that the azimuthal position with time varies as
\begin{equation}
\phi(t) = \phi_0  + \Omega(R_g)t - \frac{1}{R_g}\frac{2\Omega}{\kappa}X \sin(\kappa t + \psi)
\end{equation}
\noindent
The first two terms are circular motion starting from $\phi_0$ with constant angular
frequency $\Omega(R_g)$.  The third term is a harmonic oscillation with the same
frequency $\kappa$ as the $x$ motion but $\pi/2$ out of phase, and
larger by a factor $2\Omega/\kappa$.
The motion is also retrograde!

\subsection{$\kappa$ vs. $\Omega$}

For a point mass $\kappa = \Omega$.  For a uniform sphere $\kappa = 2\Omega$.
The galaxy has $\Omega < \kappa < 2\Omega$, and near the sun $\kappa \approx 1.4 \Omega$.

\subsection{Relative Speed of Nearby Stars}

The relative speeds of stars with $R_g > R_0$ are
\begin{equation}
v_y = R_0[\dot{\phi} - \Omega(R_0)]\approx R_0 \left[ \Omega(R_g) - 2x \frac{\Omega(R_g)}{R_g} - \Omega(R_0)\right]
\end{equation}
\noindent
but since $R_0 = R_g + x$ and dropping terms in $x^2$ we have
\begin{equation}
v_y \approx -x\left[ 2\Omega(R_0) + R_0\left(\frac{d\Omega}{dR}\right)_{R_0}\right] = -\frac{\kappa^2 x}{2\Omega} = 2Bx
\end{equation}
\noindent
Taking the average of stars we can measure, we find
\begin{equation}
\ave{v_y^2} = \left(\frac{\kappa^2}{2\Omega}\right)^2\ave{x^2} = \frac{\kappa^2}{4\Omega^2}\ave{v_x^2}
\end{equation}
\noindent
and since $\kappa<2\Omega$, $\ave{v_y^2}<\ave{v_x^2}$.  For the thin disk, we find that $2\lesssim\ave{v_x^2}/\ave{v_y^2}\lesssim3$.

\end{document}


\chapter{Appendix}\label{appendix}
Here we will lay out the details of the architecture and hyperparameter settings that were used in each agent mentioned in section \ref{research-method}. We start with the agents for the Starcraft II environment, then secondly the OpenAI Atari Pong environment.

\section{Starcraft II: RL agent architectures}\label{appendix-agents}
In this section we will give the specific architecture and hyperparameter settings used for RL agents in the Starcraft II environment. We will start by showing the baseline agent, which uses an architecture and hyperparameters that are shared by all agents. For all other agents, each extending this baseline agent, we will only give the additional architecture and parameters. For an overview of how each agent works, we refer to sections \ref{research-exp} and \ref{research-env-pysc2}.

\subsection{Baseline agent}\label{appendix-baseline}
\textbf{Neural network architecture}\newline
\noindent The DDQN policy and target network for the baseline agent consists of a CNN with three convolutional layers. The first layer is a transposed convolutional layer \cite{transpose} and the other two are regular convolutional layers. The transposed convolutional layer has the possibility to upscale the dimensionality, which is needed in agents using dimensionality reduction. These agents have their observation reduced from $32 \times 32$ to $16 \times 16$. This $16 \times 16$ observation is the input for their policy and target network. The output of these networks however need to be $32 \times 32$, capturing the action space. Although this upscaling is not needed for the baseline agent since it uses the full $32 \times 32$ observation as input, we still use it as the first layer in order to keep all agents' architectures as similar as possible.

Each layer uses a stride of $1$, input padding of $1$ and no output padding, keeping the dimensionality of the input the same. Furthermore, they also each have a kernel size of $3$. The first layer has $32$ output channels. The second layer has $32$ input channels (following the output channels of its previous layer) and $32$ output channels. The third and last layer has $32$ input channels (again following the output channels of its previous layer) and $1$ output channel. Both after the second and the first layer, we use the activation function known as \emph{ReLU} \cite{relu} whose output for each neuron is defined as the maximum of $0$ and the input neuron.

When training the policy network, the optimization algorithm \emph{Adam} is used, which is an extension on \emph{stochastic gradient descent} \cite{adam}. For loss calculation we refer to section \ref{pl-dqn}, more specifically algorithm \ref{alg:ddqn}.

\noindent\textbf{Hyperparameters}\newline
\noindent The following hyperparameters are used in the baseline agent:
\begin{itemize}
\item Steps in between training the policy network: $4$.
\item Steps in between updating the target network: $250$.
\item Optimizer learning rate: $0.0001$.
\item Discount factor: $0.99$.
\item Batch size for training the policy network: $256$.
\item Number of stored batches before training: $20$.
\end{itemize}

Lastly, an $\epsilon$-greedy strategy is used for balancing exploration and exploitation. This means that a random number in $[0,1]$ is chosen; whenever this is equal to or lower than the current epsilon value, a random action is chosen, and a greedy action otherwise. Epsilon decays from $1.0$ to $0.1$ in $100.000$ steps spaced on a logarithmic scale. Each step taken by the agent corresponds to one epsilon decay step. The resulting decay of the epsilon value can be seen in figure \ref{fig:epsilon}.

\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{Epsilon_decay}
    \caption{The decay of the epsilon value per episode.}
    \label{fig:epsilon}
\end{figure}

\subsection{PCA agent}
The neural network architecture and hyperparameter settings of the PCA agent are almost exactly the same as the baseline agent (see appendix \ref{appendix-baseline}). The only difference is that in the policy and target network, the first layer (the transposed convolutional layer) now has a stride of $2$ and output padding of $1$. This is to upscale dimensionality from the $16 \time 16$ observation (gotten after dimensionality reduction using PCA) to $32 \times 32$ representing the action space.

\subsection{Pre-trained and online trained autoencoder agent} %TODO "online"
As with the PCA agent, the difference with the baseline agent with regards to the DDQN architecture is merely the first layer of the policy and target network of the agent: it now has a stride of $2$ and output padding of $1$ to upscale the dimensionality from its $16 \times 16$ input to $32 \times 32$ output. In both autoencoder agents, the autoencoder has the same architecture and hyperparameters. \par

\noindent \textbf{Autoencoder neural network architecture and hyperparameters} \par
\noindent The encoder of the autoencoder consists of two convolutional layers. The first layer has a stride of $2$ to introduce dimensionality reduction from $32 \times 32$ to $16 \times 16$. The second layer has a stride of $1$ to keep this $16 \times 16$ dimensionality. Both layers have a kernel size of $3$ and an input padding of $1$. The first layer has $1$ input channel (since the observation input only has one channel) and $32$ output channels. Hence, the second layer has $32$ input channels and $1$ output channel. After both layers, there is a \emph{GELU} activation function, which is a nonlinear variant of ReLU \cite{gelu}.

The decoder consists of three layers. Because the decoder has to reconstruct the original input from the output of the encoder, the first is a transposed convolutional layer to upscale its $16 \times 16$ input back to $32 \times 32$. This is done using a stride of $2$ and output padding of $1$. It has $1$ input channel (corresponding to the $1$ output channel of the last encoder layer) and $32$ output channels. The other two layers are regular convolutional layers, with stride $1$ and no output padding. For the second layer, there are $32$ input and output channels, and for the third and last layer there are $32$ input channels and $1$ output channel (corresponding to the $1$ input channel of the first layer of the policy and target network). Each layer has a kernel size of $3$ and input padding of $1$. After the first and second layer there is a GELU activation function.

For training the autoencoder, the loss is calculated by the mean-scared-error between the original input and the reconstructed input. Furthermore, the Adam optimization algorithm is used, with a learning rate of $0.0001$.

\subsection{DeepMDP agent}
Compared to the baseline agent, the policy and target network of the DeepMDP agent have a prepended encoder. Furthermore it has an additional neural network for the transition loss (i.e. the auxiliary objective). Apart from these changes (including a different loss calculation) the only difference with the baseline agent is again the first layer of the target and policy network that now has a stride of $2$ and output padding of $1$ to upscale the dimensionality from $16 \times 16$ to $32 \times 32$. \par

\noindent \textbf{DeepMDP encoder and transition loss architectures and hyperparameters} \par
\noindent The encoder has the same architecture as the encoder in the autoencoder agents. It has two convolutional layers, with the first layer having a stride of $2$ for dimensionality reduction. The first layer has $1$ input channel and $32$ output channels and vice versa for the second layer. Both have a kernel size of $3$ and input padding of $1$. After both layers the activation function GELU is used.

The transition loss neural network has only $1$ layer, a convolutional layers. Most importantly, it has $1024$ output channels, corresponding to the $32 \times 32$ action space. It has a stride of $1$ and kernel size $2$.

Besides the usual DDQN loss calculation as with the baseline agent, the DeepMDP has an additional loss added to this; this total loss is used to train all neural networks of the DeepMDP. The transition loss is calculated by comparing the prediction of the next observation after dimensionality reduction given by the transition loss network, with the actual next observation after dimensionality reduction (i.e. the output of the encoder). The loss is calculated using the L1 loss function \cite{l1}. Added to this loss, is the gradient penalty which is discounted by a hyperparameter set to $0.01$. The gradient penalty is a combination of the gradient penalty of the encoder, the policy network and the transition loss network. For each of these three networks, the penalty is calculated using the Wasserstein Generative Adversarial Network penalty \cite{wgan}.

\section{OpenAI Pong: RL agent architectures}\label{appendix-agents-pong}
%TODO pong: explain policy network image reduction?
In this section we will give the specific architecture and hyperparameter settings used for RL agents in the OpenAI Atari Pong environment. We will start by showing the baseline agent, which uses an architecture and hyperparameters that are shared by all agents. For all other agents, each extending this baseline agent, we will only give the additional architecture and parameters. For an overview of how each agent works, we refer to sections \ref{research-exp} and \ref{research-env-pong}.

\subsection{Baseline agent}\label{appendix-baseline-pong}
\textbf{Neural network architecture}\par
\noindent The DDQN policy and target network for the baseline agent consists of three convolutional layers and two linear layers. Its input is $n \times 4 \times 84 \times 84$, for batches of size $n$. The $4$ channels represent the four consecutive frames that are used for a single observation. Each convolutional layer has no padding. The strides for each layer are $6$, $4$ and $3$ respectively, and the kernel/filter sizes are $3$, $2$ and $1$ respectively. The first layer has 4 channels, one for each input frame. It has $32$ output channels, thus the second layer has $32$ input channels. The second layer has $64$ output channels, thus the third layer has $64$ input channels. This last convolutional layer also has $64$ output channels. For input with batch size $n$, the downsampling through the convolutional layers is from $n \times 4 \times 84 \times 84$, to $n \times 32 \times 27 \times 27$, to $n \times 64 \times 12 \times 12$ to $n \times 64 \times 10 \times 10$.

The output after the last convolutional layer is flattened to $n \times (64 \cdot 10 \cdot 10) = n \times 6400$, which will be the input for the first linear layer. Thus, the first linear layer has $6400$ input features. It has $512$ output features. The second linear layer has $512$ input features and $6$ output features, covering the action-space. Furthermore, after each convolutional layer, there is batch normalisation layer to normalise the layer outputs \cite{batchnorm}, and a ReLU activation function \cite{relu}. After the first linear layer there is only a ReLU activation function. No activation function or batch normalisation is used after the final layer.

When training the policy network, the optimization algorithm \emph{Adam} is used, which is an extension on \emph{stochastic gradient descent} \cite{adam}. For loss calculation we refer to section \ref{pl-dqn}, more specifically algorithm \ref{alg:ddqn}.

\noindent\textbf{Hyperparameters}\par
\noindent The following hyperparameters are used in the baseline agent:
\begin{itemize}
\item Steps in between training the policy network: $1$.
\item Steps in between updating the target network: $1000$.
\item Optimizer learning rate: $5\mathrm{e}{-5}$.
\item Discount factor: $0.97$.
\item Batch size for training the policy network: $32$.
\item Number of stored batches before training: $313$.
\end{itemize}

Lastly, an $\epsilon$-greedy strategy is used for balancing exploration and exploitation. This means that a random number in $[0,1]$ is chosen; whenever this is equal to or lower than the current epsilon value, a random action is chosen, and a greedy action otherwise. Epsilon decays from $1.0$ to $0.02$ in $400.000$ steps spaced on a logarithmic scale. Each step taken by the agent corresponds to one epsilon decay step. One episode takes roughly between $800$ and $3000$ steps (depending on the length of the episode). The resulting decay of the epsilon value can be seen in figure \ref{fig:epsilon-pong}.

\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\textwidth]{Pong/Epsilon_decay_pong}
    \caption{The decay of the epsilon value per step in Pong.}
    \label{fig:epsilon-pong}
\end{figure}

\subsection{PCA agent}
The neural network architecture and hyperparameter settings of the PCA agent are exactly the same as the baseline agent (see appendix \ref{appendix-baseline-pong}). In the PCA agent though, the input for the policy network is now $n \times 4 \times 42 \times 42$, having reduced the dimensionality of each frame from $84 \times 84$ to $42 \times 42$. In the policy network, because of the stride and filter size settings in the convolutional layer, this input is downsampled from $n \times 4 \times 42 \times 42$, to $n \times 32 \times 13 \times 13$ after the first layer, to $n \times 64 \times 5 \times 5$ after the second layer, to $n \times 64 \times 3 \times 3$ after the third convolutional layer. Thus, the first linear layer has $64 \cdot 3 \cdot 3 = 576$ input features.

\subsection{Pre-trained and online trained autoencoder agent} %TODO "online"
As with the PCA agent, the policy network and hyperparameter settings are the same as the baseline agent \ref{appendix-baseline-pong}. Again, the input for the policy network is now $n \times 4 \times 42 \times 42$, which is downsampled through the convolutional layers to $n \times 64 \times 3 \times 3$. \par

\noindent \textbf{Autoencoder neural network architecture and hyperparameters}\par
\noindent The \emph{encoder} of the autoencoder consists of three convolutional layers. The first layer has a stride of $2$ to introduce dimensionality reduction from $84 \times 84$ to $42 \times 42$. The second and third layer have a stride of $1$ to keep this $42 \times 42$ dimensionality. All three layers have a kernel size of $3$ and an input padding of $1$. The first layer has $1$ input channel (since the frame input only has one colour channel) and $32$ output channels. Hence, the second layer has $32$ input channels, and it has $32$ output channels. The third convolutional layer has $32$ input channels and $1$ output channel. After each convolutional layer, there is a \emph{GELU} activation function, which is a nonlinear variant of ReLU \cite{gelu}.

The \emph{decoder} consists of two layers. Because the decoder has to reconstruct the original input from the output of the encoder, the first is a transposed convolutional layer to upscale its $42 \times 42$ input back to $84 \times 84$. This is done using a stride of $2$ and output padding of $1$. It has $1$ input channel (corresponding to the $1$ output channel of the last encoder layer) and $32$ output channels. The other layer is a regular convolutional layers, with stride $1$ and no output padding. For this second convolutional layer, there are $32$ input channels and $1$ output channel (corresponding to the $1$ colour channel of a frame). Each layer has a kernel size of $3$ and input padding of $1$. After the first layer there is a GELU activation function.

For training the autoencoder, the loss is calculated by the mean-scared-error between the original input and the reconstructed input. Furthermore, the Adam optimization algorithm is used, with a learning rate of $0.0001$.


\subsection{Demand Forecasting with Classical Forecasting Methods}
\label{class_methods}

Forecasting became a formal discipline starting in the 1950s and has its
    origins in the broader field of statistics.
\cite{hyndman2018} provide a thorough overview of the concepts and methods
    established, and \cite{ord2017} indicate business-related applications
    such as demand forecasting.
These "classical" forecasting methods share the characteristic that they are
    trained over the entire $Y$ first.
Then, for prediction, the forecaster specifies the number of time steps for
    which he wants to generate forecasts.
That is different for ML models.


%=============================================================================
%=============================================================================

\chapter{Semi-Structured-Grid System Interface (SStruct)}
\label{ch-SStruct}

The \code{SStruct} interface is appropriate for applications with grids that
are mostly---but not entirely---structured, e.g. block-structured grids (see
Figure~\ref{fig-sstruct-example}), composite grids in structured adaptive mesh
refinement (AMR) applications (see Figure~\ref{fig-sstruct-samr-grid}), and
overset grids.  In addition, it supports more general PDEs than the
\code{Struct} interface by allowing multiple variables (system PDEs) and
multiple variable types (e.g. cell-centered, face-centered, etc.).  The
interface provides access to data structures and linear solvers in \hypre{}
that are designed for semi-structured grid problems, but also to the most
general data structures and solvers.
%These latter solvers are usually provided via the \code{FEI} or \code{IJ}
%interfaces described in Chapters~\ref{ch-FEI} and \ref{ch-IJ}.

The \code{SStruct} grid is composed out of a number of structured grid {\em
parts}, where the physical inter-relationship between the parts is arbitrary.
Each part is constructed out of two basic components: boxes (see
Figure~\ref{fig-struct-boxes}) and {\em variables}.  Variables represent the
actual unknown quantities in the grid, and are associated with the box indices
in a variety of ways, depending on their types.  In \hypre{}, variables may be
cell-centered, node-centered, face-centered, or edge-centered.  Face-centered
variables are split into x-face, y-face, and z-face, and edge-centered
variables are split into x-edge, y-edge, and z-edge.  See Figure
\ref{fig-gridvars} for an illustration in 2D.

\begin{figure}
\centering
\includegraphics[width=.3\textwidth]{figSStructGridVars}
\caption{%
Grid variables in \hypre{} are referenced by the abstract cell-centered index
to the left and down in 2D (analogously in 3D).  In the figure, index $(i,j)$
is used to reference the variables in black.  The variables in grey---although
contained in the pictured cell---are not referenced by the $(i,j)$ index.}
\label{fig-gridvars}
\end{figure}

The \code{SStruct} interface uses a {\em graph} to allow nearly arbitrary
relationships between part data.  The graph is constructed from stencils or
finite element stiffness matrices plus some additional data-coupling information
set by the \code{GraphAddEntries()} routine.  Two other methods for relating
part data are the \code{GridSetNeighborPart()} and \code{GridSetSharedPart()}
routines, which are particularly well suited for block-structured grid problems.
The latter is useful for finite element codes.

There are five basic steps involved in setting up the linear system to be
solved:
%\begin{enumerate}
\begin{list}{\arabic{enumi}.}{\usecounter{enumi}\setlength{\itemsep}{0in}}
\item set up the grid,
\item set up the stencils (if needed),
\item set up the graph,
\item set up the matrix,
\item set up the right-hand-side vector.
\end{list}
%\end{enumerate}
%In the remainder of this section, we consider three examples: block-structured
%grid problems with stencils (Section~\ref{sec-Block-Structured-Grids});
%block-structured grid problems with finite elements
%(Section~\ref{sec-Block-Structured-Grids-FEM}); and structured adaptive mesh
%refinement problems (Section~\ref{sec-Structured-Adaptive-Mesh-Refinement}).

%-----------------------------------------------------------------------------

\section{Block-Structured Grids with Stencils}
\label{sec-Block-Structured-Grids}

In this section, we describe how to use the \code{SStruct} interface to define
block-structured grid problems.  We do this primarily by example, paying
particular attention to the construction of stencils and the use of the
\code{GridSetNeighborPart()} interface routine.

Consider the solution of the diffusion equation
\begin{equation} \label{eqn-block-diffusion}
- \nabla \cdot (D \nabla u) + \sigma u = f
\end{equation}
on the block-structured grid in Figure~\ref{fig-sstruct-example}, where $D$ is
a scalar diffusion coefficient, and $\sigma \geq 0$.  The discretization
\cite{JEMorel_RMRoberts_MJShashkov_1998} introduces three different types of
variables: cell-centered, $x$-face, and $y$-face.  The three discretization
stencils that couple these variables are also given in the figure.  The
information in this figure is essentially all that is needed to describe the
nonzero structure of the linear system we wish to solve.

\begin{figure}
\centering
\mbox{}\hfill
\includegraphics[width=.45\textwidth]{figSStructExample1a}
\hfill
\includegraphics[width=.4\textwidth]{figSStructExample1b}
\hfill\mbox{}
\caption{%
Example of a block-structured grid with five logically-rectangular blocks and
three variables types: cell-centered, $x$-face, and $y$-face.  Discretization
stencils for the cell-centered (left), $x$-face (middle), and $y$-face (right)
variables are also pictured.}
\label{fig-sstruct-example}

\end{figure}
\begin{figure}
\centering
\includegraphics[width=.6\textwidth]{figSStructExample1c}
\caption{%
One possible labeling of the grid in Figure~\ref{fig-sstruct-example}.}
\label{fig-sstruct-example-parts}
\end{figure}

The grid in Figure~\ref{fig-sstruct-example} is defined in terms of five
separate logically-rectangular parts as shown in
Figure~\ref{fig-sstruct-example-parts}, and each part is given a unique label
between 0 and 4.  Each part consists of a single box with lower index $(1,1)$
and upper index $(4,4)$ (see Section~\ref{sec-Struct-Grid}), and the grid data
is distributed on five processes such that data associated with part~$p$ lives
on process~$p$.  Note that in general, parts may be composed out of arbitrary
unions of boxes, and indices may consist of non-positive integers (see
Figure~\ref{fig-struct-boxes}).  Also note that the \code{SStruct} interface
expects a domain-based data distribution by boxes, but the actual distribution
is determined by the user and simply described (in parallel) through the
interface.

\begin{figure}
\centering
\begin{tabular}{@{}c@{}}
\includegraphics[width=.28\textwidth]{figSStructGrid1} \\ 1
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.28\textwidth]{figSStructGrid2} \\ 2
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.28\textwidth]{figSStructGrid3} \\ 3
\end{tabular}
\vspace{1em} \\
\begin{tabular}{@{}c@{}}
\includegraphics[width=.28\textwidth]{figSStructGrid4} \\ 4
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.28\textwidth]{figSStructGrid5} \\ 5
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.28\textwidth]{figSStructGrid6} \\ 6
\end{tabular}
\vspace{2em} \\
\begin{minipage}{0.9\textwidth}
\begin{verbatim}

    HYPRE_SStructGrid grid;
    int ndim = 2, nparts = 5, nvars = 3, part = 3;
    int extents[][2] = {{1,1}, {4,4}};
    int vartypes[]   = {HYPRE_SSTRUCT_VARIABLE_CELL,
                        HYPRE_SSTRUCT_VARIABLE_XFACE,
                        HYPRE_SSTRUCT_VARIABLE_YFACE};
    int nb2_n_part      = 2,              nb4_n_part      = 4;
    int nb2_exts[][2]   = {{1,0}, {4,0}}, nb4_exts[][2]   = {{0,1}, {0,4}};
    int nb2_n_exts[][2] = {{1,1}, {1,4}}, nb4_n_exts[][2] = {{4,1}, {4,4}};
    int nb2_map[2]      = {1,0},          nb4_map[2]      = {0,1};
    int nb2_dir[2]      = {1,-1},         nb4_dir[2]      = {1,1};

1:  HYPRE_SStructGridCreate(MPI_COMM_WORLD, ndim, nparts, &grid);

    /* Set grid extents and grid variables for part 3 */
2:  HYPRE_SStructGridSetExtents(grid, part, extents[0], extents[1]);
3:  HYPRE_SStructGridSetVariables(grid, part, nvars, vartypes);

    /* Set spatial relationship between parts 3 and 2, then parts 3 and 4 */
4:  HYPRE_SStructGridSetNeighborPart(grid, part, nb2_exts[0], nb2_exts[1],
       nb2_n_part, nb2_n_exts[0], nb2_n_exts[1], nb2_map, nb2_dir);
5:  HYPRE_SStructGridSetNeighborPart(grid, part, nb4_exts[0], nb4_exts[1],
       nb4_n_part, nb4_n_exts[0], nb4_n_exts[1], nb4_map, nb4_dir);

6:  HYPRE_SStructGridAssemble(grid);

\end{verbatim}
\end{minipage}
\caption{%
Code on process 3 for setting up the grid in Figure~\ref{fig-sstruct-example}.}
\label{fig-sstruct-grid}
\end{figure}

As with the \code{Struct} interface, each process describes that portion of the
grid that it ``owns'', one box at a time.  Figure~\ref{fig-sstruct-grid} shows
the code for setting up the grid on process~3 (the code for the other processes
is similar).  The ``icons'' at the top of the figure illustrate the result of
the numbered lines of code.  Process~3 needs to describe the data pictured in
the bottom-right of the figure.  That is, it needs to describe part~3 plus some
additional neighbor information that ties part~3 together with the rest of the
grid.  The \code{Create()} routine creates an empty 2D grid object with five
parts that lives on the \code{MPI_COMM_WORLD} communicator.  The
\code{SetExtents()} routine adds a new box to the grid.  The
\code{SetVariables()} routine associates three variables of type cell-centered,
$x$-face, and $y$-face with part~3.

At this stage, the description of the data on part~3 is complete.  However, the
spatial relationship between this data and the data on neighboring parts is not
yet defined.  To do this, we need to relate the index space for part~3 with the
index spaces of parts 2 and~4.  More specifically, we need to tell the interface
that the two grey boxes neighboring part~3 in the bottom-right of
Figure~\ref{fig-sstruct-grid} also correspond to boxes on parts 2 and~4.  This
is done through the two calls to the \code{SetNeighborPart()} routine.  We
discuss only the first call, which describes the grey box on the right of the
figure.  Note that this grey box lives outside of the box extents for the grid
on part~3, but it can still be described using the index-space for part~3
(recall Figure~\ref{fig-struct-boxes}).  That is, the grey box has extents
$(1,0)$ and $(4,0)$ on part~3's index-space, which is outside of part~3's grid.
The arguments for the \code{SetNeighborPart()} call are simply the lower and
upper indices on part~3 and the corresponding indices on part~2.  The final two
arguments to the routine indicate that the positive $x$-direction on part~3
(i.e., the $i$ component of the tuple $(i,j)$) corresponds to the positive
$y$-direction on part~2 and that the positive $y$-direction on part~3
corresponds to the positive $x$-direction on part~2.

The \code{Assemble()} routine is a collective call (i.e., must be called on all
processes from a common synchronization point), and finalizes the grid
assembly, making the grid ``ready to use''.

With the neighbor information, it is now possible to determine where off-part
stencil entries couple.  Take, for example, any shared part boundary such as
the boundary between parts 2 and~3.  Along these boundaries, some stencil
entries reach outside of the part.  If no neighbor information is given, these
entries are effectively zeroed out, i.e., they don't participate in the
discretization.  However, with the additional neighbor information, when a
stencil entry reaches into a neighbor box it is then coupled to the part
described by that neighbor box information.

Another important consequence of the use of the \code{SetNeighborPart()} routine
is that it can declare variables on different parts as being the same.  For
example, the face variables on the boundary of parts 2 and~3 are recognized as
being shared by both parts (prior to the \code{SetNeighborPart()} call, there
were two distinct sets of variables).  Note also that these variables are of
different types on the two parts; on part~2 they are $x$-face variables, but on
part~3 they are $y$-face variables.

For brevity, we consider only the description of the $y$-face stencil in
Figure~\ref{fig-sstruct-example}, i.e. the third stencil in the figure.  To do
this, the stencil entries are assigned unique labels between 0 and 8 and their
``offsets'' are described relative to the ``center'' of the stencil.  This
process is illustrated in Figure \ref{fig-sstruct-stencil}.  Nine calls are
made to the routine \code{HYPRE_SStructStencilSetEntry()}.  As an example, the
call that describes stencil entry 5 in the figure is given the entry number~5,
the offset $(-1,0)$, and the identifier for the $x$-face variable (the variable
to which this entry couples).  Recall from Figure~\ref{fig-gridvars} the
convention used for referencing variables of different types.  The geometry
description uses the same convention, but with indices numbered relative to the
referencing index $(0,0)$ for the stencil's center.
Figure~\ref{fig-sstruct-graph} shows the code for setting up the graph .

\begin{figure}
\centering
\mbox{}\hfill
\includegraphics[width=.25\textwidth]{figSStructStenc0}
\hfill
\includegraphics[width=.2\textwidth]{figSStructStenc1}
\hfill\mbox{}
\caption{%
Assignment of labels and geometries to the $y$-face stencil in
Figure~\ref{fig-sstruct-example}.}
\label{fig-sstruct-stencil}
\end{figure}

\begin{figure}
\centering
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGraph1}\vspace{-.5em} \\ 1
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGraph2}\vspace{-.5em} \\ 2
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGraph5}\vspace{-.5em} \\ 3
\end{tabular}
\vspace{1em} \\
\begin{minipage}{0.9\textwidth}
\begin{verbatim}

    HYPRE_SStructGraph graph;
    HYPRE_SStructStencil c_stencil, x_stencil, y_stencil;
    int c_var = 0, x_var = 1, y_var = 2;
    int part;

1:  HYPRE_SStructGraphCreate(MPI_COMM_WORLD, grid, &graph);

    /* Set the cell-centered, x-face, and y-face stencils for each part */
    for (part = 0; part < 5; part++)
    {
2:     HYPRE_SStructGraphSetStencil(graph, part, c_var, c_stencil);
       HYPRE_SStructGraphSetStencil(graph, part, x_var, x_stencil);
       HYPRE_SStructGraphSetStencil(graph, part, y_var, y_stencil);
    }

3:  HYPRE_SStructGraphAssemble(graph);

\end{verbatim}
\end{minipage}
\caption{%
Code on process 3 for setting up the graph for Figure~\ref{fig-sstruct-example}.}
\label{fig-sstruct-graph}
\end{figure}

With the above, we now have a complete description of the nonzero structure for
the matrix.  The matrix coefficients are then easily set in a manner similar to
what is described in Section~\ref{sec-Struct-Matrix} using routines
\code{MatrixSetValues()} and \code{MatrixSetBoxValues()} in the \code{SStruct}
interface.  As before, there are also \code{AddTo} variants of these routines.
Likewise, setting up the right-hand-side is similar to what is described in
Section~\ref{sec-Struct-RHS}.  See the \hypre{} reference manual for details.

An alternative approach for describing the above problem through the interface
is to use the \code{GraphAddEntries()} routine instead of the
\code{GridSetNeighborPart()} routine.  In this approach, the five parts would be
explicitly ``sewn'' together by adding non-stencil couplings to the matrix
graph.  The main downside to this approach for block-structured grid problems
is that variables along block boundaries are no longer considered to be the
same variables on the corresponding parts that share these boundaries.  For
example, any face variable along the boundary between parts 2 and~3 in
Figure~\ref{fig-sstruct-example} would represent two different variables that
live on different parts.  To ``sew'' the parts together correctly, we would
need to explicitly select one of these variables as the representative that
participates in the discretization, and make the other variable a dummy
variable that is decoupled from the discretization by zeroing out appropriate
entries in the matrix.  All of these complications are avoided by using the
\code{GridSetNeighborPart()} for this example.

%-----------------------------------------------------------------------------

\section{Block-Structured Grids with Finite Elements}
\label{sec-Block-Structured-Grids-FEM}

In this section, we describe how to use the \code{SStruct} interface to define
block-structured grid problems with finite elements.  We again do this by
example, paying particular attention to the use of the \code{FEM} interface
routines and the \code{GridSetSharedPart()} routine.  See example code
\file{ex14.c} for a complete implementation.

Consider a nodal finite element (FEM) discretization of the Laplace equation on
the star-shaped grid in Figure~\ref{fig-sstruct-fem-example}.  The local FEM
stiffness matrix in the figure describes the coupling between the grid
variables.  Although we could still describe this problem using stencils as in
Section~\ref{sec-Block-Structured-Grids}, an FEM-based approach (available in
\hypre{} version \code{2.6.0b} and later) is a more natural alternative.

\begin{figure} [t]
\centering
\includegraphics[width=.54\textwidth]{figSStructExample3a}
\hfill
\includegraphics[width=.44\textwidth]{figSStructExample3b}
\caption{%
Example of a star-shaped grid with six logically-rectangular blocks and one
nodal variable.  Each block has an angle at the origin given by $\gamma=\pi/3$.
The finite element stiffness matrix (right) is given in terms of the pictured
variable ordering (left).}
\label{fig-sstruct-fem-example}
\end{figure}

%\begin{figure}
%\centering
%\includegraphics[width=.5\textwidth]{figSStructExample3c}
%\caption{%
%One possible labeling of the grid in Figure~\ref{fig-sstruct-fem-example}.}
%\label{fig-sstruct-fem-example-parts}
%\end{figure}

The grid in Figure~\ref{fig-sstruct-fem-example} is defined in terms of six
separate logically-rectangular parts, and each part is given a unique label
between 0 and 5.  Each part consists of a single box with lower index $(1,1)$
and upper index $(9,9)$, and the grid data is distributed on six processes such
that data associated with part~$p$ lives on process~$p$.

\begin{figure}
\centering
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGridFEM1} \\ 1
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGridFEM2} \\ 2
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGridFEM3} \\ 3
\end{tabular}
\vspace{1em} \\
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGridFEM4} \\ 4
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGridFEM5} \\ 5
\end{tabular}
\hfill
\begin{tabular}{@{}c@{}}
\includegraphics[width=.32\textwidth]{figSStructGridFEM6} \\ 6
\end{tabular}
\vspace{2em} \\
\begin{minipage}{0.9\textwidth}
\begin{verbatim}

    HYPRE_SStructGrid grid;
    int ndim = 2, nparts = 6, nvars = 1, part = 0;
    int ilower[2]    = {1,1}, iupper[2] = {9,9};
    int vartypes[]   = {HYPRE_SSTRUCT_VARIABLE_NODE};
    int ordering[12] = {0,-1,-1,  0,+1,-1,  0,+1,+1,  0,-1,+1};

    int s_part   = 2;
    int ilo[2]   = {1,1}, iup[2]   = {1,9}, offset[2]   = {-1,0};
    int s_ilo[2] = {1,1}, s_iup[2] = {9,1}, s_offset[2] = {0,-1};
    int map[2]   = {1,0};
    int dir[2]   = {-1,1};

1:  HYPRE_SStructGridCreate(MPI_COMM_WORLD, ndim, nparts, &grid);

    /* Set grid extents, grid variables, and FEM ordering for part 0 */
2:  HYPRE_SStructGridSetExtents(grid, part, ilower, iupper);
3:  HYPRE_SStructGridSetVariables(grid, part, nvars, vartypes);
4:  HYPRE_SStructGridSetFEMOrdering(grid, part, ordering);

    /* Set shared variables for parts 0 and 1 (0 and 2/3/4/5 not shown) */
5:  HYPRE_SStructGridSetSharedPart(grid, part, ilo, iup, offset,
       s_part, s_ilo, s_iup, s_offset, map, dir);

6:  HYPRE_SStructGridAssemble(grid);

\end{verbatim}
\end{minipage}
\caption{%
Code on process 0 for setting up the grid in Figure~\ref{fig-sstruct-fem-example}.}
\label{fig-sstruct-fem-grid}
\end{figure}

As in Section~\ref{sec-Block-Structured-Grids}, each process describes that
portion of the grid that it ``owns'', one box at a time.
Figure~\ref{fig-sstruct-fem-grid} shows the code for setting up the grid on
process~0 (the code for the other processes is similar).  The ``icons'' at the
top of the figure illustrate the result of the numbered lines of code.
Process~0 needs to describe the data pictured in the bottom-right of the figure.
That is, it needs to describe part~0 plus some additional information about
shared data with other parts on the grid.  The \code{SetFEMOrdering()} routine
sets the ordering of the unknowns in an element (an element is always a grid
cell in \hypre{}).  This determines the ordering of the data passed into the
routines \code{MatrixAddFEMValues()} and \code{VectorAddFEMValues()} discussed
later.

At this point, the layout of the data on part~0 is complete, but there is no
relationship to the rest of the grid.  To couple the parts, we need to tell
\hypre{} that some of the boundary variables on part~0 are shared with other
parts, i.e., they are the same as some of the variables on other parts.  This is
done through five calls to the \code{SetSharedPart()} routine.  Only the first
call is shown in the figure; the other four calls are similar.  The arguments to
this routine are the same as \code{SetNeighborPart()} with the addition of two
new offset arguments, named \code{offset} and \code{s_offset} in the figure.
Each offset represents a pointer from the cell center to one of the following:
all variables in the cell (no nonzeros in offset); all variables on a face (only
1 nonzero); all variables on an edge (2 nonzeros); all variables at a point (3
nonzeros).  The two offsets must be consistent with each other.

The graph is set up similarly to Figure~\ref{fig-sstruct-graph}, except that the
stencil calls are replaced by calls to \code{GraphSetFEM()}.  The nonzero
pattern of the stiffness matrix can also be set by calling the optional routine
\code{GraphSetFEMSparsity()}.

Matrix and vector values are set one element at a time.  For the example in this
section, calls on part~0 would have the following form:
\begin{verbatim}
   int part = 0;
   int index[2] = {i,j};
   double m_values[16] = {...};
   double v_values[4]  = {...};

   HYPRE_SStructMatrixAddFEMValues(A, part, index, m_values);
   HYPRE_SStructVectorAddFEMValues(v, part, index, v_values);
\end{verbatim}
Here, \code{m_values} contains local stiffness matrix values and \code{v_values}
contains local variable values.  The global matrix and vector are assembled
internally by \hypre{}, using the shared variables to couple the parts.

%-----------------------------------------------------------------------------

\section{Structured Adaptive Mesh Refinement}
\label{sec-Structured-Adaptive-Mesh-Refinement}

We now briefly discuss how to use the \code{SStruct} interface in a structured
AMR application.  Consider Poisson's equation on the simple cell-centered
example grid illustrated in Figure \ref{fig-sstruct-samr-grid}.  For structured
AMR applications, each refinement level should be defined as a unique part.
There are two parts in this example: part~0 is the global coarse grid and
part~1 is the single refinement patch.  Note that the coarse unknowns
underneath the refinement patch (gray dots in Figure
\ref{fig-sstruct-samr-grid}) are not real physical unknowns; the solution in
this region is given by the values on the refinement patch.  In setting up the
composite grid matrix \cite{SFMcCormick_1989a} for \hypre{} the equations for
these ``dummy'' unknowns should be uncoupled from the other unknowns (this can
easily be done by setting all off-diagonal couplings to zero in this region).

\begin{figure}
\centering
\includegraphics[width=.7\textwidth]{figSStructExample2a}
\caption{%
Structured AMR grid example. Shaded regions correspond to process~0, unshaded
to process~1.  The grey dots are dummy variables.}
\label{fig-sstruct-samr-grid}
\end{figure}

In the example, parts are distributed across the same two processes with
process 0 having the ``left'' half of both parts.  The composite grid is then
set up part-by-part by making calls to \code{GridSetExtents()} just as was done
in Section~\ref{sec-Block-Structured-Grids} and Figure~\ref{fig-sstruct-grid}
(no \code{SetNeighborPart} calls are made in this example).  Note that in the
interface there is no required rule relating the indexing on the refinement
patch to that on the global coarse grid; they are separate parts and thus each
has its own index space.  In this example, we have chosen the indexing such
that refinement cell $(2i,2j)$ lies in the lower left quadrant of coarse cell
$(i,j)$.  Then the stencil is set up.  In this example we are using a finite
volume approach resulting in the standard 5-point stencil in
Figure~\ref{fig-struct-stencil-b} in both parts.

The grid and stencil are used to define all intra-part coupling in the graph,
the non-zero pattern of the composite grid matrix.  The inter-part coupling at
the coarse-fine interface is described by \code{GraphAddEntries()} calls.  This
coupling in the composite grid matrix is typically the composition of an
interpolation rule and a discretization formula.  In this example, we use a
simple piecewise constant interpolation, i.e. the solution value in a coarse
cell is equal to the solution value at the cell center.  Then the flux across a
portion of the coarse-fine interface is approximated by a difference of the
solution values on each side.  As an example, consider approximating the flux
across the left interface of cell $(6,6)$ in Figure
\ref{fig-sstruct-samr-stencil}.  Let $h$ be the coarse grid mesh size, and
consider a local coordinate system with the origin at the center of cell
$(6,6)$.  We approximate the flux as follows
\begin{eqnarray}
\int_{-h/4}^{h/4}{u_x(-h/4,s)} ds
& \approx & \frac{h}{2} u_x(-h/4,0)
  \approx \frac{h}{2} \frac{u(0,0)-u(-3h/4,0)}{3h/4} \\
& \approx & \frac{2}{3} (u_{6,6}-u_{2,3}) \nonumber .
\end{eqnarray}
The first approximation uses the midpoint rule for the edge integral, the second
uses a finite difference formula for the derivative, and the third the piecewise
constant interpolation to the solution in the coarse cell.  This means that the
equation for the variable at cell $(6,6)$ involves not only the stencil
couplings to $(6,7)$ and $(7,6)$ on part~1 but also non-stencil couplings to
$(2,3)$ and $(3,2)$ on part~0.  These non-stencil couplings are described by
\code{GraphAddEntries()} calls.  The syntax for this call is simply the part and
index for both the variable whose equation is being defined and the variable to
which it couples.  After these calls, the non-zero pattern of the matrix (and
the graph) is complete.  Note that the ``west'' and ``south'' stencil couplings
simply ``drop off'' the part, and are effectively zeroed out (currently, this is
only supported for the \code{HYPRE_PARCSR} object type, and these values must be
manually zeroed out for other object types; see \code{MatrixSetObjectType()} in
the reference manual).

\begin{figure}
\centering
\includegraphics[width=.4\textwidth]{figSStructExample2b}
\caption{%
Coupling for equation at corner of refinement patch. Black lines
(solid and broken) are stencil couplings. Gray line are non-stencil
couplings.}
\label{fig-sstruct-samr-stencil}
\end{figure}

The remaining step is to define the actual numerical values for the composite
grid matrix.  This can be done by either \code{MatrixSetValues()} calls to set
entries in a single equation, or by \code{MatrixSetBoxValues()} calls to set
entries for a box of equations in a single call.  The syntax for the
\code{MatrixSetValues()} call is a part and index for the variable whose
equation is being set and an array of entry numbers identifying which entries
in that equation are being set.  The entry numbers may correspond to stencil
entries or non-stencil entries.


\documentclass[10pt]{article}
\usepackage[a4paper, margin=1in]{geometry}
\usepackage{hyperref}
\usepackage{setspace}
\usepackage[style=iso]{datetime2}
\usepackage{amsmath}
\usepackage{eufrak}
\usepackage{amssymb}
\usepackage{mathtools}

\newcommand{\defeq}{\vcentcolon=}

\title{Automatic Differentiation Variational Inference \\ Mean Field Simplification and Constraint Scalar}
\author{Harshad Deo \\
  \href{mailto:harshad@moreficent.com}{harshad@moreficent.com} \\
  \href{mailto:harshad@simianquant.com}{harshad@simianquant.com}
}
\date{}

\setlength{\parindent}{0cm}

\hypersetup{
  colorlinks,
  citecolor=blue,
  filecolor=blue,
  linkcolor=blue,
  urlcolor=blue
}

\setlength{\parskip}{\baselineskip}%

\begin{document}

\maketitle

This monograph is a follow up to the article introducing Auto Differentiation Variational Inference and develops simplifying
assumptions that allow the technique to be used to train large, complex models over large datasets, for example for Bayesian
Deep Learning.

\section*{Decoupling The Latent Space}

The full rank approximation, developed in the previous monograph, allows all the latent variables ($\theta$) to be coupled
with each other through the correlation matrix of the variational approximation. As a result, the number of parameters
grows quadratically with the size of the latent space. This makes it intractable for
use in all but the simplest problems, say with a few thousand latent variables.

The mean field approximation assumes that all the latent variables are independent. This makes it practical to scale the
models, as the number of parameters grows linearly with the size of the latent space. Formally,

\begin{align*}
  q(\zeta, \phi) \defeq& \mathcal{N}\big(\zeta; \mu, \text{diag}(\exp(\omega) ^2)\big) \\
  =& \prod_{k=1}^K \mathcal{N}(\zeta_k; \mu_k, \exp(\omega_k)^2)
\end{align*}

With this parameterization, the space of the variational parameters is given by:

\begin{equation*}
  \Phi = \{\mu_1, \ldots, \mu_k, \omega_1, \ldots, \omega_k\} = \mathbb{R}^{2K}
\end{equation*}

And the elliptical standardization is given by:

\begin{equation*}
  \eta_k = S_{\phi}(\zeta) = \frac{\zeta_k - \mu_k}{\exp \omega_k}
\end{equation*}

Correlation between the latent variables, if required, now needs to be modelled in explicitly as a function of the
latent variables. For example, the Lewandowski-Kurowicka-Joe transform \footnote{Lewandowski, D., Kurowicka, D., \& Joe, H. (2009). Generating random correlation matrices based on vines and extended onion method. Journal of multivariate analysis, 100(9), 1989-2001.}
can be used to explicitly model a correlation matrix for a subset of the latent variables. This transformation, as well as several
other useful ones, ship with the library.

\section*{Entropy Simplification}

The contribution of the entropy of the variational approximation to the ELBO can be simplified as:

\begin{align*}
  \frac{1}{2}\ln| \det \Sigma ^ 2| &= \frac{1}{2}\ln |\det \big(\text{diag}(\exp(\omega) ^ 2)\big)|  \\
  &= \frac{1}{2}\ln \prod_{k=1}^{K}\big(\exp(\omega_k)^2\big) \\
  &= \ln \prod_{k=1}^{K}\exp \omega_k \\
  &= \sum_{k=1}^{K}\omega_k
\end{align*}

Therefore the optimization objective can be simplified to:

\begin{equation*}
  \phi^* = \underset{\phi}{\text{argmax}} \, \mathbb{E}_{\mathcal{N}(\eta; 0, 1)}\big[\log p(x, T^{-1}(S_\phi^{-1}(\eta))) + \log |\det J_{T^{-1}}(S_\phi^{-1}(\eta))|\big] + \sum_{k=1}^{K}\omega_k
\end{equation*}

\section*{Joint Probability Simplification}

The joint probability of the data and the parameters, $p\big(x, T^{-1}(S_\phi^{-1}(\eta))\big)$ can be factorized as the product
of the probability of the data given the parameters, and the prior probability of the parameters. The objective can thus be
reexpressed as:

\begin{equation*}
  \phi^* = \underset{\phi}{\text{argmax}} \, \mathbb{E}_{\mathcal{N}(\eta; 0, 1)}\big[\log p(x | T^{-1}(S_\phi^{-1}(\eta))) + \log p(T^{-1}(S_\phi^{-1}(\eta))) + \log |\det J_{T^{-1}}(S_\phi^{-1}(\eta))|\big] + \sum_{k=1}^{K}\omega_k
\end{equation*}

It is observed that the prior probability acts as a regularizing term on the distribution of the latent space. This gives
a clear and simple interpretation to standard regularization techniques like $L_1$ and $L_2$ regularization as being equivalent to
assigning Laplace and Gaussian priors respectively, with some fixed scale parameters.

\section*{Graph Simplification}

To simplify the expression further, the computational graph is assumed to be directed and acyclic, and the family of
constraint relaxation functions, $T(\theta)$, is restricted to that for which the Jacobian of the inverse transform is
a triangular matrix. In practice, this is a benign assumption as it is true for practically all models and all commonly used
transformations. Since the Jacobian of a triangular matrix is the product of its diagonal elements,
the computational graph can be factorized into mutually exclusive subgraphs $U_1 \ldots U_M, M \leq K$ such that
$U_m, 1 < m \leq M$ is only dependent on $U_1 \ldots U_{m - 1}$. Let

\begin{align*}
  K_m \defeq&\quad \text{Indices of the latent space for the m-th subgraph} \\
  \tau_m \defeq&\quad \text{The contribution of the m-th subgraph to the jacobian of the inverse constraint transform} \\
  z_m \defeq&\quad \text{The sampled outputs of the m-th subgraph, implicitly being functions of $\phi$} \\
  \rho_m \defeq&\quad \text{The averaged log prior probability of the m-th subgraph} \\
  \mathcal{P}(\cdot) \defeq&\quad \text{The averaged log probability of the arguments}
\end{align*}

$\tau_m$ is equal to the sum of the diagonal elements in rows $K_m$ of the jacobian of the inverse constraint transform matrix. The optimization
objective can be reexpressed as:

\begin{equation*}
  \phi^* = \underset{\phi}{\text{argmax}} \, \mathcal{P}(x | z_M) + \sum_{m=1}^{M}\Big(\rho_m(z_1, \ldots, z_m ) + \tau_m + \sum_{j \in K_m}\omega_j \Big)
\end{equation*}

The first term can be interpreted as the log probability of the output given the input and the model. Each of the summands of the
second term can be interpreted as a \textit{constraint scalar} that ensures that the latent variables for the subgraph satisfy their
domain constraint and are regularized by their priors. Let $\mathcal{C}_m$ denote the constraint scalar for subgraph $m$. The optimization
objective can be reexpressed as:

\begin{equation*}
  \phi^* = \underset{\phi}{\text{argmax}} \, \mathcal{P}(x | z_M) + \sum_{m=1}^{M}\mathcal{C}_m(z_1, \ldots, z_m )
\end{equation*}

This can be interpreted by analogy with the architecture of modern deep learning libraries, like TensorFlow and PyTorch:

\begin{enumerate}
  \item $P$ is equivalent to the cost function. For example, if the output is normally distributed with a fixed variance, the optimization objective is mathematically identical to a Mean Square Error loss.
  \item Instead of a single tensor, each subgraph outputs a tuple. The first is a sample tensor of the output and the second is a scalar constraint term.
  \item All of the constraint scalars are summed and added to the loss given by the cost function.
\end{enumerate}

These parallels motivate the abstractions of the library.

\end{document}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \input{./Ressources/Presentation/Preamble4to3.tex} % Layout 4:3
\input{./Ressources/Presentation/Preamble16to9.tex} % Layout 16:9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{./_Config.tex}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\Rplus}{\protect\hspace{-.1em}\protect\raisebox{.35ex}{\smaller{\smaller\textbf{+}}}}
\newcommand{\Cpp}{\mbox{C\Rplus\Rplus}\xspace}
\newcommand{\CppTw}{\mbox{C\Rplus\Rplus 20}\xspace}

\newcommand{\Datum}{\today}

\renewcommand{\PraesentationFusszeileZusatz}{| Amortized Time Complexity of Union-Find in Isabelle/HOL}

\title{Amortized Time Complexity of Union-Find in Isabelle/HOL \newline \newline {\Large Colloquium to the Bachelor's Thesis \newline}}
\author{\PersonTitel{} \PersonVorname{} \PersonNachname}
\institute[]{\UniversitaetName \\ \FakultaetName \\ \LehrstuhlName {\newline}
Supervisor: Prof. Tobias Nipkow, Ph.D. {\newline} Advisor: Maximilian P.L. Haslbeck, M.Sc.}
\date[\Datum]{\PersonStadt, October 16, 2019}
\subject{Amortized Time Complexity of Union-Find in Isabelle/HOL}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{./Ressources/Presentation/Beginning.tex}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FOLIENSTIL: Standard
% !!!ÄNDERUNG HIER:!!!
\PraesentationMasterStandard
%\PraesentationMasterKopfzeileDreizeiler
%\PraesentationMasterWeissBlau

%\PraesentationStartseiteFlaggen
\PraesentationStartseiteUhrenturm
\PraesentationTitelseite % Fügt die Startseite ein

\begin{frame}
	\frametitle{Overview}
	\vspace{1cm}
	\begin{minipage}[s]{\textwidth}
	\tableofcontents
	\end{minipage}
\end{frame}

\section{Union-Find}
\begin{frame}
\frametitle{Union-Find}
\begin{itemize}
	\item Models a partial equivalence relation
over a finite domain
	\item Implemented by disjoint set forests
\item The graph structure is represented by an array
	\item Supports \textbf{Union} and \textbf{Find} operations
\end{itemize}
\vspace{-2cm}
\begin{figure}
	\centering
	\begin{minipage}{5cm}
		\caption{Two equivalence classes}\end{minipage}
	\begin{minipage}{8cm}\includegraphics[scale=1.0]{UnionFindFigure}\end{minipage}
\end{figure}
\end{frame}

\subsection{Path Compression and Union by Rank}
\begin{frame}
\frametitle{Path Compression and Union by Rank}
\begin{itemize}
	\item As with many tree-based data structures, trees should be kept flat
	\item This is done in two ways:
	\begin{enumerate}
		\item \textbf{Path Compression}
		\item \textbf{Union by Rank}
	\end{enumerate}
\end{itemize}
\begin{figure}
	\centering
	\begin{minipage}{5cm}
		\caption{Illustration of Path Compression}\end{minipage}
	\begin{minipage}{8cm}\includegraphics[scale=0.8]{PathCompressionFigure}\end{minipage}
\end{figure}
\end{frame}

\subsection{Design Choices}
\begin{frame}
	\frametitle{Design Choices}
	\begin{itemize}
		\item Done in Imperative/HOL, which can then be exported to several languages
		\item The arrays used and therefore the domain are static
		\item We define the operations in Imperative/HOL:
		\begin{itemize}
			\item \includegraphics{RepofDef}
			\item \includegraphics{CompressDef}
			\item \includegraphics{RepofcDef}
			\item \includegraphics{CmpDef}
			\item \includegraphics{UnionBigDef.png}
		\end{itemize}
	\end{itemize}
\end{frame}

\section{History of the Proof}
\begin{frame}
	\frametitle{History of the Proof}
	\begin{itemize}
		\item Several, slightly different results about the amortized time complexity of the operations of Union-Find
		\item The first result involving $\alpha$ by Tarjan in 1975. The proof was simplified until the version in CLRS
		\item In 1989 Fredman and Saks prove (in some sense) the optimality of the result
		\item The latest result by Alstrup et al. in 2014 tightens the bound
		\item In 2017, Charguéraud and Pottier formalize the result in Coq
		\item Now, we present this formalization in Isabelle/HOL
		\item In all these proofs, but especially since Alstrup et al., most work is needed for the abstract analysis
	\end{itemize}
\end{frame}

\section{Timeline of the Project}
\begin{frame}
	\frametitle{Timeline of the Project}
	\vspace{-0.7cm}
	\begin{table}
		\centering
		\begin{minipage}[t]{\linewidth}
			\color{gray}
			\ytl{May}{Background work: Familiarisation with Sepreftime and the paper by Charguéraud and Pottier}
			\vspace{-0.1cm}
			\ytl{May 15th}{Official thesis registration}
			\vspace{-0.1cm}
			\ytl{June}{Cleanup of the previous work by Lammich and Haslbeck}
			\vspace{-0.1cm}
			\ytl{June 5th}{Armaël Guéneau visits TUM}
			\vspace{-0.1cm}
			\ytl{June}{\textbf{Bottom-up}: Ackermann and InverseNatNat theories and important definitions}
			\vspace{-0.1cm}
			\ytl{July}{First abstract proofs: rank, level, index}
			\vspace{-0.1cm}
			\ytl{July 16th}{\textbf{Top-down}: Sanity check of definitions done, skipping the rest and proof of the Hoare-Triples}
			\vspace{-0.1cm}
			\ytl{August}{Exam phase}
			\vspace{-0.1cm}
			\ytl{September}{Parallel writing of the thesis, proof gap-filling and correction of definitions}
			\vspace{-0.1cm}
			\ytl{September 8th}{Complete sound theory}
			\vspace{-0.1cm}
			\ytl{Semptember 13th}{Submission of the thesis}
			\vspace{-0.1cm}
			\bigskip
		\end{minipage}%
	\end{table}
\end{frame}

\section{Overview of the Isabelle Proof}
\begin{frame}
	\frametitle{Overview}
	\vspace{-2.5cm}
	\begin{figure}
		\includegraphics[scale=0.8]{OverviewFigure}
	\end{figure}
\end{frame}

\section{Inverses of Functions $f: \mathbb{N} \rightarrow \mathbb{N}$}
\begin{frame}
	\frametitle{Inverses of Functions $f: \mathbb{N} \rightarrow \mathbb{N}$}
	\begin{minipage}[t]{0.55\linewidth}
		\vspace{-4cm}
	\begin{itemize}
		\item Defined in InverseNatNat.thy
		\item Upper inverse $\alpha_f$ and Lower inverse $\beta_f$
		\item Lemmas to change the proof obligations between inverses and the original function
		\item Used for Inverse Ackermann Function, but also the ``index'' of a node
	\end{itemize}
	\end{minipage}
\begin{minipage}[c]{0.4\linewidth}
\includegraphics[scale=0.7]{InverseNatNatFigure}
\end{minipage}
\end{frame}

\section{The Ackermann Function and its Inverse}
\begin{frame}
	\frametitle{The Ackermann Function and its Inverse}
	\begin{itemize}
		\item There is no single Ackermann Function ``$A$'' or inverse Ackermann Function ``$\alpha$''
		\item All definitions share the property of growing faster than any primitive recursive function
		\item $\alpha$ grows \textbf{very} slowly
		\item We use the definition of $A$ and $\alpha$ by Tarjan:
	\end{itemize}
\begin{minipage}{0.45\linewidth}
\begin{dfn} Ackermann Function
	\begin{align*}
	A \, 0 \, x &= x + 1  \\
	A \, (k + 1)\, x &= (A\, k)^{(x + 1)}\, x
	\end{align*}
\end{dfn}
\end{minipage}
\begin{minipage}{0.45\linewidth}
\begin{dfn} Inverse Ackermann Function
	\begin{align*}
	\alpha \, n &= \min \{ k \,\mid\, A\, k\, 1 \geq n \}\\
	\alpha_r \, n &= 1 + \min\{ k \,\mid\, A\, k\, r \geq (n + 1) \}
	\end{align*}
\end{dfn}
\end{minipage}

\begin{itemize}
	\item In Isabelle/HOL, the definitions are expressed slightly differently and make use of InverseNatNat.thy
\end{itemize}
\end{frame}

\begin{frame}
	\frametitle{The Ackermann Function and its Inverse}
	\vspace{0.6cm}
	\begin{lma}{observable\_universe\_$\alpha$}
		\newline
		\textbf{Assume:} $n \leq 10^{80} $
		\begin{equation}
		\alpha \, n \leq 4 \label{universealpha}
		\end{equation}
	\end{lma}
\begin{itemize}
	\item $10^{80}$ is an estimate of the number of atoms in the universe
\end{itemize}

\begin{lma}{$\alpha$\_n\_0\_$\alpha$\_logn}
	\newline
	\textbf{Assume:} $16 \leq n$
	\begin{equation}
	\alpha \, n \leq 1 + (\alpha \, (\log{n}))
	\end{equation}
\end{lma}
\begin{itemize}
	\item $\alpha$ and $\alpha(\log\, n)$ are asymptotically equivalent
	\item True for every primitive recursive strictly monotonic function
\end{itemize}
\end{frame}

\section{Separation Logic with Time Credits}
\begin{frame}
	\frametitle{Separation Logic with Time Credits}
	\begin{itemize}
		\item Logic to reason about mutable resources in a heap. Enables Hoare-Triple definition
		\item It also allows for ``pure'' assertions, predicates independent of the heap content
		\item Time Credits can also appear in assertions and are required to execute atomic operations
		\item The components of the logic are: \begin{itemize}
			\item $\uparrow(P)$
			\item true and false
			\item $p \mapsto_a xs$
			\item $P_1 * P_2$
			\item $\exists_A x.\, P$
		\end{itemize}
	\item The Framework by Haslbeck implementing this for Isabelle/HOL, as well as this thesis as a usage example will be published in the AFP.
	\end{itemize}
\end{frame}

\subsection{Amortized Analysis with Time Credits}
\begin{frame}
	\frametitle{Amortized Analysis with Time Credits}
	\begin{itemize}
		\item We define a potential function $\Phi$ that measures the ``entropy'' of the data structure
		\item The idea is to ``hide'' $\Phi$ credits in the assertion defining the data structure
		\item If we are able to prove a Hoare-Triple of the form:
		\begin{equation*}
		\langle \mathrm{invar}(\mathcal{D}) * \$(\Phi(\mathcal{D})) * \underbrace{\$(f(\mathcal{D}))}_{\text{Advertised Cost}} \rangle
		\quad \mathtt{op}(\mathcal{D}) \quad
		\langle \mathrm{invar}(\mathcal{D'}) * \$(\Phi(\mathcal{D}')) \rangle
		\end{equation*}
		for any $\Phi$ and $f \in \mathcal{O}(g)$, we can conclude that the operation \texttt{op} has an amortized cost in $\mathcal{O}(g)$
		\item Remaining questions: \begin{itemize}
			\item What $\Phi$ do you choose? How does $\Phi$ evolve?
			\item How do you prove the functional correctness? \newline
			$\Longrightarrow$ Mathematical analysis of the data structure
		\end{itemize}
	\end{itemize}
\end{frame}

\section{The Potential Function $\Phi$}
\begin{frame}
	\frametitle{The Potential Function $\Phi$}
	\vspace{0.6cm}
	\begin{definition}{Potential for a single node}
		\begin{equation*}
		\philr i :=
		\begin{cases}
		\alpha_r\, (\RR_r\, i) \cdot (1 + (\RR_r\, i)) & \mathrm{if}\, \LL!i=i \,   \\
		(\alpha_r\, (\RR_r\, i) - \level i) \cdot \RR_r\, i - \iindex i + 1  &\mathrm{if}\, \alpha_r\, (\RR_r\, i) = \alpha_r\, (\RR_r\, (\LL!i))\\
		0 & \mathrm{otherwise}
		\end{cases}
		\end{equation*}
	\end{definition}

\begin{definition}{Potential of the data structure}
	\begin{equation}
	\Philr :=  \sum_{i = 0}^{|\LL| - 1}{\philr i}
	\end{equation}
\end{definition}

\begin{itemize}
	\item $\{0,\dots, |\LL|-1\}$ is in this case the domain of our equivalence relation
\end{itemize}

\end{frame}

\section{Results of the Thesis}
\begin{frame}
	\frametitle{Results of the Thesis}
	The $\,\,\mathrm{is\_uf}$ Assertion takes a relation and two arrays as arguments and ensures:\begin{itemize}
		\item The well-formedness of the disjoint set forest and the ranks
		\item That the relation modeled by the array is the one given
		\item That the necessary potential is stored as Time Credits
	\end{itemize}
	\vspace{0.6cm}
	\begin{dfn}
	\begin{align}
	\begin{split}
	\mathrm{is\_uf}\, \mathcal{X} \, (s,p) :=
	&\exists_A \LL\, \RR.\, p \mapsto_a \LL * s \mapsto_a \RR\, * \\
	&\uparrow (\ufaalpha = \mathcal{X} \land \mathrm{invar\_rank}\, \LL \, \RR)\, * \\
	&\$(4\cdot\Philr)
	\end{split}
	\end{align}
	\end{dfn}
\vspace{-0.5cm}
\end{frame}

\begin{frame}
	\frametitle{Results of the Thesis}
	\vspace{0.6cm}
	\begin{minipage}{0.48\linewidth}
\begin{lma}
	\begin{equation*}
	\mathrm{uf\_cmp\_time}\, \in \mathcal{O}(\alpha_r\,n)
	\end{equation*}
\end{lma}

\begin{thm}
	\,\newline
	\begin{align*}
	\begin{split}
	\langle \mathrm{is\_uf}\, \mathcal{X}\, u\, * &\$(\mathrm{uf\_cmp\_time}\, |\mathrm{Dom}\, \mathcal{X}|)\rangle \quad \\
	&\mathtt{uf\_cmp}\, u\, i\, j\\
	&\langle \mathrm{is\_uf}\, \mathcal{X}\, u\, * \uparrow(r \leftrightarrow (i,j)\in\mathcal{X}) \rangle_t
	\end{split}
	\end{align*}
\end{thm}
	\end{minipage}
	\begin{minipage}{0.40\linewidth}
\begin{lma}
	\begin{equation*}
	\mathrm{uf\_union\_time}\, \in \mathcal{O}(\alpha_r\,n)
	\end{equation*}
\end{lma}
\begin{thm}\,\newline
	\textbf{Assumes: } $i,j \in \mathrm{Dom}\, \mathcal{R}$
	\begin{align*}
	\begin{split}
	\langle \mathrm{is\_uf}\, \mathcal{X}\, u\, * &\$(\mathrm{uf\_union\_time}\, |\mathrm{Dom}\, \mathcal{X}|)\rangle \quad \\
	&\mathtt{uf\_union}\, u\, i\, j\\
	&\langle \mathrm{is\_uf}\, (\mathrm{per\_union}\, \mathcal{X}\, i\, j)\rangle_t
	\end{split}
	\end{align*}
\end{thm}
\end{minipage}
\vspace{-0.4cm}
\begin{itemize}
	\item \texttt{uf\_union} corresponds to the \textbf{Union} and \texttt{uf\_cmp} to the \textbf{Find} operation
	\item These theorems follow from abstract results about disjoint set forests
	\item The whole proof is about 5KLoc long in Isabelle/HOL
\end{itemize}
\end{frame}

\section{Conclusions}
\begin{frame}
	\frametitle{Conclusions}
	\begin{itemize}
		\item Formalization of the state-of-the-art result about Union-Find
		\item Comprehensive theory about Ackermann, including quantitative and asymptotic results
		\item The proofs of the imperative programs are still too long:
		 \begin{itemize}
			\item The automation does not deal well with arithmetic
			\item It also instantiates existentials too aggressively
			\item Repetitive proofs generated by branching $\Longrightarrow$ optimization possible
		\end{itemize}
		\item Formal verification of non-trivial results about runtime, not only correctness are possible
		\item Some overhead, but this helps to reveal hidden assumptions
	\end{itemize}
\end{frame}

%\PraesentationMasterKopfzeileDreizeiler
\begin{frame}
\frametitle{\,}
\Huge Thank You for listening! \newline
\Huge Any questions?
\end{frame}

\begin{frame}
	\frametitle{Important Definitions}
	\vspace{1cm}
	\begin{definition}{invar\_rank}
		\begin{align}
		\mathrm{invar\_rank}\, \LL \, \RR :=
		&\mathrm{ufa\_invar} \, \LL \, \land \\
		&|\LL| = |\RR| \, \land \\
		&(\forall (i,j) \in \ufabstart. \, \RR!i < \RR!j) \\
		&(\forall i < |\LL|.\, \LL!i = i \longrightarrow 2^{\RR!i} \leq |\mathrm{descendants}_\LL \, i|)
		\end{align}
	\end{definition}
	\begin{definition}{ufa\_invar}
	\begin{equation}
	\mathrm{ufa\_invar} \, \LL \, := \forall i < |\LL|.\, i \in \mathrm{Dom}\, \repof \land \LL!i < |\LL|
	\end{equation}
	\end{definition}

\begin{definition}{ufa\_$\beta$\_start}
\begin{equation}
\ufabstart := \{(x,y) \,\mid\, x<|\LL| \land y<|\LL| \land x \neq y \land \LL!x = y \}
\end{equation}
\end{definition}

\end{frame}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document} % !!! NICHT ENTFERNEN !!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\section{Data Flow Experiments: Supplementary Details}

This section provides additional details for the experiments presented in
Section~5.

\subsection{Models}

\paragraph{(I) Sequential Model} The inst2vec model consists of 619,650
trainable parameters in the  configuration outlined in
Figure~\ref{figure:lstm_node_level}. The model, implemented in TensorFlow, uses
the same parameters as in the original work: 2$\times$ 64 dimensional LSTM
layers followed by a 64 dimensional dense layer and the final 2 dimensional
output layer. Sequences are padded and truncated to 5k tokens and processed in
batches of 64.

\paragraph{(II) Graph Models} For CDFG and \programl approaches we use the same
model architecture. The model, implemented in PyTorch, consists of a customized
GGNN with 87,070 trainable parameters. Batches are implemented as disconnected
graphs that are constructed to enable efficient processing of graphs of
differing size in parallel without padding. We use a combined batch size of
$10,000$ vertices. If a single graph contains more than $10,000$ vertices, it is
processed on its own.

\begin{figure}
  \centering %
  \includegraphics[width=\columnwidth]{images/lstm_node_level}%
  \caption{%
    Extending inst2vec~\citep{Ben-nun2018} to perform per-instruction
    classification of LLVM-IR. The $\frown$ operator denotes vector
    concatenation.%
  }%
  \label{figure:lstm_node_level}%
\end{figure}

\subsection{Experimental Setup}
\label{app:dataflow_experimental_setup}

\paragraph{Training Details and Parameters}
All models were trained in an end-to-end fashion with the Adam
optimizer~\citep{Kingma2015} using the default configuration and a learning rate
of $1\cdot10^{-3}$ for the LSTMs and $2.5\cdot 10^{-4}$ for the GGNNs. We
trained the models on 1M training graphs, evaluating on a fixed 10k validation
set at 10k intervals for the first 50k training graphs, and at 100k intervals
thereafter. The checkpoint with the greatest validation F$_1$ score is used for
testing.

\paragraph{Runtimes} All experiments were conducted on shared machines equipped
with an NVIDIA GTX 1080 GPU, 32GB of RAM, mechanical hard drives, and
server-grade Intel Xeon processors. Figure~\ref{tables:model_timings} provides
measurements of the average runtimes of each approach across the five DDF-30
tasks. In our implementation, we find training and testing to be I/O bound as
programs are processed faster than loading many small files from disk. In
particular, CDFG performance suffers relative to \programl as the conversion
from \programl to CDFG representations is performed on-demand. For validation,
inputs are loaded once into system memory and re-used, so the measured time
provides a more accurate estimate of processing requirements.

\begin{table*}
\centering%
\footnotesize
\begin{tabular}{r c c c c c}
  & Train time & Test time & Train time/graph & Val time/graph & Test time/graph \\
  \toprule
  inst2vec & 10h52m & 1h33m & 45ms & 3ms & 36ms\\
  CDFG & 13h14m & 3h27m & 64ms & 1ms & 62ms\\
  \programl & 7h21m & 1h39m & 26ms & 3ms & 24ms\\
\end{tabular}
\caption{Average training and inference times on DDF-30 tasks}
\label{tables:model_timings}
\end{table*}


\subsection{Subsection} \label{sec:subsection1}

\lipsum[2-4]
\cite{latexcompanion}

\begin{equation}\label{eqn:test}
  E = m \cdot c^{2}
\end{equation}


%-------------------------------------------------------------------------------
\FloatBarrier\section{Static model of educational choice}
%-------------------------------------------------------------------------------
Consider the framework of the generalized Roy model presented in class for the static analysis of educational choice.

\begin{boenumerate}

\item Write down and briefly describe the key equations of the model.

\item Formally define the conventional average treatment effects and describe their limited policy relevance. What is potentially lost by focusing on average effects instead of looking at the whole distribution of individual benefits?

\item Define and describe the concept of essential heterogeneity. How does its presence and absence affect the relationship between the conventional average treatment effect parameters. Please integrate the conventional average treatment effects in the absence of essential heterogeneity into Figure \ref{Distribution of effects} which already shows a hypothetical distribution of individual-specific benefits.

\begin{figure}[htp]\centering
\caption{Distribution of effects}\label{Distribution of effects}\scalebox{0.35}
{\includegraphics{fig-static-model-distribution-canvas}}
\end{figure}

\item Define and describe the marginal benefit of treatment. What exactly is the conditioning set? Complete the empty canvas below by sketching the marginal benefit of treatment in the presence and absence of essential heterogeneity. Ensure that both axes are properly labeled.

\begin{figure}[htp]\centering
\caption{Marginal benefit of treatment}\scalebox{0.35}
{\includegraphics{fig-static-model-marginal-benefit-canvas}}
\end{figure}

\item What are the main findings in \cite{Carneiro.2011} on the marginal benefit of a college education?

\item Briefly outline the shortcomings of a static model of educational choice compared to a dynamic model.
\end{boenumerate}

Consider the following parameterization of the generalized Roy model presented in class for the static analysis of educational choice.

\begin{align*}
Y_1 & = 0.25     & D = \mathbbm{1}[\,0.50 > U\,] \\
Y_0 & = U &
\end{align*}

Assume that $U$ is unobservable and follows a uniform distribution between zero and one. Please be careful about correctly labeling all graphs that you decide to include in your answers.

\begin{boenumerate}

\item Define the individual effect of treatment. What are the sources of heterogeneity in the model. What fraction of individuals have a positive benefit of treatment?  How many do select into treatment?

\item Formally define the conventional average treatment effects and describe their limited policy relevance. How does the distribution of benefits for the model above look like? What is its exact range? Please mark the part of the distribution conditional on treatment status. Calculate the conventional effects of treatment.

\item Define and describe the concept of essential heterogeneity. Does the parameterized model exhibit essential heterogeneity? Please explain your answer.

\item Define and describe the marginal benefit of treatment $B^{MTE}$. How exactly does the $B^{MTE}$ for the parameterized model above look like?

\end{boenumerate}


\documentclass[inequalities.tex]{subfile}

\begin{document}
	\section{Smoothing and Isolated Fudging}\label{sec:smoothfudging}
	In many inequalities of the form
		\begin{align*}
			f(x_{1},\ldots,x_{n})
				& \geq a
		\end{align*}
	for some real number $a$, we may be able to establish the property that $f$ assumes smaller values when the difference between two variables $x_{i}$ and $x_{j}$ decreases. In such cases, we can use the fact that $f$ assumes the smallest value when $x_{1}=\ldots=x_{n}$. This is known as the \textit{smoothing principle}. Recall that we used a similar argument for arithmetic-geometric mean inequality when we replaced the product $a_{1}a_{2}$ by $\bar{a}(\bar{a}+k-h)$ where $a_{1}=\bar{a}-h$ and $a_{2}=\bar{a}+k$.
		\begin{problem}[USA $1996$]\label{prob:usa1996-3}
			Let $a_{0},\ldots,a_{n}$ be real numbers in the interval $\left(0,\frac{\pi}{2}\right)$. If
				\begin{align*}
					\tan\left(a_{0}-\dfrac{\pi}{4}\right)+\ldots+\tan\left(a_{n}-\dfrac{\pi}{4}\right)
						& \geq n-1
				\end{align*}
			prove that
				\begin{align*}
					\tan{a_{0}}\cdots\tan{a_{n}}
						& \geq n^{n+1}
				\end{align*}

				\begin{solution}
					If $x_{i}=\tan\left(a_{i}-\frac{\pi}{4}\right)$ so $-1<x_{i}<1$ and
						\begin{align*}
							x_{i}
								& = \dfrac{\tan{a_{i}}-1}{1+\tan{a_{i}}}\\
								& = \dfrac{y_{i}-1}{1+y_{i}}
						\end{align*}
					where $y_{i}=\tan{a_{i}}$. Then
						\begin{align*}
							y_{i}
								& = \dfrac{1+x_{i}}{1-x_{i}}
						\end{align*}
				\end{solution}
		\end{problem}
\end{document}