\documentclass[journal]{IEEEtran}
\usepackage[utf8]{inputenc}
\usepackage{minted}
\usepackage{booktabs}
\usepackage{color}
\usepackage{mathtools}
\usepackage{mathrsfs}
\usepackage{multirow}
\usepackage{clrscode3e}

\newcommand{\lagr}{\mathscr{L}}

\usepackage[binary-units=true]{siunitx}

\newcommand{\scala}[1]{\mintinline{scala}{#1}}

\title{Advanced Algorithms (\texttt{LINGI2266}) \\ Assignment 2: Weighted Set Cover Problem}
\author{Gilles Peiffer}
\date{November 22, 2019}

\begin{document}

\maketitle

\begin{abstract}
	The present document contains an explanation of the solution to the weighted set cover problem using the method of Lagrangian relaxation.
	Using this relaxation, one is able to find a consistent lower bound on the cost of a solution, which, coupled with the feasibility of the intermediate solutions, leads to an efficient technique to find an optimal assignment of variables, or a good lower bound on the cost of this assignment.

	Some code fragments in Scala are also showcased.
\end{abstract}

\section{Introduction}
\label{sec:intro}
The \emph{weighted set cover problem} is concerned with selecting the minimal subset of a list of \(m\) sets containing elements from \(\{1, \ldots n\}\) such that the union of this minimal subset contains all the elements at least once.
Minimality is taken with respect to the costs of the sets which are chosen.
If no such subset exists, the problem is infeasible.

\section{Weighted Set Cover Problem}
We use \(\mathscr{N}\) and \(\mathscr{M}\) to denote the \(n\) first and \(m\) first strictly positive integers, respectively.

\subsection{Initial Formulation}
The weighted set cover problem can be written as an optimization problem as follows:
\[
\renewcommand{\arraystretch}{1.5}
\begin{array}{lrcl@{\quad}l}
\textnormal{minimize} & \sum_{i \in \mathscr{M}} w_i x_i, &&&\\
\textnormal{subject to} & \sum_{i : j \in \mathcal{S}_i} x_i & \ge & 1, & \forall j \in \mathscr{N},\\
& x_i &\in& \{0, 1\}, & \forall i \in \mathscr{M},
\end{array}
\]
where \(w_i\) is the cost of the \(i\)th set, \(x_i\) is a binary variable determining whether the \(i\)th set is taken, and \(\mathcal{S}_i\) is the \(i\)th set.

\subsection{Lagrangian Relaxation}
The \emph{Lagrangian relaxation} of this problem is then found by relaxing the covering constraint by modifying the objective function so that it takes into account constraint violations.
The problem then becomes
\[
\renewcommand{\arraystretch}{1.5}
\begin{array}{lrcl@{\quad}l}
\textnormal{minimize} & \multicolumn{4}{l}{\sum_{i \in \mathscr{M}} w_i x_i - \sum_{j \in \mathscr{N}} \lambda_j \left(1 - \sum_{i : j \in \mathcal{S}_i} x_i \right),}\\
\textnormal{subject to} & x_i &\in& \{0, 1\}, & \forall i \in \mathscr{M},
\end{array}
\]
where \(\lambda_j\) is a nonnegative Lagrange multiplier pertaining to the \(j\)th element.
One can observe the fundamental property of this modified problem, which is that its optimal value for a feasible assignment \(x\) is always less than or equal to the optimal value of the original problem.
It is also much easier to solve than the original problem.
This then leads to the following observation: if one finds the assignment \(\lambda\) which maximizes the lower bound, this can be used as an efficient pruning function in a branch and bound search; this assignment is only concerned with applying it to the root of the search tree.

\subsection{Finding the Lower Bound: Subgradient Algorithm}
We denote the lower bound associated to a given assignment \(\lambda\) by \(\mathscr{L}\).
The problem of finding the optimal lower bound \(\mathscr{L}^*\) then corresponds to the following:
\[
\mathscr{L}^* = \max_\lambda \min_{x} \left(\sum_{i \in \mathscr{M}} w_i x_i - \sum_{j \in \mathscr{N}} \lambda_j \left(1 - \sum_{i : j \in \mathcal{S}_i} x_i \right)\right).
\]

In order to find this optimal lower bound, one can use a \emph{subgradient algorithm} to find the optimal assignment of \(\lambda\):
\begin{enumerate}
	\item Start with an initial assignment \(\lambda^{(0)}\); in this case, \(0\) was used, and set a step size \(\mu^{(0)}\); in this case \(\mu^{(0)} = 1\).
	\item Let \(x^{(k)}\) be the variable assignment at iteration \(k\).
	The update rule then becomes
	\[
	\lambda_j^{(k+1)} = \max\left\{0, \lambda_j^{(k)} + \mu^{(k)} \left(1 - \sum_{i : j \in \mathcal{S}_i} x_i^{(k)}\right)\right\}.
	\]
	This is done by the following bit of code.
\begin{minted}[fontsize=\scriptsize]{scala}
// Update the lambdas using the update rule.
for (j <- lambda.indices) {
  var mul: Int = 1
  for (i <- setsContaining(j) if x(i) == 1)
    mul -= 1 // Find the sets in which j appears.
  lambda(j) = Math.max(0, lambda(j) + mu * mul)
}
\end{minted}

	The variable assignment for the next iteration is then computed as follows.
\begin{minted}[fontsize=\scriptsize]{scala}
val coeff: Array[Double] = new Array[Double](m)
// Coefficients of the decision variables.
x = new Array[Int](m)
for (i <- coeff.indices) {
  coeff(i) = w(i)
  for (j <- elementsIn(i))
    coeff(i) -= lambda(j) // Update coefficients.
  if (coeff(i) < 0.0)
    x(i) = 1 // Decide which sets to take.
}
\end{minted}

	Finally, one must also update \(\mu^{(k)}\) in a way which satisfies the following convergence hypotheses:
	\begin{align*}
	\lim_{k \to \infty} \mu^{(k)} &= 0, \\
	\sum_{k = 0}^{+\infty} \mu^{(k)} &= +\infty.
	\end{align*}
	In this case, the harmonic sequence \(\mu^{(k)} = 1/(k+1)\) was chosen.
\end{enumerate}
This algorithm ends after a certain number of iterations, though other measures can be used such as a threshold on the step size \(\mu\) or on the optimality gap \(\mathscr{G}\), defined as follows:
\[
\mathscr{G}^{(k)} = \frac{c_{x^{(k)}} - \lagr^*}{\lagr^*},
\]
where \(c_{x^{(k)}}\) is the cost of assignment \(x^{(k)}\).

Using this procedure, the Lagrangian lower bound \(\mathscr{L}^{(k)}\) is guaranteed to change nondecreasingly.

In the code, the lower bound is updated by the following bit of code.
\begin{minted}[fontsize=\scriptsize]{scala}
lb = 0.0
for (i <- x.indices if x(i) == 1) lb += w(i)
for (j <- lambda.indices) {
  var mul: Int = 1
  for (i <- setsContaining(j) if x(i) == 1)
    mul -= 1 // Find the sets in which j appears.
  lb += lambda(j) * mul
}
lb = Math.ceil(lb)
\end{minted}
Section~\ref{sec:ceil} explains why the last line is allowed.

\subsection{Complete Algorithm}
The complete algorithm for solving the weighted set covering problem can then be written as follows.
\begin{codebox}
	\Procname{\(\proc{Weighted-Set-Cover}\)}
	\li \(\lagr^* \gets -\infty, \mu^{(0)} \gets 1, \lambda^{(0)} \gets 0\)
	\li \If \(\bigcup_i \mathcal{S}_i \ne \mathscr{N}\)
	\li 	\Then \Return ``infeasible''
	\End
	\li \For \(k \gets 1\) \To maxiter \Do
	\li 	compute the optimal assignment \(x^{(0)}\) \Indentmore
	\zi 		using the modified objective function \End
	\li 	set \(\lagr^{(k)}\) to the objective value
	\li 	\If \(\lagr^{(k)} \ge \lagr^*\)
	\li 		\Then
	\(\lagr^* \gets \lagr^{(k)}\)
	\li			\If \(x^{(k)}\) is feasible
	\li 				\Then
	\(x^* \gets x^{(k)}\)
	\End
	\End
	\li 	update \(\lambda^{(0)}\) and \(\mu^{(k)}\)
	\End
\end{codebox}

\section{I/O}
The program starts by reading the input and detecting whether the problem is feasible; if not, it prints ``infeasible'' and returns.
The function used to test for feasibility is the following.

\begin{minted}[fontsize=\scriptsize]{scala}
def isFeasible(): Boolean = {
  // See which elements are in the solution.
  val elemsTaken: Array[Int] = new Array[Int](n)
  for (i <- y.indices if y(i) == 1; j <- elementsIn(i))
    elemsTaken(j) = 1 // Set to 1 when element is taken.
  !elemsTaken.contains(0)
}
\end{minted}

If the problem is feasible, the program solves the problem and outputs according to the type of solution and the corresponding format specified in the problem statement.

\section{Improvements}
\label{sec:improvements}
Several improvements to the algorithm were made in order to pass the various test cases on INGInious.

\subsection{Avoiding Lower Bounds With No Solution}
Once feasibility has been established, one can immediately see that taking all the sets is a (very naive) feasible solution to the problem; its associated cost is then the sum of all the set costs.
By doing this at the start, the program never runs into the case where a lower bound with no solution has been found.

\subsection{Integrality of the Cost}
\label{sec:ceil}
Since the cost of a solution is a sum of integers, it must itself be an integer.
This means that fractional lower bounds can be rounded up to the nearest integer, which drastically improves the efficiency of the program by requiring fewer operations.

By doing this, one also gets rid of some of the problems due to numerical instability.

\section{Submission on INGInious}
By adding the improvements detailed in Section~\ref{sec:improvements}, the program (written in Scala) was able to pass all the test instances without needing other modifications.

\end{document}


\documentclass[11pt,a4paper]{report}
\usepackage{amsmath,amsfonts,amssymb,amsthm,epsfig,epstopdf,titling,url,array}
\usepackage{enumitem}
\usepackage{changepage}
\usepackage{graphicx}
\usepackage{caption}
\theoremstyle{plain}
\newtheorem{thm}{Theorem}[section]
\newtheorem{lem}[thm]{Lemma}
\newtheorem{prop}[thm]{Proposition}
\newtheorem*{cor}{Corollary}
\theoremstyle{definition}
\newtheorem{defn}{Definition}[section]
\newtheorem{conj}{Conjecture}[section]
\newtheorem{exmp}{Example}[section]
\newtheorem{exercise}{Exercise}[section]
\theoremstyle{remark}
\newtheorem*{rem}{Remark}
\newtheorem*{note}{Note}
\def\changemargin#1#2{\list{}{\rightmargin#2\leftmargin#1}\item[]}
\let\endchangemargin=\endlist
\begin{document}

\section*{Problem}
Evaluate $lim_{x\to 0} sin(x)/x$.

\section*{Solution}
This can be evaluated using l'Hospital's rule, which states that if $f$ and $g$ are continuously differentiable at $a$, and  $\lim_{x \to a} f(x) = 0 =  \lim_{x \to a} g(x)$ then $\lim_{x \to a} {f(x)/g(x)} = f'(0) / g'(0)$.  So $lim_{x\to 0} sin(x)/x = \lim_{x \to 0} {cos(0) / 1} = 1.$

But why is l'Hospital's rule true?  This follows nicely from the definition of the derivative.  Recall that the derivative of $f$ at $x$ is defined by
$$f'(x) = \lim_{h \to 0} \frac{f(x + h) - f(x)}{h}.$$
So $$\frac{f'(0)}{g'(0)} = $$ $$\frac{\mathop{\lim}\limits_{h \to 0} \frac {f(0 + h) - f(0)} {h}} {\mathop{\lim}\limits_{h \to 0} \frac {g(0 + h) - g(0)} {h}} = $$ $$\lim_{h \to 0} \frac {f(h) - f(0)} {g(h) - g(0)}$$.
\end{document}


\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage[nodayofweek]{datetime}

\usepackage{minted}

% Set size of text area with total parameter
\usepackage[a4paper, total={155mm, 255mm}]{geometry}

\title{Higher Probability Q14}
\author{Dyson}
\date{\today}

\newcommand{\oo}[1]{\frac{1}{#1}}

\begin{document}

\maketitle

% Set paragraph spacing here to avoid messing with title
\setlength{\parindent}{0em}
\setlength{\parskip}{1em}

\section{The Question}

Higher Probability Question 14 in the A Level Summer Work is quite an interesting question. It says:

David has designed a game.\\
He uses a fair 6-sided dice and a fair 5-sided spinner.\\
The dice is numbered 1 to 6.\\
The spinner is numbered 1 to 5.

Each player rolls the dice once and spins the spinner once.\\
A player can win £5 or £2.

For a player to win £5, they must roll a 5 \textbf{and} spin a 5.\\
For a player to win £2, they must roll a 1 \textbf{or} spin a 1 \textbf{or} both.

David expects 30 people will play his game.\\
Each person will pay David £1 to play the game.

Work out how much profit David can expect to make.

\hspace*{\fill}(4 marks)

\section{The Original Working}

Initially, my thinking was: each of the 30 people pays £1 to play, so we have a £30 gross profit. Then, the probability of rolling a 5 is $\oo{6}$, the probability of spinning a 5 is $\oo{5}$, so the probability of both is $\oo{6} \times \oo{5} = \oo{30}$. This means we can expect 1 of the 30 people to win £5, so our net profit at this point becomes £25.

The probability of rolling a 1 is $\oo{6}$, the probability of spinning a 1 is $\oo{5}$, and the probability of both is therefore $\oo{6} \times \oo{5} = \oo{30}$. Then, to get the probability of A \textbf{or} B \textbf{or} C, I added these probabilities together to get $\frac{2}{5}$. This is $\frac{12}{30}$, meaning 12 people win £2. This means we subtract £24 from our net profit and get a final profit of £1.

Now, this seemed off to me. It just didn't feel right that David would only make £1 profit. So, I wrote some Julia code to simulate it.

\newpage

\section{The Improved Working}

\begin{minted}{julia}
using Statistics

function game()
	total = 0

	for _ in 1:30
		# Add one to the total for each person
		total += 1

		# Roll a die and spin a spinner
		d = rand(1:6)
		s = rand(1:5)

		# Check the conditions and subtract the relevant amounts from the total
		if d == 5 && s == 5
			total -= 5
		elseif d == 1 || s == 1 || (d == 1 && s == 1)
			total -= 2
		end
	end

	return total
end

println(mean([game() for _ in 1:10000]))
\end{minted}

This code consistently gave me a mean of £5. I spent about an hour carefully checking through my code and making sure that everything was correct and eventually concluded that £5 was the real answer and my maths must have been wrong.

After some thinking, I realised that the \textit{both} part of the second condition is irrelevant. If a person both rolls a 1 \textbf{and} spins a 1, then they must have already rolled a 1 \textbf{or} spun a 1. We can show this with some boolean algebra.

Let $R$ be whether the person has rolled a 1 and let $S$ be whether the person has spun a 1. Then, our expression is $R \vee S \vee (R \wedge S)$. By associativity of $\vee$, we can write this as $R \vee (S \vee (R \wedge S))$. Then, by absorption, $S \vee (R \wedge S) = S$, so our expression gets simplified to $R \vee S$. Therefore, the \textit{both} part of the second condition can be ignored.

Changing the code confirms that by removing the check for both, the answer doesn't change. However, this probability of both \textit{must} be removed from the probability calculation. This gives us $P(\text{£}2) = \frac{11}{30}$, so 11 people win £2 and we get a final total of £3. This is still wrong.

I had to do some research on combining probabilities and learned that $P(A \vee B)$ only equals $P(A) + P(B)$ if $A$ and $B$ are dependent events, meaning they influence each other. If $A$ happens, then $B$ cannot. This is not the case with this question and we cannot simply add the probabilities of independent events like this.

In the platonic world of perfect probabilities with 30 people playing the game, 5 people roll a 1 and 6 people spin a 1. This does \textbf{not} mean that 11 people rolled a 1 \textbf{or} spun a 1. This is because $P(R \wedge S) = P(R) \times P(S) = \oo{6} \times \oo{5} = \oo{30}$. That means that 1 person rolled a 1 \textbf{and} spun a 1, so this person gets double counted when we simply add the probabilities.

\newpage

This means that for two independent events $A$ and $B$, $P(A \vee B) = P(A) + P(B) - P(A \wedge B)$. Thus, $$P(R \vee S \vee (R \wedge S)) = P(R \vee S)$$
$$= P(R) + P(S) - P(R \wedge S)$$
$$= \oo{6} + \oo{5} - \oo{30} = \oo{3}$$

This means that $\oo{3}$ of the 30 people win £2, meaning we only take £20 from our £25 net profit, finally getting the £5 answer.

Quite frankly, this question was a bitch.

\end{document}


\documentclass{article}
\usepackage{tocloft}
\include{common_symbols_and_format}
\renewcommand{\cfttoctitlefont}{\Large\bfseries}

\begin{document}
\logo
\rulename{Average Directional Movement Index} %Argument is name of rule
\tblofcontents

\ruledescription{The Average Directional Index (ADX) introduce by Wells Wilder, is a technical indicator that is used to help measure the overall strength of the trend. This indicator attempts to measure the strength of price movement in positive and negative direction using the $+$DMI and $-$DMI indicators along with the ADX. A trend is considered strong when the value of the ADX is above 25 and considered weak when the value is below 25. A trend is also considered bullish when the $+$DMI is above the $-$DMI and considered bearish when the $+$DMI is below the $-$DMI.
}

\howtotrade
{The strategy is to identify the trend and the strength of the trend using the values of ADX, $+$DMI and $-$DMI. \\
Bullish Trend - When the $+$DMI is above the $-$DMI and the ADX value is above 25. \\
Bearish Trend - When the $+$DMI is below the $-$DMI and ADX is below 25.
}

\ruleparameters %You can include however many arguments (in groups of 4) as you want!
{Look Back Length}{14}{Number of timestamps used to calculate ADX.}{$\lookbacklength$}
\stoptable %must be included or Tex engine runs infinitely

\newpage
\section{Equation}
Below are the equations which govern how this specific trading rule calculates a trading position.

\begin{equation}
    TR_{\currenttime} = \max{\{P_{\currenttime}^{h}-P_{\currenttime}^{l},\ |P_{\currenttime}^{h} - P_{\currenttime-1}^{c}|, \
    |P_{\currenttime-1}^{c} - P_{\currenttime}^{h}|}\}
\end{equation}
\begin{equation}
    ATR_{\currenttime} = \frac{1}{\lookbacklength} \sum_{i=1}^{\lookbacklength} TR_{i}
\end{equation}
\begin{equation}
    +DM_{\currenttime} = \begin{cases}
    0 & P_{\currenttime}^{h}-P_{\currenttime-1}^{h} < 0 \\
    P_{\currenttime}^{h}-P_{\currenttime-1}^{h} & else
    \end{cases}
\end{equation}
\begin{equation}
    -DM_{\currenttime} = \begin{cases}
    0 & P_{\currenttime-1}^{l}-P_{\currenttime}^{l} < 0 \\
    P_{\currenttime-1}^{l}-P_{\currenttime}^{l} & else
    \end{cases}
\end{equation}
\begin{equation}
    +/-DM_{\currenttime}^{s} = \sum_{i=1}^{\lookbacklength} DM_{i} + \sum_{i=1}^{\lookbacklength} \frac{DM_{i}}{\lookbacklength} + DM_{c}
\end{equation}
\begin{equation}
    +DI_{\currenttime} = \frac{+DM_{\currenttime}^{s}}{ATR_{\currenttime}} \times 100
\end{equation}
\begin{equation}
    -DI_{\currenttime} = \frac{-DM_{\currenttime}^{s}}{ATR_{\currenttime}} \times 100
\end{equation}
\begin{equation}
    DX_{\currenttime} = \Big( \frac{|+DI_{\currenttime} - -DI_{\currenttime}|}{|+DI_{\currenttime} + -DI_{\currenttime}|}\Big) \times 100
\end{equation}
\begin{equation}
ADX_{t} =
    \begin{cases}
        \frac{1}{L} \sum_{i=1}^{\lookbacklength} DX_{i} & \currenttime = 0 \\ \\
        \frac{(ADX_{\currenttime-1} \times (\lookbacklength -1)) + DX_{\currenttime}}{\lookbacklength} & \currenttime > 0
    \end{cases}
\end{equation}
\\ % creates some space after equation
where:

$P_{\currenttime}^{h}$: is the asset's high price at time \currenttime.

$P_{\currenttime}^{c}$: is the asset's close price at time \currenttime.

$P_{\currenttime}^{l}$: is the asset's low price at time \currenttime.

$TR_{\currenttime}$: is the True Range at time \currenttime.

$ATR_{\currenttime}$: is the Average True Range at time \currenttime.

$DM_{c}$: is the Directional Movement at current time.

$+/-DM_{\currenttime}$: is the Directional Movement at time \currenttime.

$+/-DM_{\currenttime}^{s}$: is the Smoothed Directional Movement at time \currenttime.

$+/-DI_{\currenttime}$: is the Directional Index at time \currenttime.

$DX_{\currenttime}$: is the Directional Movement Index at time \currenttime.

$ADX_{\currenttime}$: is the Average Directional Movement Index at time \currenttime.

\keyterms
\furtherlinks %The footer
\end{document}


\chapter{detection}
The \textit{quantum efficiency} of a detector is the fraction of the incident photons that contributes to the output of the detecting system.  This is the same as saying that the quantum efficiency is equal to the probability that a single incident x-ray photon will be detected.
\textit{detective quantum efficiency} is the fraction of incident photons that would have to be detected without additional noise to yield the same signal-to-noise ratio as it actually observed by the detector in question.
DQE $\le$ QE $\le$ 1 \newline

From a pragmatic (dealing with things sensibly and realistically in a way that is based on practical rather than theoretical considerations) viewpoint it does not matter what the QE is: the limits of detectability of a signal are set by the SNR, which is determined by DQE and not QE.  The QE is useful only for determining the amount of gain required to bring the signal up to some desired level.

Noise factor (NF) of the detector is the decrease in the signal-to-noise ratio that accompanies the detection process. Given by:
\begin{equation}
\begin{split}
NF = &(DQE)^{-1/2} \\
NF = &\frac{1}{\sqrt{DQE}}
\end{split}
\end{equation}

In radiology the speed of the film is usually stated as the reciprocal of the exposure in roentgens required to produce a final film density of a stated amount, usually in the range of 0.7-1.0.  The source spectrum (or equivalently, the necessary details concerning tube target, accelerating voltage, and beam filtration), the development conditions, and the fluorescent screens used (if any) must be stated for the speed measure to be a valid and useful quantity.

\subsection{spectral analysis BM}
Fourier transform of a random process is another random process, and we are usually more interested in averages than in properties of individual samples.  In particular, with finite-power processes, we often want to know how the average power is distributed as a function of frequency.  Frequency-domain description of the average power is known as \textit{spectrum, power spectrum} or \textit{power spectral density}.
\newline
In the limit of an infinite number of realizations, \textit{Wiener-Khinchin theorem} amounts to incorporating a statistical average in the definition of the spectrum.  Khinchin's definition was:
\begin{equation}
S_{ac}(v) = \mathcal{F} \{ R(\Delta t) \} = \int_{-\infty}^{\infty} d \Delta t \langle f(t + \Delta t) f^{\ast} (t) \rangle exp(-2 \pi i\nu \Delta t),
\end{equation}
where the subscript $\mathit{ac}$ indicates that this version of the spectrum is derived from the autocorrelation function $\mathit{R(\Delta t)}$ of a stationary random process.  The spectrum defined this way is well behaved mathematically and universally used.

\noindent
$\mathit{Spatial power spectra}$
If we use the stationary spatial random process, then the spatial version of the Wiener-Khinchin theorem is:
\begin{equation}
S(\mathbf{\rho}) = \int_{\infty} d^q \Delta r \: R(\Delta \mathbf{r}) \, exp(-2 \pi i \mathbf{\rho} \cdot \Delta \mathbf{r}).
\end{equation}

\noindent
$\mathit{Stochastic Wigner distribution function}$
A general way of applying Fourier analysis to non-stationary random processes is to make use of the Wigner distribution function.  For a spatial random process $f(\mathbf{r})$, we define the stochastic Wigner function by:

\begin{equation}
W_f (\mathbf{r}_0, \mathbf{\rho}) = \int_{\infty} d^{q} \Delta r \; \langle f(\mathbf{r}_0 + \frac{1}{2} \Delta \mathbf{r}) f^{\ast}(\mathbf{r}_0 - \frac{1}{2}) \rangle
exp(-2 \pi i \mathbf{\rho} \cdot \Delta \mathbf{r}).
\end{equation}

\noindent Wigner distribution can be thought as a sliding-window Fourier transform, where the function itself serves as the window.
We can use the Wigner distribution function for a spatial random process and compare it to the Wiener-Khinchin theorem:
\begin{equation}
\begin{split}
S(\mathbf{\rho}) =& \int_{\infty} d^q \Delta r \langle f(r + \Delta r) f^*(r) \rangle exp(-2 \pi i \rho \cdot \Delta r) \\
= & \int_{\infty} d^q \Delta r \langle f(r_0 + \frac{1}{2} \Delta r) f^*(r_0 - \frac{1}{2} \Delta r) \rangle exp(-2\pi i \rho \cdot \Delta r),
\end{split}
\end{equation}
So if the process is stationary, the stochastic Wigner function is independent of $\mathbf{r}_0$ and is precisely the power spectral density.

For non-stationary processes, however, $W_f(r_0, \rho)$ is a function of $r_0$ as well as $\rho$; it can be interpreted as the spectral content associated with point $r_0$.
The Wigner distribution is just the Fourier transform of the short-range part of the autocorrelation function, modulated by the shift-variant strength of the slowly varying component at $r_0$.

\subsection{Notes from Handbook of medical imaging-Image quality metrics for Digital Systems (Chap3)}
The increment of exposure values used should be sufficient to adequately fit a curve to the data on both a logarithmic curve and a linear curve. For example, 0.03, 0.3, 3, and 30 mR, which covered the majority of the usable range of clinical exposures to be encountered.  The shape of the characteristic curve for most systems is not highly dependent on beam spectrum.  A reasonable compromise spectrum might be 70 $kV_p$ with 0.5-mm Cu filtration, because that is the spectrum has has been used for a number of MTF and DQE measurements~\citep{Dobbins1995}, \citep{Bradford1999}, \citep{Hillen1987}.
It is important to make multiple measurements of the exposure (but not image data, dosimeter) for the low-exposure range of the curve.  The need for multiple measurements of exposure is because of the limited precision of most exposure meters at low exposure.

\subsubsection{Signal-to-noise ratio}
For a given number of detected photons, N, and a stochastic signal fluctuation, $\sigma$, the maximum available signal-to-noise (SNR) is
\begin{equation}
\frac{S}{\sigma} = \frac{N}{\sqrt{N}} = \sqrt{N},
\end{equation}
because, for Poisson-distributed x-ray quanta, the standard deviation of measured pixel values goes as the square root of the mean number of quanta.  This is the ``raw'' signal-to-noise ratio, because all detected quanta are included in ``signal.''  Often of more interest is the differential signal-to-noise ratio, $SNR_{diff}$, which uses the difference in signal behind the object of interest relative to its background.
\begin{equation}
SNR_{diff} = \frac{\Delta S}{\sigma} = \frac{C \; S}{\sigma} = \frac{C \; N}{\sqrt{N}} = C \sqrt{N},
\end{equation}
where C is the contrast, $\Delta S / S$.
If an object has area A, and there are $N_a$ photons per unit area detected, then the measured $SNR_{diff}$ of the object is:
\begin{equation}
\begin{split}
& SNR_{diff} = C \; \sqrt{N} = C \; \sqrt{N_a A}.\\
& N_a = \frac{SNR_{diff}^2}{C^2 A}
\end{split}
\end{equation}

\subsubsection{MTF - handbook of medical imaging chap 3}
MTF traditionally has been described mathematically in one of two ways:
\begin{enumerate}
\item as the ratio of frequency content output vs frequency content input:
\begin{equation}
MTF(u,v) = \frac{|FT_{out}(u,v)|}{|FT_{in}(u,v)|}
\end{equation}

\item as the Fourier amplitude of the response to a delta-function input to the system:
\begin{equation}
MTF(u,v) = |OTF(u,v)|
\end{equation}
where OTF(u,v) is the optical transfer function, the Fourier transform (FT) of PSF.  Both of these descriptions are equivalent for systems without aliasing.  However, with aliasing, the two give different results.
\end{enumerate}
For digital imaging systems, all MTF are basically undersampled.
Three methods of measuring MTF, square wave, edge and slit.  Square wave is the least accurate, good for quick test.  Slit is good for measuring high frequencies and edge is good for low frequencies.  Ideally one should use both the edge and slit.

\subsubsection{Noise-power spectrum}
The noise-power spectrum may be understood in several ways.  First, it may be thought of as the variance of image intensity (i.e., image noise) divided among the various frequency components of the image.  Alternatively, the NPS may be pictured as the variance (per frequency bin) of a given spatial-frequency component in an ensemble of measurements of that spatial-frequency.  These concepts are equivalent.
NPS is the pixel variance spread over all frequencies.
There are two options for computing the NPS in the presence of a background signal.  One may either subtract the background signal from the image prior to NPS analysis, or may compute the ensemble-averaged Fourier transform square of the noise+signal and then subtract the square of the Fourier transform of the background signal.  Numerical simulation reveals that both are equivalent if an infinite number of values are averaged in the ensemble.  However, the certainty in measurement is better when one first subtracts off the background signal.

\begin{equation}
NPS(0) = (N \Delta x) \sigma^2_{ROImean}
\end{equation}
where N = number of points in the region of interest, $\Delta x$ is the sample interval (pixel size), $\sigma^2_{ROImean}$ is the variance inside the region of interest.

\comment{still need to read up on NPS, and noise aliasing, I just can't concentrate anymore}

\textbf{Measuring NPS experimentally}
The appropriate x-ray spectrum for the study must be selected.  Ideally, the same x-ray spectrum should be used for NPS measurement as was used for measurement of MTF.  There is unfortunately not accepted standard x-ray spectra for NPS measurements in the literature.  Many measurements have been made at 70 kV (including scree-film and some CR measurements).  Several beam filtrations have been quoted with 70 kV: 0.5 mm Cu (\citep{Dobbins1995}, \citep{Bradford1999}, \citep{Hillen1987}, \citep{Chotas1997} and 19 mm Al \citep{Samei1997}.
Once the spectrum has been selected, flat-field images over a range of exposure must be acquired.  Exposure values covering the usable dynamic range of the device should be used because the NPS is often exposure dependent (Exposure in terms of mR).  The characteristic curve of the device should be measured (linearity).
Once the flat-field images have been acquired, the next thing to be determined for NPS measurement is the size of ROI to be used for the analysis, and the number of ROIs to be averaged.    In practice, it is necessary to select the best possible values of ROI size (as given by N) and the number of ROIs in the ensemble average (as given my M), under the constraint of a finite amount of available data.
\begin{enumerate}
\item first choose N such that there is minimal distortion of the NPS
\item compute what certainty in the estimate of NPS is required.  This latter step gives the number of ensemble averages, M, required.
\end{enumerate}

\textbf{Fixed pattern noise}
It is important philosophically to include this structured noise, such as would occur from phosphor granularity in a phosphor screen, in the estimate of NPS.  It is included by default in all screen film NPS calculations.  It is important to include structured noise because it is part of the spatially-stochastic intensity variation that affects the ability of the observer to pick out a signal from the noise.
\subsubsection{NEQ and DQE}

From Handbook of medical imaging Volume 1, by Myers, chapter 9.
NEQ(v) can be interpreted as the frequency-dependent density of quanta at the input of a perfect detector that would yield the same output noise as the real detection system under evaluation.
\begin{equation}
SNR^2_{Ideal} = \int d \nu |\Delta \tilde{\bar{g}}(\nu)|^2 \; NEQ(\nu)
\end{equation}


\chapter{On-Policy Prediction with Approximation}

\section{Summary}

\subsection{Function approximation}
In the previous chapters tables were used to represent the value function. This means that every state is updated separately. If the number of states goes up, this becomes infeasible. The state function can be approximated by $\hat{v}(s, w)$, with $w \in \Re^d$, the dimension of w is much smaller then the number of states $d << |s|$. $\hat{v}$ generalizes the update of one state over many.

\subsection{The prediction objective $\overline{VE}$}

\begin{itemize}
	\item $\mu(s)$: state distribution/on-policy distribution, indicates how important a certain state is.
	\item $h(s)$: probability that the episode began in state $s$
	\item $\eta(s)$: number of timesteps spend on average in state $s$
\end{itemize}

The value function updates don't update the state estimation directly but have to adjust the weights of a function. A common metric used is the \textbf{mean squared value error} illustrated in equation~\ref{eq:mean squared value error}.

\begin{equation}
\overline{VE}(w) = \sum_{s \in S} \mu(s)\big[v_{\pi}(s) - \hat{v}(s, w) \big]^2
\label{eq:mean squared value error}
\end{equation}

When training a episodic task on-policy $\mu$ can be derived from $\eta$ using equation~\ref{eq:on-policy average time spend in state system of equations}. Solving the sytem of equations results in $\eta$, which can be used to find $\mu(s)$ $\mu = \frac{\mu(s)}{\sum_{s'}\mu(s')}$.

\begin{equation}
\eta(s) = h(s) + \sum_{\bar{s}} \eta(\bar{s}) \sum_a \pi(a | \bar{s})p(s | \bar{s}, a)
\label{eq:on-policy average time spend in state system of equations}
\end{equation}

The value function $\overline{VE}$ might not always be the the best option, but it's a common used one. The updates of the approximation sometime lead to a local optimum, and not to a global one.

\section{Stochastic gradient and semi-gradient methods}

\begin{itemize}
	\item $w = (w_1, w_2, ... w_d)^T$: weights
	\item $\hat{v}(s, w)$: approximation function
	\item $w_t$: update of $w$ at timestep $t$
\end{itemize}

Often there will be no $w$ that gets all the states right. So the $w$ with the lowest error is picked by stochastic gradient descent (SGD). If the actual value function is present the update of the approximation is equation~\ref{eq:gradient descent update rule}. However $v_{\pi}$ is not known in practice, so take $v_{\pi} \approx U_t$ and the update rule then becomes equation~\ref{eq:stochastic gradient descent update rule}.

\begin{equation}
\begin{split}
w_{t+1} & = w_t - \frac{1}{2} \alpha \nabla \big[ v_{\pi}(S_t) - \hat{v}(S_t, w_t) \big]^2 \\
& = w_t + \alpha \big[ v_{\pi}(S_t) - \hat{v}(S_t, w_t) \big] \hat{\nabla}(S_t, w_t)
\end{split}
\label{eq:gradient descent update rule}
\end{equation}

\begin{equation}
w_{t+1} = w_t + \alpha \big[ U_t - \hat{v}(S_t, w_t) \big] \hat{\nabla}(S_t, w_t)
\label{eq:stochastic gradient descent update rule}
\end{equation}

\textbf{Monte carlo methods} approximate $U_t=G_t$, the update rule then becomes equation~\ref{eq:stochastic gradient descent monte carlo update rule}. We know that $G_t$ is an unbiased estimate of $v_{\pi}$.($\EX[U_t | S_t = s]=v_{\pi}(s)$). With \textbf{bootstrapping methods}(equation~\ref{eq:bootstrapping Ut approximation}) this is not the case anymore, as $U_t$ relies on the weights $w_t$ it has a bias. They can however converge much quicker, but are as robust. We call these \textbf{semi-gradient methods}.

\begin{equation}
w_{t+1} = w_t + \alpha \big[ U_t - \hat{v}(S_t, w_t) \big] \hat{\nabla}(S_t, w_t)
\label{eq:stochastic gradient descent monte carlo update rule}
\end{equation}

\begin{equation}
U_t = \sum_{a,s',r} \pi(a|S_t)p(s', r| S_t, a)[r+ \gamma\hat{v}(s', w)]
\label{eq:bootstrapping Ut approximation}
\end{equation}

So the TD(0) algorithm with approximation is a \textbf{semi-gradient method}, the update is illustrated in equation~\ref{eq:TD(0) stochastic gradient update rule}.

\begin{equation}
w_{t+1} = w_t + \alpha \big[ R_{t+1} - \gamma \hat{v}(S_t, w_t) \big] \hat{\nabla}(S_t, w_t)
\label{eq:TD(0) stochastic gradient update rule}
\end{equation}

\textbf{State aggregation} is a simplified version of general function approximation. The states are grouped, and one component of $w$ represents the whole group.

\subsection{Linear methods}
\begin{itemize}
	\item $x(s)$: feature vector, representing basis functions
	\item $x_i \in S$: all features are just states
	\item $\hat{v}(s, w) = w^Tx(s) = \sum_{i=1}^{d}w_ix_i$: linear value function
	\item $\nabla \hat{v}(s, w) = x(s)$: gradient value function
\end{itemize}

Monte carlo with linear approximation has the update rule of equation~\ref{eq:monte carlo update gradient descent linear approximation}. It converges robustly to the global optimum.

\begin{equation}
w_{t+1} = w_t + \alpha \big[ G_t - \hat{v}(S_t, w_t) \big]x(s_t)
\label{eq:monte carlo update gradient descent linear approximation}
\end{equation}

TD(0) has the update rule of equation~\ref{eq:TD(0) update semi-gradient descent linear approximation}, which only converges to the local optimum.

\begin{equation}
\begin{split}
w_{t+1} & = w_t + \alpha \big( R_{t+1} + \gamma w_t^Tx_{t+1} - w_t^T x_t\big)x_t\\
& = w_t + \alpha \big[R_{t+1}x_t - x_t ( x_t - \gamma x_{t+1} )^Tw_t\big]
\end{split}
\label{eq:TD(0) update semi-gradient descent linear approximation}
\end{equation}

The expected TD(0) weight vector is derived from equation~\ref{eq:TD(0) update semi-gradient descent linear approximation} in equation~\ref{eq:TD(0) linear approximation expected weight vector}. The TD(0) steady state vector $w_{TD}$ can be solved from this as a fixed point $w_{TD} = A^{-1}b$.

\begin{equation}
\begin{split}
& \EX[w_{t+1}| w_t] = w_t + \alpha (b-Aw_t) \\
& b = \EX[R_{t+1}x_t] \in \Re^d \\
& A = \EX[x_t(x_t - \gamma x_{t+1})^T]
\end{split}
\label{eq:TD(0) linear approximation expected weight vector}
\end{equation}

The upper bound error of $\overline{VE}$ when using TD is defined by equation~\ref{eq:upper bound error TD(0) linear approximation}. The Monte Carlo error is $\min_w \overline{VE}$. When $\gamma$ is near zero the error  goes up drastically, but because it's a TD method, it has low variance.

\begin{equation}
\overline{VE}(W_{TD}) \leq \frac{1}{1-\gamma}\min_w \overline{VE}(w)
\label{eq:upper bound error TD(0) linear approximation}
\end{equation}

\subsection{Feature construction for Linear Methods}
A big limitation of the linear form is that no interactions between features can be modeled. Such as presence of a feature being good only in the absence of an other feature.

\subsubsection{Polynomials}
Polynomials are a simple way to model interpolation and regression. The calculation of the weights $w$ is still a linear problem.

\begin{itemize}
	\item high dimensional feature vector $x(s)= (1, s_1, s_2, s_1s_2, s_1^2,s_2^2,s_1^2s_2,s_1s_2^2,s_1^2,s_2^2)$
\end{itemize}

\begin{equation}
\begin{split}
x_i(s) = \prod_{j=1}^{k}s_j^{c_{i,j}} \\
c_{i,j} = {0, 1, ..., n} \\
(n+1)^k \text{ features} \\
\end{split}
\label{eq:n ordered polynomial basis feature}
\end{equation}

\subsubsection{Fourier basis}
The Fourier series(linear combination) can be a basis for the function approximation. It works good with SARSA on smooth functions, it has some problems with discontinuations.

\begin{equation}
\begin{split}
& x_i(s) = cos(\pi s^Tc^i), s \in [0,1] \\
& c^i = (c_1^i, ... c_k^i)  \\
& c_j^i \in {0, ..., n} \\
& (n+1)^k \text{ features}
\end{split}
\label{eq:fourier basis}
\end{equation}

\begin{equation}
\alpha_i = \frac{\alpha}{\sqrt{(c_1^i)^2 + ... + (c_k^i)^2}}
\label{eq:step size TD with fourier approximation}
\end{equation}

\subsubsection{Coarse Coding}
The state space is covered by overlapping shapes(typically circles). A state is a point on in the state space. All the shapes that have this point inside their borders become 1, the other zero. The shape/width of the shapes determines the generalization. Small shapes give very little generalization, while big ones will give a lot of generalization.

\subsubsection{Tile coding}
Similar to coarse coding, but the shapes (such as rectangle) do not overlap. Only points in the same tile are generalized with each other. In order to get the same kind of generalization as in coarse coding, several layers of tiles can be made. This results in faster then coarse coding, but equally good results. The step size is more intuitive $\alpha = \frac{1}{n}$ would move 1 tile per iteration. Or if there are multiple layers $\alpha = \frac{w}{n}$, with w the offset between the layers.

\subsubsection{Radial basis functions}
The Radian basis functions (RBF) are the natural generalization of coarse coding to continuous valued features. It can be anything in $[0,1]$, while the coarse coding is a Boolean.

\begin{itemize}
	\item $c_i$: position of the RBF curve
	\item $\sigma$: width of the RBF curve
\end{itemize}

\begin{equation}
x_i(s) = \exp \left( \frac{|| s - c_i ||^2}{2 \sigma_i^2} \right)
\end{equation}

\subsection{Selecting step-size parameters manually}

The classical choice for step size is $\alpha = \frac{1}{t}$, this works great with MC methods, but not with TD methods.

In the tabular case, $\alpha=1$ would eliminate the error after just one step. $\alpha=\frac{1}{\tau}$ eliminates the error after $\tau$ steps. This rule can be generalized to the linear approximation $\alpha = \EX[x^Tx]]$, with $x$ a random feature vector. This does assume that the size of $x^Tx$ is about constant.

\subsection{Nonlinear function approximation: Artificial Neural network}

The text in the book is rather vague, the only relevant take away is that TD-error's are used as well to update the value function if you use ANN.

\subsection{Least-Squared TD}
Earlier on in the chapter we used Least-Squares to do linear approximation. We ended up a fixed point $W_{TD}=A^{-1}b$ where $A=\EX[x_t(x_t - \gamma x_{t+1})^T]$ and $b=\EX[R_{t+1}x_t]$. Instead of interating over the fixed point, $W_{TD}$ can be found in 1 go.  This is illustrated in equation~\ref{eq:TDLS update equation}, a more detailed algorithm can be found on page 230 of the book.

\begin{equation}
\begin{split}
\hat{A}_t & = \sum_{k=0}^{t-1}x_k(x_k - \gamma x_{k+1})^T + \epsilon I \\
w_t & = \hat{A}_t^{-1}b_t
\end{split}
\label{eq:TDLS update equation}
\end{equation}

If all the samples are used in the update, we don't get the forgetting behavior of old samples, as we had before. This can cause some issues if the target policy $\pi$ is updated. There are some extra steps required to add forgetting in the algorithm. There is however no need to pick a step size, but you do have to pick the size of $\epsilon$, so this is not really a win.

\subsection{Memory-based function approximation}

Instead of using the training examples to find the proper value of function parameters. The training data itself can be saved, and when the approximation is called upon with a certain state. It could return the answer of \textbf{the nearest neighbor}. Alternatively \textbf{the weighted average} of a set of neighbors could be returned, or a surface could be fit on the neighbors. The value can then be approximated using this surface, this is called \textbf{locally weighted regression}.

The 2 major advantages of this kind of approximation are:
\begin{enumerate}
	\item No parameters.
	\item The effect on the value function of adding a sample to the set is immediate.
\end{enumerate}
Memory-based functions can however become slow in execution as the number of samples grows. This can be mitigated by using \textbf{k-d trees}, to speedup the look ups.

\subsection{Kernel-based function approximation}
Any linear parametric regression method that uses feature vectors can be recasted as kernel regression with $k(s',s)=x(s)^Tx(s)$. (the kernel trick)
\begin{itemize}
	\item $g(s)$: Target for the state s.
	\item $D$: Set of stored samples.
\end{itemize}

\begin{equation}
\hat{V}(s, D) = \sum_{s' \in D} k(s, s')g(s')
\end{equation}

The text on page 232-233 is very vague on this method, might require some further investigation.

\subsection{Looking deeper at on-policy learning: Interest and Emphasis}
Not all states are as relevant to the RL problem. For example states that only occur after a series of very poor choices don't need to have an as accurately value function as those frequently visited by the greedy policy.

\begin{itemize}
	\item $I_t$: interest, the degree to which we are interested in accurately valuing the state. An interest of $0$ means there is no interest, and a value of $1$ means it's of maximum interest
	\item $M_t$: emphasis, is multiplied with the learning rate
	\item $M_t = I_t + \gamma^nM_{t-n}$
\end{itemize}

\begin{equation}
w_{t+n} = w_{t+n-1} + \alpha M_t\big[ G_{t:n+n} - \hat{v}(s_t, w_{t+n-1}) \big] \nabla \hat{v}(s_t, w_{t+n-1})
\end{equation}

\section{Exercises}
\subsection{Exercise 9.1 page 209}
\textbf{Show that tabular methods such as presented in Part I of the book are a special case of linear function approximations. What would the feature vectors be?}

The weights $w$ would be the value that used to be in the table. The feature vectors x(s) would be a vector that is 1 on the state that is active so, if $S_t=3$ then $x(3) = (0, 0, 0, 1 , 0 , 0)^T$.(one hot encoding)) This means that the value function is the weight on the index of that state $\hat{v}(s=3, w)=w^Tx(3)=w[3]$.

\subsection{Exercise 9.2 page 211}
\textbf{Why does (9.17 in the book) define $(n+1)^k$ distinct features for dimension k?}
The highest degree of polynomial is $n$, so there are $n+1$ terms in a polygon that can be turned on or off. There are $k$ dimensions, so to the power of $k$.

\subsection{Exercise 9.3 page 211}
\textbf{What n and $c_{i,j}$ produce the feature vectors $x(s)=(1, s_1, s_2, s_1s_2, s_1^2,s_2^2,s_1^2s_2,s_1s_2^2,s_1^2,s_2^2)$?}

$1, s_1, s_2, s_1s_2, s_1^2,s_2^2,s_1^2s_2,s_1s_2^2,s_1^2,s_2^2$ has basis functions of a degree at most 2, and a dimension of 2 $(k=2)$. A max degree of 2 leads to $n=2$.

\begin{itemize}
	\item $c_{i,j}$: weight vector
	\item $i$: feature base index
	\item $j$: power of polynomial term
\end{itemize}

The basis functions exists at most out of 2 terms, one of each base index. The table below show the powers used on the terms to construct the base function.

\begin{center}
\begin{tabular}{c|c|c|c}
i & basis function & $c_{i,0}$ & $c_{i,1}$ \\
\hline
0 & $1$ & 0 & 1 \\
1 & $s_1$ & 1 & 0 \\
2 & $s_2$ & 0 & 1 \\
3 & $s_1s_2$ & 1 & 1 \\
4 & $s_1^2s_2$ & 2 & 1 \\
5 & $s_1s_2^2$ & 1 & 2 \\
6 & $s_1^2s_2^2$ & 2 & 2 \\
\end{tabular}
\end{center}

\subsection{Exercise 9.4 page 221}
\textbf{Suppose we believe that one of two state dimensions is more likely to have an effect on the value function than is the other, that generalization should be primarily across the dimension rather then along it. What kind of tilings could be used to take advantage of this prior knowledge}

This is mentioned on page 220, a form of tiling that is more elongated along the less relevant dimension could work very well.

\subsection{Exercise 9.5 page 223}

\begin{itemize}
	\item 7 dimensions
	\item 8 strip tiling's
	\item 7*8 = 56 dimension independent tiling's
	\item $\binom{7}{2}$=21 pairs of 2 dimensional
	\item total tiling's = 21*2 + 56 = 98
\end{itemize}

For any x, it will belong to exactly 8 strip tilings. And it will belong to 6 pairwise interactions so 12 tilings. To represent this you need at 20 non-zero entries equal to 1, therefore $\EX[x^Tx] = 20$. This leads to $\alpha = (\tau\EX[x^Tx])^{-1}=20^{-1}$

\subsection{Exercise 9.6 page 223}
\textbf{If $\tau=1$ prove that (9.19) together with (9.7) results in the error being reduced to zero in one update}

\begin{itemize}
	\item equation 9.19 from book page 223: $\alpha = (\tau \EX[x^Tx])^{-1}$
	\item equation 9.7 from book page 202: $w_{t+1} = w_t + \alpha \big[ U_t - \hat{v}(S_t, w_t)\big]\nabla \hat{v}(S_t, w_t)$
\end{itemize}

I am not sure how to continue here, it seems $\bar{x}$ must be $1$, for this to work out.

\begin{equation}
\begin{split}
w_{t+1} & = w_t + \alpha \big[ U_t - \hat{v}(S_t, w_t)\big]\nabla \hat{v}(S_t, w_t) \\
& = w_t +  \EX[x^Tx]^{-1}  e x \\
& = w_t +  (x^Tx)^{-1} ex \\
& = w_t +  e\bar{x} \\
e & =  U_t - \hat{v}(S_t, w_t) \\
e & = w_{t+1} - w_{t} \\
\bar{x} & = \frac{x}{x^Tx} \\
\nabla \hat{v}(S_t, w_t) & = x
\end{split}
\end{equation}


\documentclass[11pt,a4paper]{article}
\usepackage[top=1cm, bottom=1cm, left=2cm, right=2cm, includefoot, heightrounded]{geometry}
\usepackage{fontspec}
\setmainfont{Liberation Serif}

\title{\bf{Golang Workshop Exercises}}
\author{Baiju Muthukadan \\ Architect, ZeOmega}
\date{}

\begin{document}
\maketitle

\centerline{\LARGE\bf Exercises}
\section*{Exercise 1}
Write a program to print "Hello, World!" and save this in a
file named {\it helloworld.go}.  Compile the program and run
it like this: {\it./helloworld}

\section*{Exercise 2}
Write a program to print whether the number given as the command line
argument is even or odd

\section*{Exercise 3}
Write a program to print sum of all numbers below 50 completely
divisible by 3 or 5 (i.e., remainder 0)

\section*{Exercise 4}

Write a program to print area and perimeter of a given circle and
rectangle.  Use {\it struct} to represent circle and rectangle.  The
type of shape and dimensions can be read from command line as given
here:

\begin{verbatim}
$ ./shape circle 2
Area: 12.56
Perimeter: 12.56
$ ./shape rectangle 2 3
Area: 6
Perimeter: 8
\end{verbatim}

\section*{Exercise 5}

Update the previous program (Exercise 4) to use interfaces.

\section*{Exercise 6}

Rewrite the program in Exercise 2 using goroutine and channel.  The
task is to print sum of all numbers below 50 completely divisible by 3
or 5 (i.e., remainder 0)

\section*{Exercise 7}

Write a program to download a list of web pages concurrently using
Goroutines.

\noindent
Hint: Use this tool for serving junk content for testing:
https://github.com/baijum/lipsum

\newpage

\centerline{\LARGE\bf Answers}
\section*{Answer 1}

\begin{enumerate}
\item Content of {\it helloworld.go}:
\begin{verbatim}
package main

import "fmt"

func main() {
        fmt.Println("Hello, World!")
}
\end{verbatim}

\item Build program:
\begin{verbatim}
$ go build helloworld.go
\end{verbatim}

\item Run program and verify output like this:
\begin{verbatim}
$ ./helloworld
Hello, World!
\end{verbatim}
\end{enumerate}

\section*{Answer 2}
\begin{enumerate}
\item Content of the file {\it evenodd.go}:
\begin{verbatim}
package main

import (
        "fmt"
        "os"
        "strconv"
)

func main() {
        i := os.Args[1]
        n, err := strconv.Atoi(i)
        if err != nil {
                fmt.Println("Not a number:", i)
                os.Exit(1)
        }

        if n%2 == 0 {
                fmt.Println("even number:", n)
        } else {
                fmt.Println("odd number:", n)
        }
}
\end{verbatim}

\item Run program and verify output like this:
\begin{verbatim}
$ go run evenodd.go 2
even number: 2
$ go run evenodd.go 3
odd number: 3
\end{verbatim}

\end{enumerate}

\section*{Answer 3}
\begin{enumerate}
\item Content of the file {\it sum.go}:
\begin{verbatim}
package main

import "fmt"

func main() {
        sum := 0
        for i := 1; i < 50; i++ {
                if i%3 == 0 {
                        sum = sum + i
                } else {
                        if i%5 == 0 {
                                sum = sum + i
                        }
                }
        }
        fmt.Println(sum)
}
\end{verbatim}

\item Run program and verify output like this:
\begin{verbatim}
$ go run sum.go
543
\end{verbatim}

\end{enumerate}

\section*{Answer 4}
\begin{enumerate}
\item Content of the file {\it shapes.go}:
\begin{verbatim}
package main

import (
        "fmt"
        "os"
        "strconv"
)

type Rectangle struct {
        length float64
        width  float64
}

type Circle struct {
        radius float64
}

func (r Rectangle) Area() float64 {
        return r.length * r.width
}

func (r Rectangle) Perimeter() float64 {
        return 2 * (r.length + r.width)
}

func (c Circle) Area() float64 {
        return 3.14 * c.radius * c.radius
}

// Circumference
func (c Circle) Perimeter() float64 {
        return 2 * 3.14 * c.radius
}

func main() {

        shape := os.Args[1]

        if shape == "circle" {

                r := os.Args[2]
                radius, _ := strconv.Atoi(r)

                circle := Circle{float64(radius)}

                area := circle.Area()
                fmt.Println("Area:", area)

                perimeter := circle.Perimeter()
                fmt.Println("Perimeter:", perimeter)

        } else {
                w := os.Args[2]
                h := os.Args[3]

                width, _ := strconv.Atoi(w)
                height, _ := strconv.Atoi(h)

                rectangle := Rectangle{float64(width), float64(height)}

                area := rectangle.Area()
                fmt.Println("Area:", area)

                perimeter := rectangle.Perimeter()
                fmt.Println("Perimeter:", perimeter)
        }
}
\end{verbatim}

\item Run program and verify output like this:
\begin{verbatim}
$ go run shapes1.go circle 4
Area: 50.24
Perimeter: 25.12
$ go run shapes1.go rectangle 2 3
Area: 4
Perimeter: 8
\end{verbatim}

\end{enumerate}

\section*{Answer 5}
\begin{enumerate}
\item Change the previous source file ({\it shapes.go}) to include the below code:
\begin{verbatim}
type Geometry interface {
        Area() float64
        Perimeter() float64
}

func Measure(g Geometry) {
        area := g.Area()
        fmt.Println("Area:", area)

        perimeter := g.Perimeter()
        fmt.Println("Perimeter:", perimeter)
}

func main() {

        shape := os.Args[1]

        if shape == "circle" {

                r := os.Args[2]
                radius, _ := strconv.Atoi(r)

                circle := Circle{float64(radius)}
                Measure(circle)

        } else {
                w := os.Args[2]
                h := os.Args[3]

                width, _ := strconv.Atoi(w)
                height, _ := strconv.Atoi(h)

                rectangle := Rectangle{float64(width), float64(height)}
                Measure(rectangle)
        }
}
\end{verbatim}

\end{enumerate}

\section*{Answer 6}
\begin{enumerate}
\item Content of the file {\it newsum.go}:
\begin{verbatim}
package main

import "fmt"

func Sum(s chan int) {
        sum := 0
        for i := 1; i < 50; i++ {
                if i%3 == 0 {
                        sum = sum + i
                } else {
                        if i%5 == 0 {
                                sum = sum + i
                        }
                }
        }
        s <- sum
}

func main() {
        t := make(chan int)
        go Sum(t)
        fmt.Println("Sum:", <-t)
}
\end{verbatim}

\item Run program and verify output like this:
\begin{verbatim}
$ go run sum.go
543
\end{verbatim}

\end{enumerate}

\section*{Answer 7}
\begin{enumerate}
\item Content of the file {\it download.go}:
\begin{verbatim}
package main

import (
        "io/ioutil"
        "log"
        "net/http"
        "net/url"
        "sync"
)

func main() {
        urls := []string{
                "http://localhost:9999/1.txt",
                "http://localhost:9999/2.txt",
                "http://localhost:9999/3.txt",
                "http://localhost:9999/4.txt",
        }
        var wg sync.WaitGroup
        for _, u := range urls {
                wg.Add(1)
                go func(u string) {
                        defer wg.Done()
                        ul, err := url.Parse(u)
                        fn := ul.Path[1:len(ul.Path)]
                        res, err := http.Get(u)
                        if err != nil {
                                log.Println(err, u)
                        }
                        content, _ := ioutil.ReadAll(res.Body)
                        ioutil.WriteFile(fn, content, 0644)
                        res.Body.Close()
                }(u)
        }
        wg.Wait()
}
\end{verbatim}
\end{enumerate}

\end{document}


% ***********************************************************************************
% Pure LaTeX part to be inserted in a document (be careful of depencies of packages & commands)
% Prepared by XXX and YYY under the supervision of Arnaud de La Fortelle
% Fall 2017
% 12 random walk subsection of the simulation part
% ***********************************************************************************

\subgroup{4}{Yue Hu, Carlin Liao and Robert Ruigrok}

\paragraph{Model presentation}
In this example we simulate the random walk of a particle in a 2D space. A random walk is a mathematical object, known as a stochastic or random process, that describes a path that consists of a succession of random steps. In order to simulate this process, we let a particle move over a discretized grid where its motion is drawn from a set of possible directions. In this simulation we are interested in finding expected distribution of particles after a certain number of time steps as well as the position where they hit the boundaries of the spatial grid.\newline

A particle starts at a specified initial position, from where it begins moving through the grid. In our code, we used a coordinate system to represent the location of a particle as provided in figure \ref{fig:RandomWalkGrid}. The outer border of the grid is enclosed by a ``wall''. When the particle hits this wall, its motion stops and the location where it makes contact is registered.

\begin{figure}[htb]
    \label{fig:RandomWalkGrid}
	\centering
	\includegraphics[width=6cm]{RandomWalkGrid.png}
	\caption{Coordinate representation in spatial grid}
\end{figure}

The dynamics of a particle are relatively straightforward and can be described by equation \ref{eq:RandomWalkDynamics}. A particle has 5 options for its motion: moving up, right, down, left or no motion (options are depicted in figure \ref{fig:RandomWalkMotion}). Every motion has a certain probability $p$ to occur. These probabilities can be given as input and must add up to 1.

\begin{equation}
\label{eq:RandomWalkDynamics}
X_{k+1}(x,y) = X_k(x,y) +  \begin{cases}
(0,1) &\text{with probability $p\uparrow$}\\
(1,0) &\text{with probability $p\rightarrow$}\\
(0,-1) &\text{with probability $p\downarrow$}\\
(-1,0) &\text{with probability $p\leftarrow$}\\
(0,0) &\text{with probability $p\ \bullet$}
\end{cases}
\end{equation}

\begin{figure}[htb]
    \label{fig:RandomWalkMotion}
	\centering
	\includegraphics[width=3cm]{RandomWalkMotion.png}
	\caption{Potential motion per time step}
\end{figure}

\paragraph{Implementation}
At the top of the file, it is possible to set the grid size, starting position of particles, \# of particles, simulation horizon and motion direction probabilities. The script will also generate snapshots of the particle distribution at different moments in time during the simulation. By selecting the number of subplots, you can determine how many instances you would like to see. This will provide insights into how the particle distribution develops over time. \newline

Particles are simulated one at a time. The simulation runs until the time horizon $T$ is reached or the particle hits the wall. Their position is saved in a 3-dimensional array (time, x-position, y-position) at specified moments in time only; this way the amount of required memory is kept to a minimum. %You do not save the position of every particle at every time step, but you only ``count'' their positions at time steps that you are interested in. Information about individual particles gets lost, but that is fine.
\newline

Information about where particles hit the wall is included in the same arrays. This data ``circumvents'' the $n \times n$ data about the particle distribution within the grid. As a result, when we plot the full array we can see the distribution of particles in the grid at their respective location, and the distribution of particles at the wall directly ``behind'' the wall.\newline

\begin{lstlisting}[language = python, caption = 2D Ramdom Walk Simulation]
import numpy as np
import matplotlib.pyplot as plt
from random import *
import pylab

############## START INPUT #################

GridSize = 20 # will create an 20x20 square grid
Pos_init = np.ceil(np.array([0.4,0.4])*GridSize)  # start position
T = 0.3*np.power(GridSizeSquare, 2)  # total # of time steps
n_particles = 10000 # number of particles, 10000+ recommended
# specify subplots for intermediate time snap shots
subplot_row = 2
subplot_column = 2
#define the probabilities of motion: ([up,right,down,left,0])
motion_prob = np.array([0.2,0.2,0.2,0.2,0.2])

############## END INPUT #################

x_grid = GridSizeSquare
y_grid = GridSizeSquare
n_subplot = subplot_row*subplot_column
# calculate time step for snapshots of process
Plot_interval = np.floor((T-1)/(n_subplot-1))
# Normalize probabilities in case they don't add up to 1
motion_prob = motion_prob/np.sum(motion_prob)
# define the change in coordinates of every motion:
motion_xy = np.array([[0,1],[1,0],[0,-1],[-1,0],[0,0],])
motion_prob_sum = np.cumsum(motion_prob)
# this is used later to draw from with randomizer

# make an empty data grid to sum the particle positions
Data = np.zeros((x_grid+2,y_grid+2))  # +2 for wall data
# Some resizing here and later are for ploting purposes
Data_resized = np.zeros((Data.shape[0]+1,Data.shape[1]+1))
# Create a new empty data set for the intermediate plots:
Data_Snap=np.zeros((n_subplot,Data_resized.shape[0],Data_resized.shape[1]))

# construct some arrays for plotting later on:
xx, yy = pylab.meshgrid(
    pylab.linspace(-1,x_grid+1,x_grid+3),
    pylab.linspace(-1,y_grid+1,y_grid+3))

# start loop over all the particles
for i in range(1, n_particles+1):
    # Initialize simulation
    t = 0
    HitWall = False
    Pos = Pos_init
    Subplot = 1

    # Simulation Process
    while t < T and not HitWall:
        MotionRandom = random()
        IndexMotion = np.argmax(motion_prob_sum>MotionRandom)
        Pos = Pos + motion_xy[IndexMotion,:]

        # Now check for hitting the wall
        if Pos[0] == 0|x_grid+1 or Pos[1] == 0|y_grid+1:
            if Subplot <= n_subplot:
                Data_Snap[Subplot-1,Pos[0],Pos[1]] = \
                Data_Snap[Subplot-1,Pos[0],Pos[1]]+1
            HitWall = True

        # Record the position for each time snap
        if t % Plot_interval==0 and Subplot <= n_subplot and not(HitWall):
            Data_Snap[Subplot-1,Pos[0],Pos[1]] =\
            Data_Snap[Subplot-1,Pos[0],Pos[1]]+1
            Subplot = Subplot+1

        t = t+1

    #Save the final results
    Data[Pos[0],Pos[1]] = Data[Pos[0],Pos[1]] + 1
    Data_resized[:-1,:-1] = Data

# Add the particles that hit the wall in earlier time steps
# to the later plots
Data_Snap_New = np.cumsum(Data_Snap,axis=0)
Data_Snap_New[:,1:x_grid+1,1:y_grid+1] = Data_Snap[:,1:x_grid+1,1:y_grid+1]

# Visualize the outcomes at each snap of process
plt.figure()
for j in range(1, n_subplot+1):
    pylab.subplot(subplot_row, subplot_column, j)
    pylab.pcolor(xx,yy,np.transpose(Data_Snap_New[j-1,:,:]))
    Str = 'Distribution at t = ' + str((j-1)*Plot_interval+1)
    pylab.title(Str)
    # add a color bar
    pylab.colorbar()
    pylab.hold(True)
    pylab.plot([0, x_grid],[0, 0], 'r',
               [0, x_grid],[y_grid, y_grid], 'r',[0, 0],[0, y_grid], 'r',
               [x_grid, x_grid],[0, y_grid], 'r')
    pylab.plot(Pos_init[0]-0.5,Pos_init[1]-0.5,'ro')

pylab.show()

# Plot the final distribution
plt.figure()
pylab.pcolor(xx,yy,np.transpose(Data_resized))
pylab.title('Final distribution at t = %d, including hitting walls' %T)
# add a color bar
pylab.colorbar()
pylab.hold(True)
pylab.plot([0, x_grid],[0, 0], 'r',
           [0, x_grid],[y_grid, y_grid], 'r',[0, 0],[0, y_grid], 'r',
           [x_grid, x_grid],[0, y_grid], 'r')
pylab.plot(Pos_init[0]-0.5,Pos_init[1]-0.5,'ro')
pylab.show
\end{lstlisting}

\paragraph{Results}
In this section we included two simulation for both a $10x10$ grid and a $20 \times 20$ grid, with a different simulation time horizon $T$. Both simulations use 10,000 particles and have a motion probability of $0.2$ in all directions. \newline

It is clearly visible how the particles spread out over time and make their way to the walls over time. The more particles that are simulated per grid resolution, the smoother the distribution becomes. You can clearly see that 10,000 particles simulated lead to a clean distribution in the smaller plot of figure \ref{fig:RandomWalk10}, while the larger plot of \ref{fig:RandomWalk20} shows a more grainy distribution.

\begin{figure}[htb]
    \label{fig:RandomWalk10}
	\centering
	\includegraphics[width=14cm]{figure10x10.png}
	\caption{Particle distribution for $10 \times 10$ grid at different time steps}
\end{figure}

\begin{figure}[htb]
    \label{fig:RandomWalk20}
	\centering
	\includegraphics[width=14cm]{figure20x20.png}
	\caption{Particle distribution for $20 \times 20$ grid at different time steps}
\end{figure}

\paragraph{Interpretation}
{\it Relate these quantities to the model and to theoretical knowledge of the course.}\newline

{\it I think this motion is described by Fick's Law in 2 dimension. The concentration on a specific point changes over time, depending on the concentration of its surroundings. Should we derive why the second derivative matters? $\phi$ is the concentration, $D$ the diffusion coefficient.}

\begin{equation}
\label{eq:FicksLaw}
\frac{d\phi}{dt} = D\nabla\phi = D \big(\frac{d^2\phi}{dx^2} + \frac{d^2\phi}{dy^2}\big)
\end{equation}

 \paragraph{Conclusion}
 \textit{What have we learned? Is everything aligned (theory and practice)? What was difficult? Provide perspectives.}

 The dynamics of the random walk were easy to model. The challenge in this simulation was to save the data for the intermediate time steps. Since the particles are simulated one by one for the full time horizon, we had to write some non-intuitive code to save the location of every particle at the relevant intermediate time steps. \newline

 From the lecture we recall that diffusion distance scales with the square root of time. Here we tried to simulate that. When doubling the grid size and taking a four times higher simulation horizon, the distribution looks similar. However, we have the idea that the scaling did not work for 100\%. At the end of the scaled simulation horizon, it seems as if the smaller grid has relatively more particles in the grid than the larger grid has. What could cause this difference?


\documentclass[12pt]{article}
\usepackage{amsfonts,amsmath}
\usepackage{fourier}

\title{Problem Description}

\begin{document}
\maketitle

\section{Introduction}

In this document, we aim to detail the implementation of a Fortran project using ...

\section{Problem Description}

Given some matrix $P \in {\mathbb{R}}^{4\times 4}$, let $x=(x_1,x_2,x_3,x_4)$, $D = \text{diag}(x)$ and $\varepsilon = (\varepsilon_{ij}) \in \mathbb{R}^{4\times 4}$. We are interested in solving the following problem:

\begin{align*}
	\text{minimize} & \qquad \sum_{i=1}^4\sum_{j=1}^4 \varepsilon_{ij}^2\\
	\text{subject to} & \qquad x_4=1\\
    & \qquad D(P+\varepsilon) \text{ must be persymmetric.}
\end{align*}
This can be written as the following problem:
\begin{align*}
	\text{minimize} & \quad \sum_{i=1}^4\sum_{j=1}^4 \varepsilon_{ij}^2\\
	\text{subject to} & \quad x_4=1\\
	& \quad x_i (P_{ij}+\varepsilon_{ij}) - x_{\alpha(j)} (P_{\alpha(j)\alpha(i)}+\varepsilon_ {\alpha(j)\alpha(i)}) = 0,\\
    & \quad \text{for } i=1, 2, 3, j=1, \ldots, 4-i \text{ where } \alpha(i)=5-i.
\end{align*}

\section{Solving}

\section{Results}
\end{document}


% TeX Source
%
% Author: Tetsuya Ishikawa <tiskw111gmail.com>
% Date  : October 16, 2021
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SOURCE START %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\documentclass[twocolumn, a4paper, 10pt]{article}
\usepackage{tiskw}

\begin{document}

\title{Random Fourier Features for Gaussian Process Model}
\author{Tetsuya Ishikawa \\ \normalsize\texttt{tiskw111@gmail.com}}
\maketitle

\section*{Abstract}\titlebar
% {{{

This article describes the procedure for applying random Fourier features~\cite{Rasmussen2006}
to the Gaussian process model~\cite{Rahimi2007}. This makes it possible to speed up the training
and inference of the Gaussian process model, and to apply the model to larger data.

The Gaussian process model~\cite{Rahimi2007} is one of the supervised machine learning frameworks
designed on a probability space, and is widely used for regression and classification tasks, like
support vector machine and random forest. The major difference between Gaussian process models and
other machine learning models is that the Gaussian process model is a \textit{stochastic} model.
In other words, since the Gaussian process model is formulated as a stochastic model,
it can provide not only the predicted value but also a measure of uncertainty for the prediction.
This is a very useful property that can improve the explainability of machine learning model.

On the other hand, the Gaussian process model is also known for its high computational cost
of training and inrefence. If the total number of training data is $N \in \mathbb{Z}^{+}$,
the computational cost required for training the Gaussian process model is $O(N^3)$, and
computational cost required for inference is $O(N^2)$, where $O$ is the
\textit{Bachmann–Landau notation}. The problem is that the computational cost is given by
a power of the total number of training data $N$, which can be an obstacle when appliying
the model to large-scale data. This comes from the fact that the Gaussian process model has
the same mathematical structure as the kernel method, in other words,
the kernel support vector machine also has the same problem.

One of the methods to speed up the kernel method is random Fourier features~\cite{Rasmussen2006}
(hereinafter abbreviated as RFF). This method can significantly reduces the computational cost
while keeping the flexibility of the kernel method by approximating the kernel function as the inner
product of finite dimensional vectors. Specifically, the compurational cost required for training
can be reduced to $O(N D^2)$, and the amount of calculation required for inference can be reduced
to $O(D^2)$. However, $D \in \mathbb{Z}^{+}$ is a hyperparameter of RFF and can be specified
independently of the total number of training data $N$.

Since the Gaussian process model has the same mathematical structure as the kernel method,
RFF can be applied to the Gaussian process model as well. This evolves the Gaussian process model
into a more powerful, easy-to-use, and highly reliable ML tool.

However, when applying RFF to a Gaussian process model, some mathematical techniques are required
that are not straightforward. However, unfortunately, there seems to be no articles in the world
that mentions it's difficulties and solutions, so I left an explanation of the procedure.

If you preffer the Japanese version of this document, see this repository
\footnote{\texttt{https://github.com/tiskw/mathematical-articles}}.

% }}}

\section{Gaussian Process Model Revisited}\titlebar
% {{{

This section gives an overview of the Gaussian process model. Unfortunately, this document
does not cover details such as the formulation and derivation of Gaussian process models,
so if you are interested in the details, please refer \cite{Rasmussen2006}.

Let $\mathcal{D} = \{(\bs{x}_n, y_n)\}_{n=1}^{N}$ be a training data, and $\sigma \in \mathbb{R}^{+}$
be a standard deviation of the label observation error, where $\bs{x}_n \in \mathbb{R}^M$, $y_n \in \mathbb{R}$.
The Gaussian process model describes the prediction as a probability variable that follows normal distribution.
If the test date is $\bs{\xi} \in \mathbb{R}^M$, the expectation and standard deviation is given by:
\begin{equation}
    m (\bs{\xi}) = \widehat{m} (\bs{\xi}) + \left( \bs{y} - \widehat{\bs{m}} \right)\tran
    \left (\bs{K} + \sigma^2 \bs{I} \right)^{-1} \bs{k} (\bs {\xi}),
    \label{eqn:gp_exp} \\
\end{equation}
and the covariance of the test data $\bs{\xi}_1$, $\bs{\xi}_2$ is given by:
\begin{equation}
    v (\bs{\xi}_1, \bs{\xi}_2) = k (\bs{\xi}_1, \bs{\xi}_2)
    - \bs{k} (\bs{\xi}_1)\tran \left( \bs{K} - \sigma^2 \bs{I} \right)^{-1} \bs{k} (\bs{\xi}_2),
    \label{eqn:gp_cov}
\end{equation}
where the function $k: \mathbb{R}^M \times \mathbb{R}^M \to \mathbb{R}$ is a kernel function,
the matrix $\bs{K} \in \mathbb{R}^{N \times N}$ is a kernel matrix defined as
\begin {equation}
    \bs{K} = \begin{pmatrix}
        k (\bs{x}_1, \bs{x}_1) & \cdots & k (\bs{x}_1, \bs{x}_N) \\
        \vdots & \ddots & \vdots \\
        k (\bs{x}_N, \bs{x}_1) & \cdots & k (\bs{x}_N, \bs{x}_N) \\
    \end{pmatrix},
\end{equation}
and the vector $\bs{k} (\bs {\xi}) \in \mathbb{R}^N$ and
the vector $\bs{y} \in \mathbb{R}^N$ is defined as
\begin{equation}
    \bs{k} (\bs{\xi}) = \begin{pmatrix}
        k (\bs{\xi}, \bs{x}_1) \\
        \vdots \\
        k (\bs{\xi}, \bs{x}_N) \\
    \end{pmatrix},
    \hspace{10pt}
    \bs{y} = \begin{pmatrix}
        y_1 \\ \vdots \\ y_N \\
    \end{pmatrix},
\end{equation}
respectively.
Also, $\widehat{m} (\bs{\xi})$ is the prior distribution of the prediction, and
$\widehat{\bs{m}} = (\widehat{m} (\bs{x}_1), \ldots, \widehat{m} (\bs{x}_N))\tran$ is
the prior distribution of the predicted values of the training data. If you don't need to set
prior distribution, it's common to set $\widehat{m} (\cdot) = 0$ and $\widehat{\bs{m}} = \bs{0}$.

You can compute the variance of the prediction of the test data $\bs{\xi}$
by substituting $\bs{\xi}_1 = \bs{\xi}_2 = \bs{\xi}$ into the equation (\ref{eqn:gp_cov}),
\begin{equation}
    v (\bs{\xi}, \bs{\xi}) = k (\bs{\xi}, \bs{\xi})
    - \bs{k} (\bs{\xi})\tran \left( \bs{K} - \sigma^2 \bs{I} \right)^{-1} \bs{k} (\bs{\xi}).
\end{equation}

% }}}

\section{RFF Revisited}\titlebar
% {{{

This section, we revisit random Fourier features. Unfortunately, this article don't have
enough space to explain the details, therefore if you would like to know more details,
please refer to the original paper \cite{Rahimi2007}.

Let the function $k: \mathbb{R}^M \times \mathbb{R}^M \to \mathbb{R}$ be the kernel function.
In RFF, the kernel function can be approximated as
\begin{equation}
    k (\bs{x}_1, \bs{x}_2) \simeq \bs{\phi} ({\bs{x}_1})\tran \bs{\phi} ({\bs{x}_2) }),
    \label{eqn:rff_kernel_approx}
\end{equation}
where the dimension $D$ of the vector $\bs{\phi} (\bs{x}_1)$ is a hyperparamter of RFF.
The larger the dimension $D$, the higher the approximation accuracy of the equation
(\ref{eqn:rff_kernel_approx}), while the larger the dimension $D$, the greater compurational cost.

For example, in the case of the RBF kernel
\begin{equation}
    k (\bs{x}_1, \bs{x}_2) = \exp \left (- \gamma \| \bs{x}_1 - \bs{x}_2 \|^2 \right),
\end{equation}
which is famous as one of the kernel functions, the vector $\bs{\phi} (\bs{x})$ is given by
\begin{equation}
    \bs{\phi} (\bs{x}) = \begin{pmatrix}
        \cos \bs{Wx} \\
        \sin \bs{Wx}
    \end{pmatrix},
\end{equation}
where, the matrix $\bs{W} \in \mathbb{R}^{D/2 \times M} $ is a random matrix in which each element
is sampled from the normal distribution $\mathcal{N} (0, \frac{1}{4 \gamma})$.

% }}}

\section{Gaussian process model and RFF}\titlebar
% {{{

In this section, we apply RFF to the Gaussian process model
and theoretically confirm the effect of speeding up.

\subsection{Computational complexity of Gaussian process model before applying RFF}

First, let's check the computational cost required for training and inferring a normal Gaussian
process model. As a premise, it is assumed that the number of training data $N \in \mathbb{Z}^{+}$
is sufficiently larger than the dimension $M \in \mathbb{Z}^{+}$ of the input vector and
dimention $D \in \mathbb{Z}^{+}$ which is a hyperparameter of RFF. Here, the bottleneck of
training computational cost is obviously the calculation of the inverse matrix
$\left (\bs{K} + \sigma^2 \bs{I} \right)^{-1}$ in the formulas (\ref{eqn:gp_exp}) and (\ref{eqn:gp_cov}).
Since the size of this matrix is $N \times N$, the computational cost for training is $O(N^3)$.

Next, the bottleneck of the inference is matrix multiplications
$\left (\bs{y} -\widehat{\bs{m}} \right)\tran \left( \bs{K} + \sigma^2 \bs{I} \right)^{-1}$ or
$\bs{k} (\bs{\xi}_1)\tran \left( \bs{K} - \sigma^2 \bs{I} \right)^{-1} \bs{k} (\bs{\xi}_2)$,
and either of these computational cost is $O(N)$.

\subsection{Applying RFF to expectation of prediction}

Now, let's apply RFF to the Gaussian process model. First of all, if you substitute the RFF
approximation formula (\ref{eqn:gp_cov}) into the formula of expectation of the prediction
in the Gaussian process (\ref{eqn:gp_exp}), you'll get
\begin{equation}
    m (\bs{\xi}) = \widehat{m} (\bs{\xi}) + \left( \bs{y} - \widehat{\bs{m}} \right)\tran
    \left( \bs{\Phi}\tran \bs{\Phi} + \sigma^2 \bs{I} \right)^{-1} \bs{\Phi}\tran \bs{\phi} (\bs{\xi}),
    \label{eqn:rffgp_exp_naive}
\end{equation}
where the matrix $\bs{\Phi} \in \mathbb{R}^{D \times N}$ is defined as
$\bs{\Phi} = (\bs{\phi} (\bs{x}_1), \ldots, \bs{\phi} (\bs{x}_N))$.
However, this has not yet speeded up. The complexity bottleneck of the above expression
(\ref{eqn:rffgp_exp_naive}) is still the inverse of the $N \times N$ matrix
$\left( \bs{\Phi}\tran \bs{\Phi} + \sigma^2 \bs{I} \right)^{-1}$.

Now we will add a bit of contrivance to the equation (\ref{eqn:rffgp_exp_naive}).
At first, let us introduce the \textit{matrix inversion lemma} (it's also referred as
\textit{binominal inverse lemma}) which is a useful formula for expansion of matrix inverse.

\begin{theorem}[Matrix Inversion Lemma]
    Let
    $\bs{A} \in \mathbb{R^{N \times N}}$,
    $\bs{B} \in \mathbb{R^{N \times M}}$,
    $\bs{C} \in \mathbb{R^{M \times N}}$,
    and
    $\bs{D} \in \mathbb{R^{M \times M}}$
    be real matrices. Then the equation
    \begin{equation}
        \left( \bs{A} + \bs{BDC} \right)^{-1} = \bs {A}^{-1} - \bs{A}^{-1} \bs{B}
        \left( \bs{D}^{-1} + \bs{CA}^{-1} \bs{B} \right)^{-1} \bs{CA}^{-1}
        \label{eqn:matrix_inversion_lemma}
    \end{equation}
    holds, where the matrix $\bs{A}$ and $\bs{D}$ are regular matrices.
\end{theorem}

The proof of the matrix inversion lemma is given at the end of this article,
and let us move on to the utilization of the lemma to the equation (\ref{eqn:rffgp_exp_naive}).

By replacing $\bs{A} = \sigma^2 \bs{I}$, $\bs{B} = \bs{\Phi}\tran$, $\bs{C} = \bs{\Phi}$,
and $\bs{D} = \bs{I}$ on the equation (\ref{eqn:matrix_inversion_lemma}),
we obtain the following equation:
\begin{equation}
    \left( \bs{\Phi}\tran \bs{\Phi} + \sigma^2 \bs{I} \right)^{-1}
    = \frac{1}{\sigma^2} \left (\bs{I} - \bs{\Phi}\tran
    \left( \bs{\Phi \Phi}\tran + \sigma^2 \bs{I} \right)^{-1} \bs{\Phi} \right),
    \label{eqn:rffgp_exp_solving}
\end{equation}
where $\bs{P} = \bs{\Phi \Phi}\tran \in \mathbb{R}^{D \times D}$.
Then multiply $\bs{\Phi}$ from the right the to the above equation (\ref{eqn:rffgp_exp_solving}),
we get
\begin{equation}
    \left( \bs{\Phi}\tran \bs{\Phi} + \sigma^2 \bs{I} \right)^{-1} \bs{\Phi}
    = \frac{1}{\sigma^2} \bs{\Phi}\tran
    \left( \bs{I} - \left( \bs{P} + \sigma^2 \bs{I} \right)^{-1} \bs{P} \right).
    \label{eqn:rff_key_eqn}
\end{equation}
Therefore, the expression (\ref{eqn:rffgp_exp_naive}) can be written as
\begin{equation}
    m (\bs{\xi}) = \widehat{m} (\bs{\xi}) + \frac{1}{\sigma^2}
    \left( \bs{y} - \widehat{\bs{m}} \right)\tran \bs{\Phi}\tran \bs{S},
    \label{eqn:rffgp_exp}
\end{equation}
where
\begin{equation}
    \bs{S} = \bs{I} - \left( \bs{P} + \sigma^2 \bs{I} \right)^{-1} \bs{P}.
    \label{eqn:rffgp_exp_cache}
\end{equation}

Clever readers would have already noticed that the bottleneck has been resolved.
The inverse matrix $(\bs{K} + \sigma^2 \bs{I})^{-1}$, which was the bottleneck of
the expression (\ref{eqn:rffgp_exp_naive}), became $(\bs {P} + \sigma^2 \bs{I})^{-1}$
in the expressions (\ref{eqn:rffgp_exp}) and (\ref{eqn:rffgp_exp_cache}) where the size of
the inverse matrix is $D \times D$. Normally, the RFF dimension $D$ is set sufficiently
smaller than the number of training data $N$, therefore the inverse matrix
$(\bs {P} + \sigma^2 \bs{I})^{-1}$ is no longer a bottleneck of computational cost.
The bottleneck of the expressions (\ref{eqn:rffgp_exp}) and (\ref{eqn:rffgp_exp_cache})
is the matrix product $\bs{P} = \bs{\Phi \Phi}\tran$, whoes computational cost is $O(ND^2)$.
Therefore we've achieved a considerable speedup of the training of the Gaussian process model
by applying RFF because the calculational cost before RFF is $O(N^3)$.

\subsection{Applying RFF to covariance of prediction}

Next, we apply RFF to the covariance of the prediction (\ref{eqn:gp_cov}).
By substitute RFF approximation (\ref{eqn:rff_key_eqn}) to the expression (\ref{eqn:gp_cov}),
we obtain
\begin{align}
    v (\bs{\xi}_1, \bs{\xi}_2)
    & = \bs{\phi} (\bs{\xi}_1)\tran \bs{\phi} (\bs{\xi}_2)
    - \frac{1}{\sigma^2} \bs{\phi} (\bs{\xi}_1)\tran \bs{PS} \bs{\phi} (\bs{\xi}_2) \notag \\
    & = \bs{\phi} (\bs{\xi}_1)\tran
    \left( \bs{I} - \frac{1}{\sigma^2} \bs{PS} \right)
    \bs{\phi} (\bs{\xi}_2),
    \label{eqn:rffgp_cov}
\end{align}
The bottleneck of the expression (\ref{eqn:rffgp_cov}) is, as the same as the expectation of the
prediction, the matrix product $\bs{P} = \bs{\Phi \Phi}\tran$ whoes calculation cost is $O(ND^2)$.

The procedure of training and inference of the Gaussian process model after applying RFF is
descrived in algorithm \ref{alg:rffgp_train} and \ref{alg:rffgp_infer} as pseudo code.
Note that the prior distribution of the Gaussian process model is set to 0 for the sake of
simplicity in Algorithm \ref{alg:rffgp_train} and \ref{alg:rffgp_infer}.

\begin{algorithm}[t]
    \caption{\bf Training of the GP model after RFF}
    \label{alg:rffgp_train}
    \KwData{$\mathcal{D} = \left\{ (\bs{x}_n, y_n) \right\}_{n=1}^{N}$, \, $\sigma \in \mathbb{R}^{+}$}
    \KwResult{$\bs{c}_\mathrm{m} \in \mathbb{R}^D$, \, $\bs{C}_\mathrm{v} \in \mathbb{R}^{D \times D}$}
    $\bs{y} \gets (y_1, \ldots, y_N)\tran$ \\
    $\bs{\Phi} \gets (\bs{\phi}(\bs{x}_1), \ldots, \bs{\phi}(\bs{x}_N))$ \\
    $\bs{P} \gets \bs{\Phi\Phi}\tran$ \\
    $\bs{S} \gets \bs{I} - \left( \bs{P} + \sigma^2 \bs{I} \right)^{-1} \bs{P}$ \\
    $\bs{c}_\mathrm{m} \gets \frac{1}{\sigma^2} \bs{y}\tran \bs{\Phi}\tran \bs{S}$
    \hfill\Comment{{\footnotesize Cache for expectation}\hspace*{-48pt}\mbox{}}
    $\bs{C}_\mathrm{v} \gets \bs{I} - \frac{1}{\sigma^2} \bs{PS}$
    \hfill\Comment{{\footnotesize Cache for covariance}\hspace*{-45pt}\mbox{}}
\end{algorithm}

\begin{algorithm}[t]
    \caption{\bf Inference of the GP model after RFF}
    \label{alg:rffgp_infer}
    \KwData{$\bs{\xi} \in \mathbb{R}^M$, \, $\bs{c}_\mathrm{m} \in \mathbb{R}^D$, \, $\bs{C}_\mathrm{v} \in \mathbb{R}^{D \times D}$}
    \KwResult{$\mu \in \mathbb{R}$, $\eta \in \mathbb{R}$}
    $\bs{z} \gets \bs{\phi}(\bs{\xi})$ \\
    $\mu \gets \bs{c}_\mathrm{m} \bs{z}$
    \hfill\Comment{{\footnotesize Inference of expectation}\hspace*{-70pt}\mbox{}}
    $\eta \gets \bs{z}\tran \bs{C}_\mathrm{v} \bs{z}$
    \hfill\Comment{{\footnotesize Inference of covariance}\hspace*{-58pt}\mbox{}}
\end{algorithm}

Finally, the calculational cost after applying RFF is summarized in the table
\ref{tab:gp_complexity}, where $N \in \mathbb{Z}^{+}$ is the number of training data
and $D \in \mathbb{Z}^{+}$ is the dimension of RFF.

\begin{table}[t]
    \caption{Computational cost of the GP model before/after RFF}
    \label{tab:gp_complexity}
    \begin{center}\begin{tabular}{ccc}
        \hline
         & Training & Inference \\
        \hline
        Before RFF & $O(N^3)$   & $O(N)$   \\
        After RFF  & $O(N D^2)$ & $O(D^2)$ \\
        \hline
    \end{tabular}\end{center}
\end{table}

% }}}

\appendix

\section{Appendices}\titlebar
% {{{

\subsection{Proof of matrix inversion lemma}

The matrix inversion lemma is reprinted and proved.

\begin{theorem}[Matrix Inversion Lemma]
    Let
    $\bs{A} \in \mathbb{R^{N \times N}}$,
    $\bs{B} \in \mathbb{R^{N \times M}}$,
    $\bs{C} \in \mathbb{R^{M \times N}}$,
    and
    $\bs{D} \in \mathbb{R^{M \times M}}$
    be real matrices. Then the equation
    \begin{equation}
        \left( \bs{A} + \bs{BDC} \right)^{-1} = \bs {A}^{-1} - \bs{A}^{-1} \bs{B}
        \left( \bs{D}^{-1} + \bs{CA}^{-1} \bs{B} \right)^{-1} \bs{CA}^{-1}
    \end{equation}
    holds, where the matrix $\bs{A}$ and $\bs{D}$ are regular matrices.
\end{theorem}
\begin{proof}
The following equation holds:
\begin{align*}
    \begin{pmatrix}
        \bs{A} & \bs{B} \\
        \bs{C} & \bs{D}
    \end{pmatrix}^{-1}
    &= \begin{pmatrix}
        \bs{A}^{-1} + \bs{A}^{-1} \bs{BSCA}^{-1} & - \bs{A}^{-1} \bs{BS} \\
        - \bs {SCA}^{-1}                         & \bs {S}
    \end{pmatrix} \\
    &= \begin{pmatrix}
        \bs{T}                & -\bs{TBD}^{-1} \\
        - \bs{D}^{-1} \bs{CT} & \bs{D}^{-1} + \bs{D}^{-1} \bs{CTBD}^{-1}
    \end{pmatrix},
\end{align*}
where
\begin{align}
    \bs{T} &= \left( \bs{D} - \bs {CA}^{-1} \bs{B} \right)^{-1}, \\
    \bs{S} &= \left( \bs{A} - \bs {BD}^{-1} \bs{C} \right)^{-1}.
\end{align}
It is easy to verify the above equation from a direct calculation.
By comparing the corresponding parts of the above block matrix, we get
\begin{align}
    \bs{T} &= \bs{A}^{-1} + \bs{A}^{-1} \bs{BSCA}^{-1},
    \label{eqn:binomial_theorem_proof_1} \\
    \bs{S} &= \bs{D}^{-1} + \bs{D}^{-1} \bs{CTBD}^{-1}, \\
    - \bs{A}^{-1} \bs{BS} &= - \bs{TBD}^{-1}, \\
    - \bs{SCA}^{-1} &= - \bs{D}^{-1} \bs{CT},
\end{align}
By replacing with
\begin{center}
    $\bs{A} \to \bs{D}^{-1}$, \hspace{5pt}
    $\bs{B} \to -\bs{C}$, \hspace{5pt}
    $\bs{C} \to \bs{B}$, \hspace{5pt}
    $\bs{D} \to \bs{A}$,
\end{center}
in the equation (\ref{eqn:binomial_theorem_proof_1}), we get the formula to be proved.
\end{proof}

% }}}

\pagebreak

\begin{thebibliography}{9}
% {{{

    \bibitem{Rahimi2007}
    A.~Rahimi and B.~Recht,
    ``Random Features for Large-Scale Kernel Machines'',
    Neural Information Processing Systems, 2007.

    \bibitem{Rasmussen2006}
    C.~Rasmussen and C.~Williams, ``Gaussian Processes for Machine Learning'', MIT Press, 2006.

% }}}
\end{thebibliography}

\end{document}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SOURCE FINISH %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% vim: expandtab tabstop=4 shiftwidth=4


\chapter{Visualize spectral distances}
\label{ch:visualize-spectral-distances}

\begin{wrapfigure}{o}{0.65\textwidth}
	\vspace{-1.5 cm}
    \includegraphics[scale=0.6]{ch-visualize_spectral_distances-fig1.png}
\end{wrapfigure}

\newthought{Let's consider a spectrum}, or any other data entry for that matter, as a point in a multidimensional space. We can define distance metrics between these points and visualize the distance values from one another or from a selected reference point or reference spectrum. By doing so, we can explore how similar our measurements are to a selected reference. We can do this on a series of spectra or even on hyperspectral maps!

If you build the workflow shown above this paragraph in \mutation\ you will be able to explore various distance metrics. First, let's use the \textit{'Liver cirrhosis - spectral image'} dataset provided by the \widget{Datasets} widget, then calculate the \textit{Euclidean distances} from the average spectrum with the \widget{Neighbors} widget and visualize them in \widget{Hyperspectra}.

\medskip
Can you reproduce the results below? Pay attention to the color scheme.

\begin{figure*}[h]
\centering
\infinitewidthbox{
  \stackinset{r}{-0.5\linewidth}{t}{+0.1\linewidth}
  {\includegraphics[scale=0.4]{ch-visualize_spectral_distances-fig3.png}}
  {\includegraphics[scale=0.6]{ch-visualize_spectral_distances-fig2.png}}
  \hspace{8cm}
  }
%\caption{Try changing the parameters!}

\end{figure*}

Explore different distance metrics, inspect distances in a \widget{Data Table} widget. Don't forget, you can select points on the top map and see the corresponding spectra on the bottom in \widget{Hyperspectra}.

% I would like to have a special environment called notes for example that we can switch on or off to print or hide lecturer notes.
\lecnotes{Possibility for discussion of the general mathematical properties of distance functions. See \url{https://en.wikipedia.org/wiki/Metric_(mathematics)}}


\documentclass{article}
%\usepackage{fullpage}
\usepackage{nopageno}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{color}
\usepackage{tabu}
\usepackage{longtable}
\usepackage{mathrsfs}
\usepackage{enumerate}
\usepackage[margin=1in]{geometry}
\usepackage{fancyhdr}
\pagestyle{fancy}
\lhead{Final 02}
\rhead{Jon Allen}
\allowdisplaybreaks

\newcommand{\abs}[1]{\left\lvert #1 \right\rvert}
\newcommand{\degree}{\ensuremath{^\circ}}

\begin{document}
\subsubsection*{PDE A.}
\begin{align*}
  \text{PDE.}&&\frac{\partial u}{\partial t}&=\frac{\partial^2u}{\partial x^2}&&\text{for}&0&<x<1,&0&<t<\infty\\
  \text{BC.}&&u_x(0,t)&=0=u_x(1,t)&&\text{for}&&&0&<t<\infty\\
  \text{IC.}&&u(x,0)&=f(x)&&\text{for}&0&<x<1
\end{align*}

For PDE A, determine the full solution for the general initial condition $f(x)$. State how orthogonality is used and how coefficients in the series expansion are determined using $f(x)$
\begin{align*}
  u_0(x,t)&=c_0\\
  u_n(x,t)&=c_ne^{-n^2\pi^2t}\cos(n\pi x)&n=1,2,3,\dots\\
  u(x,t)&=c_0+\sum\limits_{n=1}^\infty{c_ne^{-n\pi^2t}\cos(n\pi x)}\\
  u(x,t)&=\sum\limits_{n=0}^\infty{c_ne^{-n\pi^2t}\cos(n\pi x)}\\
  f(x)&=u(x,0)=\sum\limits_{n=0}^\infty{c_n\cos(n\pi x)}&\text{let }m\in\mathbb{Z}\\
  \int_{0}^1{f(x)\cos(m\pi x)\,\mathrm{d}x}&=\int_{0}^1{\cos(m\pi x)\sum\limits_{n=0}^\infty{c_n\cos(n\pi x)}\,\mathrm{d}x}\\
  \text{let }n&=m=0\\
  \int_{0}^1{c_0\cos(0)^2\,\mathrm{d}x}&=c_0\\
  \text{let }n&=m\ne 0\\
  \int_{0}^1{c_m\cos(m\pi x)^2\,\mathrm{d}x}&=\frac{1}{2}c_m\int_0^1{2\cos(m\pi x)^2\,\mathrm{d}x}\\
  &=\frac{1}{2}c_m\int_0^1{1+\cos(2m\pi x)\,\mathrm{d}x}\\
  &=\frac{1}{2}c_m\left\lvert x+\frac{1}{2m\pi}\sin(2m\pi x)\right\rvert_0^1\\
  &=\frac{1}{2}c_m+\frac{1}{2}c_m\frac{\sin(2m\pi)}{2m\pi}=\frac{1}{2}c_m&m\in\mathbb{Z}\to\sin(2m\pi)=0
  \intertext{and to establish orthogonality let $n\ne m$}
  \int_{0}^1{c_m\cos(n\pi x)\cos(m\pi x)\,\mathrm{d}x}&=\frac{1}{2}c_m\int_0^1{2\cos(n\pi x)\cos(m\pi x)\,\mathrm{d}x}\\
  &=\frac{1}{2}c_m\int_0^1{\cos(n\pi x-m\pi x)+\cos(n\pi x+m\pi x)\,\mathrm{d}x}\\
  &=\frac{1}{2}c_m\left[\frac{1}{(n-m)\pi x}\sin((n-m)\pi x)\right.\\
  &\qquad\quad\left.+\frac{1}{(n+m)\pi x}\sin((n+m)\pi x)\right]_0^1\\
  &=\frac{1}{2}c_m\left[\frac{1}{(n-m)\pi}\sin((n-m)\pi)\right.\\
  &\qquad\quad\left.+\frac{1}{(n+m)\pi}\sin((n+m)\pi)\right]&n-m,n+m\in\mathbb{Z}\\
  &=\frac{1}{2}c_m\cdot 0=0&\sin((m\pm n)\pi)=0\\
\end{align*}
And now we have everything we need to determine the full solution. Since we can find the coefficient to the $m$th term by multiplying $\cos(m\pi x)$ and then integrating, letting orthogonality kill off all the extra terms.
\begin{align*}
  u(x,t)&=\sum\limits_{n=0}^\infty{c_ne^{-n\pi^2t}\cos(n\pi x)}\\
  c_0&=\int_0^1{f(x)\,\mathrm{d}x}\\
  c_m&=2\int_{0}^1{f(x)\cos(m\pi x)\,\mathrm{d}x}&\text{where }m&=1,2,3,\dots
\end{align*}
\end{document}


As a setting to illustrate computer techniques for describing variability, take
the data that Galton collected on the heights of adult children
and their parents. \datasetGalton
The file \texttt{galton.csv} stores these data in a modern,
case/variable format.

\begin{Schunk}
\begin{Sinput}
> require(mosaic)
> galton = fetchData("galton.csv")
\end{Sinput}
\end{Schunk}

\subsection{Simple Statistical Calculations}

\index{C}{descriptive statistics!computing|(}

Simple numerical descriptions are easy to compute.  Here are the mean,
median, standard deviation and variance of the children's heights (in
inches).
\index{P}{Descriptive Statistics!mean@\texttt{mean}}
\index{P}{Descriptive Statistics!sd@\texttt{sd}}
\index{P}{Descriptive Statistics!median@\texttt{median}}
\index{P}{mean@\texttt{mean}}
\index{P}{median@\texttt{median}}
\index{P}{sd@\texttt{sd}}
\index{P}{var@\texttt{var}}
\index{C}{variance!sqrt of standard deviation}
\begin{Schunk}
\begin{Sinput}
> mean(height, data=galton)
\end{Sinput}
\begin{Soutput}
[1] 66.8
\end{Soutput}
\begin{Sinput}
> median(height, data=galton)
\end{Sinput}
\begin{Soutput}
[1] 66.5
\end{Soutput}
\begin{Sinput}
> sd(height, data=galton)
\end{Sinput}
\begin{Soutput}
[1] 3.58
\end{Soutput}
\begin{Sinput}
> var(height, data=galton)
\end{Sinput}
\begin{Soutput}
[1] 12.8
\end{Soutput}
\end{Schunk}

Notice that the variance function (\function{var}) returns the square
of the standard deviation (\function{sd}).
Having both is merely a convenience.

\index{P}{Descriptive Statistics!pdata@\texttt{pdata}}
\index{P}{Descriptive Statistics!qdata@\texttt{qdata}}
\index{C}{percentile!quantile operator}
\index{P}{quantile@\texttt{quantile}}
\index{P}{qdata@\texttt{qdata}*}
\index{P}{pdata@\texttt{pdata}*}
A percentile tells where a given value falls in a distribution.  For example, a height of 63 inches is on the short side in Galton's data:
\begin{Schunk}
\begin{Sinput}
> pdata(63, height, data=galton)
\end{Sinput}
\begin{Soutput}
[1] 0.192
\end{Soutput}
\end{Schunk}
Only about 19\% of the cases have a height less than or equal to 63 inches.  The \code{pdata} operator takes one or more values as a first argument and finds where they fall in the distribution of values in the second argument.

A quantile refers to the same sort of calculation, but inverted.  Instead of giving a value in the same units as the distribution, you give a probability: a number between 0 and 1.  The \code{qdata} operator then calculates the value whose percentile would be that value:
\begin{Schunk}
\begin{Sinput}
> qdata(0.20, height, data=galton)
\end{Sinput}
\begin{Soutput}
 20%
63.5
\end{Soutput}
\end{Schunk}
Remember that the probability is given as a number between 0 and 1, so use 0.50 to indicate that you want the value which falls at the 50th percentile.

\begin{itemize}
\index{C}{quantiles!and coverage intervals}
\index{C}{coverage interval!quantiles}
\item The 25th and 75th percentile in a single command --- in other
  words, the 50 percent coverage interval:
\begin{Schunk}
\begin{Sinput}
> qdata(c(0.25, 0.75), height, data=galton)
\end{Sinput}
\begin{Soutput}
 25%  75%
64.0 69.7
\end{Soutput}
\end{Schunk}

\item The 2.5th and 97.5th percentile --- in other words, the 95
  percent coverage interval:
\begin{Schunk}
\begin{Sinput}
> qdata(c(0.025, 0.975), height, data=galton)
\end{Sinput}
\begin{Soutput}
 2.5% 97.5%
   60    73
\end{Soutput}
\end{Schunk}
\end{itemize}

The interquartile range is the width of the 50 percent coverage
interval:
\begin{Schunk}
\begin{Sinput}
> IQR(height, data=galton)
\end{Sinput}
\begin{Soutput}
[1] 5.7
\end{Soutput}
\end{Schunk}

Some other useful operators are \function{min}, \function{max}, and
\function{range}.
\index{P}{min@\texttt{min}}
\index{P}{max@\texttt{max}}
\index{P}{range@\texttt{range}}

\index{C}{descriptive statistics!computing|)}

\subsection{Simple Statistical Graphics}

\index{C}{graphics!statistical|(}
\index{C}{statistical graphics|(}
There are several basic types of statistical graphics to display
the distribution of a variable: histograms, density plots, and
boxplots.  These are easily mastered by example.

\subsubsection{Histograms and Distributions}

\index{C}{histogram!drawing}
\index{P}{histogram@\texttt{histogram}}
\index{P}{Plotting \& Graphics!histogram@\texttt{histogram}}

Constructing a histogram involves dividing the range of a variable up
into bins and counting how many cases fall into each bin.  This is
done in an almost entirely automatic way:
\begin{Schunk}
\begin{Sinput}
> histogram( galton$height )
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var1-hist}

When constructing a histogram, R makes an automatic but sensible
choice of the number of bins.  If you like, you can control this
yourself.  For instance:
\begin{Schunk}
\begin{Sinput}
> histogram( galton$height, breaks=25 )
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var2-hist}

The  horizontal axis of the histogram is always in the units of the variable.
For the histograms above, the  horizontal axis is in ``inches'' because that
is the unit of the \code{galton$height} variable.       % $

The vertical axis is conventionally drawn in one of three ways:
controlled by an optional argument named \code{type}.
\begin{description}
\item[Absolute Frequency or Counts]  A simple count of the number of cases that
  falls into each bin.  This mode is set with
  \code{type="count"} as in
\begin{Schunk}
\begin{Sinput}
> histogram( galton$height, type="count")
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var3-hist}

\item[Relative Frequency] The vertical axis is scaled so that the
height of the bar give the proportion of cases that fall into the
bin.  This is the default.
\item[Density] The vertical axis
{\em area} of the bar gives the relative proportion of cases that fall
into the bin.  Set \code{type="density"} as in \code{histogram(galton$height,type="density")} .   % $ -kill the math mode
\end{description}
In a density plot, areas can be interpreted as probabilities and the
area under the entire histogram is equal to 1.

Other useful optional arguments set the labels for the axes and the
graph as a whole and color the bars.  For example,
\begin{Schunk}
\begin{Sinput}
> histogram(galton$height, type="density",
     xlab="Height (inches)",
     main="Distribution of Heights",
     col="gray")
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var4-hist}

The above command is so long that it has been broken into several
lines for display purposes.  R ignores the line breaks, holding off on
executing the command until it sees the final closing parentheses.
Notice the use of quotation marks to delimit the labels and names like
\code{"blue"}.

\subsubsection{Density Plots}

\index{P}{densityplot@\texttt{densityplot}}
\index{P}{Plotting \& Graphics!densityplot@\texttt{densityplot}}

\index{C}{density plot!drawing}
A \newword{density plot} avoids the need to create bins and plots out
the distribution as a continuous curve.  Making a density plot
involves two operators.  The \newword{density} operator performs the
basic computation which is then displayed using either the \code{plot}
or the \code{lines} operator.  For example:
\begin{Schunk}
\begin{Sinput}
> densityplot(galton$height)
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var5-density}

If you want to suppress the rug-like plotting of points at the bottom
of the graph, use \code{densityplot(galton$height,plot.points=FALSE)}. % $

\subsubsection{Box-and-Whisker Plots}

Box-and-whisker plots are made with the \code{bwplot} command:
\begin{Schunk}
\begin{Sinput}
> bwplot(galton$height)
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var6-bw}

The median is represented by the heavy dot in the middle.  Outliers,
if any, are marked by dots outside the whiskers.
\index{C}{outlier!in box plots}
\index{C}{box plot!outliers}

\index{C}{box plot!drawing}
\index{P}{bwplot@\texttt{bwplot}}
\index{P}{Plotting \& Graphics!bwplot@\texttt{bwplot}}
\index{C}{box and whisker plots|see{box plots}}
The real power of the box-and-whisker plot is for comparing
distributions.  This will be raised again more systematically in later
chapters, but just to illustrate, here is how to compare the heights
of males and females:

\begin{Schunk}
\begin{Sinput}
> bwplot(height ~ sex, data=galton)
\end{Sinput}
\end{Schunk}
\includegraphics{Figures/variation-var7-bw}

\subsection{Displays of Categorical Variables}

\index{C}{counts!computing}
\index{C}{proportions!computing}
\index{P}{counts@\texttt{counts}}
\index{P}{props@\texttt{props}}
\index{P}{Descriptive Statistics!props@\texttt{props}}
\index{C}{table!of counts}
For categorical variables, it makes no sense to compute descriptive
statistics such as the mean, standard deviation, or variance.
Instead, look at the number of cases at each level of the variable.
\begin{Schunk}
\begin{Sinput}
> counts(sex, data=galton)
\end{Sinput}
\begin{Soutput}
  F   M
433 465
\end{Soutput}
\end{Schunk}
Proportions can be found in a similar way:
\begin{Schunk}
\begin{Sinput}
> props(sex, data=galton)
\end{Sinput}
\begin{Soutput}
    F     M
0.482 0.518
\end{Soutput}
\end{Schunk}

\index{C}{graphics!statistical|)}
\index{C}{statistical graphics|)}