\documentclass[a4paper]{article}

\usepackage[english,ngerman]{babel}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage{amsmath}
\usepackage{subcaption}
\usepackage{icomma}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows,positioning}
\renewcommand{\u}[1]{\;\mathrm{#1}}
\newcommand{\uf}[1]{\;\mathrm{#1}}
\useshorthands*{"}
\addto\extrasenglish{\languageshorthands{ngerman}}

\begin{document}

\tikzstyle{block} = [draw, rectangle, minimum height=2em, minimum width=2em]
\tikzstyle{sum} = [draw, circle]
\tikzstyle{input} = [coordinate]
\tikzstyle{output} = [coordinate]
\tikzstyle{pinstyle} = [pin edge={to-,thin,black}]

\author{Oliver Arend}
\title{Developing an appropriate PID controller for RTVC using a Kalman filter for state estimation}
\date{2017--12}
\maketitle

\section{Model development}

\begin{figure}[b]
\begin{center}
\begin{tikzpicture}[auto,node distance=2cm,>=latex']
    \node [input] (input) {};
    \node [sum, right of=input] (sum_x) {};
    \node [block, right of=sum_x] (PID) {PID};
    \node [block, right of=PID] (rocket) {system};
    \node [output, right of=rocket] (output) {};

    \draw [->] (input) -- node {$x_0$} node [pos=0.9] {$+$} (sum_x);
    \draw [->] (sum_x) -- node {$e$} (PID);
    \draw [->] (PID) -- node {$u$} (rocket);
    \draw [->] (rocket) -- node [near start] {$x$} (output);

    \draw node at (7,0) {\textbullet};
    \draw [->] (7,0) |- (2, -1) -| node [pos=0.90] {$-$} (sum_x);
    \draw node at (6,1) {process noise $w$};
    \draw [->] (6,0.8) -| (rocket);
\end{tikzpicture}
\end{center}
\caption{Simple system including a PID controller} \label{fig:simple}
\end{figure}

\begin{figure}[t]
\begin{center}
\begin{tikzpicture}[auto,node distance=2cm,>=latex']
    \node [input] (input) {};
    \node [sum, right of=input] (sum_x) {};
    \node [block, right of=sum_x] (PID) {PID};
    \node [block, right of=PID] (servo) {servo};
    \node [block, right of=servo] (rocket) {rocket};
    \node [output, right of=rocket] (output) {};

    \draw [->] (input) -- node {$x_0$} node [pos=0.9] {$+$} (sum_x);
    \draw [->] (sum_x) -- node {$e$} (PID);
    \draw [->] (PID) -- node {$u$} (servo);
    \draw [->] (servo) -- node {$M$} (rocket);
    \draw [->] (rocket) -- node [near start] {$x$} (output);

    \draw node at (9,0) {\textbullet};
    \draw [->] (9,0) |- (2, -1) -| node [pos=0.90] {$-$} (sum_x);
    \draw node at (8,1) {process noise $w$};
    \draw [->] (8,0.8) -| (rocket);
\end{tikzpicture}
\end{center}
\caption{Separating complete system into servo and rocket subsystems} \label{fig:subsystems}
\end{figure}

Typically, a system is designed to operate in a certain state described by one or more state variables $x$. The desired state is described by the setpoint $x_0$, and the difference between these two values is the error $e$. A controller is then designed to give an input $u$ to the system such that the error is minimized. Such a system is shown in figure \ref{fig:simple}. The behavior of the system is not completely deterministic since some unknown process noise $w$ is acting on the system, hence the need for a controller.

In our case, the system is basically comprised of two subsystems, considering one axis of yaw/pitch:
\begin{enumerate}
\item The servo being controlled by the controller through the command $u$ and accordingly exerting a torque $M$ on
\item the rocket, which has certain known characteristics such as its moment of inertia $J$, but is also subject to unknown disturbances (process noise) from wind or lack of detail in the model.
\end{enumerate}
Such a system is shown in figure \ref{fig:subsystems}.

\section{PID controller design} \label{PID}

\begin{figure}[b!]
\begin{center}
\includegraphics[width=120mm]{model.png}
\end{center}
\caption{\textsc{scilab} model used for PID controller design} \label{fig:scilabmodel}
\end{figure}

A PID controller is described by three values $K_P$, $K_I$ and $K_D$ determining the output $u$ as a function of the error $e$ (in continuous form): \begin{equation}u(t) = K_P e(t) + K_I \int^t_0 e(t) dt + K_D \frac{de(t)}{dt}\end{equation}i. e. it takes into account
\begin{itemize}
\item the current magnitude of the error $e(t)$ at time $t$ and producing a proportional output with a proportionality factor $K_P$ -- the larger the error, the larger the corrective action. This in turn means that the error would never disappear entirely, hence the need for an
\item integral output. If the error accumulates over time $\int e(t) dt$ the corrective action will be greater, with a factor of $K_I$.
\item The last part is an output proportional to the current rate of change of the error $\frac{de(t)}{dt}$ with a factor of $K_D$; if it changes more quickly, the corrective action will need to be greater.
\end{itemize}
The values $K_P$, $K_I$ and $K_D$ were determined empirically using the \textsc{scilab} model shown in figure \ref{fig:scilabmodel}. It includes an environment where airspeed $V$ increases linearly from $0$ to $10\u{m/s}$ in $0.4\u{s}$ with an angle of attack $\alpha = \min \left(1.2, \frac{2\u{m/s}}{V} \right)\u{rad}$. Through this angle of attack the rocket, in particular the nosecone, creates an aerodynamic torque \begin{equation}M_{aero} = \frac{1}{2} \rho V^2 c_{A_{\alpha}} \alpha A \ell \end{equation} around its yaw/pitch axis. Air density is assumed standard conditions $\rho = 1.225 \u{kg/m^3}$, the coefficient of lift gradient is $c_{A_{\alpha}} = 2$ for nosecones, the reference section is $A = 0.00353\u{m^2}$ for a rocket diameter of $67\u{mm}$ and the moment arm $\ell = 0.1\u{m}$ as the distance between the nosecone's center of pressure and the rocket's center of gravity. The torque translates into an angular acceleration $\ddot{\gamma} = \frac{M_{aero}}{J}$ of the rocket's path $\gamma$ with the rocket's inertia $J=8.1 \cdot 10^{-4}\u{kg\,m^2}$, integrated twice to yield path angular velocity $\dot{\gamma}$ and path angle, respectively. The angular velocity results in an effective reduction of the angle of attack through moment arm and velocity $\Delta \alpha = - \frac{\ell}{V} \dot{\gamma}$.

The PID controller factors yielding a satisfactory behavior of the rocket as described above are \begin{eqnarray}
K_P & = & -5 \\
K_I & = & -5 \\
K_D & = & -1
\end{eqnarray}
with the output as the setpoint for a servo motor controlling the angle $\varphi$ (in the same unit as the path angle of the rocket) of the rocket motor relative to the longitudinal axis of the rocket.

The servo of course does not move instantaneously, but the reaction to a change in the setpoint is very similar to a PT2 element with the transfer function \begin{equation}G(s) = \frac{1}{0.000088 s^2 + 0.019 s + 1}\end{equation}corresponding to the two time constants $T_1 = 0.008\u{s}$ and $T_2=0.019\u{s}$. This behavior can also be described in the state space as \begin{equation}\dot{X} = \begin{pmatrix}0 & 1 \\ -11364 & -216\end{pmatrix} X + \begin{pmatrix}0 \\ 11364\end{pmatrix} u\label{eq:servo}\end{equation} with $X=\begin{pmatrix}\varphi \\ \dot{\varphi}\end{pmatrix}$ and $u$ the servo angle setpoint.

\section{Kalman filter design}

\begin{figure}[t]
\begin{center}
\begin{tikzpicture}[auto,node distance=2cm,>=latex']
%    \draw[help lines] (0,-2) grid (8,3);
    \node [input] (input) {};
    \node [block, minimum width=3cm, right of=input, align=center] at (0.5,0) (system) {system \\ $\dot{X} = AX+w$ \\ $Y = CX$};
    \node [sum, right=1.3cm of system] (sum_y) {};
    \node [block, right of=sum_y, align=center] (kalman) {Kalman\\filter};
    \node [output, right of=kalman] (output) {};

    \draw [->] (system) -- node {$Y$} node[pos=0.8] {$+$} (sum_y);
    \draw [->] (sum_y) -- node {$\tilde{Y}$} (kalman);

    \draw node at (2.5,1.5) {process noise $w$};
    \draw [->] (2.5,1.3) -| (system);

    \draw node at (5.5,1.5) {signal noise $v$};
    \draw [->] (5.5,1.3) -| node[pos=0.9] {$+$} (sum_y);

    \draw [->] (kalman) -- node {$\hat{X}$} (output);
\end{tikzpicture}
\end{center}
\caption{Typical Kalman filter approach} \label{fig:Kalman}
\end{figure}

A Kalman filter can be used to estimate the current state of a system by using knowledge about the behavior of the system, the quality of the measurement and of course the measurements itself. Based on this, for every timestep the filter will first predict the current state of the system and then correct this estimate based on a measurement and the prediction's certainty.
The behavior of a system can be described as \begin{eqnarray}\dot{X} &=& A X + B U + w \\
Z &=& C X + v\end{eqnarray} with the state of the system $X$, commands $U$, process noise $w$ (which includes uncertainties about the behavior of the system and unknown outside influences), measurements $Z$, measurement noise $v$ (which is more or less known) and matrices $A$, $B$, $C$ and $D$ describing the relationships between these. From a time-discrete perspective, this can also be written as \begin{eqnarray}X_i &=& A X_{i-1} + B U_i + w_{i-1} \\
Z_i &=& H X_i + v_i\end{eqnarray}The Kalman filter uses this information to estimate the system's state using two steps:\begin{description}
\item[Prediction]In this step the current state will be predicted from the last estimate according to the system's behavior \begin{eqnarray}\hat{X}^-_i &=& A \hat{X}_{i-1} + B U_i \\
P^-_i &=& A P_{i-1} A + Q\end{eqnarray} with the system error covariance matrix $Q$ and the error covariance $P$. $Q$ is unknown and can only be estimated. $P$ can be initialized to the identity matrix.
\item[Correction]The predicted state will now be corrected according to the measured values describing (part of) the state:\begin{eqnarray}K_i &=& P^-_i H^T(H P^-_i  H^T+R)^{-1} \\
\hat{X}_i &=& \hat{X}^-_i + K_i(Z_i - H\hat{X}^-_i) \\
P_i &=& (I - K_i H)P^-_i\end{eqnarray}
\end{description} A rough sketch of how a Kalman filter estimates the system's state from its measurement output(s) is shown in figure \ref{fig:Kalman}.

\subsection{Model rocket apogee detection}

As a simple first example, the Kalman filter is applied to a model rocket flying up and whose apogee should be detected. The state of the rocket can be described as \begin{equation}X = \begin{pmatrix}h\\v\\a\end{pmatrix}\end{equation}with altitude $h$, (vertical) velocity $v$ and (vertical) acceleration $a$. The evolution from one state to the next is done through simple integration with a time constant $\Delta t$. No commands $U$ are imparted to the rocket, and the measurement is simply the altitude $h$, with a measurement noise covariance of $R=0.25$. The system variables are in basic SI units (meters and seconds). The relevant matrices are thus \begin{align}A&=\begin{pmatrix}1 & \Delta t & 0 \\ 0 & 1 & \Delta t \\ 0 & 0 & 1\end{pmatrix}, &B&=0 \\ C&=\begin{pmatrix}1 & 0 & 0\end{pmatrix}, &D&=0\end{align}

\begin{figure}[b]
\centering
\begin{subfigure}[t]{0.48\textwidth}
\centering
\includegraphics[width=\textwidth]{kalman_altitude.png}
\caption{From altitude measurement only} \label{fig:altitude}
\end{subfigure}
\begin{subfigure}[t]{0.48\textwidth}
\centering
\includegraphics[width=\textwidth]{kalman_altitude_accel.png}
\caption{From both altitude and acceleration measurements} \label{fig:altitude_accel}
\end{subfigure}
\caption{Estimating altitude and apogee}
\end{figure}

Data was created with a time increment of $0.01\u{s}$ from a rocket flight simulation, with additional noise added to the altitude measurement. The results from \texttt{kal""man\_""rocket""flight\_""alti""tude"".py} are shown in figure \ref{fig:altitude}. The measured altitude is shown in light blue, and its estimate in orange. The filter reduces the noisiness quite a bit, but does not completely eliminate it ($Q=0.01 I$ was chosen). Velocity (true red, estimate green) and acceleration (true dark purple, estimate light purple) were also estimated, but do not match the true values closely. Only apogee detection, with $v=0$, would work reliably.

Results can be improved considerably using an accelerometer, hence changing the measurement matrix to \begin{equation}C=\begin{pmatrix}1 & 0 & 0 \\ 0 & 0 & 1\end{pmatrix}\end{equation} and the measurement covariance matrix to \begin{equation}R=\begin{pmatrix}0.25 & 0 \\ 0 & 1\end{pmatrix},\end{equation} assuming independent error. The results from \texttt{kal""man\_""rocket""flight\_""alti""tude\_""accel"".py} are shown in figure \ref{fig:altitude_accel}. Velocity matches very well, while the acceleration estimate takes some time to converge to the true value.

\subsection{Simple model rocket attitude control}

The actual application of the Kalman filter towards an active control of the rocket's attitude involves measuring the rocket's angular velocity and estimating its path angle, which should be kept at or very near 0. It is simplified to a single pitch/yaw axis, because both axes can be regarded as independent of each other.

A simple model would only involve a state representing the rocket's attitude and its evolution \begin{equation}X=\begin{pmatrix}\gamma \\ \dot{\gamma} \\ \ddot{\gamma} \end{pmatrix}\end{equation} with the path angle $\gamma$ and its time derivatives. Reusing the \textsc{scilab} model to design the PID controller (see section \ref{PID}), noisy data representing the angular velocity $\dot{\gamma}$ is created. For comparison, clean data for path angle $\gamma$, angular velocity and the corrective command to the servo $u$ is also exported.

\begin{figure}[t]
\centering
\begin{subfigure}[t]{0.48\textwidth}
\centering
\includegraphics[width=\textwidth]{kalman_attitude_B0.png}
\caption{Ignoring $u$ ($B=0$)} \label{fig:simple_attitude_B0}
\end{subfigure}
\begin{subfigure}[t]{0.48\textwidth}
\centering
\includegraphics[width=\textwidth]{kalman_attitude_Bdirect.png}
\caption{Translating $u$ directly to angular acceleration} \label{fig:simple_attitude_Bdirect}
\end{subfigure}
\caption{Estimating the rocket's attitude using only path angle and derivatives as state} \label{fig:simple_attitude}
\end{figure}

Two approaches were used: \begin{itemize}
\item completely ignoring the servo command in the prediction, such that \begin{equation}A = \begin{pmatrix}1 & \Delta t & 0 \\ 0 & 1 & \Delta t \\ 0 & 0 & 1\end{pmatrix}, \quad B = \begin{pmatrix}0 \\ 0 \\ 0\end{pmatrix}\end{equation}
\item and directly translating the setpoint of the servo $u$ to an angular acceleration such that \begin{equation}A = \begin{pmatrix}1 & \Delta t & 0 \\ 0 & 1 & \Delta t \\ 0 & 0 & 1\end{pmatrix}, \quad B = \begin{pmatrix}0 \\ 0 \\ \frac{Fa}{J}\end{pmatrix}\end{equation}with the motor's thrust $F$, the moment arm of the motor $a$ and the rocket's angular inertia $J$.\end{itemize}
The results of both approaches are shown in figure \ref{fig:simple_attitude}. Obviously the approach considering the torque applied by the rotating motor leads to a divergent estimate, see figure \ref{fig:simple_attitude_Bdirect}, since the servo does not actually move that fast -- the timestep in the simulation is $0.01\u{s}$, whereas the time constant of the servo is about $0.019\u{s}$. Ignoring $u$, as shown in figure \ref{fig:simple_attitude_B0}, leads to a decent estimate of the path angle $\gamma$, but some error and phase offset in angular velocity $\dot{\gamma}$ and the servo command $u$.

\subsection{Complex attitude estimate and control}

\begin{figure}[t]
\hspace{-10mm}
\begin{tikzpicture}[auto,node distance=2cm,>=latex']
    \node [input] (input) {};
    \node [sum, right of=input] (sum_x) {};
    \node [block, right of=sum_x] (PID) {PID};
    \node [block, right of=PID] (servo) {servo};
    \node [block, right of=servo] (rocket) {rocket};
    \node [sum, right of=rocket] (sum_y) {};
    \node [block, minimum height=1.5cm, minimum width=2cm, right of=sum_y, align=center] (kalman) {Kalman\\filter};
    \node [output, right of=kalman] (output) {};

    \draw [->] (input) -- node {$x_0$} node [pos=0.9] {$+$} (sum_x);
    \draw [->] (sum_x) -- node {$\hat{e}$} (PID);
    \draw [->] (PID) -- node {$u$} (servo);
    \draw [->] (servo) -- node {$M$} (rocket);
    \draw [->] (rocket) -- node {$Y$} node[pos=0.8] {$+$} (sum_y);
    \draw [->] (sum_y) -- node {$\tilde{Y}$} (kalman);
    \draw [->] (kalman) -- node {$\hat{X}$} (output);
    \draw node at (5,0) {\textbullet};
    \draw [->] (5,0) |- (10.5,-1) -| (10.5,-0.5) -- (11,-0.5);
    \draw node at (13.5,0) {\textbullet};
    \draw [->] (13.5,0) |- (2,-1.5) -| node [pos=0.9] {$-$} (sum_x);

    \draw [dashed] (5.2,0.5) rectangle (8.8,-0.5);
    \draw node at (7,1.5) {process noise $w$};
    \draw [->] (7,1.3) -| (7,0.5);

    \draw node at (10,1.5) {signal noise $v$};
    \draw [->] (10,1.3) -| node[pos=0.9] {$+$} (sum_y);
\end{tikzpicture}
\caption{Full model including PID controller, Kalman filter and system separation} \label{fig:full_attitude}
\end{figure}

A possible approach to improve the state estimate and thus the control signal is to include the servo's rotation in the state \begin{equation}X=\begin{pmatrix}\gamma \\ \dot{\gamma} \\ \ddot{\gamma} \\ \varphi \\ \dot{\varphi}\end{pmatrix}\end{equation} and to have the servo behave as described in equation \ref{eq:servo}. The system and command matrices thus change to \begin{equation}A=\begin{pmatrix}1 & \Delta t & 0 & 0 & 0 \\
0 & 1 & \Delta t & 0 & 0 \\
0 & 0 & 1 & \frac{Fa}{J} & 0 \\
0 & 0 & 0 & 1 & \Delta t \\
0 & 0 & 0 & -11364 \Delta t & 1-216 \Delta t\end{pmatrix}, \quad B = \begin{pmatrix}0 \\ 0 \\ 0 \\ 0 \\ 11364 \Delta t\end{pmatrix}\end{equation} The measurement matrix simply reflects the enlargement of the state $C=\begin{pmatrix}0 & 1 & 0 & 0 & 0\end{pmatrix}$.

\begin{figure}[b]
\centering
\begin{subfigure}[t]{0.48\textwidth}
\centering
\includegraphics[width=\textwidth]{kalman_attitude_servo_Q0_01_usaved.png}
\caption{Using saved values for $u$} \label{fig:attitude_Q001_usaved}
\end{subfigure}
\begin{subfigure}[t]{0.48\textwidth}
\centering
\includegraphics[width=\textwidth]{kalman_attitude_servo_Q0_01_ulive.png}
\caption{Calculating $u$ from state variables during runtime} \label{fig:attitude_Q001_ulive}
\end{subfigure}
\caption{Estimating the rocket's attitude using a more complex state including the servo angle} \label{fig:attitude_Q001}
\end{figure}

For comparison, the command $u$ was either taken from the simulation or calculated during runtime of \texttt{kal""man\_""atti""tude\_""servo"".py} from the state variable estimates according to the PID controller constants described in section \ref{PID}. Keeping the system error covariance as before at $Q=0.01I$, the path angle estimate diverges slightly, whereas the error on the angular velocity $\dot{\gamma}$ is rather large and, in the case of live calculation of $u$, results in a significant error. The results are shown in figure \ref{fig:attitude_Q001}.

\section{Conclusion}

Attitude estimation yields better results using a simple model only taking the path angle and its derivatives into account and regarding servo input and other ``disturbances'' as process noise. The reasons for this are unclear. Of course the \textsc{scilab} simulation is not exactly reproduced in the Kalman filter implementation, and the simple $X_{i+1} = \begin{pmatrix}1 & \Delta t & 0\end{pmatrix} X_i$ integration will diverge from the original data, which was obtained through integration by more refined methods.

The underlying question, which Kalman filter architecture and which PID controller will be able to successfully control RTVC, could not be answered with sufficient certainty.

\end{document}


The term \emph{coindexed optics} is sometimes brought up.
But what are they?
One interpretation is \emph{optics with error reporting},
i.e. which can tell why e.g. |Prism| didn't match\footnote{%
\url{https://blog.fp-tower.com/2020-01-27-introducing-error-reporting-in-optics/} looks like an example of that. In Scala.
}.
For some time I started to dislike that interpretation.
It doesn't feel right.

Recently I run into documentation of
\href{https://hackage.haskell.org/package/witherable}{\texttt{witherable}}.
There is |Wither|, which is like a lens, but not quite.
I think that is closer to what \emph{coindexed optics} could be.
(However, there are plenty arrows to flip, and you may flip others).

This blog post is a literate Haskell file, so we start with
language extensions

\begin{code}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
\end{code}

The import list is shorter,
|Data.SOP| is the only module (from
\href{https://hackage.haskell.org/package/sop-core}{\texttt{sop-core}})
which is not in \texttt{base} library.

\begin{code}
import Control.Applicative (liftA2)
import Data.Kind           (Type)
import Data.Bifunctor      (Bifunctor (first))
import Data.Char           (toUpper)
import Data.Coerce         (coerce)
import Data.SOP            (NP (..), NS (..), I (..))

import qualified Data.Maybe as L (mapMaybe)
\end{code}

I will use a variant of profunctor encoding of optics. The plan is to show
\begin{itemize}
\item ordinary, unindexed optics;
\item then indexed optics;
\item and finally coindexed optics.
\end{itemize}

\subsection{Ordinary, unindexed optics}

The profunctor encoding of optics is relatively simple.
However, instead of ordinary profunctors, we will
use a variant with additional \emph{type level list} argument.
This is similar to
\href{https://hackage.haskell.org/package/indexed-profunctors}{\texttt{indexed-profunctors}},
though there the type list is curried.
Currying works well for indexed optics, but complicates coindexed story.

\begin{code}
type Optic p (is :: [Type]) (js :: [Type]) s t a b = p is a b -> p js s t
\end{code}

To not make this post unnecessarily long,
we will use only a subset of profunctor hierarchy: |Profunctor| and |Mapping| for now.
|Profunctor| is used to encode isomorphisms (isos),
and |Mapping| is used to encode setters.

\begin{code}
class Profunctor (p :: [Type] -> Type -> Type -> Type) where
    dimap :: (a -> b) -> (c -> d) -> p is b c -> p is a d

class Profunctor p => Mapping p where
    roam :: ((a -> b) -> s -> t) -> p is a b -> p is s t
\end{code}

A go to example of a setter is |mapped|.
With |mapped| we can set, or map over, elements in a |Functor|.

\begin{code}
mapped :: (Mapping p, Functor f)
       => Optic p is is (f a) (f b) a b
mapped = roam fmap
\end{code}

To implement the |over| operation we need a concrete profunctor.
If we used ordinary profunctors, the function arrow would do.
In this setup we need a newtype to adjust the kind:

\begin{code}
newtype FunArrow (is :: [Type]) a b =
    FunArrow { runFunArrow :: a  -> b }
\end{code}

Instance implementations are straight forward:

\begin{code}
instance Profunctor FunArrow where
    dimap f g (FunArrow k) = FunArrow (g . k . f)

instance Mapping FunArrow where
    roam f (FunArrow k) = FunArrow (f k)
\end{code}

Using |FunArrow| we can implement |over|.
|over| uses a setter to map \emph{over} focused elements in a bigger structure.
Note, we allow any index type-lists.
We (or rather |FunArrow|) simply ignore them.

\begin{code}
over :: Optic FunArrow is js s t a b
     -> (a -> b)
     -> (s -> t)
over o f = runFunArrow (o (FunArrow f))
\end{code}

Some examples, to show it works what we have written so far.
|over mapped| is a complicated way to say |fmap|:

\begin{code}
-- "FOOBAR"
example01 :: String
example01 = over mapped toUpper "foobar"
\end{code}

Optics compose. |over (mapped . mapped)| maps over two composed functors:

\begin{code}
-- ["FOOBAR","XYZZY"]
example02 :: [String]
example02 = over (mapped . mapped) toUpper ["foobar", "xyzzy"]
\end{code}

This was a brief refresher of profunctor optics.
It is "standard", except that we added an additional
type-level list argument to the profunctors.

We will next use that type-level list to implement indexed optics.

\subsection{Indexed optics}

Indexed optics let us set, map, traverse etc. using an additional index.
The operation we want to generalize with optics is provided
by few classes, like |FunctorWithIndex|:

\begin{code}
class Functor f => FunctorWithIndex i f | f -> i where
    imap :: (i -> a -> b) -> f a -> f b
\end{code}

|imap| operation is sometimes called |mapWithKey| (for example
in |containers| library).

Ordinary lists are indexed with integers. |Map k v| is indexed with |k|.
We will use lists in the examples, so let us define an instance:

\begin{code}
instance FunctorWithIndex Int [] where
    imap f = zipWith f [0..]
\end{code}

Next, we need to make that available in optics framework.
New functionality means new profunctor type class.
Note how an indexed combinator conses the index to the list.

\begin{code}
class Mapping p => IMapping p where
    iroam :: ((i -> a -> b) -> s -> t) -> p (i ': is) a b -> p is s t
\end{code}

Using |iroam| and |imap| we can define |imapped|,
which is an example of \emph{indexed setter}.

\begin{code}
imapped :: (FunctorWithIndex i f, IMapping p)
        => p (i ': is) a b -> p is (f a) (f b)
imapped = iroam imap
\end{code}

Here, we should note that |FunArrow| can be given an instance of |IMapping|.
We simply ignore the index argument.

\begin{code}
instance IMapping FunArrow where
    iroam f (FunArrow k) = FunArrow (f (\_ -> k))
\end{code}

That allows us to use |imapped| instead of |mapped|.
(both \texttt{optics} and \texttt{lens} libraries have tricks to make that efficient).

\begin{code}
-- ["FOOBAR","XYZZY"]
example03 :: [String]
example03 = over (mapped . imapped) toUpper ["foobar", "xyzzy"]
\end{code}

To actually use indices, we need new concrete profunctor.
The |IxFunArrow| takes a heterogeneous list, |NP I| (n-ary product),
of indices in addition to the element as an argument of an arrow.

\begin{code}
newtype IxFunArrow is a b =
    IxFunArrow { runIxFunArrow :: (NP I is, a) -> b }
\end{code}

The |IxFunArrow| instances are similar to |FunArrow| ones,
they involve just a bit of additional plumbing.

\begin{code}
instance Profunctor IxFunArrow where
    dimap f g (IxFunArrow k) = IxFunArrow (g . k . fmap f)

instance Mapping IxFunArrow where
    roam f (IxFunArrow k) = IxFunArrow (\(is, s) -> f (\a -> k (is, a)) s)
\end{code}

|IMapping| instance is the most interesting.
As the argument provides an additional index |i|,
it is consed to the the list of existing indices.

\begin{code}
instance IMapping IxFunArrow where
    iroam f (IxFunArrow k) = IxFunArrow $
        \(is, s) -> f (\i a -> k (I i :* is, a)) s
\end{code}

As I already mentioned, \texttt{indexed-profunctors} uses curried
variant, so the index list is implicitly encoded in uncurried
form |i1 -> i2 -> ...|.
That is clever, but hides the point.

Next, the indexed |over|.
The general variant takes an optic with any indices list.

\begin{code}
gen_iover :: Optic IxFunArrow is '[] s t a b
         -> ((NP I is, a) -> b)
         -> s -> t
gen_iover o f s = runIxFunArrow (o (IxFunArrow f)) (Nil, s)
\end{code}

Usually we use the single-index variant, |iover|:

\begin{code}
iover :: Optic IxFunArrow '[i] '[] s t a b
      -> (i -> a -> b)
      -> s -> t
iover o f = gen_iover o (\(I i :* Nil, a) -> f i a)
\end{code}

We can also define the double-index variant, |iover2| (and so on).

\begin{code}
iover2 :: Optic IxFunArrow '[i,j] '[] s t a b
       -> (i -> j -> a -> b)
       -> (s -> t)
iover2 o f = gen_iover o (\(I i :* I j :* Nil, a) -> f i j a)
\end{code}

Lets see what we can do with indexed setters.
For example we can upper case every odd character in the string:

\begin{code}
-- "fOoBaR"
example04 :: String
example04 = iover imapped (\i a -> if odd i then toUpper a else a) "foobar"
\end{code}

In nested case, we have access to all indices:

\begin{code}
-- ["fOoBaR","XyZzY","uNoRdErEd-cOnTaInErS"]
example05 :: [String]
example05 = iover2
    (imapped . imapped)
    (\i j a -> if odd (i + j) then toUpper a else a)
    ["foobar", "xyzzy", "unordered-containers"]
\end{code}

We don't need to index at each step,
e.g. we can index only at the top level:

\begin{code}
-- ["foobar","XYZZY","unordered-containers"]
example06 :: [String]
example06 = iover
    (imapped . mapped)
    (\i a -> if odd i then toUpper a else a)
    ["foobar", "xyzzy", "unordered-containers"]
\end{code}

Indexed optics are occasionally very useful.
We can provide extra information in indices,
which would otherwise not fit into optical frameworks.

\section{Coindexes}

The indexed optics from previous sections can be flipped to be coindexed ones.
As I mentioned in the introduction, I got an idea at looking at
\href{https://hackage.haskell.org/package/witherable}{\texttt{witherable}}.
package.

\texttt{witherable} provides (among many things) a useful type-class,
in a simplified form:

\begin{code}
class Functor f => Filterable f where
    mapMaybe :: (a -> Maybe b) -> f a -> f b
\end{code}

It is however too simple. (Hah!).
The connection to indexed optics is easier to see using
an |Either| variant:

\begin{code}
class Functor f => FunctorWithCoindex j f | f -> j where
    jmap :: (a -> Either j b) -> f a -> f b
\end{code}

We'll also need a |Traversable| variant (|Witherable| in \texttt{witherable}):

\begin{code}
class (Traversable f, FunctorWithCoindex j f)
    => TraversableWithCoindex j f | f -> j
  where
    jtraverse :: Applicative m => (a -> m (Either j b)) -> f a -> m (f b)
\end{code}

Instances for list are not complicated.
The \emph{coindex} of list is a unit |()|.

\begin{code}
instance FunctorWithCoindex () [] where
    jmap f = L.mapMaybe (either (const Nothing) Just . f)

instance TraversableWithCoindex () [] where
    jtraverse _ [] = pure []
    jtraverse f (x:xs) = liftA2 g (f x) (jtraverse f xs) where
        g (Left ()) ys = ys
        g (Right y) ys = y : ys
\end{code}

With "boring" coindex, like the unit, we can recover |mapMaybe|:

\begin{code}
mapMaybe' :: FunctorWithCoindex () f => (a -> Maybe b) -> f a -> f b
mapMaybe' f = jmap (maybe (Left ()) Right . f)
\end{code}

With |TraversableWithCoindex| class, doing the same tricks as previously
with indexed optics, we get coindexed optics. Easy.

I didn't manage to get |JMapping| (a coindexed mapping) to work,
so I'll use |JTraversing|.
We abuse the index list for coindices.

\begin{code}
class Profunctor p => Traversing p where
    wander :: (forall f. Applicative f => (a -> f b) -> s -> f t)
           -> p js a b -> p js s t

class Traversing p => JTraversing p where
    jwander
        :: (forall f. Applicative f => (a -> f (Either j b)) -> s -> f t)
        -> p (j : js) a b -> p js s t
\end{code}

Using |JTraversing| we can define our first coindexed optic.

\begin{code}
traversed :: (Traversable f, Traversing p) => p js a b -> p js (f a) (f b)
traversed = wander traverse

jtraversed :: (TraversableWithCoindex j f, JTraversing p)
           => p (j : js) a b -> p js (f a) (f b)
jtraversed = jwander jtraverse
\end{code}

To make use of it we once again need a concrete profunctor.

\begin{code}
newtype CoixFunArrow js a b = CoixFunArrow
    { runCoixFunArrow :: a -> Either (NS I js) b }

instance Profunctor CoixFunArrow where
    dimap f g (CoixFunArrow p) = CoixFunArrow (fmap g . p . f)

instance Traversing CoixFunArrow where
    wander f (CoixFunArrow p) = CoixFunArrow $ f p

instance JTraversing CoixFunArrow where
    jwander f (CoixFunArrow p) = CoixFunArrow $ f (plumb . p) where
        plumb :: Either (NS I (j : js)) b -> Either (NS I js) (Either j b)
        plumb (Right x)        = Right (Right x)
        plumb (Left (Z (I y))) = Right (Left y)
        plumb (Left (S z))     = Left z
\end{code}

Interestingly, |Traversing CoixFunArrow| instance looks like
|Mapping FunArrow|, and it seems to be impossible to write |Mapping IxFunArrow|.

Anyway, next we define a coindexed |over|, which I unimaginatively call |jover|.
Like in the previous section, I start with a generic version first.

\begin{code}
gen_jover
    :: Optic CoixFunArrow is '[] s t a b
    -> (a -> Either (NS I is) b) -> s -> t
gen_jover o f s = either nsAbsurd id
                $ runCoixFunArrow (o (CoixFunArrow f)) s

jover
    :: Optic CoixFunArrow '[i] '[] s t a b
    -> (a -> Either i b) -> s -> t
jover o f = gen_jover o (first (Z . I) . f)

jover2
    :: Optic CoixFunArrow '[i,j] '[] s t a b
    -> (a -> Either (Either i j) b)
    -> s -> t
jover2 o f = gen_jover o (first plumb . f) where
    plumb (Left i)  = Z (I i)
    plumb (Right j) = S (Z (I j))
\end{code}

And now the most fun: the coindexed optics examples.
First we can recover the |mapMaybe| behavior:

\begin{code}
-- ["foobar"]
example07 :: [String]
example07 = jover jtraversed
    (\s -> if length s > 5 then Right s else Left ())
    ["foobar", "xyzzy"]
\end{code}

And because we have separate coindexes in the type level list,
we can filter on the different levels of the structure!
If we find a character |'y'|, we skip the whole
word, otherwise we skip all vowels.

\begin{code}
-- ["fbr","nrdrd-cntnrs"]
example08 :: [String]
example08 = jover2 (jtraversed . jtraversed)
    predicate
    ["foobar", "xyzzy", "unordered-containers"]
  where
    predicate 'y'           = Left (Right ())  -- skip word
    predicate c | isVowel c = Left (Left ())   -- skip character
    predicate c             = Right c

isVowel :: Char -> Bool
isVowel c = elem c ['a','o','u','i','e']
\end{code}

Note, the coindex doesn't need to mean filtering.
For example, consider the following type:

\begin{code}
newtype JList j a = JList { unJList :: [Either j a] }
  deriving (Functor, Foldable, Traversable, Show)
\end{code}

It's not |Filterable|, but it can write a |FunctorWithCoindex| instance:

\begin{code}
instance FunctorWithCoindex j (JList j) where
    jmap f (JList xs) = JList (map (>>= f) xs) where

instance TraversableWithCoindex j (JList j) where
    jtraverse f (JList xs) = fmap JList (go xs) where
        go []             = pure []
        go (Left j : ys)  = fmap (Left j :) (go ys)
        go (Right x : ys) = liftA2 (:) (f x) (go ys)
\end{code}

Using |JList| we can do different things.
In this example, we return why elements didn't match,
but that information is returned embedded inside the structure itself.
We "filter" long strings:

\begin{code}
jlist :: [a] -> JList j a
jlist = JList . map Right

ex_jlist_a :: JList Int String
ex_jlist_a = jlist ["foobar", "xyzzy", "unordered-containers"]

-- JList {unJList = [Left 6,Right "xyzzy",Left 20]}
example09 :: JList Int String
example09 = jover jtraversed
    (\s -> let l = length s in if l > 5 then Left l else Right s)
    ex_jlist_a
\end{code}

Similarly we can filter, or rather "change structure", on different levels,
and these levels can have different coindices:

\begin{code}
ex_jlist_b :: JList Int (JList Bool Char)
ex_jlist_b = fmap jlist ex_jlist_a

example88b :: JList Int (JList Bool Char)
example88b = jover2
    (jtraversed . jtraversed)
    predicate
    ex_jlist_b
  where
    predicate 'x'           = Left (Right 0)
    predicate 'y'           = Left (Right 1)
    predicate 'z'           = Left (Right 2)
    predicate c | isVowel c = Left (Left (c == 'o'))
    predicate c             = Right c

{-
[ Right [Right 'f',Left True,Left True,Right 'b',Left False,Right 'r']
, Left 0
, Right [Left False,Right 'n',Left True,Right 'r',Right 'd',Left False, ...
]
-}
example88b' :: [Either Int [Either Bool Char]]
example88b' = coerce example88b
\end{code}

The |"xyzzy"| is filtered immediately, we see |Left 0| as a reason.
We can also see how vowels are filtered, and |'o'| are marked specifically
with |Left True|.

Having coindices reside inside the structure makes composition just work.
That what makes this different from "error reporting optics".
And using coindices approach we can compose filters,
the |Wither| from \texttt{witherable} doesn't seem to compose
with itself.

\section{Both}

Obvious follow up question is whether we can have both indices and coindices.
Why not, the concrete profunctor would look like:

\begin{code}
newtype DuplexFunArrow is js a b = DuplexFunArrow
    { runDuplexFunArrow :: (NP I is, a) -> Either (NS I js) b }
\end{code}

Intuitively, the structure traversals would provide additional
information in indices, and we'll be able to alter it by optionally
returning coindices.

Would that be useful? I have no idea.

\appendix

\section{Utilities}

\begin{code}
nsAbsurd :: NS I '[] -> a
nsAbsurd x = case x of {}
\end{code}


%!TEX root = ../thesis.tex
%*******************************************************************************
%****************************** Second Chapter *********************************
%*******************************************************************************

\chapter{Concept}

\ifpdf
    \graphicspath{{Chapter2/Figs/Raster/}{Chapter2/Figs/PDF/}{Chapter2/Figs/}}
\else
    \graphicspath{{Chapter2/Figs/Vector/}{Chapter2/Figs/}}
\fi

\fbox{
    \parbox{\textwidth}
    {
        Chapter Overview
        \begin{itemize}
            \item Bayesian \acp{cnn} with Variational Inference based on Bayes by Backprop.
            \item Bayesian convolutional operations with mean and variance
            \item Local reparameterization trick for Bayesian \acp{cnn}.
            \item Uncertainty estimation in a Bayesian network.
            \item Using L1 norm for reducing the number of parameters in a Bayesian network.
        \end{itemize}
    }
}

\pagebreak

\section{Bayesian Convolutional Neural Networks with Variational Inference}
In this section, we explain our algorithm of building a \ac{cnn} with probability distributions over its weights in each filter, as seen in Figure \ref{fig:filter_scalar}, and apply variational inference, i.e. \textit{Bayes by Backprop}, to compute the intractable true posterior probability distribution, as described in the last Chapter. Notably, a fully Bayesian perspective on a \ac{cnn} is for most \ac{cnn} architectures not accomplished by merely placing probability distributions over weights in convolutional layers; it also requires probability distributions over weights in fully-connected layers (see Figure \ref{fig:CNNwithdist_grey}).
%
\begin{figure}[H]
\centering
\begin{minipage}{.4\textwidth}
\centering
\includegraphics[width=\linewidth]{Chapter4/Figs/filter_scalars.png}
\end{minipage}
%
\begin{minipage}{.4\textwidth}
\centering
\includegraphics[width=\linewidth]{Chapter4/Figs/CNNwithdist.png}
\end{minipage}
\caption{Input image with exemplary pixel values, filters, and corresponding output with point-estimates (top) and probability distributions (bottom) over weights.\cite{shridhar2018bayesian}}
\label{fig:filter_scalar}
\end{figure}
%
\begin{figure}[b!]
\begin{center}
\includegraphics[width=\linewidth]{Chapter4/Figs/CNNwithdist_grey.png}
\caption{Fully Bayesian perspective of an exemplary CNN. Weights in filters of convolutional layers, and weights in fully-connected layers have the form of a probability distribution. \cite{shridhar2018bayesian}}
\label{fig:CNNwithdist_grey}
\end{center}
\end{figure}
%
\subsection{Local Reparameterization Trick for Convolutional Layers}
We utilise the local reparameterization trick \cite{kingma2015variational} and apply it to \acp{cnn}. Following \cite{kingma2015variational,neklyudov2018variance}, we do not sample the weights $w$, but we sample instead layer activations $b$ due to its consequent computational acceleration. The variational posterior probability distribution $q_{\theta}(w_{ijhw}|\mathcal{D})=\mathcal{N}(\mu_{ijhw},\alpha_{ijhw}\mu^2_{ijhw})$ (where $i$ and $j$ are the input, respectively output layers, $h$ and $w$ the height, respectively width of any given filter) allows to implement the local reparamerization trick in convolutional layers. This results in the subsequent equation for convolutional layer activations $b$:
\begin{equation}
    b_j=A_i\ast \mu_i+\epsilon_j\odot \sqrt{A^2_i\ast (\alpha_i\odot \mu^2_i)}
\end{equation}
where $\epsilon_j \sim \mathcal{N}(0,1)$, $A_i$ is the receptive field, $\ast$ signalises the convolutional operation, and $\odot$ the component-wise multiplication.

\subsection{Applying two Sequential Convolutional Operations (Mean and Variance)}
The crux of equipping a \ac{cnn} with probability distributions over weights instead of single point-estimates and being able to update the variational posterior probability distribution $q_{\theta}(w|\mathcal{D})$ by backpropagation lies in applying \textit{two} convolutional operations whereas filters with single point-estimates apply \textit{one}. As explained in the last chapter, we deploy the local reparametrization trick and sample from the output $b$. Since the output $b$ is a function of mean $\mu_{ijwh}$ and variance $\alpha_{ijhw}\mu^2_{ijhw}$ among others, we are then able to compute the two variables determining a Gaussian probability distribution, namely mean $\mu_{ijhw}$ and variance $\alpha_{ijhw}\mu^2_{ijhw}$, separately.
\newline We do this in two convolutional operations: in the first, we treat the output $b$ as an output of a \ac{cnn} updated by frequentist inference. We optimize with Adam \cite{kingma2014adam} towards a single point-estimate which makes the validation accuracy of classifications increasing. We interpret this single point-estimate as the mean $\mu_{ijwh}$ of the variational posterior probability distributions $q_{\theta}(w|\mathcal{D})$. In the second convolutional operation, we learn the variance $\alpha_{ijhw}\mu^2_{ijhw}$. As this formulation of the variance includes the mean $\mu_{ijwh}$, only $\alpha_{ijhw}$ needs to be learned in the second convolutional operation \cite{molchanov2017variational}. In this way, we ensure that only one parameter is updated per convolutional operation, exactly how it would have been with a \ac{cnn} updated by frequentist inference.
\newline In other words, while we learn in the first convolutional operation the MAP of the variational posterior probability distribution $q_{\theta}(w|\mathcal{D})$, we observe in the second convolutional operation how much values for weights $w$ deviate from this MAP. This procedure is repeated in the fully-connected layers. In addition, to accelerate computation, to ensure a positive non-zero variance $\alpha_{ijhw}\mu^2_{ijhw}$, and to enhance accuracy, we learn $\log \alpha_{ijhw}$ and use the \textit{Softplus} activation function as further described in the Experiments section.
%
\section{Uncertainty Estimation in CNN}
In classification tasks, we are interested in the predictive distribution $p_{\mathcal{D}}(y^*|x^*)$, where $x^*$ is an unseen data example and $y^*$ its predicted class. For a Bayesian neural network, this quantity is given by:
\begin{align}
p_{ \mathcal{D}}(y^*|x^*) = \int p_{w}(y^*|x^*) \ p_{\mathcal{D}}(w) \ dw
\end{align}
%
In \textit{Bayes by Backprop}, Gaussian distributions $q_{\theta}(w|\mathcal{D}) \sim \mathcal{N}(w|\mu, \sigma^2)$, where $\theta = \{ \mu, \sigma \}$ are learned with some dataset $\mathcal{D} = \{ x_{i}, y_{i} \}_{i=1}^{n}$ as we explained previously. Due to the discrete and finite nature of most classification tasks, the predictive distribution is commonly assumed to be a categorical. Incorporating this aspect into the predictive distribution gives us
\begin{align}
p_{\mathcal{D}}(y^*|x^*)& = \int \text{Cat}(y^*|f_w(x^*)) \mathcal{N}(w|\mu, \sigma^2) \ dw\\
&=  \int \prod_{c=1}^{C} f(x_{c}^*|w)^{y_{c}^*} \frac{1}{\sqrt{2\pi \sigma^2}} e^{-\frac{(w - \mu)^2}{2\sigma^2}} \ dw
\end{align}
where $C$ is the total number of classes and $\sum_c f(x_{c}^*|w) = 1$.
\newline As there is no closed-form solution due to the lack of conjugacy between categorical and Gaussian distributions, we cannot recover this distribution. However, we can construct an unbiased estimator of the expectation by sampling from $q_{\theta}(w|\mathcal{D})$:
\begin{align}
\mathbb{E}_{q}[p_{\mathcal{D}}(y^*|x^*)] &= \int q_{\theta}(w|\mathcal{D}) \ p_w(y|x) \ dw \\ & \approx \frac{1}{T}\sum_{t=1}^{T} p_{w_t}(y^*|x^*)
\end{align}
where $T$ is the pre-defined number of samples.
This estimator allows us to evaluate the uncertainty of our predictions by the definition of variance, hence called \textit{predictive variance} and denoted as $\text{Var}_q$:
\begin{align} \label{variance}
\text{Var}_q\big( p(y^*|x^*) \big) = \mathbb{E}_q[yy^T] - \mathbb{E}_q[y]\mathbb{E}_q[y]^T
\end{align}
This quantity can be decomposed into the aleatoric and epistemic uncertainty \cite{kendall2017uncertainties,kwon2018uncertainty}.
\begin{equation}
    \begin{aligned}
    \text{Var}_q\big( p(y^*|x^*) \big) &= \underbrace{\frac{1}{T} \sum_{t=1}^T \text{diag}(\hat{p}_t)-\hat{p}_t \ \hat{p}_t^T}_\text{aleatoric} \\ &+ \underbrace{\frac{1}{T}\sum_{t=1}^T (\hat{p}_t - \Bar{p}) (\hat{p}_t - \Bar{p})^T}_\text{epistemic}
    \end{aligned}
\end{equation}
where $\Bar{p} = \frac{1}{T}\sum_{t=1}^T \hat{p}_t$ and $\hat{p}_t = \text{Softmax}\big ( f_{w_{t}}(x^*) \big )$.

\begin{figure}[H]
\centering
\begin{minipage}{.4\textwidth}
\centering
\includegraphics[width=\linewidth]{Chapter4/Figs/det.pdf}
\end{minipage}
%
\begin{minipage}{.4\textwidth}
\centering
\includegraphics[width=\linewidth]{Chapter4/Figs/bbb.pdf}
\end{minipage}
\caption{Predictive distributions is estimated for a low-dimensional active learning task. The predictive distributions are visualized as mean and two standard deviations shaded. \textcolor{blue}{$\blacksquare$} shows the epistemic uncertainty and \textcolor{red}{$\blacksquare$} shows the aleatoric noise. Data points are shown in \textcolor{grey}{$\blacksquare$}.
\textbf{(Left)} A deterministic network conflates uncertainty as part of the noise and is overconfident outside of the data distribution.
\textbf{(Right)} A variational Bayesian neural network with standard normal prior represents uncertainty and noise separately but is overconfident outside of the training distribution as defined by \cite{hafner2018reliable}}
\label{fig:filter_scalar}
\end{figure}

\newline It is of paramount importance that uncertainty is split into aleatoric and epistemic quantities since it allows the modeller to evaluate the room for improvements: while aleatoric uncertainty (also known as statistical uncertainty) is merely a measure for the variation of ("noisy") data, epistemic uncertainty is caused by the model. Hence, a modeller can see whether the quality of the data is low (i.e. high aleatoric uncertainty), or the model itself is the cause for poor performances (i.e. high epistemic uncertainty). The former cannot be improved by gathering more data, whereas the latter can be done so. \cite{Kiureghian} \cite{kendall2017uncertainties}.

\section{Model Pruning}

Model pruning means the reduction in the model weights parameters to reduce the model overall non-zero weights, inference time and computation cost. In our work, a Bayesian Convolutional Network learns two weights, i.e: the mean and the variance compared to point estimate learning one single weight. This makes the overall number of parameters of a Bayesian Network twice as compared to the parameters of a point estimate similar architecture.

To make the Bayesian \acp{cnn} parameters equivalent to point estimate architecture, the number of filters in the Bayesian architectures is reduced to half. This makes up for the double learned parameters (mean and variance) against one in point estimates and makes the overall parameters equal for both networks.

Another technique used is the usage of the \textit{L1 normalization} on the learned weights of every layer.  By L1 norm, we make the vector of learned weight in various model layers very sparse, as most of its components become close to zero, and at the same time, the remaining non-zero components capture the most important features of the data. We put a threshold and make the weights to be zero if the value falls below the threshold. We only keep the non zero weights and this way the model number of parameters is reduced without affecting the overall performance of the model.


\chapter[Linear Systems]{Linear Systems}
\begin{moduleinfo}
\item[Authors] {Srikrishna Sridhar}
\item[History]
	\begin{modulehistory}
		\item[v1.0] Initial version
	\end{modulehistory}
\end{moduleinfo}

\section{Introduction}\label{sec:intro}
In this document, we describe solution methods for systems of a consistent
linear equations.
\begin{equation}
  \label{eq:linear_system}
  Ax = b
\end{equation}
where $x \in \R^{n}$, $A \in \R^{m \times n}$ and $b \in \R^{m}$. We assume
that all rows of $A$ are non-zero. We denote the rows of $A$ and $b$
by $a^T_i$ and $b_i$, respectively. This can be written
as
\begin{alignat}{2}
A &= \begin{bmatrix} a^T_1 \  a^T_2  \  \ldots \  a^T_m   \end{bmatrix} \ \ \ \
b &&= \begin{bmatrix} b_1  \  b_2   \ \ldots \  b_m   \end{bmatrix}
\end{alignat}

The algorithms discussed in this document are suitable for large sparse
linear systems which are expensive for ordinary elimination. Amongst the many methods for
iteratively solving linear systems, algorithms like the Jacobi and over-relaxation
methods not as effective as methods like conjugate gradient. The preconditioned
conjugate gradient (CG) method is one of the most commonly used algorithms for
solving large sparse systems for symmetric $A$. The textbook CG algorithm has been modified
to be applicable even when $A$ is not symmetric. The disadvantage of CG is that
in each iteration, it must perform a matrix-vector product. To avoid this computation,
some applications implement a new algorithm called the randomized Kaczmarz (RK)
algorithm. It is a popular choice for extremely large scale applications.
The algorithm is known to have a linear convergence rate and each iteration
requires an $O(n)$ operation. In some applications, it outperforms CG. In
general, it is be difficult to predict which one of CG or RK is preferable
for a given linear system.

We now discuss three different approaches to solve linear systems. Direct method,
Conjugate Gradient and Randomized Kaczmarz. Each method has its own advantages
and disadvantages which will be highlighted.

\section{Direct Methods}
Direct methods are suitable for solving small linear systems that fit completely
in memory. The workhorse of several commercial codes is the LU decomposition.
The LU decomposition factors a matrix as the product of a lower triangular matrix
($L$) and an upper triangular matrix ($U$) such that
$$
PA = LU
$$
where $P$ is a permutation matrix which re-orders the rows of $A$. Such an
LU-decomposition can be used to solve \eqref{eq:linear_system} using
$$
  Ax = b \Rightarrow LUx = Pb
$$

Now, we can solve for $x$ using the following steps
\begin{enumerate}
  \item Solve for $y$ in the equation $Ly = Pb$
  \item Solve for $x$ in the equation $Ux = b$
\end{enumerate}
Since both $L$ and $U$ are triangular matrices, we can efficiently solve both
the equations directly using forward and backward substitutions.

The main advantage of solving linear systems with direct methods is that direct
methods are independent of the conditioning of the system. Solve time depends
purely on the sparsity and size of the matrices. The major disadvantage is
that the LU-decomposition has large memory requirements. Even when the matrix
$A$ is sparse, the $L$ and $U$ factors might be dense. The large memory
requirements make it unsuitable for solving large or very sparse linear
systems.

\section{Iterative Methods}
In solving \eqref{eq:linear_system} a convergent iterative method starts
with an initial estimate $x_0$ of the solution and generates a sequence of iterates
$x_k$ that are successively closer to the solution $x^*$. Iterative methods
are often useful even for linear problems involving a large number of variables.
Amongst the many iterative methods, we will review the two most popular methods;
the conjugate gradient method (CG) and the randomized Kaczmarz (RK) method.

\subsection{Conjugate Gradient (CG)}
The linear conjugate gradient method (not to be confused with the non-linear
conjugate gradient method) to solve large sparse linear systems with a
{\it symmetric positive definite} $A$ matrix. Such a system can be stated as:
\begin{equation}
  \label{eq:sym_linear_system}
  Ax = b
\end{equation}
where $x \in \R^{n}$, $A \in \R^{n \times n}$ is symmetric and positive
definite and $b \in \R^{n}$.

Unlike direct methods, the time taken to solve a linear system using CG depends on the
distribution of the eigenvalues of the $A$ matrix. In some applications,
the $A$ matrix is appropriately scaled by a process called pre-conditioning to
generate an equivalent system with a more favorable distribution of eigenvalues.

The system \eqref{eq:sym_linear_system} can be restated as the quadratic minimization
$$
  \min \phi(x) := \frac{1}{2} x^T A^T A x - b^T x
$$
which allows us to interpret CG as an algorithm to minimize convex quadratic
functions. In the rest of this section, we will refer to the gradient $\nabla \phi(x)$
as the residual of the linear system:
$$
  \nabla \phi(x) := r(x) := Ax - b
$$
The linear conjugate gradient method generates a sequence of directions ${p_0, p_1 \ldots p_l}$
that satisfy an important property called conjugacy which implies that the method
can minimize the function $\phi(x)$ in exactly $n$ steps. We refer the reader
to the textbook by Nocedal and Wright \cite{nocedal2006numerical} for details on the
theoretical and algorithmic aspects of CG.

We now discuss an efficient implementation of the linear CG algorithm. In each,
iteration ($k$), we keep track of the direction vector $p_k$, the residual
vector $r_k$ and the solution vector $x_k$. The computational bottleneck
is in a matrix-vector multiplication between $A$ and $p$.

\begin{algorithm}%
% [Conjugate gradient for symmetric positive definite linear systems]
% \caption{Conjugate gradient for symmetric positive definite linear systems.}\label{alg:cg}
\alginput{Symmetric matrix $A \in \R{m \times n}$, $b \in \R{m}$}
\algoutput{Solution to $Ax=b$}
\begin{algorithmic}[1]
  \State Choose $x_0 \in \R^n$, $r_0 \leftarrow Ax_0$, $p_0 \leftarrow -r_0$, $k \leftarrow 0$
  \While{$\norm{r_k} \leq \epsilon$}
    \State$z_k \leftarrow Ap_k$
    \State$\alpha_k \leftarrow \frac{r_k^T r_k}{p_k^T z_k}$
    \State$x_{k+1} \leftarrow x_k + \alpha_k p_k$
    \State$r_{k+1} \leftarrow r_k + \alpha_k z_k$
    \State$\beta_k \leftarrow \frac{r_{k+1}^T r_{k+1}}{r_k^T r_k}$
    \State$p_{k+1} \leftarrow -r_{k+1} + \beta_{k+1} p_k$
    \State$k = k + 1$
  \EndWhile
\end{algorithmic}
\label{alg:cg}
\end{algorithm}

The conjugate gradient method is suitable for large sparse linear systems where
direct methods can often run into memory bottlenecks. This is mainly because,
the only memory requirements of the CG method is to store the latest copies
of the vectors $p_k$, $r_k$ and $x_k$. The majority of the computational efforts
are spent in the step $z_k \leftarrow A p_k$. Hence, CG tends to perform better
in sparse linear systems.

\subsubsection*{Conjugate gradient Least Squares (CGLS)}
In this section, we will extend the CG algorithm to be numerically suited to any linear system of the form
\eqref{eq:linear_system}. The naive extension of CG to \eqref{eq:sym_linear_system}
solves $A^TAx = A^Tb$. In addition to requiring an expensive matrix-matrix
multiplication algorithm, it has it use of vectors of the form $A^TAp$. An
algorithm with better numerical properties was developed by Hestenes et. al \cite{hestenes1952methods}.

\begin{algorithm}
% \caption{Conjugate Gradient (least squares) for general linear systems.} \label{alg:cgls}
\alginput{Matrix $A \in \R{m \times n}$, $b \in \R{m}$}
\algoutput{Solution to $Ax=b$}
\begin{algorithmic}[1]
\State Choose $x_0 \in \R^n$, $r_0 \leftarrow b$,\ $s_0 \leftarrow A^Tb$, $p_0 \leftarrow s_0$, $\gamma_0=\norm{s_0}^2$, $k \leftarrow 0$
\While{$\norm{r_k} \leq \epsilon$}
  \State$z_k \leftarrow Ap_k$
  \State$\alpha_k \leftarrow \frac{\gamma_{k}}{z_k^Tz_k}$
  \State$x_{k+1} \leftarrow x_k + \alpha_k p_k$
  \State$r_{k+1} \leftarrow r_k - \alpha_k z_k$
  \State$s_{k+1} \leftarrow A^T r_{k+1} $
  \State$\gamma_{k+1} \leftarrow s_{k+1}^T s_{k+1}$
  \State$\beta_{k+1} \leftarrow \frac{\gamma_{k+1}}{\gamma_k}$
  \State$p_{k+1} \leftarrow s_{k+1} + \beta_{k+1} p_k$
  \State$k = k + 1$
\EndWhile
\end{algorithmic}
\label{alg:cgls}
\end{algorithm}

Paige et. al \cite{paige1982lsqr} developed an algorithm called LSQR which has similar performance
to CGLS. We might consider implementing LSQR in case CG performs poorly on
linear systems.

\subsection{Randomized Kaczmarz (RK)}
As discussed earlier, the randomized Kaczmarz (RK) algorithm, is a popular
algorithm for solving \eqref{eq:linear_system}. Each iteration requires an
$O(n)$ storage and computational effort. During each iteration, RK picks a
row $a_i$ of the matrix $A$, and does an orthogonal projection of the current
solution vector $x_k$ to the hyperplane $a_i^Tx = b$. The update step is given by
$$
x_{k+1} = x_k - \frac{(a_i^T x_k - b_i)}{\norm{a_i}} a_i
$$
An alternate interpretation of RK is that the algorithm is identical to the
stochastic gradient  descent algorithm on the problem
$$
  \min \phi(x) := \frac{1}{2} x^T A^T A x - b^T x
$$
The algorithm performs best when a row $i$ is chosen randomly but proportional
to $\norm{a_i}$. Since sequential scans are preferred for in-database algorithms,
a common pre-processing procedure for RK is to rescale the system so that each
equation $a_i^Tx = b$ has the same norm.

\begin{algorithm}%[Randomized Kaczmarz for general linear systems]
% \caption{Randomized Kaczmarz for general linear systems.}\label{alg:rk}
\alginput{Matrix $A \in \R{m \times n}$, $b \in \R{m}$}
\algoutput{Solution to $Ax=b$}
\begin{algorithmic}[1]
\State Choose $x_0 \in \R^n$, $k \leftarrow 0$
\While{$\norm{Ax - b} \leq \epsilon$}
\State$x_{k+1} \leftarrow x_k - \frac{(a_i^T x_k - b_i)}{\norm{a_i}}$
  \State$k = k + 1$
\EndWhile
\end{algorithmic}
\label{alg:rk}
\end{algorithm}

The termination criterion of the algorithm is implemented by computing the
residual $\norm{Ax-b}$ extremely infrequently. Typically, this computation
is performed every $K$ epochs where an epoch is defined as one whole pass of
the data which in the case of RK is $m$ iterations.


\documentclass[12pt]{article}
\usepackage{fullpage}
\usepackage{amsthm}
\usepackage{amsfonts,amsmath, amssymb,latexsym,mathrsfs}
\usepackage[margin=1.15in]{geometry}
\usepackage{enumitem}
\setlength{\parindent}{0pt}
\usepackage{tikz-cd}
\usepackage{fancyhdr}

\theoremstyle{definition}
\newtheorem{thm}{Theorem}[section]

\newtheorem{prop}{Proposition}[section]

\theoremstyle{definition}
\newtheorem{definition}{Definition}[section]

\theoremstyle{remark}
\newtheorem*{remark}{Remark}

\theoremstyle{definition}
\newtheorem{example}{Example}[section]

\theoremstyle{definition}
\newtheorem{lem}{Lemma}[section]

\theoremstyle{definition}
\newtheorem{cor}{Corollary}[section]

\date{}
\title{Parametrization and Polar Coordinates}

\begin{document}
\maketitle
\section{Parametric Equations and Polar Coordinate}
\subsection{Parametric Equations}
To represent the motion of a particle in the $xy$-plane we use two equations, $x=f(t)$ and $y=g(t)$, then at the time $t$ the particle is at the location $(f(t),g(t)$. In this case, we call the equations for $x$ and $y$ the parametric equations, with parametrization $t$.

Remember that, in parametric equation, for the same line, the parametrization is not unique, and the different parametrization encodes two information:\\
1. Speed of the particle.\\
2. Direction of the motion.\\

\subsubsection{Special Parametric Equations}

\begin{itemize}
\item \textcolor{red}{Parametric Equations for a Straight Line}

An object moving along a line through the point $(x_0, y_0)$, with $dx/dt = a$ and $dy/dt = b$,
has parametric equations
$x = x_0 + at, y = y_0 + bt$.
The slope of the line is $m = b/a$.
\item\textcolor{red}{Parametric Equations for a circle with radius $k$}

An object moving along a circle of radius $k$ counterclockwise has parametric equations
$x = k\cos(t), y = k\sin(t)$.
\end{itemize}

\subsubsection{Slope and concavity of the curve}
As we discussed in class, we can think of this as a result due to chain rule if we have that $y=F(x)$ as well.

But to summarize, we have the \textcolor{red}{slope} of the parametrized curve to be
\[\frac{dy}{dx}=\frac{dy/dt}{dx/dt}\]
and the \textcolor{red}{concavity} of the parametrized curve to be
\[\frac{d^2y}{dx^2}=\frac{(dy/dx)/dt}{dx/dt}\]

\subsubsection{Speed and distance}

The \textcolor{red}{instantaneous speed} of a moving object is defined to be
$$v = \sqrt{(dx/dt)^2 + (dy/dt)^2} =\sqrt{(v_x)^2 + (v_y)^2}$$.
The quantity $v_x = dx/dt$ is the instantaneous velocity in the $x$-direction; $v_y = dy/dt$ is the
instantaneous velocity in the $y$-direction.
And we call that $(v_x,v_y)$ to be the velocity vector.

Moreover, the \textcolor{red}{distance} traveled from time $a$ to $b$ is $$\int^b_a v(t) dt = \int_a^b \sqrt{(dx/dt)^2 + (dy/dt)^2} dt$$

\subsection{Polar Coordinate}

Polar coordinates is the coordinates determined by specifying the distance of the point to origin and the angle measured counterclockwise from positive $x$-axis to the line joining the line connecting the point and the origin.

\subsubsection{Relation between Cartesian and Polar}

\textcolor{red}{Cartesian to Polar}: $$(x,y) \to (r= \sqrt{x^2 + y^2}, \theta) \text{ (Here we have that } \tan \theta = \frac{y}{x} \text{)}$$
Note that $\theta$ does not have to be $\arctan(\frac{y}{x})$!

\textcolor{red}{Polar to Cartesian}: $$(r,\theta) \to (x=r \cos \theta, y=r \sin \theta)$$

\subsubsection{Slope, Arc length and Area in Polar Coordinates}

By the relation $x=r \cos \theta, y=r \sin \theta$, given a curve $r=f(\theta)$, we have that $x=f(\theta) \cos \theta, y=f(\theta) \sin \theta$, and thus are parametrized equations of parameter $\theta$. Therefore we have that the \textcolor{red}{slope} of to be
\[\frac{dy}{dx}=\frac{dy/d\theta}{dx/d\theta}\]

The \textcolor{red}{arc length} from angle $a$ to $b$ is $$\int_a^b \sqrt{(dx/d\theta)^2 + (dy/d\theta)^2} d\theta$$

Moreover, due to the fact that the \textcolor{red}{area of the sector} is $1/2 r^2 \theta$, we have that for a curve $r = f(\theta)$, with \textcolor{red}{$f(\theta) \geq 0$}, the area of the region enclosed is $$\frac{1}{2}\int^{b}_{a}f(\theta)^2 d\theta$$

\end{document}


\chapter{Conclusion}
Our work presents a functional implementation of a backend engine for playing games in normal form against a computer.
Besides that, we have defined several new notions of equilibria: perfectly transparent best response equilibrium, perfectly transparent best profile equilibrium, and perfectly transparent optimal profile equilibrium.
With the help of our analysis of randomly generated datasets, we have determined the inclusion relations between most of these equilibria and between individual rationality and minimax rationalizability.

The relations of minimax rationalizability to PTOPE and PTE remain an open problem.

The next step in training people for non-Nashian thinking will be to develop a more user-friendly client for the backend, such as a mobile app or a web interface.
Subsequently, the app can be used to conduct experiments.
Our backend will store the results of all games played in a database for future analysis.


\chapter{Lecture 31 Jul 16th 2018}%
\label{chp:lecture_31_jul_16th_2018}
% chapter lecture_31_jul_16th_2018

\section{Factorizations in Integral Domains (Continued)}%
\label{sec:factorizations_in_integral_domains_continued}
% section factorizations_in_integral_domains_continued

\subsection{Irreducibles and Primes (Continued)}%
\label{sub:irreducibles_and_primes_continued}
% subsection irreducibles_and_primes_continued

\begin{note}
  Recall that if $R$ is an integral domain and $a, b \in R$, we say that $a \, | \, b$ if $\exists c \in R$ such that $b = ca$.
\end{note}

Also, recall the definition of \hlnoteb{associativity}.

\begin{defnnonum}[Associativity]
  If $a \, | \, b$ and $b \, | \, a$, then we say that $a$ is associative to $b$, and denote $a \sim b$ if and only if $\exists u \in R$, which is a unit, such that $a = ub$, and we have $\lra{a} = \lra{b}$.
\end{defnnonum}

\begin{defn}[Irreducible]\index{Irreducible}
\label{defn:irreducible}
  Let $R$ be an integral domain. We say $p \in R$ is \hlnoteb{irreducible} if $p \neq 0$ is not a unit, and $p = ab \in R$, then either $a$ or $b$ is a unit. An element that is not \hlnoteb{irreducible} is \hlnoteb{reducible}\index{reducible}.
\end{defn}

\begin{eg}\label{eg:irreducible_eg}
  Let $R = \mathbb{Z}[\sqrt{-5}] = \{ m + n \sqrt{-5} : m, \, n \in \mathbb{Z} \}$ and $p = 1 + \sqrt{-5}$. We want to show that $p$ is an irreducible in $R$. Note that for $z = m + n \sqrt{-5} \in R$, the \hldefn{norm} of $z$ is defined to be
  \begin{equation*}
    N(z) = \left(m + n \sqrt{-5}\right)\left(m - n \sqrt{-5}\right) = m^2 + 5n^2 \in \mathbb{N} \cup \{0\}
  \end{equation*}
  Note that\sidenote{
  \begin{proof}
    Let $x = m + n \sqrt{-5}$ and $y = a + b \sqrt{-5}$. Note that
    \begin{equation*}
      N(x) = m^2 + 5n^2.
    \end{equation*}
    Then
    \begin{align*}
      &N(x) N(b) \\
      &= m^2 a^2 + 25 n^2 b^2 + 5 (n^2 a^2 + m^2 b^2).
    \end{align*}
    and since
    \begin{equation*}
      xy = ma - 5nb + \sqrt{-5} ( na + mb ),
    \end{equation*}
    we have
    \begin{align*}
      &N(xy) \\
      &= (ma - 5nb)^2 + 5(na + mb)^2 \\
      &= m^2 a^2 + 25 n^2 b^2 + 5 ( n^2 a^2 + m^2 b^2 )
    \end{align*}
  \end{proof}
  }
  \begin{equation*}
    N(xy) = N(x) N(y).
  \end{equation*}
  Now suppose that $p = ab \in R$. Then
  \begin{equation*}
    6 = N(p) = N(a)N(b).
  \end{equation*}
  However, since $N(z) = m^2 + 5n^2$ for some $m, \, n \in \mathbb{Z}$, we must have that $N(z) \neq 2, \, 3$. Thus, we have either $N(a) = 1$ or $N(b) = 1$, which in turn implies that $a = \pm 1$ and $b = \pm 1$, which implies that $a$ or $b$ is a unit. Therefore, $p$ is irreducible.
\end{eg}

\begin{propo}[Properties of Irreducibles]
\label{propo:properties_of_irreducibles}
  Let $R$ be an integral domain. Let $0 \neq p \in R$. TFAE:
  \begin{enumerate}
    \item $p$ is irreducible;
    \item $d \, | \, p \implies d \sim 1 \veebar d \sim p$;
    \item $p \sim ab \in R \implies p \sim a \veebar p \sim b$;
    \item $p = ab \in R \implies p \sim a \veebar p \sim b$.
  \end{enumerate}
  Consequently, if $p \sim q$, we have $p$ is irreducible if and only if $q$ is irreducible.
\end{propo}

\begin{proof}
  $(1) \implies (2)$: $\quad d \, | \, p \implies \exists c \in R \quad dc = p$. \\
  $d$ is a unit $\implies d \sim 1 \enspace \square$ ;\\
  $d$ is not a unit $\implies c$ is a unit $\because p$ is irreducible\\
  $\implies \exists c^{-1} \in R \quad cc^{-1} = 1 \implies d = pc^{-1} \implies d \sim p$.

  \noindent $(2) \implies (3)$ : $\quad p \sim ab \implies \exists c, c^{-1} \in R \enspace cc^{-1} = 1 \quad p = cab$\\
  Suppose $p \not\sim a$.\\
  $a \, | \, cab \implies a \, | \, p \overset{(2)}{\implies} a \sim 1 \implies ca$ is a unit $\implies p \sim b$.

  \noindent $(3) \implies (4)$ : $\quad 1$ is a unit and so $p = ab \implies p \sim ab$, and the result follows from $(3)$.

  \noindent $(4) \implies (1)$ : $\quad \because (4) \enspace p = ab \implies p \sim a \veebar p \sim b$.\\
  WLOG $p \sim a \implies \exists c, c^{-1} \in R \enspace cc^{-1} = 1 \quad p = ac\implies ac = ab$\\
  Note $a \neq 0 \because p \neq 0 \, \land \, p \sim a$. \\
  Then by \cref{propo:ring_cancellations_and_zeros}, $c = b \implies b$ is a unit $\implies p$ is irreducible.

  By $(3)$ and $(1)$, $p \sim q \iff p, \, q$ are irreducibles.\qed
\end{proof}

\begin{defn}[Prime]\index{Prime}
\label{defn:prime}
  Let $R$ be an integral domain and $p \in R$. We say $p$ is \hlnoteb{prime} in $R$ if $p \neq 0$ is not a unit, and if $p \, | \, ab \in R \implies p \, | \, a \veebar p \, | \, b$.
\end{defn}

\begin{note}
  If $p \sim q$, then $p$ is prime $\iff q$ is prime. This is a clear result, since $p \sim q \implies p \, | \, q \, \land \, q \, | \, p$, and if $p$ is prime, then $q \, | \, p \, | \, ab \implies q \, | \, p \, | \, a \; \veebar \; q \, | \, p \, | \, b$.

  Also, by induction, if $p$ is prime and
  \begin{equation*}
    p \, | \, a_1 a_2 ..., a_n,
  \end{equation*}
  then $p \, | \, a_i$ for some $1 \leq i \leq n$.
\end{note}

\begin{propo}[Primes are Irreducible]
\label{propo:primes_are_irreducible}
  Let $R$ be an integral domain and $p \in R$. $p$ is prime $\implies p$ is irreducible.
\end{propo}

\begin{proof}
  $\because p$ is prime $\quad p = ab \implies p \, | \, a \, \veebar \, p \, | \, b$. \\
  WLOG $p \, | \, a \implies \exists d \in R \quad dp = a$\\
  $\implies a = dp = dab = adb \quad \because R$ is commutative \\
  $\because a \neq 0$ and $R$ is an integral domain, by \cref{propo:ring_cancellations_and_zeros}, $1 = db \implies b$ is a unit (with $d$ being its multiplicative inverse). \\
  $\therefore p$ is irreducible.\qed
\end{proof}

The converse of \cref{propo:primes_are_irreducible} is false.

\begin{eg}
  Recall from \cref{eg:irreducible_eg} that $1 + \sqrt{-5}$ is irredubile in $\mathbb{Z}[\sqrt{-5}]$. Recall that for $d = m + n \sqrt{-5} \in \mathbb{Z}[\sqrt{-5}]$, we defined the \hlnoteb{norm} as
  \begin{equation*}
    N(d) = m^2 + 5n^2 \in \mathbb{N} \cup \{0\}.
  \end{equation*}
  Before proceeding further, note that
  \begin{equation*}
    2 \cdot 3 = 6 = (1 + \sqrt{-5})(1 - \sqrt{-5}) = p ( 1 - \sqrt{-5} ).
  \end{equation*}
  Suppose $p$ is prime, which then $p \, | \, 2 \cdot 3 \implies p \, | \, 2 \, \veebar \, p \, | \, 3$. Suppose $p \, | \, 2 \implies \exists q \in \mathbb{Z}[\sqrt{-5}] \quad 2 = pq$. It follows that
  \begin{equation*}
    4 = N(2) = N(p)N(q) = 6 N(q)
  \end{equation*}
  which is impossible. Similarly, $p \, | \, 3 \implies \exists r \in R \quad 3 = rp \implies$
  \begin{equation*}
    9 = N(3) = N(r)N(p) = 6N(r)
  \end{equation*}
  is also impossible. Therefore, $p$ is not prime.
\end{eg}

% subsection irreducibles_and_primes_continued (end)

\subsection{Ascending Chain Condition}%
\label{sub:ascending_chain_condition}
% subsection ascending_chain_condition

\begin{defn}[Ascending Chain Condition on Principal Ideals (ACCP)]\index{Ascending Chain Condition on Principal Ideals}\index{ACCP}
\label{defn:ascending_chain_condition_on_principal_ideals}
An integral domain $R$ is said to satisfy the \hlnoteb{ascending chain condition on principal ideals} (ACCP) if for any ascending chain
\begin{equation*}
  \lra{a_1} \subseteq \lra{a_2} \subseteq \lra{a_3} \subseteq \hdots
\end{equation*}
of principal ideals in $R$, $\exists n \in \mathbb{N}$ such that
\begin{equation*}
  \lra{a_n} = \lra{a_{n + 1}} = \hdots \; .
\end{equation*}
\end{defn}

\begin{eg}
  $\mathbb{Z}$ satisfies ACCP.

  If $\lra{a_1} \subseteq \lra{a_2} \subseteq \lra{a_3} \subseteq \hdots$ in $\mathbb{Z}$, then
  \begin{equation*}
    a_2 \, | \, a_1, \, a_3 \, | \, a_2, \, \hdots \; .
  \end{equation*}
  Taking the absolute value of each of the $a_i$'s, we have that
  \begin{equation*}
    \abs{a_1} \geq \abs{a_2} \geq \abs{a_3} \geq \hdots \; .
  \end{equation*}
  Since each of the $\abs{a_i} \geq 0$ is an integer, there must be some $n \in \mathbb{N}$ where
  \begin{equation*}
    \abs{a_n} = \abs{a_{n + 1}} = \hdots \; .
  \end{equation*}
  This implies that $a_{i + 1} = \pm a_i$ for $i \geq n$. Therefore, we have that
  \begin{equation*}
    \lra{a_i} = \lra{a_{i + 1}} \quad \text{for } i \geq n,
  \end{equation*}
  thus showing that the ACCP is satisfied.
\end{eg}

\begin{thm}[Factorization on an Integral Domain Satisfying ACCP]
\label{thm:factorization_on_an_integral_domain_satisfying_accp}
  Let $R$ be an integral domain that satisfies ACCP. Let $0 \neq a \in R$ be a non-unit. Then $a$ is a product of irreducible elements of $R$.
\end{thm}

\begin{proof}
  Suppose to the contrary that $a$ is not a product of irreducible elements of $R$. Then $a$ itself must not be irreducible. By \cref{propo:properties_of_irreducibles}, $\exists x_1 \in R$ such that
  \begin{equation*}
    a = x_1 a_1 \quad a \not\sim x_1 \, \land \, a \not\sim a_1.
  \end{equation*}
  Note that at least one of $x_1$ or $a_1$ is not a product of irreducible elements, for otherwise $a$ would be a product of irreducible elements. WLOG, suppose $a_1$ is not a product of irreducible elements. Then \cref{propo:properties_of_irreducibles} $\implies \exists x_2 \in R$
  \begin{equation*}
    a_1 = x_2 a_2 \quad a_1 \not\sim x_2 \, \land \, a \not\sim a_2.
  \end{equation*}
  We can continue this argument infinitely so, in which we will then get an ascending chain of principal ideals
  \begin{equation*}
    \lra{a} \subseteq \lra{a_1} \subseteq \lra{a_2} \subseteq \hdots \; .
  \end{equation*}
  However, since
  \begin{equation*}
    a \not\sim a_1 \not\sim a_2 \not\sim \hdots \;,
  \end{equation*}
  \cref{propo:division_in_an_integral_domain} implies that
  \begin{equation*}
    \lra{a} \subsetneq \lra{a_1} \subsetneq \lra{a_2} \subsetneq \hdots\; ,
  \end{equation*}
  which contradicts the assumption that $R$ satisfies ACCP. Therefore, all non-unit $0 \neq a \in R$ is a product of irreducible elements of $R$.\qed
\end{proof}

% subsection ascending_chain_condition (end)

% section factorizations_in_integral_domains_continued (end)

% chapter lecture_31_jul_16th_2018 (end)