\documentclass[conf]{new-aiaa}
\usepackage[utf8]{inputenc}

\usepackage{graphicx}
\usepackage{amsmath}
\usepackage{siunitx}
\usepackage{float}
\usepackage{longtable,tabularx}
\usepackage{multirow, multicol}
\usepackage{minted}
\usepackage{verbatim}
\usepackage{lscape}
\usepackage[ruled,vlined]{algorithm2e}

\usepackage[mathletters]{ucs}

% From https://tex.stackexchange.com/questions/323297/
\newcommand{\rvline}{\hspace*{-\arraycolsep}\vline\hspace*{-\arraycolsep}}

\graphicspath{{../../../plots}}

\usepackage{hyperref}
\renewcommand\refname{}
\urlstyle{same}
\hypersetup{
    colorlinks=false,
    linkcolor=black,
    filecolor=black,
    urlcolor=cyan,
}

\title{Exploring Periodic Orbit Computation and Invariant Manifolds \\ within the Circular Restricted Three-body Problem}

\author{Joseph D. Carpinelli
    \footnote{
        M.S. Candidate,
        Department of Aerospace Engineering,
        University of Maryland, College Park}}

\begin{document}

\maketitle

\begin{abstract}
    Periodic orbits within the Circular Restricted Three-body Problem
    (CR3BP) are more difficult to find than periodic orbits within the
    Restricted Two-body Problem (R2BP). While any  elliptical or circular
    R2BP orbit is periodic, the periodic subset of CR3BP orbits is far
    more selective. Periodic CR3BP orbit-finding algorithms
    have been known for decades, but their implementations are not easily
    found in free and open-source software -- the few implementations
    which do exist in free and open-source software don't hold
    \textit{generally}. Instead, publicly accessible implementations may
    find periodic orbits for one particular CR3BP system (e.g. Sun-Earth),
    or  may find periodic orbits which have non-zero z-amplitudes.
    General solutions for periodic CR3BP orbits are incredibly useful, as
    CR3BP analysis is can be used as an approximate starting-point during
    mission design. Invariant manifolds about periodic
    CR3BP orbits can provide low-cost interplanetary transfers when
    compared with traditional transfer designs. This paper introduces
    a periodic CR3BP orbit-finding implementation that ties together
    known methods and existing code implementations; as a result,
    this implementation works \textit{generally}. The numerical Halo
    orbit solver is used to highlight several
    Halo orbit families in familiar CR3BP systems, and calculate invariant
    manifolds about Halo orbits. Interplanetary manifold-based transfer
    designs are explored, and challenges that inhibit methods for
    finding intersections are presented. All source code
    is available on GitHub as part of
    \textit{GeneralAstrodynamics.jl}, an astrodynamics package written
    with the Julia programming language.
\end{abstract}

\begin{multicols*}{2}

\tableofcontents

\section{Nomenclature}
\begin{flushleft}
\begin{tabularx}{\columnwidth}{ccl}
    $\overrightarrow{r}$ & $=$ & Spacecraft position \\
    $\overrightarrow{v}$ & $=$ & Spacecraft velocity \\
    $\Phi_m$             & $=$ & Monodromy matrix \\
    $\Phi$               & $=$ & State transition matrix \\
    R2BP                 & $=$ & Restricted Two-body Problem \\
    CR3BP                & $=$ & Circular Restricted Three-body Problem \\
    $S_L \triangleq a$   & $=$ & Distance between CR3BP bodies \\
    $S_T$                & $=$ & Time scale factor \\
    $\mu^\star$          & $=$ & Normalized CR3BP mass parameter \\
    $\overrightarrow{r}^\star$ & $=$ & Normalized spacecraft position \\
    $\overrightarrow{v}^\star$ & $=$ & Normalized spacecraft velocity \\
    $\overrightarrow{a}^\star$ & $=$ & Normalized spacecraft acceleration \\
    $r_i$                & $=$ & Nondimensional $x$ position of $i_{\text{th}}$ body \\
    $H$                  & $=$ & CR3BP potential energy Hessian matrix\\
    $M$                  & $=$ & Monodromy matrix\\
\end{tabularx}
\end{flushleft}

\section{Introduction}
As space exploration targets shift from Earth's moon to Mars and
beyond, low-cost trajectory designs are increasingly important
\cite{nasa2020artemis}. One such family of low-cost trajectory
designs utilizes invariant manifolds about Lagrange points
\cite{rund2018interplanetary}. Halo orbits can be estimated
analytically with an expansion, as originally shown by Richardson
\cite{richardson1980analytical} \cite{koon2008dynamical}. A known
numerical algorithm can iterate on non-periodic initial Halo orbit
conditions to produce numerically periodic Halo orbits
\cite{howell1984three}. When placed in series, these two algorithms
provide a proverbial \textit{black box} for astrodynamicists:
given desired physical features (orbit amplitude, phase, etc.),
the analytical algorithm can produce a Halo orbit estimate for the
numerical algorithm to iterate on \cite{rund2018interplanetary}.
These algorithms were recently implemented with the Julia
programming language \cite{carpinelli2020halos}
\cite{carpinelli2020astro} \cite{bezanson2017julia}.

This paper presents technical and implementation details, lessons learned,
and periodic orbit and manifold results for common CR3BP systems in
our solar system.
First, an overview of the Circular Restricted Three-body Problem,
and periodic CR3BP orbits, is provided. Methods for calculating
periodic CR3BP orbits are briefly discussed, and a Julia
implementation is introduced.

Next, a short catalog of Sun-Earth, Sun-Mars, and Sun-Jupiter
Halo orbits is presented using the developed Halo solvers.
This catalog will provide parameters for each Halo orbit,
and initial conditions and orbital periods from which to propagate.
These catalogues orbits may be a helpful reference for future
engineers who wish to explore periodic orbits within CR3BP dynamics
with applications in low-cost mission design.

Visualizations for stable and unstable
manifolds near each chosen Halo orbit are shown. Points along the
Halo orbits' stable manifolds are found, and
transfers between LEO and these stable manifolds are defined.
These manifolds are then used to generate interplanetary
transfers. Methods and challenges relating to manifold-based
transfer design are presented and discussed.

All code written for this project is included in the open-source
Julia package titled \textit{GeneralAstrodynamics.jl} \cite{carpinelli2020astro}.
A Pluto (Jupyter-like) notebook with code examples, and an informal
project summary is provided
\cite{fosnp2020Pluto} \cite{carpinelli2020halos}.

\section{CR3BP Overview}
The Circular Restricted Three-body Problem is a simplified
dynamical model of an infinitesimally small spacecraft traveling
near two finite-mass celestial bodies. All masses are described
as point masses. The system's barycenter is the
center of mass of the two celestial bodies, and both celestial
bodies are constrained to travel in a circle about an inertial
frame placed at the system barycenter. CR3BP spacecraft dynamics are
typically described in the \textit{Synodic} frame, which is placed
at the barycenter of the system, and rotates about its Z axis such
that each celestial body is fixed on the Synodic X axis.
CR3BP spacecraft dynamics are also typically described with
normalized units,
as shown in equations $\left(1\right)$ $\left(2\right)$ $\left(3\right)$
$\left(4\right)$. Normalized equations of motion for a spacecraft
within the CR3BP are shown in equations
$\left(5\right)$ $\left(6\right)$ $\left(7\right)$ $\left(8\right)$
$\left(9\right)$. Note that $\mu_2 \leq \mu_1$ by definition.

\subsection*{Normalized Synodic CR3BP State}
\begin{align}
    \mu^\star & = \frac{\mu_2}{\mu_1+\mu_2} \\
    S_t & = \sqrt{\frac{a^3}{\mu_1+\mu_2}} \\
    \overrightarrow{r}^\star & \triangleq \begin{bmatrix} x^\star & y^\star & z^\star \end{bmatrix}^T  = \frac{1}{S_L} \overrightarrow{r} \\
    \overrightarrow{v}^\star & \triangleq \begin{bmatrix} \dot{x}^\star & \dot{y}^\star & \dot{z}^\star \end{bmatrix}^T  = \frac{1}{S_T} \overrightarrow{v}
\end{align}

\subsection*{Normalized Synodic CR3BP Dynamics}

\begin{align}
    r_1 & = \sqrt{(x^\star+\mu^\star)^2 + (y^\star)^2 + (z^\star)^2} \\
    r_2 & = \sqrt{(x^\star+\mu^\star-1)^2 + (y^\star)^2 + (z^\star)^2} \\
    \ddot{x}^\star & = 2\dot{y}^\star + x^\star - \frac{(1-\mu^\star)(x^\star + \mu^\star)}{r_1^3} -
        \frac{\mu^\star (x^\star - 1 + \mu^\star)}{r_2^3} \\
    \ddot{y}^\star & = -2\dot{x}^\star + y^\star - \frac{(1 - \mu^\star)y^\star}{r_1^3} - \frac{\mu^\star y^\star}{r_2^3} \\
    \ddot{z}^\star & = -\frac{(1-\mu^\star)z^\star}{r_1^3} - \frac{\mu^\star z^\star}{r_2^3} \\
    \dot{\Phi} & = \begin{bmatrix} I_{3 \times 3} & 0_{3 \times 3} \\ H \triangleq \frac{\partial^2 U}{\partial \overrightarrow{r}^2} & \begin{bmatrix} 0 & 2 & 0 \\ -2 & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix} \end{bmatrix} \Phi
\end{align}

\begin{equation}
    \begin{aligned}
        H_{11} &= 1 - \frac{\mu}{r_2^{3}} - \frac{\left( 1 - \mu \right)}{r_1^{3}} + \frac{\frac{3}{4} \left( -2 + 2 x^{\star} + 2 \mu \right)^{2} \mu}{r_2^{5}} \\
        &- \frac{\frac{3}{2} \left(  - x^{\star} - \mu \right) \left( 2 x^{\star} + 2 \mu \right) \left( 1 - \mu \right)}{r_1^{5}}
    \end{aligned}
  \end{equation}

\begin{equation}
    H_{12} = \frac{\frac{3}{2} y^{\star} \mu \left( -2 + 2 x^{\star} + 2 \mu \right)}{r_2^{5}} - \frac{3 y^{\star} \left(  - x^{\star} - \mu \right) \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{13} =\frac{\frac{3}{2} z^{\star} \mu \left( -2 + 2 x^{\star} + 2 \mu \right)}{r_2^{5}} - \frac{3 z^{\star} \left(  - x^{\star} - \mu \right) \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{21} =\frac{\frac{3}{2} y^{\star} \mu \left( -2 + 2 x^{\star} + 2 \mu \right)}{r_2^{5}} - \frac{3 y^{\star} \left(  - x^{\star} - \mu \right) \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{22} =1 - \frac{\mu}{r_2^{3}} - \frac{\left( 1 - \mu \right)}{r_1^{3}} + \frac{3 \left(y^{\star}\right)^{2} \mu}{r_2^{5}} + \frac{3 \left(y^{\star}\right)^{2} \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{23} = \frac{3 y^{\star} z^{\star} \mu}{r_2^{5}} + \frac{3 y^{\star} z^{\star} \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{31} =\frac{\frac{3}{2} z^{\star} \mu \left( -2 + 2 x^{\star} + 2 \mu \right)}{r_2^{5}} - \frac{3 z^{\star} \left(  - x^{\star} - \mu \right) \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{32} =\frac{3 y^{\star} z^{\star} \mu}{r_2^{5}} + \frac{3 y^{\star} z^{\star} \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\begin{equation}
    H_{33} = - \frac{\mu}{r_2^{3}} - \frac{\left( 1 - \mu \right)}{r_1^{3}} + \frac{3 \left(z^{\star}\right)^{2} \mu}{r_2^{5}} + \frac{3 \left(z^{\star}\right)^{2} \left( 1 - \mu \right)}{r_1^{5}}
\end{equation}

\section{Periodic CR3BP Orbits}

Planar ($z \equiv 0$) periodic orbits about Lagrange point within
CR3BP dynamics are known as Lypunov orbits, while periodic CR3BP orbits
about with non-zero $Z$ components are known as Halo orbits
\cite{koon2008dynamical}.
Periodic CR3BP orbits are desirable for many reasons, including
eclipse avoidance
\cite{williams2017targeting}.
Of course, orbits within the CR3BP are \textbf{not} guaranteed to be
periodic. An estimated analytical periodic orbit solution can be found
with a third-order expansion, as originally shown by Richardson
\cite{richardson1980analytical}
\cite{koon2008dynamical}
\cite{rund2018interplanetary}.
Howell developed an iterative algorithm find a numerically
periodic CR3BP orbit
\cite{howell1984three}
\cite{koon2008dynamical}
\cite{rund2018interplanetary}.
The analytical and iterative periodic orbit-finding algorithms
are described in more detail in the remainder of this section.

\subsection{Analytical Solution}
Approximate analytical solutions exist for periodic orbits within
the Circular Restricted Three-body Problem. CR3BP dynamics can
be written as a polynomial expansion
\cite{koon2008dynamical}.
Richardson used a third-order expansion to develop an
analytical solution for periodic CR3BP orbits about L1 or L2;
the solution involves changing coordinates to be centered
at the desired Lagrange point and normalized to the
distance between the lagrange point and the less-massive
celestial body
\cite{koon2008dynamical}
\cite{richardson1980analytical}
\cite{rund2018interplanetary}.
This analytical solution is described in far more detail
by Rund and Koon et al
\cite{rund2018interplanetary}
\cite{koon2008dynamical}.
Here, the reader should know two important points
about this analytical method. First, periodic orbits
can be completely described by their $Z$-axis amplitudes.
This is a consequence of a $X$ and $Z$ amplitude constraint;
given a Halo orbit's $X$ (or $Z$) amplitude, one has everything
they need to calculate the orbit's analytical $Z$ (or $X$)
amplitude. Second, analytical solution is only
an \textit{approximation}; propagating any
analytical Halo orbit solution does \textit{not} result
in a numerically periodic orbit
\cite{koon2008dynamical}.
The latter point is shown by \figurename{1}.

\vskip -0.3cm
\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{analytical_propagation.png}
    \caption{Numerically propagated analytical solution}
\end{figure}

\subsection{Numerical Solution}

As shown previously, the analytical Halo orbit approximation is
not numerically periodic when provided as an initial condition
to a numerical integrator. A differential correction scheme can
be used to find a numerically periodic orbit within CR3BP dynamics,
as described by Howell, summarized by Rund and Mireles,
and implemented in private code written by Barbee, and
with publicly available notes and code by Mireles
\cite{howell1984three}
\cite{rund2018interplanetary}
\cite{barbeeCode}
\cite{mirelesNotes}
\cite{mirelesCode}.
There are several \textit{flavors} of this Newton-iteration correction algorithm.
Each flavor \textit{typically} chooses two of the following initial condition
components to iterate on: $x_0$, $z_0$, $\dot{y}_0$, $\frac{T_0}{2}$.
Barbee's private Lyapunov orbit finding implementation chooses
$\dot{y}_0$ and $\frac{T_0}{2}$ \cite{barbeeCode}.
Mireles' publicly available implementation chooses \textit{three}
values: $z_0$, $\dot{y}_0$, and $\frac{T_0}{2}$ \cite{mirelesCode}.
For this project, Mireles'
approach was combined with Barbee's Lyapunov orbit computation aproach.
More detail about these flavors, and the differential
correction scheme more broadly, is provided in the remainder of this subsection.

Broadly, the differential correction scheme works as follows.
Given an initial Halo orbit guess of the form provided by equations
$\left(20\right)$ and $\left(21\right)$, and an initial Halo orbit
period $T_0$, propagate the orbit for $\frac{T_0}{2}$, and record
the final state transition matrix $\Phi$,
Cartesian position $\overrightarrow{r}^{\star}$,
velocity $\overrightarrow{v}^{\star}$, and acceleration
$\overrightarrow{a}^{\star}$. Here, we check if
the final $x$-axis and $z$-axis velocities are within some tolerance of zero;
$10^{-8}$ is one reasonable tolerance to use. If the final $x$-axis and $z$-axis
velocities are outside of your chosen tolerance, then a new Halo orbit
initial condition must be found. There are several differential correction
options for refining your Halo orbit initial conditions. After
applying one such method, and generating \textit{new} initial conditions,
this process is repeated until some maximum number of iterations
is reached, or final $x$-axis and $z$-axis velocities are successfully
within some tolerance of zero.

\begin{align}
    \overrightarrow{r}^{\star} &= \begin{bmatrix} x_0 & 0 & z_0 \end{bmatrix} \\
    \overrightarrow{v}^{\star} &= \begin{bmatrix} 0 & \dot{y}_0 & 0 \end{bmatrix}
\end{align}

\subsubsection*{Implementation used by Howell, Rund}
Howell presents two options, as shown in equations $\left(22\right)$ and
$(23)$ \cite{howell1984three}. Equation $(22)$ iterates on the initial
$z_0$ and $\dot{y}_0$ conditions, and equation $(23)$ iterates on the initial
$x_0$ and $\dot{y}_0$ conditions. These corrections do not refine your
$\frac{T_0}{2}$ guess, so they rely on your numerical integration stopping
when the orbit's $y$-axis component enters within some tolerance of zero;
this timepoint is the assumed half-period $\frac{T_0}{2}$ of the Halo orbit
at this iteration. Investigations as part of this project found this approach
problematic; approximate Halo orbit initial conditions produced by the
previously discussed analytical algorithm may not cross the $X-Z$ plane in
any reasonable time, and an arbitrary tolerance that doesn't
produce "false positives" may be difficult to select. Still, others have
implemented working versions of this particular algorithm. Rund summarized
this correction scheme, and used equation $(23)$ to calculate Halo orbit
and invariant manifold results in a 2018 MS thesis \cite{rund2018interplanetary}.

\begin{equation}
\begin{aligned}
    F = & \left\{
        \begin{bmatrix} \Phi_{43} & \Phi_{45} \\ \Phi_{63} & \Phi_{65} \end{bmatrix}
        - \frac{1}{\dot{y}_f} \begin{bmatrix} \ddot{x}_f \\ \ddot{z}_f \end{bmatrix}
        \begin{bmatrix} \Phi_{23} & \Phi_{25} \end{bmatrix}\right\} \\
    & \hspace{1cm} \begin{bmatrix} z_0 \\ \dot{y}_0 \end{bmatrix} \leftarrow
    \begin{bmatrix} z_0 \\ \dot{y}_0 \end{bmatrix} - F^{-1} \begin{bmatrix} \dot{x}_f \\ \dot{z}_f \end{bmatrix}
\end{aligned}
\end{equation}

\begin{equation}
\begin{aligned}
    F = & \left\{
        \begin{bmatrix} \Phi_{41} & \Phi_{45} \\ \Phi_{61} & \Phi_{65} \end{bmatrix}
        - \frac{1}{\dot{y}_f} \begin{bmatrix} \ddot{x}_f \\ \ddot{z}_f \end{bmatrix}
        \begin{bmatrix} \Phi_{21} & \Phi_{25} \end{bmatrix}\right\} \\
    & \hspace{1cm} \begin{bmatrix} x_0 \\ \dot{y}_0 \end{bmatrix} \leftarrow
    \begin{bmatrix} x_0 \\ \dot{y}_0 \end{bmatrix} - F^{-1} \begin{bmatrix} \dot{x}_f \\ \dot{z}_f \end{bmatrix}
\end{aligned}
\end{equation}

\subsubsection*{Implementation used by Barbee}
Barbee's Lyapunov orbit-finding MATLAB implementation uses a slightly
different approach. Rather than refine $x_0$ and $\dot{y}_0$, his implementation
iterates on $\dot{y}_0$ and $\frac{T_0}{2}$ \cite{barbeeCode}. This approach
works for Lyapnuov orbits: periodic orbits with $z \equiv 0$. The iteration
of $\frac{T_0}{2}$ removes the reliance on accurate numerical integration
terminal when $y$ reaches some tolerance of the $x-z$ plane; the integration
can simply terminate when the current half-period guess, $\frac{T_0}{2}$, is
reached. Investigations as part of this project found
that correcting $\frac{T_0}{2}$, as opposed to relying on an integration
termination condition to refine $\frac{T_0}{2}$,
produces a far more robust orbit-finding
implementation. Barbee's chosen initial condition refining
approach is shown in equation $(24)$.

\begin{equation}
    \begin{aligned}
        F &= \begin{bmatrix} \Phi_{25} & \dot{y}_f \\ \Phi_{45} & \ddot{x}_f \end{bmatrix} \\
        \begin{bmatrix} \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} & \leftarrow
        \begin{bmatrix} \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} - F^{-1} \begin{bmatrix} y_f \\ \dot{x}_f \end{bmatrix}
    \end{aligned}
\end{equation}

At this point, we've discussed three flavors of the periodic-orbit-finding
differential correction algorithm. The first two implementations,
as originally presented by Howell in \cite{howell1984three},
do \textit{not} refine the half-period guess for the periodic orbit; this
results in a potential implementation weakness when used in tandem with
the analytical solution, as previously discussed. The third implementation,
as provided by Barbee in \cite{barbeeCode}, removes this weakness by
correcting the half-period initial guess with each iteration. Still, Barbee's
implementation does not refine three-dimensional (Halo) orbit guesses.
Combining the best aspects of each flavor would allow for Lyapunov \textit{and}
Halo orbit computation, without relying on numerical integration
termination conditions. Mireles provides one such implementation in
publicly available notes and code \cite{mirelesNotes} \cite{mirelesCode}.

\subsubsection*{Implementation used by Mireles}
Mireles' implementation iterates on \textit{three} initial conditions:
$z_0$, $\dot{y}_0$, and $\frac{T_0}{2}$ \cite{mirelesNotes} \cite{mirelesCode}.
This approach to initial condition correction is shown in equation $(25)$.
Investigations as part of this project found that the approach described by
equation $(25)$ is robust when applied to Halo orbit guesses provided
by the previously discussed analytical solution. The implementation of this
approach developed for this project failed to converge on numerically
periodic Lyapunov (two-dimensional) orbits. This is likely a result
of the $z_0$ iteration used. Lyapunov orbits have $z \equiv 0$ by definition,
so an initial condition with $z_0 = 0$ would not produce any correction.
In other words, this scheme relies on using $z_0$ corrections to
converge on a numerically periodic orbit. If $z \equiv 0$, then we've lost
a degree of freedom for this correction algorithm. Next, one final
implementation is provided that corrects this issue.

\begin{equation}
    \begin{aligned}
        F &= \begin{bmatrix} \Phi_{43} & \Phi_{45} & \ddot{x}_f \\
                             \Phi_{63} & \Phi_{65} & \ddot{z}_f \\
                             \Phi_{23} & \Phi_{25} & \dot{y}_f \end{bmatrix} \\
        \begin{bmatrix} z_0 \\ \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} & \leftarrow
        \begin{bmatrix}z_0 \\ \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} - F^{-1}
        \begin{bmatrix} \dot{x}_f \\ \dot{z}_f \\ y_f \end{bmatrix}
    \end{aligned}
\end{equation}

\subsubsection*{General Implementation}
Recall that Howell presented two iteration options: one to refine $x_0$, and
another to refine $z_0$. We can use this approach in combination with Mireles'
implementation to produce a general periodic orbit solver that works for both
Lyapunov and Halo orbits. This approach is also discussed in Mireles'
course notes \cite{mirelesNotes}. The general orbit solver implementation
can use an \textit{if, else} block to check whether the initial condition
is that of an approximate Lyapunov orbit ($z_0 = 0$), or a Halo orbit
($z_0 \neq 0$). If the initial condition is an approximate Lyapunov orbit,
then equation $(26)$ should be used. Otherwise, investigations as part of this
project found equation $(27)$ produced robust results.

\begin{equation}
    \begin{aligned}
        F &= \begin{bmatrix} \Phi_{41} & \Phi_{45} & \ddot{x}_f \\
                             \Phi_{61} & \Phi_{65} & \ddot{z}_f \\
                             \Phi_{21} & \Phi_{25} & \dot{y}_f \end{bmatrix} \\
        \begin{bmatrix} x_0 \\ \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} & \leftarrow
        \begin{bmatrix} x_0 \\ \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} - F^{-1}
        \begin{bmatrix} \dot{x}_f \\ \dot{z}_f \\ y_f \end{bmatrix}
    \end{aligned}
\end{equation}

\begin{equation}
    \begin{aligned}
        F &= \begin{bmatrix} \Phi_{43} & \Phi_{45} & \ddot{x}_f \\
                             \Phi_{63} & \Phi_{65} & \ddot{z}_f \\
                             \Phi_{23} & \Phi_{25} & \dot{y}_f \end{bmatrix} \\
        \begin{bmatrix} z_0 \\ \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} & \leftarrow
        \begin{bmatrix}z_0 \\ \dot{y}_0 \\ \frac{T_0}{2} \end{bmatrix} - F^{-1}
        \begin{bmatrix} \dot{x}_f \\ \dot{z}_f \\ y_f \end{bmatrix}
    \end{aligned}
\end{equation}

\subsection{Halo Orbit Results}
This final implementation (the combination of equations $(26)$ and $(27)$)
is robust for Lyapunov \textit{and} Halo orbits about collinear Lagrange points.
This implementation was impemented within \textit{GeneralAstrodynamics.jl}, and
was used with the previously discussed analytical algorithm to generate
periodic orbits for the remainder of this project \cite{carpinelli2020astro}.
The analytical algorithm takes physical orbit attributes as inputs: $z$-axis
amplitude, phase angle, Lagrange point ($L1$ or $L2$), and hemisphere
(northern, or southern) \cite{rund2018interplanetary}.
The \textit{approximate} analytical solution generated
with Richardson's analytical algorithm can then be used as an initial
condition for the numerical algorithm \cite{rund2018interplanetary}
\cite{richardson1980analytical}. When placed in series in this way, the
analytical and numerical orbit-finding algorithms discussed so far form a
kind of "black box"; the user specifies desired Halo orbit attributes,
and the algorithms provide a numerically periodic Halo orbit initial condition.
\figurename{2} shows one result of the analytical and numerical algorithms
working in tandem; the numerical algorithm found a periodic orbit \textit{nearby}
the approximate analytical solution.

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{analytical_numerical_halo.png}
    \caption{Analytical and Iterative Numerical solutions}
\end{figure}

While periodic orbits within CR3BP dynamics are catalogued in literature,
they can be difficult to find. A catalog of over $130,000$ periodic orbits
within our solar system has been posted to GitHub as a collection of CSV files
\cite{carpinelli2020halos}. The logged files are not optimized for disk
space; they are instead optimized for clarity. Each row within the logged files
provides normalized mass parameter, Lagrange point to orbit, Jacobi constant,
normalized $z$-axis amplitude, orbital period, and
normalized, Synodic Cartesian states. Periodic orbits were catalogued for
Sun-Venus, Sun-Earth, Earth-Moon, Sun-Mars, Sun-Jupiter, and Sun-Saturn CR3BP
systems. A fraction of the computed Halo orbits are provided in the Appendix,
\tablename{1}.

A collection of periodic orbits can be computed with slightly varying
$z$-axis amplitudes; this can be referred to as a family of Halo orbits
\cite{rund2018interplanetary}.
Example families of periodic orbits within the Earth-Moon, Sun-Mars,
and Sun-Jupiter systems are presented in \figurename{3}, \figurename{4},
and \figurename{5}. Note that both \figurename{4} and \figurename{5}
look very similar because all orbits are plotted with nondimensional units.

In summary, several Halo orbit solvers have been pieced together to form
a robust, open-source Julia implementation. This implementation produced
all results presented so far, and was also used to explore invariant
manifolds within CR3BP dynamics. The remainder of this paper summarizes
the existance of invariant manifolds, computational methods,
applications in mission design, and methods and associated challenges
in computing manifold-based interplanetary transfers.

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{halo_family.png}
    \caption{Famly of Halo orbits about Earth-Moon L2}
\end{figure}

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{halo_family_sm1.png}
    \caption{Famly of Halo orbits about Sun-Mars L1}
\end{figure}

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{halo_family_sj1.png}
    \caption{Famly of Halo orbits about Sun-Jupiter L1}
\end{figure}

\section{Invariant Manifolds}

Before discussing invariant manifolds, a brief discussion of
general nonlinear dynamics may be helpful.

\subsection{Nonlinear Dynamics Review}
Lagrange points
are the equilibrium points of the nonlinear CR3BP dynamics.
The phase space around these Lagrange points will have stability
characteristics, e.g. stable focus, unstable focus, and
saddle point behavior. As discussed in the preceding sections, the phase
space around Lagrange points can also feature periodic orbits, e.g.
Lyapunov and Halo orbits. Once again, similar to any nonlinear
dynamical system, the Jacobian of a CR3BP state vector is the
local linearization of the CR3BP dynamics evaluated at that particular
state vector. We can use the local linearization to characterize the
stability properties of the dynamics at that point in the phase space,
and points along periodic orbits are no exception. States
along periodic orbits can benefit from some reduced computational
expense by using the Monodromy matrix, $M$ \cite{rund2018interplanetary}.
We can find $M$ by
propagating a periodic orbit's initial conditions for one period,
with the dynamics of the state transition matrix included. The
state transition matrix should be initialized to a $6 \times 6$
identity matrix at the start of the numerical integration.
The final state transition matrix in this propagation is the
Monodromy matrix, and we can use this matrix to
evaluate local linear modes at each point along the periodic
orbit, as opposed to performing eigen-analysis at each point
we wish to evaluate.

\subsection{Calculating Invariant Manifolds}
Invariant manifolds within CR3BP dynamics are tubes of trajectories
that converge to, or diverge from, periodic orbits or Lagrange points
\cite{rund2018interplanetary} \cite{topputo2005low}. The term
\textit{manifold} comes from their three-dimensional, surface-like
shapes. The term \textit{invariant} applies because, once placed in
a manifold, a spacecraft governed by CR3BP dynamics
will stay in that manifold for all time (without external forces applied).

For this project, invariant manifolds about Halo orbits were
explored. A spacecraft on a periodic orbit can be perturbed
onto a trajectory within a manifold by perturbing the
state vector in the direction of the Mondomy matrix's stable
or unstable eigenvectors. Each Monodromy matrix should have
two real eigenvalues, and two pairs of complex eigenvalues.
The smaller real eigenvalue should be less than one,
and the larger real eigenvalue should be greater than one
\cite{gomez2001dynamicsv1}. As an additional check,
the pair of real eigenvalues should also be multiplicative
inverses of one another \cite{mirelesNotes}. The eigenvector
of the Monodromy matrix that is associated with the
larger real eigenvalue is the unstable eigenvector $V^U$, and
the eigenvector associated with the smaller real eigenvalue is
the stable eigenvector $V^S$ \cite{rund2018interplanetary}.
Equations $(28)$, $(29)$, $(30)$, $(31)$, and $(32)$ describe
the perturbation required to move from a periodic orbit
onto the orbit's stable manifold $X^S$, or unstable manifold $X^U$;
all are pulled from Rund's thesis, and were also presented
in a previous paper \cite{rund2018interplanetary} \cite{carpinelli2020halos}.
As described in upcoming sections, \textbf{I believe there is a mistake
in the presented invariant manifold plots}. I computed these plots by
perturbing the spacecraft in the direction of the stable and
unstable eigenvectors of the Monodromy matrix \textbf{directly}, instead of
changing basis by left-multiplying the eigenvector by the Jacobian. I will
look into this more, but did not have time to correct this mistake before
this paper's submission.

\begin{equation}
    V_i^{S} = \Phi(t_0 + t_i, t_0) V^S
\end{equation}
\begin{equation}
    V_i^{U} = \Phi(t_0 + t_i, t_0) V^U
\end{equation}
\begin{equation}
    X_i^{S} = X_i \pm \epsilon \frac{V_i^S}{|V_i^S|}
\end{equation}
\begin{equation}
    X_i^{U} = X_i \pm \epsilon \frac{V_i^U}{|V_i^U|}
\end{equation}

\begin{equation}
M = \Phi(t_0 + T, t_0)
\end{equation}

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{unstable_manifold.png}
    \caption{Unstable Manifold near Earth-Moon L1}
\end{figure}

\section{Manifold-based Transfers}

\subsection{Manifolds for Interplanetary Transfers}
One attempted manifold-based interplanetary transfer design follows.
Given a destination Sun-Jupiter L1 Halo orbit, one wishes to travel cheaply
from Earth to the destination orbit. Invariant manifolds can theoretically
be used to reduce the $\Delta v$ cost for an interplanetary transfer.
For this theoretical mission, the spacecraft can launch directly
into a stable manifold of a Sun-Earth L2 Halo orbit. Once the
spacecraft is on some trajectory within the stable manifold,
CR3BP dynamics will eventually cause the spacecraft to converge
on our chosen Halo orbit. The L2 lagrange point is selected because
it is located near the "mouth"
of the zero-velocity curves for nearby orbits; in other words,
selecting an orbit at random within Sun-Earth L2's unstable manifold
have a higher probability of that orbit
escaping the confines of the zero
velocity curves, and diverging into interplanetary space. This is a useful
property for the next mission step: perturb the spacecraft off of the Sun-Earth
L2 Halo orbit, and onto the orbit's unstable manifold. Next, we need to find
some intersection between the Sun-Earth Halo's unstable manifold, and
our destination Halo's stable manifold; the difference in velocity at this
intersection can be approximated as an impulsive maneuver. Once the spacecraft
is on some trajectory within our destination Halo's stable manifold,
it will eventually converge to our destination Halo orbit.

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{manifold_transfer_phase1.png}
    \caption{Launch from Earth to Stable Manifold}
\end{figure}

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{manifold_transfer_phase2.png}
    \caption{Perturb Spacecraft onto Sun-Earth Unstable Manifold}
\end{figure}

\begin{figure}[H]
    \hskip -0.3cm
    \includegraphics[width=0.5\textwidth]{manifold_transfer_phase3.png}
    \caption{Maneuver Spacecraft onto Sun-Jupiter Stable Manifold}
\end{figure}

\subsection{Implementation Challenges}
While manifold-based transfer designs are simple in concept, there
are several pitfalls that may cause project delays. This subsection
will outline several pitfalls, and associated lessons learned.

\subsubsection*{Implementation Mistakes}
An implementation mistake that affected the results in this paper
was discovered last-minute. Instead of following the manifold
perturbation equations presented in this paper, this project's
source code was written to instead perturb the spacecraft
\textit{directly} in the direction of the Monodromy matrix's
stable and unstable eigenvectors. All manifold plots here
are presented \textit{with} this mistake. After briefly correcting this,
all manifold plots differed greatly. More investigation will be
necessary to correct this issue. I plan to do so this summer, as
part of \textit{GeneralAstrodynamics.jl} development efforts.

\subsubsection*{Algorithmic Complexity}
The naive solution for finding the closest distance between two
manifolds is $O(n^2)$, which is far too algorithmically complex
for larger manifolds, which can contain millions of Cartesian states.
The naive implementation never returned, and quick calculations showed
that the implementation would never return any values in a reasonable
amount of time. After posting this issue to a Julia Discourse forum,
I was pointed towards a Julia package called \textit{NearestNeighbors.jl}
\cite{discourse2021} \cite{nearestNeighbors}. This package uses an
algorithm that find find the closest pair of points in two
large sets far faster than the naive solution. This algorithm
is apparently common in computational chemistry \cite{discourse2021}.
\textit{NearestNeighbors.jl} found the closest pair of Cartesian
states between the two manifolds in seconds.

\subsubsection*{Manifold Intersection}
After algorithmic complexity in finding the closest pair of points was
addressed, a new problem emerged; manifolds are not guaranteed to intersect.
Often, the closest pair of Cartesian states that could be found were still
hundreds of meters apart. This may be a consequence of the \textit{Implementation
Mistakes} discussed previously, but others have found similar results.
Topputo et al found that manifolds do not intersect among our solar system's
inner planets \cite{topputo2005low}. Rund did not rely on manifold
intersection for low-cost transfer design; Rund's thesis presented
manifold-based transfers to lower the cost of impulsive maneuvers
to place the spacecraft on a hyperbolic, Heliocentric trajectory
\cite{rund2018interplanetary}. It's possible that manifold intersections
are incredibly difficult to find for CR3BP systems that are so far
apart within the Heliocentric inertial frame. Topputo et al note
that transfers along manifold intersections may be best suited for specific
mission conditions, such as travel between moons of one large planet --
Koon's "Petit Grand Tour" of Jupiter's moons comes to mind
\cite{topputo2005low} \cite{koon2008dynamical}.

\section{Conclusions and Forward Work}
This project implemented added robustness and bug fixes to previously
implented analytical and numerical periodic orbit computation algorithms
within CR3BP dynamics. In a previous project, analytical and numerical
algorithms were written, but produced incorrect results \cite{carpinelli2020halos}.
Now, both analytical and numerical Lyapunov and Halo orbit algorithms appear
to be implemented correctly in \textit{GeneralAstrodynamics.jl}, an
open source Julia package with the aim of providing (at the author's
highest aspirations) another Poliastro-like tool for the scientific computing
and astrodynamics communities \cite{carpinelli2020astro}.

Pre-existing numerical Lyapunov and Halo orbit solver implementations
were explained, and
combined to form one general numerical periodic orbit solver,
as described in Mireles' notes, and partially available in
Mireles' publicly available code \cite{mirelesNotes} \cite{mirelesCode}.
This function was used to catalogue over $130,000$ periodic orbits within
CR3BP systems in our solar system \cite{carpinelli2020halos}.
Several families of Halo orbits were presented, and the mathematics
behind Halo orbit computation, and CR3BP dynamics, was reviewed.

The concept and computation of invariant manifolds within CR3BP
dynamics was discussed. A visualization of an unstable manifold
(barring implementation issues previously addressed) was presented,
and a generic mission design which uses invariant manifolds
to travel from Earth to Sun-Jupiter L1 was discussed.

Implementation complications around manifold-based transfers were
presented, and potential fixes were addressed. One large implementation mistake
was discussed -- manifold perturbation calculations are incorrectly
using the eigenvectors of the Monodromy matrix \textit{without}
left-multiplying the Jacobian at each time step. Algorithmic complexity
can be an issue when finding intersections between manifolds, but the
so-called "Nearest Neighbors" algorithm implemented in
\textit{NearestNeighbors.jl} allows for finding the minimum intersection between
manifolds in seconds \cite{nearestNeighbors}. Finally, manifold intersections
have been found to be rare in many conditions, as shown by other astrodynamicists
\cite{topputo2005low}, and this project's results.

Going forward, manifold perturbation calculations will be fixed and verified.
If Sun-Earth L2 and Sun-Jupiter L1 Halo orbit manifold intersections are
found, then a specific mission design will be
outlined using only invariant manifolds. If no intersections are found,
then manifolds will be used to reduce the costs of hyperbolic
interplanetary transfers, as shown by Rund \cite{rund2018interplanetary}.
Development for \textit{GeneralAstrodynamics.jl} will continue. Desired
future features include robust coordinate frame definitions and
transformations, realistic time-handling, catalogued physical constants
for solar system bodies, hooks into existing ephemeris and other
astrodynamics tools, and more.

\section{References}
\nocite{*}
\renewcommand\refname{\vskip -0.9cm}
\bibliography{sources}

\end{multicols*}

\section{Appendix}

A brief collection of Halo orbits are provided here for convenience.
The full results and full source code are available online,
and are far more valuable than the small fraction of results
presented below.

\subsection*{Project Links}
\begin{itemize}
    \item \href{https://github.com/cadojo/GeneralAstrodynamics.jl}{GeneralAstrodynamics on GitHub}
    \item \href{https://github.com/cadojo/GeneralAstrodynamics.jl/blob/main/src/AstrodynamicsCore/CR3BP/CR3BPCalculations.jl}{Analytical Halo Solver Implementation}
    \item \href{https://github.com/cadojo/GeneralAstrodynamics.jl/blob/main/src/Propagators/CR3BP/Halos.jl}{Numerical Halo Solver Implementation}
    \item \href{https://github.com/cadojo/Halo-Orbit-Explorations}{This project, hosted on GitHub}
    \item \href{https://github.com/cadojo/Halo-Orbit-Explorations/blob/main/data/exp_pro/halos}{Catalogued Halo Orbits}
\end{itemize}

\begin{landscape}
\begin{table}
\begin{tabular}{cccccccc}
    Mass Parameter & Lagrange Point & $Z$-Amplitude & Period & $x$ & $z$ & $\dot{y}$ \\
    $0.012150584269940356$ & $1.0$ & $0.0$ & $2.7536820171259744$ & $0.8222791805122408$ & $0.0$ & $0.13799313179964737$\\
    $0.012150584269940356$ & $1.0$ & $0.002$ & $2.7430279744649004$ & $0.8233905115990996$ & $0.0022207698036084363$ & $0.1264086161524851$\\
    $0.012150584269940356$ & $1.0$ & $0.004$ & $2.743129618348479$ & $0.8233893741253737$ & $0.004442307958743803$ & $0.12665484442364439$\\
    $0.012150584269940356$ & $1.0$ & $0.006$ & $2.743298907640046$ & $0.8233876253798795$ & $0.006665380456556792$ & $0.12706382260243482$\\
    $0.012150584269940356$ & $1.0$ & $0.008$ & $2.7435356656350174$ & $0.8233854825357569$ & $0.008890748615484967$ & $0.12763347860600016$\\
    $0.012150584269940356$ & $1.0$ & $0.01$ & $2.7438396430341294$ & $0.8233832430275673$ & $0.011119166862915583$ & $0.12836097250130557$\\
    $0.012150584269940356$ & $2.0$ & $0.001999$ & $3.4154785217654346$ & $1.1203619239893596$ & $0.001835091590818184$ & $0.17611109647933998$\\
    $3.003480593992993e-6$ & $1.0$ & $0.0$ & $3.057037166436106$ & $0.9889069589528534$ & $0.0$ & $0.008529372360506582$\\
    $3.003480593992993e-6$ & $1.0$ & $0.002$ & $3.0562630985504198$ & $0.9889296115452058$ & $0.0022759531712711633$ & $0.009571654363317172$\\
    $3.003480593992993e-6$ & $1.0$ & $0.004$ & $3.0408810610908192$ & $0.9891686188174361$ & $0.0046921863531775585$ & $0.011428450586881073$\\
    $3.003480593992993e-6$ & $1.0$ & $0.006$ & $2.9968780486251165$ & $0.9897509664037121$ & $0.007350439066516196$ & $0.013571383652713521$\\
    $3.003480593992993e-6$ & $1.0$ & $0.008$ & $2.8360875768267277$ & $0.9909674701532162$ & $0.010323704902503393$ & $0.015198885580121493$\\
    $3.003480593992993e-6$ & $2.0$ & $0.001798$ & $3.09794993304811$ & $1.0080662252502852$ & $0.001672550237255738$ & $0.010798428273484711$\\
    $3.003480593992993e-6$ & $2.0$ & $0.003798$ & $3.0755344619414036$ & $1.0068608443606484$ & $0.0035047324922114834$ & $0.014513397367974044$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0$ & $3.067790305289647$ & $0.9947153604918691$ & $0.0$ & $0.004052940170205446$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0001$ & $3.0713331541226148$ & $0.9946990969840135$ & $0.00011259909689815706$ & $0.00420141728779284$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0002$ & $3.071197879663506$ & $0.9946998314896827$ & $0.0002252842583036334$ & $0.004214196175484041$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0003$ & $3.0709713120763475$ & $0.9947010768650656$ & $0.00033814100956578$ & $0.004235364341723893$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0004$ & $3.0706517674163125$ & $0.9947028642521663$ & $0.00045125381930966155$ & $0.004264731532729223$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0005$ & $3.070236850446078$ & $0.9947052359932343$ & $0.0005647056232279373$ & $0.004302040405811711$\\
    $3.2271548760451657e-7$ & $1.0$ & $0.0006$ & $3.069723416205373$ & $0.9947082444991275$ & $0.0006785774056064239$ & $0.004346974627389325$\\
    $0.0009536838895767626$ & $1.0$ & $0.0$ & $2.9370190457587504$ & $0.9253021269565835$ & $0.0$ & $0.0585266341496578$\\
    $0.0009536838895767626$ & $1.0$ & $0.002$ & $2.9354795531765805$ & $0.9253921878089174$ & $0.0022382733013625957$ & $0.05785899301066716$\\
    $0.0009536838895767626$ & $1.0$ & $0.004$ & $2.9354974958876$ & $0.9254047001045744$ & $0.004480217902893781$ & $0.05829041425456174$\\
    $0.0009536838895767626$ & $1.0$ & $0.006$ & $2.9355234346153742$ & $0.9254269085233069$ & $0.006729454676907429$ & $0.05899947503986548$\\
    $0.0009536838895767626$ & $1.0$ & $0.008$ & $2.935551270469769$ & $0.9254607390135051$ & $0.008989508064503429$ & $0.059972051406433184$\\
    $0.0009536838895767626$ & $1.0$ & $0.01$ & $2.935572154787768$ & $0.9255086965138954$ & $0.011263768116134604$ & $0.06118987977165465$\\
    $0.0009536838895767626$ & $2.0$ & $0.001999$ & $3.223538695196383$ & $1.0560878711527533$ & $0.001854944179107667$ & $0.07004521113569465$\\
\end{tabular}
\caption{Periodic Orbits within the Earth-Moon, Sun-Earth, Sun-Mars, and Sun-Jupiter Systems}
\end{table}
\end{landscape}

\end{document}


\documentclass[11pt]{scrartcl} % Font size
\input{../structure.tex} % Include the file specifying the document structure and custom commands

%----------------------------------------------------------------------------------------
%	TITLE SECTION
%----------------------------------------------------------------------------------------

\title{
	\normalfont\normalsize
	\textsc{Harvard Privacy Tools Project}\\ % Your university, school and/or department name(s)
	\vspace{25pt} % Whitespace
	\rule{\linewidth}{0.5pt}\\ % Thin top horizontal rule
	\vspace{20pt} % Whitespace
	{\huge Snapping Mechanism Notes}\\ % The assignment title
	\vspace{12pt} % Whitespace
	\rule{\linewidth}{2pt}\\ % Thick bottom horizontal rule
	\vspace{12pt} % Whitespace
}

\date{\normalsize\today} % Today's date (\today) or a custom date

\begin{document}
\maketitle % Print the title

\section{Introduction}
The implementation of the snapping mechanism utilizes a number of ideas described in \href{http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.366.5957&rep=rep1&type=pdf}{Mironov (2012)}\footnote{specifically in section 5.2} that, as far as I can tell, are not commonly seen in implementations of other DP algorithms. This document provides an overview of these ideas. \newline

\section{Mechanism Definitions}
Below we present the mechanisms as if they are operating on the set 64-bit floating point numbers, $\mathbb{D}$, rather than $\mathbb{R}$. We will use $\oplus$ and $\otimes$ to represent the floating-point implementations of addition and multiplication, respectively.

\subsection{Laplace Mechanism}
\label{subsec:laplace}
Let $f$ be a function computed on a data set $D$ with sensitivity $\Delta_f$ and $\epsilon$ be the desired privacy parameter. Further, let $\lambda = \frac{\Delta_f}{\epsilon}$. Then the Laplace Mechanism is defined as:
\[ M_{L}(D, f(\cdot), \lambda) = f(D) \oplus Y \]
where $Y \sim Laplace(\lambda)$.

\subsection{Snapping Mechanism}
\label{subsec:snapping}
Let $B$ be a user-chosen quantity that reflects beliefs about reasonable bounds on $f(D)$ and $\Lambda$ be the smallest power of two at least as large as $\lambda$. Using the same notation as above, the snapping mechanism is defined as:
\[ M_{S}(D, f(\cdot), \lambda, B) = clamp_{B}\left( \lfloor clamp_{B}\left( f(D) \right) \oplus Y \rceil_{\Lambda} \right). \]
where $clamp_{B}(\cdot)$ restricts output to the interval $[-B, B]$ and $\lfloor \cdot \rceil_{\Lambda}$ rounds to the nearest multiple of $\Lambda$, with ties resolved toward $+ \infty$.

\section{Sampling from the Laplace}
\label{sec:sampling_from_laplace}
Mironov presents the Laplace noise as
\[ S \otimes \lambda \otimes LN(U^*) \]
where $S$ is a uniform draw over $\{\pm 1\}$, $\lambda = \frac{\Delta_f}{\epsilon}$, $LN(\cdot)$ is the floating-point implementation of the natural logarithm with exact rounding, and $U^*$ is the uniform distribution over $\mathbb{D} \cap (0,1)$ such that each double is output with proportion relative to its \href{https://en.wikipedia.org/wiki/Unit_in_the_last_place}{unit of least precision}. $\oplus$ and $\otimes$ are the floating-point implementations of addition and multiplication, respectively. \newline

We get $U^*$ as Mironov suggests, by sampling our exponent from a geometric distribution with parameter $p = 0.5$ and a mantissa uniformly from $\{0,1\}^{52}$. Let $e$ be a draw from $Geom(0.5)$ and $m_1, m_2 \hdots, m_{52}$ be the bits of our mantissa. Then we have
\[ U^{*} = (1.m_1m_2 \hdots m_{52})_2 * 2^{- e}. \]
The unit of least precision is completely decided by the value of $e$, so the floating-point values within each unit of least precision are uniformly distributed. Drawing $e$ from the geometric ensures that the probability of drawing a value from a given band is equal to the size of the band. \newline

$LN(\cdot)$ must be implemented with exact rounding, which we define below.\footnote{For all rounding, we assume that our goal is to round to the nearest number we are able to represent.} Consider that for an arbitrary $x \in \mathbb{D}$ the natural log of $x$ is not necessarily $\in \mathbb{D}$. Let $a < ln(x) < b$ where $a,b \in \mathbb{D}$ and $\not\exists c \in \mathbb{D}: a < c < b$. Without loss of generality, assume that $\vert a-x \vert < \vert b - x \vert$, so that if we had infinite precision in calculating $ln(x)$ (but still had to output an element $\in \mathbb{D}$), we would output $a$.
Many mathematical libraries do what is called \textit{accurate-faithful} rounding, which means that in the scenario above our algorithm would output $a$ with high probability. In an \textit{exact rounding} paradigm, the algorithm outputs $a$ with probability 1. You can read more about exact rounding in section 1.1 \href{http://www.ens-lyon.fr/LIP/Pub/Rapports/RR/RR2005/RR2005-37.pdf}{here}. Section 2.1 of the paper just linked appeals to proofs from a set of papers that say you need 118 bits of precision, in the worst case, to calculate the logarithm with exact rounding. So, the current implementation calculates $LN(U^*)$ with at least 118 bits of precision.\footnote{We potentially use $> 118$ because of the $\epsilon$ redefinition described later.} \newline

Finally, we can choose to perform $\oplus$ and $\otimes$ with greater than normal precision if we so choose. For now, we are using the same 118 bits of precision for all the basic floating-point operations, using the assumption that exact rounding of basic arithmetic operations should require less precision than calculating the log. This should probably be made more rigorous at some point.

\section{Implementation of $\lfloor \cdot \rceil_{\Lambda}$}
\label{sec:implementation_of_rounding}
The $\lfloor \cdot \rceil_{\Lambda}$ function takes an input and rounds it to the nearest multiple of $\Lambda$, where $\Lambda$ is the smallest power of two greater than or equal to $\lambda$. There are multiple steps to this implementation that are worth explaining.

\subsection{Finding $\Lambda$}
\label{subsec:finding_lambda}
The algorithm receives $\lambda$ as input, but must find $\Lambda$ itself. First, represent $\lambda$ in its \href{https://en.wikipedia.org/wiki/Double-precision_floating-point_format}{IEEE-754 64-bit floating-point format}:
\[ \lambda = (-1)^S (1.m_{1} \hdots m_{52})_2 * 2^{(e_1 \hdots e_{11})_2-1023}. \]
We know $\lambda > 0$, so we know $S = 0$. Now, note that powers of two correspond exactly to the IEEE representations with $m_1 = \hdots = m_{52} = 0$. If $\lambda$ is already a power of two, then we simply return $\lambda$. Otherwise, we get the smallest power of two greater than $\lambda$ by changing to mantissa to $(0 \hdots 0)_2$ and increasing the exponent by 1. So, we have
\begin{equation}
    \Lambda =
        \begin{cases}
            \lambda, & \text{ if } m_1 = \hdots = m_{52} = 0 \\
            (1.0 \hdots 0)_2 * 2^{(e_1 \hdots e_{11})_2-1022}, & \text{ if } \exists i: m_i \neq 0
        \end{cases}
\end{equation}

\subsection{Rounding to nearest multiple of $\Lambda$}
We now want to round our input $x$ to the nearest multiple of $\Lambda$. We do so via a three-step process:
\begin{enumerate}
    \item $x' = \frac{x}{\Lambda}$
    \item Round $x'$ to nearest integer, yielding $x''$
    \item $\lfloor x \rceil_{\Lambda} = \Lambda x''$
\end{enumerate}
We split the process into three steps because each step can be performed exactly (with no introduction of floating-point error) via manipulation of the IEEE floating-point representation.

\subsubsection{Calculate $x' = \frac{x}{\Lambda}$}
\label{subsec:calculate_xprime}
We can perform this division exactly because $\Lambda$ is a power of two. Let $\Lambda = 2^m$ for some $m \in \mathbb{Z}$ and let $x$ have the IEEE representation
\[ x = (-1)^S (1.m_{1} \hdots m_{52})_2 * 2^{(e_1 \hdots e_{11})_2-1023}. \]
Then we know that
\[ x' = (-1)^S (1.m_{1} \hdots m_{52})_2 * 2^{(e_1 \hdots e_{11})_2-1023-m}. \]
We can rewrite $(e_1 \hdots e_{11})_2 - m$ as $(f_1 \hdots f_{11})_2$ and represent $x'$ directly as its IEEE implementation:
\[ x' = (-1)^S (1.m_{1} \hdots m_{52})_2 * 2^{(f_1 \hdots f_{11})_2-1023}. \]

\subsubsection{Round $x'$ to nearest integer}
\label{subsec:round_xprime}
Let $y = (f_1 \hdots f_{11})_2-1023$. We present slightly different rounding algorithms based on the value of $y$. Note that we abuse notation a bit below; the repeating element notation $\bar{0}$ means to repeat the element (in this case, 0) until the rest of the larger section has been filled. For example, if the mantissa is 52 bits, then $101\bar{0}$ represents $101$ followed by 49 trailing zeros. \newline

\textbf{Case 1: $y \geq 52$} \newline
If $y \geq 52$, then we know that only integers are able to be represented at this scale, so there is no need to round.\footnote{See \href{https://www.exploringbinary.com/the-spacing-of-binary-floating-point-numbers/}{here} for an explanation.} \newline

\textbf{Case 2: $y \in \{0, 1, \hdots, 51\}$} \newline
We can think of multiplying by $2^y$ as shifting the radix point to the right $y$ times. We can then write
\[ x' = (-1)^S (1m_1 \hdots m_y.m_{y+1} \hdots m_{52})_2. \]

We know $m_1 \hdots m_y$ represent powers of two $\in \mathbb{Z}$ and $m_{y+1} \hdots m_{52}$ are powers of two $\not \in \mathbb{Z}$. Specifically, $m_{y+1}$ corresponds to $\frac{1}{2}$. So, we know to round up if $m_{y+1} = 1$ and down if $m_{y+1} = 0$. \newline

Rounding up requires incrementing up by 1 the integral part of the mantissa ($m_1 \hdots m_y$), and changing the fractional part ($m_{y+1}, \hdots, m_{52}$) to zeros. Note that there is an edge case here where $m_i = 1$ for all $i$ in which the mantissa becomes $(\bar{0})_2$ and we instead increment the exponent. Rounding down requires maintaining the integral part of the mantissa and changing the fractional part to zeros. \newline

Let $(m'_1 \hdots m'_y)_2 = (m_1 \hdots m_y)_2 + 1$ and $(f'_1 \hdots f'_{11})_2 = (f_1 \hdots f_{11})_2 + 1$. Then we get:
\begin{equation}
    x'' =
        \begin{cases}
            (-1)^S (1.m'_1 \hdots m'_y \bar{0})_2 * 2^{(f_1 \hdots f_{11})_2-1023}, & \text{ if } m_{y+1} = 1 \text{ and } \exists i: m_i = 0 \\
            (-1)^S (1.\bar{0})_2 * 2^{(f'_1 \hdots f'_{11})_2-1023}, & \text{ if } m_{y+1} = 1 \text{ and } \forall i: m_i = 1 \\
            (-1)^S (1.m_1 \hdots m_y \bar{0})_2 * 2^{(f_1 \hdots f_{11})_2-1023}, & \text{ if } m_{y+1} = 0
        \end{cases}
\end{equation}

\textbf{Case 3: $y = -1$} \newline
We think of this case similarly to the beginning of Case 2 and shift the radix point to the left:
\[ x'' = (-1)^S (0.1m_1 m_2 \hdots)_2. \]
W know the bit directly to the right of the radix point is the implicit 1 in the IEEE representation, so we know we will round up. Rounding up always rounds to 1, so we know
\[ x'' = (-1)^S (1.\bar{0})_2 * 2^{(0\bar{1})_2 - 1023}. \]

\textbf{Case 4: $y < -1$} \newline
This is exactly the same as Case 3, except we know there are some number of leading zeros between the radix point and the implicit 1. Therefore, we always round down to 0 and get:
\[ x'' = (-1)^0 (1.\bar{0})_2 * 2^{(\bar{0})_2 - 1023}. \]
The notation directly above should not be taken literally, as 0 has a special IEEE representation (all 0s) that does not quite follow the standard formula. We present the standard formally for the sake of consistency and comparison with the earlier cases. \newline

\subsubsection{Multiply $x''$ by $\Lambda$}
\label{subsubsec:multiply_xdoubleprime}
Finally, we multiply $x''$ by $\Lambda$ to get our desired result. This is effectively the opposite of Step 1, in that we add $m$ to the exponent of $x''$. The only difference is that we now have to deal with the case in which $x'' = 0$, because $0*2^m \neq 0$ if you implement multiplication by $2^m$ through exponent addition.\footnote{This is due to the special representation of 0.}

\section{Redefinition of $\epsilon$}
\label{sec:redefine_epsilon}
Mironov states in the last line of the privacy proof that the snapping mechanism respects
\[ \left( \frac{1 + 12B\eta}{\lambda'} + 2\eta \right)\text{-DP}\footnote{We use $\lambda'$ rather than $\lambda$
to reflect that it is calculated with respect to our functional $\epsilon'$} \]
where $B$ is the clamping bound and $\eta$ is the machine-$\epsilon$.\footnote{This is a relatively minor point, but I have normally seen machine-$\epsilon$ defined as the smallest value $\epsilon$ such that $1 \oplus \epsilon \neq 1$. Mironov defines it as the largest $\epsilon$ such that $1 \oplus \epsilon = 1$.} We will take $\eta$ to be our floating-point precision, rather than a value that is machine-imposed, which allows us to use high-precision libraries to get smaller values of $\eta$.
Because we have rescaled our function to $\Delta f = 1$, we have $\lambda' = \frac{1}{\epsilon'}$ and this is equivalent to
\[ \big( \epsilon'(1 + 12B\eta) + 2\eta \big)\text{-DP}. \]
For ease of notation, we will call this $\epsilon$-DP and it can be thought of as the privacy level relative to the Laplace. That is, if you were to get $\epsilon'$-DP from the Laplace Mechanism, you would get $\epsilon$-DP from the Snapping Mechanism. Put another way, you get $\epsilon$-DP from the Snapping Mechanism when you use $\epsilon'$ to parameterize the Laplace noise that is embedded within the Snapping Mechanism. \newline

This is not really sufficient to be usable in a system that might require budgeting of a privacy budget, as you cannot (as written above) simply set a privacy allocation for the Snapping Mechanism, as it relies on $B$ and $\eta$. So rather than returning $\epsilon$ as a function of $\epsilon'$, we should do the reverse.
\begin{align}
             \epsilon &= \epsilon'(1 + 12B\eta) + 2\eta \nonumber \\
    \implies \epsilon' &= \frac{\epsilon - 2\eta}{1 + 12B \eta} \nonumber
\end{align}
This $\epsilon'$ is what will be used in the parameterization in the Laplace within the Snapping Mechanism. Thus, we need $\epsilon' > 0$, or $\epsilon > 2\eta$, where $\eta = 2^{-p}$, and $p$ is our floating point precision. This simplifies to $\epsilon > 2^{-p+1}$. Assuming we want minimum sufficient precision, we can find the smallest power of two $\geq \epsilon$, call it $2^{-m}$, and let $p = m+2$. For setting our mechanism-level precision, we use the larger of the $p$ we just found or the level necessary to perform exact rounding on the logarithm as described earlier (which we currently believe to be 118).

\section{Utility}
\label{sec:utility}

\subsection{Symmetric Bounds}
\label{subsec:symmetric_bounds}
Notice that, as stated, the clamping bounds $\{-B, B\}$ are symmetric about 0 -- this is sub-optimal in many cases.
For example if the user is confident that their statistic of interest lies in the range $[1,000, 2,000]$ they
would need to set $B = 2,000$, generate a clamping range $[-2,000, 2000]$, and have noise scaled by $4,000$
rather than $1,000$. In practice, we can allow users to provide $[lower, upper]$ bounds on the statistic value rather
than a single $B$. If we let $s = \frac{upper - lower}{2}$ and pre-shift our statistic value by $s$ we can let
$B = upper - s$ and have a version with potentially much greater utility.

\subsection{Error}
\label{subsec:error}
As originally written, it is difficult to reason about error/utility of the Snapping Mechanism. The output of the Snapping Mechanism relies on the user-provided bound, $B$, which could potentially cause the output to be arbitrarily far from $f(D)$. The potential for bias of the Snapping Mechanism decreases as $B$ increases in absolute value. Note however that $\epsilon'$ decreases as $B$ increases, thus causing the amount of added Laplace noise to increase. Throughout this section, we will assume that $f(D) \geq 0$, though a very similar process can be taken to reason about $f(D) \leq 0$. Furthermore, we consider the case in which $\Delta f = 1$.
The accuracy/error calculations should be multiplied by $\Delta f$ for the case in which $\Delta f \neq 0$. \newline

One possibility is that, instead of the user choosing $B$, we set it for them within the mechanism. We can use the data bounds the user provides to calculate an
upper bound on $\vert f(D) \vert$.\footnote{This should, at least theoretically, be possible for $f: \mathcal{X} \rightarrow \mathbb{R}$ if $f$ is continuous and $\mathcal{X}$ is compact (thanks to Ira/Wikipedia for pointing this out).} We will refer to this maximal value of $f(D)$ as $B'$. This will allow us to set a $B$ such that we are sure that $clamp_B \left( f(D) \right)$ is non-binding. This will make it a bit easier to think about the error of the mechanism, as every component of the mechanism is now something with a value or distribution we can reason about. For now, we will mostly ignore exactly how this is done and focus on general analysis assuming that such a $B$ can be chosen.

Now, consider the following quantity:
\[ N \sim \big \vert f(D) - clamp_B \big( \lfloor f(D) + Y' \rceil_{\Lambda'} \big) \big \vert \]
with $Y' \sim Laplace(\lambda')$ where $\lambda' = \frac{1}{e'} = \frac{1 + 12B \eta}{\epsilon - 2\eta}$. This is the amount of noise added to $f(D)$ by the snapping mechanism.\footnote{Note that we ignore the inner $clamp_B$ inside the Snapping Mechanism because we set $B \geq f(D)$.} We have then:
\begin{equation}
	N =
		\label{snapped_noise}
		\begin{cases}
			B + f(D), &\text{ if } clamp_B \left( \lfloor f(D) + Y' \rceil_{\Lambda'} \right) = -B  \\
			B - f(D), &\text{ if } clamp_B \left( \lfloor f(D) + Y' \rceil_{\Lambda'} \right) = B  \\
			\big\vert f(D) - \lfloor f(D) + Y' \rceil_{\Lambda'} \big\vert, &\text{ otherwise }
		\end{cases}
\end{equation}

We can examine these cases further. Let $F_{Y'}$ be the CDF of $Y' \sim Laplace(\lambda')$, which we write:
\begin{equation}
	F_{Y'}(x) =
		\begin{cases}
			\frac{1}{2} \exp \left( \frac{x}{\lambda'} \right), &\text{ if } x < 0 \\
			1 - \frac{1}{2} \exp \left( \frac{-x}{\lambda'} \right), &\text{ if } x \geq 0
		\end{cases}
\end{equation}

Then:
\begin{align}
	               \mathbb{P} \big( clamp_B\left( \lfloor f(D) + Y' \rceil_{\Lambda'} \right) = -B \big) \nonumber &= \mathbb{P} \big( \lfloor f(D) + Y' \rceil_{\Lambda'} < -B \big) \nonumber \\
	&\leq \mathbb{P} \big( f(D) + Y' < -B + \frac{\Lambda'}{2} \big) \nonumber \\
	&= \mathbb{P} \big( Y' < -B - f(D) + \frac{\Lambda'}{2} \big) \nonumber \\
	&= F_{Y'} \big( -B - f(D) + \frac{\Lambda'}{2} \big) \nonumber
\end{align}

\begin{align}
	               \mathbb{P} \big( clamp_B\left( \lfloor f(D) + Y' \rceil_{\Lambda'} \right) = B \big) \nonumber &= \mathbb{P} \big( \lfloor f(D) + Y' \rceil_{\Lambda'} \geq B \big) \nonumber \\
	&\leq \mathbb{P} \big( f(D) + Y' \geq B - \frac{\Lambda'}{2} \big) \nonumber \\
	&= \mathbb{P} \big( Y' \geq B - f(D) - \frac{\Lambda'}{2} \big) \nonumber \\
	&= 1 - \mathbb{P} \big( Y' < B - f(D) - \frac{\Lambda'}{2} \big) \nonumber \\
	&= 1 - F_{Y'} \big( B - f(D) - \frac{\Lambda'}{2} \big) \nonumber
\end{align}

Recall from the triangle inequality that $\vert x-z \vert \leq \vert x-y \vert + \vert y-z \vert$. Then we have
\begin{align}
\big\vert f(D) - \lfloor f(D) + Y' \rceil_{\Lambda'} \big\vert \nonumber &\leq \big\vert f(D) - (f(D) + Y') \big\vert + \big\vert f(D) + Y' - \lfloor f(D) + Y' \rceil_{\Lambda'} \big\vert \nonumber \\
                                                                        &\leq \vert -Y' \vert + \frac{\Lambda'}{2} \nonumber \\
	                                                                    &= \vert Y' \vert + \frac{\Lambda'}{2} \nonumber
\end{align}
It is important to note that this $Y'$ is associated with the Laplace noise inside the snapping mechanism which uses the redefined $\epsilon'$, rather than the user's desired $\epsilon$. So, we need to do a bit more work in order to compare the error of the Snapping Mechanism to that we would get if we instead used a Laplace Mechanism with the same nominal privay guarantee. \newline

Let $Y \sim Laplace(\lambda)$, where $\lambda = \frac{1}{\epsilon}$, be the distribution of noise generated by the Laplace Mechanism.
We showed in \autoref{subsec:snapping} that we can represent the distribution of Laplace noise as $S \otimes \lambda \otimes LN(U^*)$. So, we have
\[ Y \sim S \otimes \frac{1}{\epsilon} \otimes LN(U^*) \]
\[ Y' \sim S \otimes \frac{1 + 12B\eta}{\epsilon - 2\eta} \otimes LN(U^*) \]
and thus,
\[ Y' = \frac{\epsilon(1 + 12B\eta)}{\epsilon - 2\eta}Y \]

So we can rewrite $\eqref{snapped_noise}$ as
\begin{equation}
	\label{snapped_noise_rewrite}
	N
		\begin{cases}
			= B + f(D), &\text{ with probability } \leq F_{Y'} \big( -B - f(D) + \frac{\Lambda'}{2} \big)  \\
			= B - f(D), &\text{ with probability } \leq 1 - F_{Y'} \big( B - f(D) - \frac{\Lambda'}{2} \big)  \\
			\leq \vert Y' \vert + \frac{\Lambda'}{2}, &\text{ otherwise }
		\end{cases}
\end{equation}
Note that $N$ is always $\leq B + f(D)$.

\subsection{Accuracy}
\label{subsec:accuracy}
We would like to convert the error into an accuracy estimate. Keeping in line with existing standards in PSI-Library, we define the accuracy $a$ for a given $\alpha$ as the $a$ such that $\alpha = \mathbb{P}(N > a)$, where $N$ is (as above) the error (relative to $f(D)$) introduced by the Snapping Mechanism. It is difficult to get an exact accuracy guarantee because of our inability to model the effects of $\lfloor \cdot \rceil_\Lambda'$, so we will instead refer to $a$ as the smallest $x$ such that $\mathbb{P}(N > x) \leq \alpha$. \newline

Recall that $N \leq B + f(D)$. If we can get an upper bound on $P_{L} = \mathbb{P}(N = B + f(D))$, then we can start concerning ourselves only with the second two lines of $\eqref{snapped_noise_rewrite}$, which we will call $N_{sub}$. \newline

Let's attempt to get bounds on $P_{L} = \mathbb{P}(N = B + f(D))$ and $P_{U} = \mathbb{P}(N = B - f(D))$ in terms of quantities we know. Remember that $\frac{\lambda'}{2} \leq \frac{\Lambda'}{2} < \lambda'$.
\begin{align}
	P_{L} &= \mathbb{P}(N = B + f(D)) \nonumber \\
		  &= F_{Y'}(-B - f(D) + \frac{\Lambda'}{2}) \nonumber \\
		  &< F_{Y'}(-B - f(D) + \lambda') \nonumber \\
		  &= P_{L}^{+} \nonumber
\end{align}
\begin{align}
	P_{U} &= \mathbb{P}(N = B - f(D)) \nonumber \\
		  &= 1 - F_{Y'}(B - f(D) - \frac{\Lambda'}{2}) \nonumber \\
		  &\geq 1 - F_{Y'}(B - f(D) - \lambda') \nonumber \\
		  &= P_{U}^{-} \nonumber
\end{align}
Because we know that $\mathbbm{P}(N=B+f(D)) \leq P_L < P_{L}^{+}$, we can reframe our original goal. We wanted to find the smallest $x$ such that $\alpha \geq \mathbb{P}(N > x)$, but this is equivalent to finding the smallest $x$ such that
\[ \alpha - P_{L}^{+} \geq \mathbb{P}(N_{sub} > x) \]
which we further reinterpret as
\[ \alpha - P_{L}^{+} \geq 1 - \mathbb{P}(N_{sub} \leq x) = 1 - F_{N_{sub}}(x). \]
Consider $N_{sub}$; we know that
\[ Y' \sim Laplace (\lambda') \]
with $\lambda' = \frac{1}{\epsilon'} = \frac{1 + 12B \eta}{\epsilon - 2 \eta}$, which implies that
\[ \vert Y' \vert \sim Exponential(\epsilon'). \]
We now construct upper and lower bounds on the CDF of $Z = \vert Y' \vert + \frac{\Lambda'}{2}$, which we will call $F_{Z}$:
\begin{align}
	F_{Z}(z) &= \mathbb{P}(Z \leq z) \nonumber \\
			 &= \mathbb{P}\left( \vert Y' \vert + \frac{\Lambda'}{2} \leq z \right) \nonumber \\
			 &= \mathbb{P} \left( \vert Y' \vert \leq z - \frac{\Lambda'}{2} \right) \nonumber \\
			 &\leq \mathbb{P} \left( \vert Y' \vert \leq z - \frac{\lambda'}{2} \right) \nonumber \\
			 &= 1 - \exp\left( -\epsilon'(z - \frac{\lambda'}{2}) \right) \nonumber \\
			 &= 1 - \exp\left( -\epsilon'z + \frac{1}{2} \right) \nonumber \\
			 &= F_{Z}^{+}(z) \nonumber
\end{align}
\begin{align}
	F_{Z}(z) &= \mathbb{P}(Z \leq z) \nonumber \\
			 &= \mathbb{P}\left( \vert Y' \vert + \frac{\Lambda'}{2} \leq z \right) \nonumber \\
			 &= \mathbb{P} \left( \vert Y' \vert \leq z - \frac{\Lambda'}{2} \right) \nonumber \\
			 &> \mathbb{P} \left( \vert Y' \vert \leq z - \lambda' \right) \nonumber \\
			 &= 1 - \exp\left( -\epsilon'(z - \lambda') \right) \nonumber \\
			 &= 1 - \exp\left( -\epsilon'z + 1 \right) \nonumber \\
			 &= F_{Z}^{-}(z) \nonumber
\end{align}

Let $f_Z$ be the PDF of $Z$, $m = \min\left(B-f(D),x\right)$, and $n = \min\left(B+f(D),x\right)$.  Then we have:
\begin{align}
	F_{N_{sub}}(x) &= \int_{0}^{m} f_{Z}(z)dz + \left( P_{U} + \int_{B - f(D)}^{n} f_{Z}(z)dz \right) \cdot \mathbbm{1}\left(x \geq B - f(D)\right) \nonumber \\
				   &= F_{Z}(m) + \left( P_{U}  + F_{Z}(n) - F_{Z}(B - f(D)) \right) \cdot \mathbbm{1}\left( x \geq B - f(D) \right)   \nonumber \\
				   &\geq F_{Z}^{-}(m) + \left( P_{U}^{-} + F_{Z}^{-}(n) - F_{Z}^{+}(B - f(D) \right) \cdot \mathbbm{1}\left(x \geq B - f(D)\right) \nonumber \\
				   &= F_{N_{sub}}^{-}(x) \nonumber
\end{align}
Now that we have $F_{N_{sub}}^{-}(x)$ as a lower bound on $F_{N_{sub}}(x)$, we know that
$1 - F_{N_{sub}}^{-}(x)$ is an upper bound on $1 - F_{N_{sub}}(x)$.
So, our objective is now to find the minimum $x$ such that $1 - F_{N_{sub}}^{-}(x) = \alpha - P_{L}^{+}$.
We rewrite this condition as $F_{N_{sub}}^{-}(x) = 1 + P_{L}^{+} - \alpha$. \newline

Observe that if for a given $x'$ we have
$F_{Z}^{-}(x') \geq 1 + P_{L}^{+} - \alpha$, we know that
\[ \exists x \leq x': x = 1 + P_{L}^{+} - \alpha \]
We can find this $x$ by performing algebra on $F_{Z}^{-}(x)$, which yields the following algorithm:

\begin{algorithm}
	\label{GetAccuracy}
	\begin{algorithmic}
		\Function{GetAccuracy}{$f(D), B, P_{L}^{+}, P_{U}^{-}, \epsilon', \alpha$}
			\If{$P_{L}^{+} \geq \alpha$}
				\State\Return{B + f(D)}
			\ElsIf{$F^{-}_{Z}(B - f(D)) \geq 1 + P_{L}^{+} - \alpha$}
				\State\Return{$\frac{1 - \ln(\alpha - P_{L}^{+})}{\epsilon'}$}
			\ElsIf{$F^{-}_{Z}(B - f(D)) + P_{U}^{-} \geq 1 + P_{L}^{+} - \alpha$}
				\State\Return{B - f(D)}
			\Else{}
				\State\Return{$\frac{1 - \ln(\alpha - P_{L}^{+} + P_{U}^{-})}{\epsilon'}$}
			\EndIf
		\EndFunction
	\end{algorithmic}
\end{algorithm}
Calculations/explanations of the return statements above can be found in $\autoref{appendix:accuracy}$. \newline

There are some complications with \emph{GetAccuracy}. \newline

First, it relies on $f(D)$ and thus is privacy-leaking. I have not yet figured out the privacy loss of releasing the accuracy,
but we could work on this in the future. James suggested that we could potentially give simulated accuracy estimates
for estimates of $f(D)$ provided by the user, thus removing the dependance on the real $f(D)$.
I think that if we did this, we could not give a post-hoc accuracy guarantee using \emph{GetAccuracy}
(it would be too easy for a user to ask for an exhaustive list of accuracies for possible $f(D)$ and then back out the true
$f(D)$ from the provided post-hoc accuracy guarantee). \newline

Second (though related), the accuracy guarantee using the actual $f(D)$ cannot be done until the mechanism has been run,
so the user cannot get a certain accuracy guarantee before running the algorithm in order to decide whether or
not they want to spend some of their privacy budget on the statistic. \newline

We instead use a more conservative accuracy metric that will be independent of $D$.\footnote{Thanks to Victor Balcer for motivating
this idea.} Note that, provided that $f(D) \in [-B, B]$ (as is guaranteed by our method for choosing $B$),
the outer $clamp_B$ (after noise is added) can only help our accuracy. Thus, we can model the noise as always being upper bounded by
$Z = \vert Y' \vert + \frac{\Lambda'}{2}$ and ignore the cases in which the outer clamping binds bound. \newline

Let's first consider the question of, for a given accuracy $a$, finding confidence $\alpha$ such that
$\mathbbm{P}(Z \geq a) \leq \alpha$. We would like for $\alpha$ to be as small as possible, though any sufficiently large
$\alpha$ would satisfy our needs.

\begin{align*}
	\mathbb{P}(Z > a) &= 1 - \mathbb{P}(Z \leq a) \\
	                  &= 1 - F_{Z}(a) \\
	                  &= \exp\left( -\epsilon'(a - \frac{\Lambda'}{2}) \right)
\end{align*}
and so we have
\[ \alpha = \exp\left( -\epsilon'(a - \frac{\Lambda'}{2}) \right). \]
We can rearrange and solve for $a$ to put this in the terms we were using earlier (finding a suitable accuracy $a$ for
a given $\alpha$). That calculation yields
\[ a = \frac{\ln \left( \frac{1}{\alpha} \right)}{\epsilon'} + \frac{\Lambda'}{2}. \]

The algorithm for getting accuracy is then as follows. Notice that we can clamp our accuracy guarantee to $2B$ if it
exceeds this, as the outer clamp ensures that the mechanism output is $\in [-B, B]$.
\begin{algorithm}
	\label{GetAccuracy2}
	\begin{algorithmic}
		\Function{GetAccuracy2}{$B, \epsilon', \Lambda', \alpha$}
			\State $a = \frac{\ln \left( \frac{1}{\alpha} \right)}{\epsilon'} + \frac{\Lambda'}{2}$
			\If{$a \geq 2B$}
					\State\Return{2B}
			\Else{}
				\State\Return{a}
			\EndIf
		\EndFunction
	\end{algorithmic}
\end{algorithm}

For a less tight, but simpler, bound we can use that $\frac{\Lambda'}{2} \leq \lambda' =
\frac{1}{\epsilon'}$ and set $a = \frac{1 + \ln \left( \frac{1}{\alpha} \right)}{\epsilon'}$.
Also recall that this accuracy statement is conditional of $f(D) \in [-B, B]$. If the clamping bounds are not
explicitly set to contain $f(D)$ with probability $1$, then we cannot give any accuracy guarantee. \newline

The accuracy for the pure Laplace is given as $\frac{\ln \left( \frac{1}{\alpha} \right)}{\epsilon}$. Recalling that
$\epsilon' = \frac{\epsilon - 2\eta}{1 + 12B\eta}$ we can represent the difference between the accuracy of the
Snapping and Laplace as follows:
\begin{align*}
	a_{Snapping} &= \frac{\ln \left( \frac{1}{\alpha} \right)}{\epsilon'} + \frac{\Lambda'}{2} \\
	&= \frac{\ln \left( \frac{1}{\alpha} \right)}{\left( \frac{\epsilon - 2\eta}{1 + 12B\eta} \right)} + \frac{\Lambda'}{2} \\
	&= \frac{(1 + 12B \eta) \left(\ln \left( \frac{1}{\alpha} \right) \right)}{\epsilon - 2\eta} + \frac{\Lambda'}{2} \\
	&= \frac{\epsilon(1 + 12B \eta)}{\epsilon - 2\eta } \cdot \left(\frac{\ln \left( \frac{1}{\alpha} \right)}{\epsilon} \right) + \frac{\Lambda'}{2} \\
	&= \frac{\epsilon(1 + 12B \eta)}{\epsilon - 2\eta} \cdot a_{Laplace} + \frac{\Lambda'}{2}
\end{align*}

We would also like to be able to go from accuracy to get epsilon. We perform some algebra
and get
\[ \epsilon' = \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{\Lambda'}{2}} \]
or, if we wanted our overall $\epsilon$
\begin{equation}
	\label{eq:accuracy_to_overall_epsilon}
	\epsilon = (1+12B\eta) \left( \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{\Lambda'}{2}} \right) + 2\eta.
\end{equation}
This is a bit unsatisfying, as both $\Lambda'$ and $\eta$ are non-trivial functions of $\epsilon$.
We can use $\frac{\Lambda'}{2} \leq \lambda' = \frac{1}{\epsilon'}$ to get a nicer statement:
\begin{align}
	\label{eq:accuracy_to_overall_epsilon_cleaner}
	\epsilon &= (1+12B\eta) \left( \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{\Lambda'}{2}} \right) + 2\eta \nonumber \\
			 &\leq (1 + 12B\eta) \left( \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{1}{\epsilon'}} \right) + 2\eta \nonumber \\
			 &= (1 + 12B\eta) \left( \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{1 + 12B\eta}{\epsilon - 2\eta}} \right) + 2\eta \nonumber \\
			 &\leq (1 + 12B\eta) \left( \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{1}{\epsilon}} \right) + 2\eta.
\end{align}
\eqref{eq:accuracy_to_overall_epsilon_cleaner} is monotonic in $\epsilon$ for $0 < \frac{1}{\epsilon} < a$ and so
we can use binary search to try to find the minimum $\epsilon$ that satisfies the desired $a$.
Technically, $\eta$ is also a function of $\epsilon$ and so we fold that into the binary search by
calculating $\eta$ anew for each tested $\epsilon$ value. \newline

For all privacy/accuracy analysis of the Snapping mechanism, note that the tradeoff between privacy/accuracy
guarantees is not smooth due to the $\Lambda'$ term.
For example, $\forall \lambda' = \frac{1}{\epsilon'} \in (\frac{1}{2}, 1]: \Lambda' = 1$, but for
$\lambda' = 1.01$ we have $\Lambda' = 2$. For an empirical evaluation of this, see
the sample notebook \href{https://github.com/opendp/smartnoise-samples/blob/cc_add_snapping/analysis/snapping_mechanism.ipynb}{here}.

\subsection{Bias}
\label{subsec:bias}
Because of the clamping to $[-B,B]$, the snapping mechanism will almost always bias estimates toward $0$.
I am not yet sure if it would be possible to give information about bias of the released statistic without leaking information
about the data (I lean toward thinking that it is not), but I believe we could provide the bias for a statistic for

a user's guesses about what $f(D)$ might be. \newline

Let $\hat{f}(D)$ be the user's estimate of $f(D)$ and $\hat{\tilde{f}}(D)$ be the output of the snapping mechanism as applied to
$\hat{f}(D)$. Without loss of generality, we will assume that $\hat{f}(D) \geq 0$. If it were not, we could
multiply $f'(D)$ by $-1$ and use this algorithm to get the correct result.\footnote{This works because our bounds, $-B \text{ and } B$, are symmetric about $0$.}
We think about the distribution of noise not as the absolute value of noise (which we used earlier), but as
being some distribution with support $[-B - \hat{f}(D), B - \hat{f}(D)]$. \newline

We write the bias of the snapping mechanism as
\[ Bias = \E(\hat{\tilde{f}}(D) - \hat{f}(D)) = \E\left( clamp_B\left( \lfloor \hat{f}(D) + Y' \rceil_{\Lambda'} \right) - \hat{f}(D) \right) \]
where $Y' \sim Laplace(\lambda')$ and the expectation is over the randomness of the snapping mechanism.
Note that bias is a property of the snapping, not of any individual output of the mechanism.
Thus, any individual output from the snapping mechanism could be as far as $2B$ from the actual raw statistic
we wish to estimate. \newline

To avoid trying to model the effects of $\lfloor \cdot \rceil_{\Lambda'}$ directly, we will move to considering
a new quantity we will call $Bias^{+}$, which is an upper bound on the bias:
\[ Bias^{+} = \E\left( clamp_B\left( f'(D) + Y^{*} \right) - \hat{f}(D) \right) \]
where $Y^{*} \sim Laplace(-\frac{\Lambda'}{2}, \lambda')$.\footnote{I believe this works,
but need to think of how to prove it.} Now, define the following:
\[ p_L = F_{Y^*}(-B - \hat{f}(D)) \]
\[ p_U = 1 - F_{Y^*}(B - \hat{f}(D)) \]
such that $F_{Y^*}$ is the CDF of $Y^*$ and $p_L, p_U$ are the probabilities that the lower/upper bounds are binding (respectively).
Then we can write
\[ Bias^+ = p_L \cdot (-B - \hat{f}(D)) + p_U \cdot (B - \hat{f}(D)) + (1-p_l-p_U) \cdot \int_{-B-\hat{f}(D)}^{B-\hat{f}(D)}y^* f(y^*) dy^* \]
where $f$ is the PDF of $Y^*$. \newline

There may be other notions of bias we could provide to a user. For example, the maximum possible bias
(i.e. when $f(D) = \pm B$) (already included in the code), or the expected bias over a set/distribution of $\hat{f}(D)$ (not
yet implemented).

\subsection{Choosing $B$}
\label{subsec:choosing_B}
Now that we have a general statements on error and bias, let's consider how best to choose $B$.
We will always face a tradeoff in choosing $B$; choosing a larger $B$ necessitates adding more noise within
our mechanism (and increases the variance), but choosing a smaller $B$ increases our bias.
We would like the user to be able to express their preferences as to this bias-variance tradeoff,
but we cannot tell them for certain how bad the bias will be, as it is a function of the private $f(D)$.
Our current method is below, though we are open to considering other possibilities.

\subsubsection{$P(\text{clamping bound binds})$}
\label{subsubsec:p_clamp_bound_binds}
Let $B'$ be the largest possible value (in terms of absolute value) of the statistic, conditional on the data bounds provided
by the user. Our current approach, adapted from a suggestion by Victor Balcer, is to set
\[ B = B' + \frac{\Lambda'}{2} \left(1 + 2\ln \left( \frac{1}{\gamma} \right) \right) \]
for some $\gamma \in (0,1]$ specified by the user. This ensures that $B$ does not bind with probability at least $1 - \gamma$,
a fact we show below. \newline

We know that $f(D) \in [-B', B']$ and that our worst case bias will happen when $f(D) = \pm B'$, so without loss of generality
let $f(D) = B'$. We can appeal to $p_L, p_U$ defined in \autoref{subsec:bias} as the probability that the lower/upper
clamping bounds are binding. We want to show that their sum is $\leq \gamma$.
Recall that we defined $Y^* \sim Laplace(-\frac{\Lambda'}{2}, \lambda')$ because setting the mean to
$-\frac{\Lambda}{2}$ produces an upper bound on the bias.
Here, we will define $Y^{**} \sim Laplace(\frac{\Lambda'}{2}, \lambda')$, as this will produce an
upper bound on the probability that the clamping bounds bind. We will define $p_{L**}, p_{U**}$
relative to this distribution and use them instead of the $p_L, p_U$ defined earlier.
\begin{align}
	\Pr(\text{clamping bound binds}) &= p_{L**} + p_{U**} \nonumber \\
							  &= F_{Y^{**}}(-B - B') + 1 - F_{Y^{**}}(B - B') \nonumber \\
							  &= \frac{1}{2} + \frac{1}{2}sign\left(-B - B' - \frac{\Lambda'}{2}\right) \left( 1-\exp\left( -\epsilon' \cdot \big\vert -B - B' - \frac{\Lambda'}{2} \big\vert \right) \right) \nonumber \\
							  &\hspace{10pt} + 1 \nonumber \\
							  &\hspace{10pt} - \frac{1}{2} - \frac{1}{2}sign\left(B - B' - \frac{\Lambda'}{2}\right) \left( 1-\exp\left( -\epsilon' \cdot \big\vert B - B' - \frac{\Lambda'}{2} \big\vert \right) \right) \nonumber \\
							  &= 1 - \frac{1}{2} \left( 1-\exp\left( -\epsilon' \cdot \big\vert -B - B' - \frac{\Lambda'}{2} \big\vert \right) \right) \nonumber \\
							  &\hspace{20pt} - \frac{1}{2} \left( 1-\exp\left( -\epsilon' \cdot \big\vert B - B' - \frac{\Lambda'}{2} \big\vert \right) \right) \label{eq:choosing_B_p1} \\
							  &= 1 - \frac{1}{2} \left(1-\exp \left( -\epsilon' \left( B + B' + \frac{\Lambda'}{2} \right) \right) \right) \nonumber \\
							  &\hspace{20pt} - \frac{1}{2} \left( 1-\exp\left( -\epsilon' \left( B - B' - \frac{\Lambda'}{2} \right) \right) \right) \nonumber \\
							  &= \frac{1}{2} \left( \exp \left( -\epsilon' \left( B + B' + \frac{\Lambda'}{2} \right) \right) + \exp\left( -\epsilon' \left( B - B' - \frac{\Lambda'}{2} \right) \right) \right) \nonumber \\
							  &= \frac{1}{2} \bigg( \exp \left( \epsilon' \left( -2B' + \Lambda' \ln(\gamma) - \Lambda'  \right) \right) + \exp\left( \epsilon' \left( \Lambda' \ln(\gamma) \right) \right) \bigg) \nonumber \\
							  &\leq \frac{1}{2} \bigg( \exp \left( \epsilon' \left( \Lambda' \ln(\gamma)\right) \right) + \exp\left( \epsilon' \left( \Lambda' \ln(\gamma) \right) \right) \bigg) \label{eq:choosing_B_p2} \\
							  &= \gamma^{\epsilon' \Lambda'} \nonumber \\
							  &\leq \gamma \label{eq:choosing_B_p3}
\end{align}
We get to \eqref{eq:choosing_B_p1} by noting that $-B-B'-\frac{\Lambda'}{2}$ is always negative and
$B-B'-\frac{\Lambda'}{2}$ is always positive. \eqref{eq:choosing_B_p2} follows because
$B', \Lambda' \geq 0$, and \eqref{eq:choosing_B_p3} because
$\Lambda'\epsilon' = \frac{\Lambda'}{\lambda'} \geq 1$ and $\gamma \in (0,1]$. \newline

Now, there is a problem in the statement above; we cannot use $\Lambda'$ to define $B$, as $B$ is used
to define $\Lambda'$. We could try to upper bound $\Lambda'$ with something and substitute that into
our formula for $B$ instead; a natural choice would be to try to use $\Lambda$.
Unfortunately, $\Lambda' > \Lambda$ and we do not have a representation
of $\Lambda'$ in terms of $\Lambda$ that is independent of $B$.
So, we need to try something else. Note that
\[ \Lambda' \leq 2\lambda' = \frac{2 + 24B\eta}{\epsilon - 2\eta}. \]
We can make $\eta$ almost arbitrarily small, which allows us to upper bound $B\eta$ by something small.
Assume that after we have set $B$, we can find $\eta$ such that $B\eta \leq 2^{-52}$ (note that $2^{-52}$
was chosen somewhat arbitrarily). Then we know that $2 + 24B\eta \leq 2 + 24 \cdot 2^{-52}$.
We know $\eta \leq 2^{-118}$ because of the precision needed for exact rounding of the natural log,
so we will use $2^{-118}$ as the $\eta$ in the denominator to remove the dependence on $\eta$.
So we have that
\[ \Lambda' \leq \frac{2 + 24B\eta}{\epsilon-2\eta} \leq \frac{2+24 \cdot 2^{-52}}{\epsilon - 2^{-117}}. \]
and thus a new statement for $B$:
\[ B = B' + \frac{k}{2} \left(1 + 2\ln \left( \frac{1}{\gamma} \right) \right), \]
where $k = \frac{2+24 \cdot 2^{-52}}{\epsilon - 2^{-117}}$. \newline

In the case where the user provides accuracy instead of $\epsilon$, we can use
\eqref{eq:accuracy_to_overall_epsilon}
to get a lower bound on $\epsilon$. We can then use this lower bound on epsilon to
calculate a $k$ that will be more than sufficiently large to satisfy our constraints.
\begin{align*}
	\epsilon &= (1+12B\eta) \left( \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{\Lambda'}{2}} \right) + 2\eta \\
			 &\geq \frac{\ln\left( \frac{1}{\alpha} \right)}{a - \frac{\Lambda'}{2}} \\
			 &\geq \frac{\ln\left( \frac{1}{\alpha} \right)}{a}.
\end{align*}
So if the user provides accuracy rather than $\epsilon$, we can set
\[ k = \frac{2+24 \cdot 2^{-52}}{\epsilon^{-} - 2^{-117}} \]
where $\epsilon^{-} = \frac{\ln\left( \frac{1}{\alpha} \right)}{a}$.
Notice that this $\epsilon^{-}$ follows what we would get if we were using the Laplace,
rather than Snapping.

\section{Finding $B'$}
\label{sec:finding_B_prime}
We have been assuming that we can find $B'$, the maximum value (in terms of absolute value) of a given statistic conditional on knowing
the bounds of the data. I believe that, at least for now, this will need to be done manually for each statistic
for which we want to use the Snapping Mechanism. I provide statements for a few statistics below.

\subsection{Mean}
\label{subsec:Bprime_mean}
Let $x$ be a realization of a random variable $X$ with support $[a,b]$. Then
\[ B' = \max \left( \vert a \vert, \vert b \vert \right). \]

\subsection{Sample Variance}
\label{subsec:Bprime_sample_variance}
Let $x$ be a realization of a random variable $X$ with support $[a,b]$ and sample size $n$.
We imagine two different cases: one with $n$ even and one with $n$ odd.
Note that the maximum variance when $n$ is even is higher than when $n$ is odd,
so we could simply use that as a universal bound. \newline

\textbf{Case 1: $n$ even} \newline
Let $x$ be such that it yields our largest possible variance;
exactly half of our observations $= a$ and the other half $= b$.
In this case our sample mean $\bar{x} = \frac{b+a}{2}$ and
$\forall i: \vert x_i - \frac{b+a}{2} \vert = \vert \frac{b-a}{2} \vert$. So we have
\begin{align*}
	Var(x) &= \frac{1}{n-1} \sum_{i=1}^{n} (x_i - \bar{x})^2 \\
		   &= \frac{1}{n-1} \sum_{i=1}^{n} \left(x_i - \frac{b+a}{2}\right)^2 \\
		   &= \frac{1}{n-1} \sum_{i=1}^{n} \frac{(b-a)^2}{4} \\
		   &= \left(\frac{n}{n-1}\right) \frac{(b-a)^2}{4}.
\end{align*}
Thus, we set $B' = \left(\frac{n}{n-1}\right) \frac{(b-a)^2}{4}$.

\textbf{Case 2: $n$ odd} \newline
Let $x$ have $\frac{n-1}{2}$ values $=a$, $\frac{n-1}{2}$ values $=b$, and one value $=\frac{b+a}{2}$
(wlog, call this value $x_n$). Then $\bar{x} = \frac{b+a}{2}$ and
$\forall i \neq n: \vert x_i - \frac{b-a}{2} \vert = \vert \frac{b-a}{2} \vert$, while
$\vert x_n - \frac{b+a}{2} \vert = 0$. Then we have
\begin{align*}
	Var(x) &= \frac{1}{n-1} \sum_{i=1}^{n} (x_i - \bar{x})^2 \\
		   &= \frac{1}{n-1} \sum_{i=1}^{n} \left(x_i - \frac{b+a}{2}\right)^2 \\
		   &= \frac{1}{n-1} \sum_{i=1}^{n-1} \frac{(b-a)^2}{4} + 0 \\
		   &= \frac{(b-a)^2}{4}.
\end{align*}
So, $B' = \frac{(b-a)^2}{4}$.

\subsection{Sample Covariance}
\label{subsec:Bprime_sample_covariance}
Let $x,y$ be realizations of random variables $X,Y$ with supports $[a,b], [c,d]$ (respectively)
and sample size $n$. Then we have
\[ cov(x,y) = \frac{1}{n-1} \sum_{i=1}^{n}(x_i-\bar{x})(y_i-\bar{y}) \]
where $\bar{x}, \bar{y}$ are the sample means of $x$ and $y$. The covariance is maximized
when the $x_i,y_i$ deviate from their mean to the greatest possible extent, and always do
so in the same direction. As with the sample variance, we have different cases for
even and odd $n$. \newline

\textbf{Case 1: $n$ even} \newline
Let $x$ be such that half of its observations $= a$ and the other half $= b$ so that
$\bar{x} = \frac{b+a}{2}$.
Let $y$ be such that $x_i = a \iff y_i = c$ and $x_i = b \iff y_i = d$ and note that
$\bar{y} = \frac{d+c}{2}$. WLOG, let $x_i=a, y_i=c$ for $i \in \{1,\hdots,\frac{n}{2}\}$ and
$x_i=b, y_i=d$ for $i \in \{\frac{n}{2}+1,\hdots,n\}$. Then,
\begin{align*}
	cov(x,y) &= \frac{1}{n-1} \sum_{i=1}^{n}(x_i-\bar{x})(y_i-\bar{y}) \\
			 &= \frac{1}{n-1} \sum_{i=1}^{n}\left(x_i-\frac{b+a}{2}\right)\left(y_i-\frac{d+c}{2}\right) \\
			 &= \frac{1}{n-1} \left( \sum_{i=1}^{n/2} \frac{b-a}{2} \cdot \frac{d-c}{2} + \sum_{i=n/2 + 1}^{n}\frac{a-b}{2} \cdot \frac{c-d}{2} \right) \\
			 &= \frac{1}{n-1} \left( \sum_{i=1}^{n/2} \frac{b-a}{2} \cdot \frac{d-c}{2} + \sum_{i=n/2 + 1}^{n}\frac{b-a}{2} \cdot \frac{d-c}{2} \right) \\
			 &= \frac{1}{n-1} \sum_{i=1}^{n} \frac{b-a}{2} \cdot \frac{d-c}{2} \\
			 &= \left( \frac{n}{n-1} \right) \cdot \frac{(b-a)(d-c)}{4},
\end{align*}
and so $B' = \left( \frac{n}{n-1} \right) \cdot \frac{(b-a)(d-c)}{4}$. \newline

\textbf{Case 2: $n$ odd} \newline
Let $x$ have $\frac{n-1}{2}$ values $=a$, $\frac{n-1}{2}$ values $=b$, and one value $=\frac{b+a}{2}$.
Let $x_i=a \iff y_i=c$, $x_i=b \iff y_i=d$, and $x_i=\frac{b+a}{2} \iff y_i=\frac{d+c}{2}$.
Note that $\bar{x} = \frac{b+a}{2}$ and $\bar{y} = \frac{d+c}{2}$. WLOG, let
$x_i=a, y_i=c$ for $i \in \{1,\hdots,\frac{n-1}{2}\}$,
$x_i=b, y_i=d$ for $i \in \{\frac{n-1}{2}+1,\hdots,n-1\}$, and
$x_n =\frac{b+a}{2}, y_n=\frac{d+c}{2}$. Then,
\begin{align*}
	cov(x,y) &= \frac{1}{n-1} \sum_{i=1}^{n}(x_i-\bar{x})(y_i-\bar{y}) \\
			 &= \frac{1}{n-1} \sum_{i=1}^{n}\left(x_i-\frac{b+a}{2}\right)\left(y_i-\frac{d+c}{2}\right) \\
			 &= \frac{1}{n-1} \left( \left( \sum_{i=1}^{(n-1)/2} \frac{b-a}{2} \cdot \frac{d-c}{2} \right) + \left( \sum_{i=(n-1)/2 + 1}^{n-1}\frac{a-b}{2} \cdot \frac{c-d}{2}\right) + 0 \right) \\
			 &= \frac{1}{n-1} \left( \sum_{i=1}^{(n-1)/2} \frac{b-a}{2} \cdot \frac{d-c}{2} + \sum_{i=(n-1)/2 + 1}^{n-1}\frac{b-a}{2} \cdot \frac{d-c}{2} \right) \\
			 &= \frac{1}{n-1} \sum_{i=1}^{n-1} \frac{b-a}{2} \cdot \frac{d-c}{2} \\
			 &= \frac{(b-a)(d-c)}{4},
\end{align*}
and so $B' = \frac{(b-a)(d-c)}{4}$.

\subsection{Histogram}
\label{subsec:Bprime_histogram}
For a vector of size $n$, the maximum count for any bin is $n$. So $B' = n$.

% Appendices
\begin{appendices}
	\section{Accuracy Calculations}
	\label{appendix:accuracy}
	We iterate over the possible cases for where our optimal $a$ could lie.
	We consider the sections of the PDF of $N$ representing where the bounds bind (Cases 1 and 3) as special cases, and use our bounds on
	$F_{Z}$ for the sections between the bounds.

	\textbf{Case 1:} $P_{L}^{+} \geq \alpha$ \newline
	$P_{L}^{+} \geq \alpha$ means that the largest bound ($B + f(D)$) on the noise binds with probability $\geq \alpha$.
	So, we can make no tighter accuracy guarantee at the $\alpha$ level than bounding by the greatest possible noise $B + f(D)$. \newline

	\textbf{Case 2:} Case 1 does not hold and $F^{-}_{Z}(B - f(D)) \geq 1 + P_{L}^{+} - \alpha$ \newline
	We know $a = x \leq B - f(D): F_{Z}^{-}(x) = 1 + P_{L}^{+} - \alpha$.
	\begin{align}
	              	 F_{Z}^{-}(a) &= 1 + P_{L}^{+} - \alpha \nonumber \\
		1 - \exp(-\epsilon'a + 1) &= 1 + P_{L}^{+} - \alpha \nonumber \\
		           \epsilon'a + 1 &= \ln(\alpha - P_{L}^{+}) \nonumber \\
		                        a &= \frac{1 - \ln(\alpha - P_{L}^{+})}{\epsilon'} \nonumber
	\end{align}

	\textbf{Case 3:} Case 1,2 do not hold and $F^{-}_{Z}(B - f(D)) + P_{U}^{-} \geq 1 + P_{L}^{+} - \alpha$ \newline
	This is conceptually similar to Case 1, in the sense that the probability of a bound binding (in this case, the bound if $B - f(D)$) pushes us past our
	$\alpha$ level. Similar to before, we can make an accuracy guarantee that corresponds to the binding bound, $B - f(D)$. \newline

	\textbf{Case 4:} Case 1,2,3 do not hold \newline
	We know $a =  x \in (B - f(D), B + f(D))$ such that
	\[ F_{Z}^{-}(x) - F_{Z}^{-}(B - f(D)) = 1 + P_{L}^{+} - \alpha - F_{Z}^{-}(B - f(D)) - P_{U}^{-} \]
	\begin{align}
		F_{Z}^{-}(a) - F_{Z}^{-}(B - f(D)) &= 1 + P_{L}^{+} - \alpha - F_{Z}^{-}(B - f(D)) - P_{U}^{-} \nonumber \\
							  F_{Z}^{-}(a) &= 1 + P_{L}^{+} - \alpha - P_{U}^{-} \nonumber \\
				1 - \exp(-\epsilon' a + 1) &= 1 + P_{L}^{+} - \alpha - P_{U}^{-} \nonumber \\
						  -\epsilon' a + 1 &= \ln(\alpha - P_{L}^{+} + P_{U}^{-}) \nonumber \\
						                 a &= \frac{1 - \ln(\alpha - P_{L}^{+} + P_{U}^{-})}{\epsilon'} \nonumber
	\end{align}
\end{appendices}

\end{document}