%%%%%%%%%%%
%% Home work template for Graduate School
%% Author : Thamme Gowda N.
%% Originally from  https://github.com/thammegowda/hw-tex-templ
%%%%%%%%%%%%%%

\documentclass[letterpaper,doc,notimes]{apa6}
%%\documentclass[tikz]{standalone}
\usepackage{tikz}
%Required by APA6 package
\usepackage[normalem]{ulem}
\usepackage[english]{babel}
\usepackage[utf8x]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{graphicx}
\usepackage{adjustbox}

%Oft-used, oft-abused
\usepackage{afterpage}
\usepackage{booktabs}
\usepackage{caption}
\usepackage{censor}
\usepackage{color}
\usepackage{csquotes}
\usepackage{enumitem}
\usepackage{float}
\usepackage{hyperref}
\usepackage{lmodern}
%\usepackage{media9}
\usepackage{multirow}
\usepackage{outlines}
\usepackage{pdfpages}
\usepackage{placeins}
\usepackage{soul}
\usepackage{tabularx}
\usepackage[colorinlistoftodos]{todonotes}
\usepackage{xcolor}
\usepackage{mathtools}
\graphicspath{ {images/}}

\usepackage{sectsty}
\sectionfont{\fontsize{14}{12}\selectfont}

\setenumerate[1]{label=\Roman*.}
\setenumerate[2]{label=\Alph*.}
\setenumerate[3]{label=\roman*.}
\setenumerate[4]{label=\alph*.}

% break page where ever is required
\allowdisplaybreaks

\title{ \textbf{ USC CSCI 567 HOMEWORK 3 SOLUTIONS} }
\shorttitle{USC CSCI567 FALL16 HW3}
\author{\textsc{ThammeGowda Narayanaswamy}}
\affiliation{ tnarayan@usc.edu \\ ID : 2074-6694-39 \\ Department of Computer Science \\ Viterbi School of Engineering \\ University of Southern California \\ Los Angeles, CA
	}

\note{\today}
%\note{ Collaborators : \\ Ishan Alok (ialok@usc.edu)}

\authornote{Produced for Fall 2016 session of CSCI 567, ``Machine Learning'', taught by Dr. Yan Liu at the University of Southern California}

\begin{document}

\maketitle
\newpage

\section{1.BIAS VARIANCE TRADE-OFF}
\subsection{a. Closed form Solution for Ridge Regression}
Given :
$$
\hat{\beta_\lambda} = argmin_\beta \bigg\{ \frac{1}{n} \sum_{i=1}{n}(y_i - x_i^T\beta)^2 + \lambda \parallel \beta \parallel_2^2 \bigg\}  \\
$$
In matrix form:
$$
\hat{\beta_\lambda} = argmin_\beta \bigg\{ \frac{1}{n} (Y - X\beta)^T (Y - X\beta) + \lambda  \beta^T \beta \bigg\}  \\
$$
where $X \in R^{n \times p}$ , $Y \in R^{n \times 1}$ and $\beta \in R^{p \times 1}$
We know that the above expression (assuming it is convex) is minimum  when its derivative is zero .
\begin{align*}
	\dfrac{\partial}{\partial\beta} \bigg[ \frac{1}{n} (Y - X\beta)^T (Y - X\beta) + \lambda  \beta^T \beta \bigg] = & 0 \\
\frac{1}{n} \dfrac{\partial}{\partial\beta} \bigg[ Y^TY - Y^T X\beta - (X\beta)^TY + (X\beta)^T(X\beta) +  \lambda  \beta^T \beta \bigg] = & 0 \\
 \dfrac{\partial}{\partial\beta} \bigg[ - Y^T X\beta - \beta^TX^TY + \beta^TX^TX\beta +  \lambda  \beta^T \beta \bigg] = & 0 \\
  - Y^T X -  X^TY + 2\beta^TX^TX +  2\lambda  \beta  = & 0 \\
				- 2 X^TY  + 2X^TX\beta +  2\lambda \beta  = & 0 \\
    [ X^TX +  \lambda I ] \beta  = &  X^T Y  \\
    \text{When $X^TX +  \lambda I$ is invertible, } & \\
     \beta  = & [ X^TX +  \lambda I ]^{-1}  X^T Y   \\
 \implies \hat{\beta_\lambda} = & [ X^TX +  \lambda I ]^{-1} X^T Y  \\
\end{align*}
We are told that the target label $y$ is from linear model plus an additional Gaussian noise $\epsilon$.\\
$\implies $ Distribution of $\epsilon$ is $N(0, \sigma^2)$\\
$\implies$ By applying affine transformations,  the distribution of $Y \approx N(X\beta^*, \sigma^2)$ \\
$\implies \text{Since  } \hat{\beta_\lambda} = H_\lambda Y \text{,  where} H_\lambda = [ X^TX +  \lambda I ]^{-1}  X^T$ \\
The distribution of $\hat{\beta_\lambda} \approx N (H_\lambda X \beta^*,   H_\lambda^T \sigma^2 I H_\lambda ) $

\subsection{b. Bias Term}
\begin{align*}
	bias = & \mathbb{E}[x^T\hat{\beta_\lambda}] - x^T\beta^* & \\
	      = &x^T[ \mathbb{E}[\hat{\beta_\lambda}] - \beta^*] &  \\
	      = & x^T[H_\lambda X \beta^* - \beta^*] & \because \text{from part a, the mean of Gaussian} \\
			 &where \text{ where} H_\lambda = [ X^TX +  \lambda I ]^{-1}  X^T & \\
   bias = & x^T(H_\lambda X  - I) \beta^* & \\
\end{align*}
\subsection{c. Variance Term}
\begin{align*}
	variance = & \mathbb{E} \bigg[ \big( x^T\hat{\beta_\lambda} - \mathbb{E}[x^T\hat{\beta_\lambda}] \big)^2 \bigg] & \\
	= & \mathbb{E} \bigg[ \big( x^T (\hat{\beta_\lambda} - \mathbb{E}[\hat{\beta_\lambda}] )\big)^2 \bigg]  &\\
	= & \bigg( x^T ( \mathbb{E}\big[\hat{\beta_\lambda} - \mathbb{E}[\hat{\beta_\lambda}] \big] )\bigg)^2  &\\
	= &  x^T ( \mathbb{E}\big[\hat{\beta_\lambda} - \mathbb{E}[\hat{\beta_\lambda}] \big] )^2 x  &\\
  = & x^T  Var(\hat{\beta_\lambda})  x &\\
Variance  = & x^T  H_\lambda^T \sigma^2 I H_\lambda x &  \because From Part-a \\
    & \text{Where, } H_\lambda = [ X^TX +  \lambda I ]^{-1}  X^T
\end{align*}

\subsection{d. Impact of $\lambda$  on Squared Error}
From the bias-variance theorem we have, squared error is proportional to sum of $variance$ and $bias^2$

The impact of $\lambda$ on squared error is as follows:
\begin{itemize}
	\item When $\lambda$ is smaller, the bias is small but variance is high. Thus the model tight fits to seen samples with less generalization.
	\item When $\lambda$ is large, the bias is larger but variance is smaller. Thus the model under fits the samples with poor prediction.
	\item Thus we cannot have least bias and least variance at the same time, we need to settle for a trade off between these.
\end{itemize}
\section{2. KERNEL CONSTRUCTION}

\subsection{a. Positive linear combination of valid kernels is a valid kernel}
To prove: $k_3(x, x') = a_1k_1(x, x') + a_2k_2(x, x')$ is a valid kernel \\
Given: $k_1$ and $k_2$ are positive definite kernel functions. $a_1, a_2 \ge 0 $ \\
Proof:
    Since $k_1$ and $k_2$ are positive definite kernel functions, we have from Morcer theorem:
    \begin{equation}\label{eqn:1}
			\int_{x}\int_{x'}k_1(x, x') f(x) f(x') dx dx' \ge 0
    \end{equation}
    And
    \begin{equation} \label{eqn:2}
   \int_{x}\int_{x'}k_2(x, x') f(x) f(x') dx dx' \ge 0
   \end{equation}
  $$
  \implies k_3(x, x') = a_1\int_{x}\int_{x'}k_1(x, x') f(x) f(x') dx dx' + a_2\int_{x}\int_{x'}k_2(x, x') f(x) f(x') dx dx'
$$
From equations \ref{eqn:1},  \ref{eqn:2}, and $a_1 \ge 0 $, $a_2 \ge 0 $ \\
 $\implies$ R.H.S is $\ge 0$ \\
 $\implies k_3$ is a positive definite kernel function

\subsection{b. }
To prove: $k_4(x, x') = f(x) f(x')$ is a valid kernel \\
Given: $f(.)$ is an arbitrary real valued function\\
Proof: \\
Let $x$ and $x'$  $\in \mathbb{R}^{n}$ \\
We can represent $k_4(x,x')$ as matrix $K_4$, given by
$$ K_4= \begin{bmatrix}
f(x_1)f(x'_1) & f(x_1)f(x'_2) & ... & f(x_1)f(x'_n)  \\
... &  &  & ... \\
f(x_n)f(x'_1) & f(x_n)f(x'_2) & ... & f(x_n)f(x'_n)  \\
\end{bmatrix} $$
The matrix can be decomposed into product of two vectors $F^T$ and $F$ , $F$ $\in \mathbb{R}^n$, such that $K_4 = F^T. F $ where

  $F =  \begin{bmatrix}  f(x_1)\\ f(x_2) \\ ... \\ f(x_n) \end{bmatrix} $

To prove that $k_4$ is a valid kernel, we have to prove that the matrix $K_4$ is positive definite.\\

Let us consider, $y \in \mathbb{R}^n$ \\
\begin{align*}
y^T K_4 y = & y^T F F^T y \\
    =& (F^T y) ^T F^T y \\
    =& \parallel F^T y \parallel_2^2
\end{align*}
Since $L_2$ norm is always positive, we can infer that for any  $y \in \mathbb{R}^n, y^T K_4 y \ge 0$

$\implies k_4 $ is a valid kernel by definition

\subsection{c. The product of valid Kernel is a valid kernel}
To prove: $k_5(x, x') = k_1(x, x') k_2(x, x')$ is a valid kernel\\
Given: $k_1$ and $k_2$ are positive definite kernel functions.\\
Proof: \\
Let us consider Kernel matrices $K_1$, $K_2$, and $K_5$ corresponding to $k_1$, $k_2$, and $k_5$.
By definition of kernel functions we can say that $K_1$ and $K_2$ are:
\begin{itemize}
	\item Symmetric
	\item Positive semi definite
\end{itemize}
We know that, product of two symmetric positive semi definite matrices is also symmetric positive semidefinite matrix. (necessary and sufficient for valid kernel )\\
$\implies$ Thus $k_5$ is a valid kernel.

\section{3. KERNEL REGRESSION}
\subsection{a. Optimal value of $w$}
Given: the cost function
$$
	J(w) = \min_w \sum_n (y_i - w^Tx_i)^2 + \lambda \parallel w \parallel^2_2
$$
Where $\lambda \ge 0$ is regularization coefficient.\\
We know that, $J$ is minimal when $\frac{\partial J}{\partial w}$
 \begin{align*}
 \dfrac{\partial}{\partial w} \bigg[ \frac{1}{n} (y - Xw)^T (y - Xw) + \lambda  w^T w \bigg] = & 0 \\
 \dfrac{\partial}{\partial w} \bigg[ y^Ty - y^T Xw - (Xw)^Ty + (Xw)^T(Xw) +  \lambda  w^T w \bigg] = & 0 \\
 \dfrac{\partial}{\partial w} \bigg[ - y^T Xw - w^TX^Ty + w^TX^TXw +  \lambda  w^T w \bigg] = & 0 \\
 - y^T X -  X^Ty + 2w^TX^TX +  2\lambda w  = & 0 \\
 - 2 X^Ty  + 2X^TXw +  2\lambda w  = & 0 \\
 [ X^TX +  \lambda I ] w  = &  X^T y  \\
 \text{When $X^TX +  \lambda I_D$ is invertible, } & \\
 \implies w^* =  [ X^TX +  \lambda I_D ]^{-1} X^T y  & \\
 \end{align*}

\subsection{b. }
Given that $x_i \in \mathbb{R}^D$  has been transformed to $\phi_i(x) \in \mathbb{R}^T$ \\
Thus the input matrix is  $\Phi \in \mathbb{R}^{N\times T}$ .
Substituting the input matrix in the equation from part a, we get \\
\begin{equation}\label{eqn:3}
	w^* =  [ \Phi^T\Phi +  \lambda I_T ]^{-1} \Phi^T y
\end{equation}
Let us consider the expression,
\begin{align*}
[ \Phi^T\Phi +  \lambda I_D ] \Phi^T  =& [ \Phi^T\Phi\Phi^T +  \lambda \Phi^T ] &  \because \text{Distributing} \Phi^T\\
[ \Phi^T\Phi +  \lambda I_D ] \Phi^T  =& \Phi^T[ \Phi\Phi^T +  \lambda I_N ]  &  \because \text{Moving to the left side} \Phi^T \\
 \Phi^T  =& [ \Phi^T\Phi +  \lambda I_D ]^{-1} \Phi^T[ \Phi\Phi^T +  \lambda I_N ]  & \because \text{Inverse Multiplied on left }\\
 \Phi^T[ \Phi\Phi^T +  \lambda I_N ]^{-1} =& [ \Phi^T\Phi +  \lambda I_D ]^{-1} \Phi^T   & \because \text{Inverse Multiplied on Right }\\
\end{align*}
Substituting the result in \ref{eqn:3}, we get \\
\begin{equation}\label{eqn:4}
w^* = \Phi^T[ \Phi\Phi^T +  \lambda I_N ]^{-1} y
\end{equation}
\subsection{c. }
Given a testing sample $\phi(x)$, the prediction is given by,\\
\begin{align*}
	\hat{y} =& w^{*T} \phi(x) & \\
				=&	(\Phi^T[ \Phi\Phi^T +  \lambda I_N ]^{-1} y)^T \phi(x) & \\
				=&	(y^T [ (\Phi\Phi^T +  \lambda I_N)^T ]^{-1} \Phi \phi(x) & \\
				=&	(y^T [(\Phi\Phi^T)^T +  \lambda I_N]^{-1} \Phi \phi(x) & \\
\end{align*}
Lets define a matrix $K = \Phi\Phi^T \in \mathbb{R}^{N \times N}$, \\
and $k(x) = \Phi\phi(x) \in \mathbb{R}^T$ \\
Since $K$ is symmetric, $K^T = K$
$$ \therefore \hat{y} = (y^T [K+  \lambda I_N]^{-1} k(x)  $$

\subsection{d. }
When the dimension of feature transformation $\phi(x) \in \mathbb{R}^T, T$, is large, kernel regressions are computationally efficient than linear ridge regression.
$\because$ kernel regression computes the kernel matrix $K  $ which is $\mathbb{R}^{N\times N}$ without actually computing the transformations $\phi(x)$.
Without kernel trick, we have to compute $T \times T$ matrix which is an expensive operation when $T  \gg N$.
\begin{itemize}
	\item \textbf{Learning}:
		\subitem Linear Ridge Regression: $O(T^3)$ time and $O(T^2)$ memory; $T$ is the dimension of new feature space.
		\subitem Kernel  Regression: $O(N^3)$ time and $O(N^2)$ memory; $N$ is the number of examples in training set.
	\item \textbf{Prediction}:
		\subitem Linear Ridge Regression: $O(T)$ time, $T$ is the dimension of new feature space.
		\subitem Kernel Regression: $O(D)$ time, $D$ is the dimensions of original feature space
\end{itemize}

\section{4. SUPPORT VECTOR MACHINES}
\subsection{1. Linearly separable?}
No. They are not linearly separable (in 2d euclidean space).

\subsection{2.Maximum margin decision surface}
$$w = \begin{bmatrix}
	0 \\ 0 \\ 0 \\ 1
\end{bmatrix} $$
 \subsection{3.  Make it  non separable}
The data can be easily made non separable by adding a negative label at the same as a positive example (or vice versa). In practice, this issue is called training data contamination.
\begin{minipage}{0.3\textwidth}
\includegraphics[scale=0.4]{4c}
\end{minipage}
\begin{minipage}{0.6\textwidth}\raggedleft
 Example: Adding positive example at (-1, 1)
\end{minipage}

\subsection{4. Kernel name}
\begin{align*}
	K(x,x) =& <\phi(x). \phi(x)>  = \phi(x)^T \phi(x) \\
	    =& [ \begin{smallmatrix}1 & x_1 & x_2 & x_1x_2  \end{smallmatrix} ]^T [ \begin{smallmatrix}1 & x_1 & x_2 & x_1x_2 \end{smallmatrix} ] \\
		=& 1 + x_1 + x_2 + x_1x_2   +   x_1 + x_1^2 + x_1x_2 + x_1^2x_2  +   x_2 + x_1x_2 + x_2^2 + x_1x_2^2  \\
		& + x_1x_2 + x_1^2x_2 + x_1x_2^2 + x_1^2x_2^2
\end{align*}
This is a polynomial kernel.
\section{5. SVMs  AND THE SLACK PENALTY $C$}
\subsection{1. }
\begin{minipage}{0.5\textwidth} \includegraphics[scale=0.3]{5a} \end{minipage}
\begin{minipage}{0.5\textwidth}\raggedleft
When $C \rightarrow \inf$, SVM tends to minimize mis classification errors, even if the margin between the decision boundary plane and the training examples is small.
\end{minipage}
\subsection{2. }
\begin{minipage}{0.5\textwidth} \includegraphics[scale=0.3]{5b} \end{minipage}
\begin{minipage}{0.5\textwidth}\raggedleft
	When $C \approx 0$, SVM tends to maximize the margin between the decision boundary and the training examples. This might even result in few mis classification errors.
 \end{minipage}
\subsection{3. }
The precision of Red Plus points and the Recall of the Green Circle points will be high.
Depending on the value of slack penalty (as discussed in the previous two sections), the recall of the Red Plus points and the precision of the Green circle points will vary and are most like to perform poorly. This is because there are few red plus points closer to green circle points which affect the position of the decision boundary.

\subsection{4. }
\begin{minipage}{0.5\textwidth} \includegraphics[scale=0.3]{5d} \end{minipage}
\begin{minipage}{0.5\textwidth}\raggedleft
	A point is added at the top right region of the plane. Since it is far from being a 'support vector', it doesnt change the decision boundary.
\end{minipage}

\subsection{5. }
\begin{minipage}{0.5\textwidth} \includegraphics[scale=0.3]{5e} \end{minipage}
\begin{minipage}{0.5\textwidth}\raggedleft
	A point is added in between the decision boundary region. Since it becomes 'support vector', it participates in  forming the decision boundary.
\end{minipage}

\section{PROGRAMMING}
\subsection{Bias Variance}
\subsection{a. 10 samples per dataset}
Note:
  The evaluation is performed as follows based on the method suggested by TA's in one of the discussion sessions:
  \begin{itemize}
	\item Generated 100 datasets with 10 points each, $D_1, D_2, D_3... D_{100}$
	\item Built a model $h_{D_i}(.)$ for each 100 datasets.
	\item A news dataset $D_t$ is generated  for testing.
	\item The bias and variance are measured based on the performance of 100 models on the $D_t$ dataset.
  \end{itemize}
\subsection{Histograms}
The histograms are as follows \\
\includegraphics[width=1.0\textwidth]{hist_10samples}

The recorded $bias^2$ and variance are as follows:

\begin{tabular}{|c|c|c|} \hline
	Function & Variance      & $Bias^2$ \\ \hline
g1		& 0.00000000		& 0.55381366 \\
g2		& 0.04447961		& 0.41991505 \\
g3		& 0.11798539		& 0.42180300 \\
g4		 &0.04600876		& 0.09363664 \\
g5		 &0.12355812		& 0.09612371 \\
g6		 &1.98816964		& 0.09745515\\ \hline
\end{tabular}

\subsubsection{b. 100 Samples per dataset}
The histograms are as follows \\
\includegraphics[width=1.0\textwidth]{hist_100samples}

The recorded $bias^2$ and variance are as follows:

 \begin{tabular}{|c|c|c|} \hline
	Function & Variance       & $Bias^2$ \\ \hline
g1		& 0.00000000		& 0.58901086 \\
g2		& 0.00464569		& 0.45072357 \\
g3		& 0.01270188		& 0.45209526 \\
g4		& 0.00269852		& 0.10926987 \\
g5		 &0.00366258		& 0.10922298 \\
g6		& 0.00511599		 & 0.10889857 \\ \hline
 \end{tabular}

\subsection{c. }
Key observations from this exercise:
\begin{itemize}
	\item As the model complexity increased, the bias decreased and the variance increased..
	\item When we added more number of samples to the dataset, we saw that the bias and variance continue to vary (bias decreased, variance increased) with increase in model complexity, however the magnitude of change is less.
\end{itemize}

\subsection{d. Ridge Regression}
\begin{tabular}{|c|c|c|} \hline
Lambda	&  Variance	 &  $Bias^2$ \\ \hline
0.001	& 0.00291082	 & 0.110499 \\
0.003	& 0.00290983	& 0.110496 \\
0.01	& 0.00290636	 & 0.110483 \\
0.03	& 0.00289664	& 0.110451 \\
0.1	 & 0.00286453	 & 0.110368 \\
0.3	& 0.00278789	& 0.110376 \\
1	 & 0.00265098	& 0.11267 \\ \hline
\end{tabular}

Analysis:
  As $\lambda$ increased, the bias increased and the variance decreased.
  Thus $\lambda$ parameter can be used to control tight fitting by introducing the bias.

\subsection{Support Vector Machines}
\subsubsection{libSVM setup}
Using anaconda distribution:
\begin{verbatim}
	conda install -c conda-forge libsvm=3.21
\end{verbatim}
This installs two command line tools called \texttt{svm\_train} \texttt{svm\_predict}

\subsubsection{Using the Linear Kernel}
The following results were recorded by using linear kernel type.
The unit of average time is seconds for all the following results.
\begin{verbatim}
# LINEAR KERNEL
#             C  AvgTime   Accuracy%
1   0.000244141  0.213693  55.75
2   0.000976562  0.201526  55.75
3    0.00390625  0.197195  55.75
4      0.015625  0.190556  55.75
5        0.0625  0.196112  74.90
6          0.25  0.147726  92.05
7             1  0.100852  92.80
8             4  0.065552  95.10
9            16  0.053958  96.40
\end{verbatim}
Observation: The accuracy increased as we increased the slack penalty $C$, while the average training time decreased.

\subsubsection{Using the polynomial and RBF kernels}
The following results were recorded:
\begin{verbatim}
# POLYNOMIAL KERNEL
#         C  Degree AvgTime   Accuracy%
1      0.015625  1  0.193540  55.75
2      0.015625  2  0.201199  55.75
3      0.015625  3  0.200625  55.75
4        0.0625  1  0.174386  90.35
5        0.0625  2  0.198155  89.00
6        0.0625  3  0.198131  74.90
7          0.25  1  0.103184  91.15
8          0.25  2  0.116746  92.15
9          0.25  3  0.147319  92.05
10             1  1  0.073813  92.85
11             1  2  0.079659  93.30
12             1  3  0.100888  92.80
13             4  1  0.056519  94.35
14             4  2  0.063589  94.90
15             4  3  0.067277  95.10
16            16  1  0.054508  94.30
17            16  2  0.057410  95.95
18            16  3  0.055024  96.40
19            64  1  0.056362  94.15
20            64  2  0.050879  96.65
21            64  3  0.051658  97.00
22           256  1  0.068880  94.50
23           256  2  0.053696  96.80
24           256  3  0.049736  96.90
25          1024  1  0.154141  94.50
26          1024  2  0.056765  96.50
27          1024  3  0.053674  96.55
28          4096  1  0.381076  94.50
29          4096  2  0.059383  96.75
30          4096  3  0.056649  96.60
31         16384  1  1.563308  94.70
32         16384  2  0.065256  96.45
33         16384  3  0.055341  96.60

# RBF KERNEL
#             C  Gamma    AvgTime    Accuracy%
1      0.015625  0.000061  0.196857  55.75
2      0.015625  0.000244  0.199696  55.75
3      0.015625  0.000977  0.193203  55.75
4      0.015625  0.003906  0.201737  55.75
5      0.015625  0.015625  0.200773  56.00
6      0.015625  0.062500  0.198204  87.30
7      0.015625  0.250000  0.200537  60.30
8        0.0625  0.000061  0.199040  55.75
9        0.0625  0.000244  0.200937  55.75
10        0.0625  0.000977  0.196819  55.75
11        0.0625  0.003906  0.203154  64.40
12        0.0625  0.015625  0.165145  90.55
13        0.0625  0.062500  0.128067  92.20
14        0.0625  0.250000  0.172642  92.05
15          0.25  0.000061  0.200721  55.75
16          0.25  0.000244  0.199568  55.75
17          0.25  0.000977  0.199016  66.60
18          0.25  0.003906  0.154790  90.85
19          0.25  0.015625  0.103935  91.40
20          0.25  0.062500  0.082446  93.10
21          0.25  0.250000  0.115713  95.55
22             1  0.000061  0.196611  55.75
23             1  0.000244  0.198686  67.85
24             1  0.000977  0.152969  91.05
25             1  0.003906  0.099703  91.40
26             1  0.015625  0.074173  93.50
27             1  0.062500  0.063382  95.90
28             1  0.250000  0.085199  97.15
29             4  0.000061  0.197674  67.95
30             4  0.000244  0.151894  90.85
31             4  0.000977  0.102306  91.45
32             4  0.003906  0.072589  93.35
33             4  0.015625  0.056027  94.90
34             4  0.062500  0.054397  96.80
35             4  0.250000  0.074961  96.95
36            16  0.000061  0.154246  90.85
37            16  0.000244  0.097384  91.50
38            16  0.000977  0.074993  93.45
39            16  0.003906  0.057111  94.55
40            16  0.015625  0.053216  95.85
41            16  0.062500  0.052186  97.10
42            16  0.250000  0.075502  96.70
43            64  0.000061  0.097574  91.50
44            64  0.000244  0.069576  93.45
45            64  0.000977  0.058329  94.45
46            64  0.003906  0.056718  94.50
47            64  0.015625  0.054045  96.75
48            64  0.062500  0.049619  97.00
49            64  0.250000  0.074851  96.70
50           256  0.000061  0.071727  93.45
51           256  0.000244  0.058747  94.40
52           256  0.000977  0.056307  94.30
53           256  0.003906  0.055413  95.90
54           256  0.015625  0.054942  97.20
55           256  0.062500  0.047539  96.85
56           256  0.250000  0.074552  96.70
57          1024  0.000061  0.057464  94.40
58          1024  0.000244  0.057587  94.40
59          1024  0.000977  0.056671  94.60
60          1024  0.003906  0.066289  96.70
61          1024  0.015625  0.057694  96.90
62          1024  0.062500  0.049985  96.85
63          1024  0.250000  0.076784  96.70
64          4096  0.000061  0.055695  94.40
65          4096  0.000244  0.058861  94.35
66          4096  0.000977  0.073948  96.20
67          4096  0.003906  0.086435  97.10
68          4096  0.015625  0.065810  96.95
69          4096  0.062500  0.050349  96.85
70          4096  0.250000  0.074639  96.70
71         16384  0.000061  0.060005  94.25
72         16384  0.000244  0.080497  94.70
73         16384  0.000977  0.114950  96.55
74         16384  0.003906  0.110726  96.75
75         16384  0.015625  0.065220  96.95
76         16384  0.062500  0.048876  96.85
77         16384  0.250000  0.073846  96.70

\end{verbatim}

Observation :
The best cross validation accuracy is $97.20\% $ and the corresponding parameters are $Kernel= RBF; C=256; gamma=0.015625$

The model built from these parameters recorded $98.5\%$ accuracy on the test dataset.

\end{document}


 \documentclass [12pt]{article}

\usepackage {amsmath}
\usepackage {amsthm}
\usepackage {amssymb}
\usepackage {graphicx}
\usepackage {float}
\usepackage {multirow}
\usepackage {xcolor}
\usepackage [ruled,vlined,commentsnumbered,titlenotnumbered]{algorithm2e} \usepackage {array}
\usepackage {booktabs}
\usepackage {url}
\usepackage {parskip}
\usepackage [margin=1in]{geometry}
\usepackage [T1]{fontenc}
\usepackage {cmbright}
\usepackage [many]{tcolorbox}
\usepackage [colorlinks = true,
            linkcolor = blue,
            urlcolor  = blue,
            citecolor = blue,
            anchorcolor = blue]{hyperref}
\usepackage {enumitem}
\usepackage {xparse}
\usepackage {verbatim}
\usepackage{algpseudocode}
\usepackage{listings}
\usepackage{xcolor}
\lstset { %
    language=C++,
    backgroundcolor=\color{black!5}, % set backgroundcolor
    basicstyle=\footnotesize,% basic font setting
}
\newtheorem{theorem}{Theorem}
\newtheorem{remark}{Remark}
\newtheorem{lemma}[theorem]{Lemma}
\theoremstyle{definition}
\newtheorem{definition}{Definition}[section]
\newtheorem{claim}{Claim}
\newtheorem{proposition}{Proposition}

\DeclareTColorBox {Solution}{}{breakable, title={Solution}} \DeclareTColorBox {Solution*}{}{breakable, title={Solution (provided)}} \DeclareTColorBox {Instruction}{}{boxrule=0pt, boxsep=0pt, left=0.5em, right=0.5em, top=0.5em, bottom=0.5em, arc=0pt, toprule=1pt, bottomrule=1pt} \DeclareDocumentCommand {\Expecting }{+m}{\textbf {[We are expecting:} #1\textbf {]}} \DeclareDocumentCommand {\Points }{m}{\textbf {(#1 pt.)}}

\begin {document}

\vspace {1em}
\begin {Instruction}
Adapted From Virginia Williams' lecture notes.
\end {Instruction}

{\LARGE \textbf {COMP 285 (NC A\&T, Spr `22)}\hfill \textbf {Lecture 28} }

\begin{centering}
\section*{Getting Greedy with Algorithms}
\end{centering}

\section{Greedy Algorithms}

Suppose we want to solve a problem, and we're able to come up with some recursive formulation of the problem that would give us a nice dynamic programming algorithm. But then, upon further inspection, we notice that any optimal solution only depends on looking up the optimal solution to one other subproblem. A greedy algorithm is an algorithm which exploits such a structure, ignoring other possible choices. Greedy algorithms can be seen as a refinement of dynamic programming; in order to prove that a greedy algorithm is correct, we must prove that to compute an entry in our table, it is sufficient to consider at most one other table entry; that is, at each point in the algorithm, we can make a “greedy”, locally-optimal choice, and guarantee that a globally-optimal solution still exists. Instead of considering multiple choices to solve a subproblem, greedy algorithms only consider a single subproblem, so they run extremely quickly – generally, linear or close-to-linear in the problem size.

Unfortunately, greedy algorithms do not always give the optimal solution, but they frequently give good (approximate) solutions. To give a correct greedy algorithm one must first identify optimal substructure (as in dynamic programming), and then argue that at each step, you only need to consider one subproblem. That is, even though there may be many possible subproblems to recurse on, given our selection of subproblem, there is always an optimal solution that contains the optimal solution to the selected subproblem.

\subsection{Activity Selection}

One problem, which has a very nice (correct) greedy algorithm, is the Activity Selection Problem.

In this problem, we have a number of activities. Your goal is to choose a subset of the activities to participate in. Each activity has a start time and end time, and you can't participate in multiple activities at once. Thus, given $n$ activities $a_1, a_2, \cdots, a_n$ where $a_i$ has start time $s_i$ and finish time $f_i$ , we want to find a maximum set of non-conflicting activities.

The activity selection problem has many applications, most notably in scheduling jobs to run on a single machine.

\subsubsection{Optimal Substructure}

Let's start by considering a subset of the activities. In particular, we'll be interested in considering the set of activities $S_{i ,j}$ that start after activity $a_i$ finishes and end before activity $a_j$ starts. That is, $S_{i ,j} = \{a_k \mid f_i \leq s_k , f_k \leq s_j\}$. We can participate in these activities between $a_i$ and $a_j$. Let $A_{i ,j}$ be a maximum subset of non-conflicting activities from the subset $S_{i ,j}$. Our first intuition would be to approach this by using dynamic programming. Suppose some $a_k \in A_{i ,j}$, then we can break down the optimal subsolution $A_{i ,j}$ as follows
$$
|A_{i ,j}| = 1 + |A_{i ,k} | + |A_{k ,j}|
$$
where $A_{i ,k}$ is the best set for $S_{i ,k}$(before $a_k$ ), and $A_{k ,j}$ is the best set for after $a_k$ . Another way of interpreting this expression is to say ``once we place $a_k$ in our optimal set, we can only consider optimal solutions to subproblems that do not conflict with $a_k$ .''

Thus, we can immediately come up with a recurrence that allows us to come up with a dynamic programming algorithm to solve the problem.
$$
|A_{i ,j}| = \max_{a_k \in S_{i ,j}} 1 + |A_{i ,k} | + |A_{k ,j}|
$$.

This problem requires us to fill in a table of size $n^2$, so the dynamic programming algorithm will run in $\Omega(n^2)$ time. The actual runtime is $O(n^3)$ since filling in a single entry might take $O(n)$ time.

But we can do better! We will show that we only need to consider the $a_k$ with the smallest finishing time, which immediately allows us to search for the optimal activity selection in linear time.

\begin{proposition}
For each $S_{i ,j}$, there is an optimal solution $A_{i ,j}$ containing $a_k \in S_{i ,j}$ of minimum finishing time $f_k$.
\end{proposition}

Note that if the proposition is true, when $f_k$ is minimum, then $A_{i ,k}$ is empty, as no activities can finish before $a_k$ ; thus, our optimal solution only depends on one other subproblem $A_{k ,j}$ (giving us a linear time algorithm).

Here, we prove the proposition.

\begin{proof}

Let $a_k$ be the activity of minimum finishing time in $S_{i ,j}$. Let $A_{i ,j}$ be some maximum set of non-conflicting activities. Consider $A'_{i ,j} = A_{i ,j} \setminus {a_l} \cup {a_k}$ where $a_l$ is the activity of minimum finishing time in $A_{i ,j}$. It’s clear that $|A'_{i ,j}| = |A_{i ,j}|$. We need to show that $A'_{i ,j}$ does not have conflicting activities. We know $a_l \in A_{i ,j} \subset S_{i ,j}$. This implies $f_l \geq f_k$ , since $a_k$ has the minimum finishing time in $S_{i ,j}$.

All $a_t \in A_{i ,j} \setminus {a_l}$ don’t conflict with $a_l $, which means that $s_t \geq f_l$ , which means that $s_t \geq f_k$ , so this means that no activity in $A_{i ,j} \setminus {a_l}$ can conflict with $a_k$ . Thus, $A'_{i ,j}$ is an optimal solution.
\end{proof}

Due to the above proposition, the expression for $A_{i ,j}$ from before simplifies to the following
expression in terms of $a_k \subseteq S_{i ,j}$, the activity with minimum finishing time $f_k$ .

\begin{align*}
|A_{i,j}| = 1 + |A_{k,j}| \\
A_{i,j} = A_{k,j} \cup \{a_k \}
\end{align*}

Algorithm Greedy-AS assumes that the activities are presorted in nondecreasing order of their finishing time, so that if $i < j$, $f_i \leq f_j$.

\begin{algorithm}
\caption{Greedy-AS(a)}
\label{alg:greed_as}
\begin{algorithmic}
\State $A \gets \{a_1\}$ \texttt{/* activity of min $f_i$}
\State $k \gets 1$
\State \For{$m = 2 \to n$} {
    \State \If{$s_m \geq f_k$} {
        \State \texttt{// $a_m$ starts after last activity in A}
        \State $A \gets A \cup \{a_m\}$
        \State $k \gets m$
    }
}
\State \Return $A$
\end{algorithmic}
\end{algorithm}

By the above claim, this algorithm will produce a legal, optimal solution via a greedy selection of activities. There may be multiple optimal solutions, but there always exists a solution that includes $a_k$ with the minimum finishing time. The algorithm does a single pass over the activities, and thus only requires $O(n)$ time – a dramatic improvement from the trivial dynamic programming solution. If the algorithm also needed to sort the activities by $f_i$ , then its runtime would be $O(n \log n)$ which is still better than the original dynamic programming solution.

\end{document}


\newpart
\section{From Lisp to Scheme}\label{sec:lisp}

After the discussions about minimalism outside programming in last part, now
we come back to the subject of programming; but before examining Unix itself,
let's first discuss something outside the Unix circle -- the Lisp family of
programming languages\cupercite{wiki:lisp}.  Born in 1958, Lisp is one of the
oldest programming languages, along with Fortran (1957), Algol (1958) and Cobol
(1959), and is perhaps the only one of them still constantly attracting new
interest as of now: Fortran finds little (and still diminishing) use outside
of numerical computation in science and engineering, few young programmers are
interested in maintaining existent (stale and also diminishing) Cobol codebases,
and it is fair to say that Algol as a language has been dead for long.  So what
is the reason for the continued vitality of Lisp?  The answer is Lisp's inherent
simplicity, and its strong \stress{expressiveness} despite the simplicity;
in this section, we will briefly examine the simplicity of Lisp.

Lisp was designed by John McCarthy\footnote{By the way,
he was also one of the pioneers in time-sharing operating systems
(\cf~Section~\ref{sec:intro}).}, who showed that a practically usable
Turing-complete language can be built with a handful of primitive
functions in addition to conditional expressions and recursive function
definitions\cupercite{mccarthy1960}.  Steve Russell noted, to McCarthy's
surprise, that the \verb|eval| function in Lisp could be directly translated
into assembly code, and the result was the first Lisp interpreter, running on
an IBM 704 mainframe, compiled manually by Russell.  Alan Kay, the designer of
Smalltalk, made the following comment\cupercite{feldman2004} about the idea:
\begin{quoting}
	\emph{[...]} that was the big revelation to me when I was in graduate
	school -- when I finally understood that the half page of code on the
	bottom of page 13 of the Lisp 1.5 manual\cupercite{mccarthy1962} was Lisp
	in itself.  These were ``Maxwell's Equations of Software!''  This is the
	whole world of programming in a few lines that I can put my hand over.
\end{quoting}
Although Lisp can be reduced to a minimal core, not all languages in
the Lisp family are indeed minimalist: for example, now the unqualified
name ``Lisp'' often means Common Lisp, which is fairly big even in terms
of core functionalities; nevertheless, proper abstractions to compress
boilerplate code are still strongly encouraged by Common Lisp experts,
like Paul Graham\cupercite{graham1993}.  However, there does exist
a truly minimalist Lisp, and it is Scheme.

Scheme was not intended to be minimalist from the beginning, according to its
designers, Gerald Jay Sussman and Guy L.\ Steele Jr.\cupercite{sussman1998}\ %
(note how similar this is to Unix's conscious pursuit of simplicity after
the inception of pipes -- \cf~Section~\ref{sec:mcilroy}):
\begin{quoting}
	We were actually trying to build something complicated
	and discovered, serendipitously, that we had accidentally
	designed something that met all our goals but was much simpler
	than we had intended.  \emph{[...]} we realized that the
	\stress{$\bm{\lambda}$-calculus} -- a small, simple formalism --
	could serve as the core of a powerful and expressive programming language.
\end{quoting}
Anyway, minimalism became a defining property of Scheme, as can be seen
from the first sentence from the introduction to its specifications,
\emph{Revised$\,^3\!$ Report on the Algorithmic Language Scheme} and
onward (usually called \rnrs{3}, \rnrs{4} \etc)\cupercite{scmreports:home}%
\footnote{\label{fn:r6rs}The specifications up to \rnrs{5} were all a few
scores (usually less than 60) pages of text, including examples and rationales;
\rnrs{6} significantly expanded both the core and standard libraries\cupercite%
{weinholt2019}, in order to standardise some (more or less legitimately)
demanded features present in mainstream languages.  \rnrs{6} was highly
controversial, most importantly because certain features are less useful
for educators, hobbyists \etc{} who use just a small subset of the
functionalities\cupercite{scmreports:position}; as a result, \rnrs{7}
was intentionally separated into a ``small'' specification and a
``large'' one.  Incidentally, the specification of Go is also
rough 50 pages, but Go is much less expressive than Scheme
(\cf~Section~\ref{sec:homoiconic} for an example).}:
\begin{quoting}
	Programming languages should be designed not by piling
	feature on top of feature, but by removing the weaknesses and
	restrictions that make additional features appear necessary.
\end{quoting}
This attitude clearly resembles the Unix philosophy, and it makes Scheme
the most expressive programming language in my opinion; for this reason,
in all following text in this document I will use Scheme to represent Lisp.

The reason for this digression about Lisp is its strong expressiveness despite
the simplicity, and this expressiveness largely comes from the way Lisp code is
written -- \stress{S-expressions} (short for symbolic expressions)\footnote%
{In the original paper for Lisp\cupercite{mccarthy1960}, McCarthy actually
intended to use another form called M-expressions (short for meta expressions)
for source code, and let the computer translate them to S-expressions;
however, programmers at that time generally preferred to use S-expression
directly.  M-expressions are homoiconic just like S-expressions,
and a format closely related to the former is used by Mathematica,
the computational software.}; for example, the factorial function
can be written in Scheme and Python respectively as\footnote{They
are not exactly equivalent: first, Scheme does not have a \texttt{return}
primitive, and instead uses expressions in \stress{tail positions} as well as
\stress{continuations} (\cf~Footnote~\ref{fn:cps}) to return values; second,
\texttt{(define (fn (args ...)) ...)} is a shorthand for \texttt{(define fn
(lambda (args ...) ...))} in Scheme, while Python's \texttt{lambda} is
severely limited (\cf~Section~\ref{sec:homoiconic} for an example).}:
\colskipa\begin{multicols}{2}
\begin{wquoting}
\begin{Verbatim}
(define (f i)
  (if (> i 1)
      (* (f (- i 1)) i)
      1))
\end{Verbatim}
\end{wquoting}
\begin{wquoting}
\begin{Verbatim}
def f(i):
  if i > 1:
    return i * f(i - 1)
  return 1
\end{Verbatim}
\end{wquoting}
\end{multicols}\colskipb\noindent%
S-expressions would probably appear unintuitive to a newbie, but they are in
fact much easier for computers to process than most alternative source code
formats, and still quite readable to the programmer after a small degree of
familiarisation.  You may note that this is very similar to why text streams
are used as the interface for traditional Unix tools (\cf~Section~%
\ref{sec:mcilroy}), so why are S-expressions more machine-friendly, and
what technical advantages do they bring us?  Please read the next section.

\newpart
\section{S-expressions and homoiconicity}\label{sec:homoiconic}

To understand the machine-friendliness of S-expressions, we first need to
know how source code for a program is represented internally by the computer:
whatever language you use, the source code will be converted (\stress{parsed})
into a data structure that represents its syntax elements necessary for the
computer to understand the program, and this data structure is called the
\stress{abstract syntax tree}\cupercite{wiki:ast}.  For instance, the
AST corresponding to the expression $4 \times 2 - (a + 3)$ and
the S-expression equivalent to the latter are shown below:
\colskipa\begin{multicols}{2}
\begin{wquoting}[innerleftmargin = 0.45em,
	innertopmargin = -0.15em, innerbottommargin = 0.15em]
\begin{forest}
	for tree = {l sep = 0pt, l = 2.25em}
	[$-$,
		[$\times$, [$4$] [$2$]]
		[$+$, [$a$] [$3$]]]
\end{forest}
\end{wquoting}
\columnbreak\vspace*{-0.64em}
\begin{wquoting}
\begin{Verbatim}
(-
  (* 4 2)
  (+ a 3))
\end{Verbatim}
\end{wquoting}
\end{multicols}\colskipb\noindent%
S-expressions can be regarded as representations for nested lists, and
as we can see from the example above, nested lists map to tree structures
(including ASTs) naturally; additionally, although S-expressions do not
eliminate the need for parsing, they are technically much easier to parse
than other formats, which makes them a most convenient representation for
ASTs.  Therefore in combination with the strong capability for list
manipulation in Lisp (originally ``LISt Processor''), S-expressions enable
Lisp to almost effortlessly process Lisp code just like regular data.

When a language can modify source code written in itself just like other
data, it is called a \stress{homoiconic} language\cupercite{wiki:homoiconic};
the ability to treat code as data has extremely profound implications,
as can be seen from the beginning of the half-joking document \emph{The
Gospel of Tux}\footnote{Apart from the von Neumann Architecture\cupercite%
{wiki:neumann}, the profundity of the ``code is data'' idea can be
traced to earlier origins, for instance Gödel numbering\cupercite%
{wiki:godelnum} and the halting problem\cupercite{wiki:halt}.}, which
is why I consider homoiconicity a notion as profound as complexity:
\begin{quoting}
	In the beginning Turing created the Machine.  And the Machine was crufty
	and bogacious, existing in theory only.  And von Neumann looked upon
	the Machine, and saw that it was crufty.  He divided the Machine into
	two Abstractions, \stress{the Data and the Code, and yet the two were
	one Architecture}.  This is a great Mystery, and the beginning of wisdom.
\end{quoting}
It was mentioned in Section~\ref{sec:boltzmann} that all Turing-equivalent
models of computation are not equally wieldy for generic discussions, and
similarly all homoiconic languages are not equally wieldy for practical ``code
as data'' usage\footnote{Another example is XML, a descendant of SGML; the
latter is in turn a document markup language, which makes the XML markup quite
verbose.  Although XML naturally models a tree structure, its use outside of
document markup often results in files with more markups than contents; in
addition, the complex specification of XML makes it nontrivial to parse, and
therefore unsuitable as source code for programs.}: for example, it might be
said that all languages which support text processing are in a sense homoiconic,
because the source code is text; however, most \stress{code transformations},
that are interesting to implementers of interpreters and compilers, would be
very cumbersome to implement only with text processing mechanisms.  For this
reason, in all following text in this document, when discussing homoiconicity
I will specifically mean it on the \stress{AST level}, or in other words
the ability to easily modify the AST of source code just like regular data.

In a language with AST-level homoiconicity, the macro system can be implemented
to use functions, that transform ASTs, as macros; with this kind of macros, new
syntaxes can be easily defined, and many \stress{language features} that are
hardcoded in non-homoiconic languages can be implemented as elegant extensions
to the core language.  For example, goroutines, which are usually considered
one of the main features of Go, are essentially \stress{syntactic sugar} for
interfaces to lightweight coroutines in the libthread\cupercite{lucent2002}/%
libtask\cupercite{swtch:libtask} model\footnote{\label{fn:cps}Another model is
based on the \stress{continuation-passing style}\cupercite{wiki:cps}.}, and
they are hardcoded in Go exactly because new syntaxes cannot be easily added
to Go.  The example about goroutines might seem slightly abstract because
we have not seen code transformations in action, and here I give
an example that is both more concrete and more advanced.

Anonymous functions, essentially $\lambda$-expressions, are very useful
when used as function arguments, as is shown in the Python code below:
\begin{wquoting}
\begin{Verbatim}
sorted(l, key = lambda e: e[0])
\end{Verbatim}
\end{wquoting}
However, the function body of \verb|lambda| in Python must be an expression,
so assignment cannot be used, for instance the following function on the left
cannot be directly transformed to a \verb|lambda|.  But if we regard assignment
as a kind of filter that converts a tuple of input values (\eg~$(x, y)$) into
a modified tuple of values (\eg~$(x, y')$), the function can be transformed
into the composition of multiple \verb|lambda|s, as is shown on the right.
\colskipa\begin{multicols}{2}
\begin{wquoting}
\begin{Verbatim}
def f1(x, y):
  y = y / (1 - x)
  x = x + y
  return x * x + y
\end{Verbatim}
\end{wquoting}
\begin{wquoting}
\begin{Verbatim}
f2 = lambda x, y:
  ((lambda v: v[0] * v[0] + v[1])
  ((lambda v: (v[0] + v[1], v[1]))
  ((x, y / (1 - x)))))
\end{Verbatim}
\end{wquoting}
\end{multicols}\colskipb\noindent%
The definition of \verb|f2| is evidently ugly, and part of the ugliness
lies in the explicit value tuple \verb|v|; another source of ugliness is the
reversed order of filters -- the last \verb|lambda| to be applied is written
first, because it is the outermost.  In Scheme, the \verb|let| form has
its input values written before its body, so we can use it to compose
filters in the desired order, as is shown below on the left.
\colskipa\begin{multicols}{2}
\begin{wquoting}
\begin{Verbatim}
(define f3
  (lambda (x y)
    (let ((y (/ y (- 1 x))))
    (let ((x (+ x y)))
    (+ (* x x) y)))))
\end{Verbatim}
\end{wquoting}
\begin{wquoting}
\begin{Verbatim}
f3 = lambda x, y: \
  (lambda y:
    (lambda x: x * x + y)
    (x + y)) \
  (y / (1 - x))
\end{Verbatim}
\end{wquoting}
\end{multicols}\colskipb\noindent%
As you might have already guessed, \verb|let| is just syntactic sugar for
\verb|lambda|, and \texttt{(let ((a \emph{e$_1$}) (b \emph{e$_2$}) ...) ...)}
is a shorthand for \texttt{((lambda (a b ...) ...) \emph{e$_1$} \emph{e$_2$}
...)}, so \verb|f3| is equivalent to the Python function above on the right.
You should have also noticed \verb|v| is absent from \verb|f3|, and this
works because arguments of inner \verb|lambda|s (\eg~the \verb|x|
in \texttt{lambda x: x * x + y}) shadows outer variables with
the same names (\eg~the argument \verb|x| of \verb|f3|).

\colskipa\begin{multicols}{2}
\begin{wquoting}
\begin{Verbatim}
f4 = lambda x, y: check(
  divide(y, 1 - x),
  (lambda y:
    (lambda x: x * x + y)
    (x + y)))
\end{Verbatim}
\end{wquoting}
\begin{wquoting}
\begin{Verbatim}
check = lambda arg, fn: \
  None if arg == None else fn(arg)

divide = lambda a, b: \
  None if b == 0 else a / b
\end{Verbatim}
\end{wquoting}
\end{multicols}\colskipb
Nevertheless, this is not the end of the story, because $1 - x$ might
be zero, and I want the function to return \verb|None| in such cases;
but considering that functions are only evaluated when applied to some
arguments, \verb|f3| can be transformed into the function above on the left,
with ancillary functions on the right.  Moreover, I did not tell you $x$ and
$y$ might be \verb|None| instead of numbers, but following the line of thought
above, we can further transform \verb|f4| into\footnote{Incidentally, this is
reminiscent of the continuation-passing style (\cf~Footnote~\ref{fn:cps}),
which is in fact not a coincidence\cupercite{troelskn2009}.}
\begin{wquoting}
\begin{Verbatim}
f5 = lambda x, y: check(
  x, (lambda x: check(
    y, (lambda y: check(
      divide(y, 1 - x), (lambda y: check(
        x + y, (lambda x: x * x + y))))))))
\end{Verbatim}
\end{wquoting}
Using this technique, we have actually implemented exceptions in a purely
functional way\footnote{Conversely, we can also see that, as a matter of fact,
exceptions have a ground in type theory.  Besides, I find it necessary to note
that unlike Haskell, Lisp does not pursue purely functional programming, though
the functional style is certainly preferred.}; if you are familiar with Haskell,
you might realise this is essentially using a monad.  A Haskell counterpart of
\verb|f5| can be written in the form below on the left, which is equivalent
to the form on the right using syntactic sugar hardcoded in Haskell\footnote%
{\texttt{return} in Haskell is just a function, and the two \texttt{return}s
on the right correspond exactly to the two \texttt{Just}s on the left,
which are needed due to type-theoretical requirements in Haskell.}.
\colskipa\begin{multicols}{2}
\begin{wquoting}
\begin{Verbatim}
f5 = \x y ->
  (x >>= \x ->
    (y >>= \y ->
      (divide y (1 - x) >>= \y ->
        (Just (x + y) >>= \x ->
          Just (x * x + y)))))
\end{Verbatim}
\end{wquoting}
\begin{wquoting}
\begin{Verbatim}
f5 = \x y -> do
  x <- x
  y <- y
  y <- divide y (1 - x)
  x <- return (x + y)
  return (x * x + y)
\end{Verbatim}
\end{wquoting}
\end{multicols}\colskipb\noindent%
So what is the role of Scheme and S-expressions here?  As was mentioned
just now, the syntactic sugar above is hardcoded in Haskell;
in Scheme, it can be implemented as a syntactic extension.

In the end of this section, I find it necessary to note that in the operating
system, \stress{directory trees resemble S-expressions} in that they are
essentially tree structures; the ``everything is a file'' principle of Unix
(\cf~Section~\ref{sec:plan9}) is a direct result of this idea, although
most important contributors to Unix probably did not realise the similar
potential of S-expressions.  For example Daniel J.\ Bernstein noted, in the
context of security, that parsing and quoting of textual data significantly
complicate software systems\cupercite{djb:qmailsec}; instead, he extensively
used directory trees with very simple formats to configure his software, and
this practice is also adopted by some programmers with close relation
to his software, as can be seen in most daemontools-ish systems.

The complexity of parsing could have been greatly alleviated had we used
homoiconic formats, like S-expressions, when processing data with complicated
structures; the implications of homoiconicity in the context of Unix philosophy
will be further examined in the rest of this document, and here I instead
want to consider a little more about directory trees: given the similarity
between directory trees and S-expressions, why don't we simply replace most
configuration directories with files containing S-expressions?  In my opinion,
an S-expression file is indeed easier to work with than a directory tree is,
but it is also more rigid and monolithic; in comparison, with a directory
tree we can update parts of the configuration atomically, and can assign
different permissions to different parts.  Both of the latter are much
harder to achieve with a single file, which I believe shows the
advantage of directory trees as a configuration interface.

\section{The New Jersey and MIT~/ Stanford styles}\label{sec:wib}

In last section, we have seen the unrivaled power from homoiconcity, which
allows the macro system to easily manipulate ASTs in order to implement new
language features; furthermore, because the macro expansion is recursive,
macros in later parts of a program can access all language features defined
earlier.  When writing high-performance interpreters and optimising compilers,
homoiconicity enables us to not only write transformations on the processed
source code succinctly by using these \stress{structural macros}, but also
implement the transformations as multiple simple, clear and reliable passes,
similar to traditional Unix tools connected by pipes.  The prime example for
this \stress{multi-pass processing} scheme\footnote{\label{fn:slew}Noticing
the analogy between directory trees and S-expressions in Section~%
\ref{sec:homoiconic}, we can also implement multi-pass preprocessors for
configuration directories\cupercite{gitea:slewman}; furthermore, from the
viewpoint of the Prototype Pattern, \texttt{fork()}/\texttt{exec()} and
Bernstein chainloading can also be regarded as similar designs.} is the
nanopass framework\cupercite{andersen2016}\footnote{Incidentally, the
name of one main author of nanopass, when abbreviated, becomes ``AWK''.},
which is used by Chez Scheme\cupercite{wiki:chez}, the prestigious Scheme
compiler that became open-source in 2016; Chez Scheme often produces
executables that are even faster than workalikes written in C, yet it
has a codebase more than one order of magnitude smaller than that of GCC,
and self-compiles in seconds while GCC requires thousands of seconds.

As can already be seen above, in comparison with Lisp, C is in many aspects an
inferior language\cupercite{graham2002}, to put it bluntly, and the pros and
cons of both will be further examined in the next section; this is a result of
effects from multiple historical and methodological factors, and I summarise
them as the following.  Due to hardware limitations, C basically began as a
portable assembly language, reasonably simple to implement with acceptable
performance on computers at Bell Labs; due to the success of Unix, continued
efforts are made to create stronger optimising C compilers, so it is still one
of the most performant languages; and while it certainly has multiple weaknesses
in comparison with other languages, people usually either do not find the
weaknesses a major drawback, or simply use alternative languages.  In simple
words, C was chosen by Unix initially because the former was simple to implement
and fairly easy to use, and later mainly because of inertia; the first reason
highlights some kind of pragmatism present throughout the development of Unix,
and a well-known summary of it is Richard P.\ Gabriel's ``worse is better''%
\cupercite{dreamsongs:wib}\footnote{As you can see from the page, Richard
P.\ Gabriel had still not decided which style was better.  Additionally,
the complexity issue of interruptible system calls in Unix can be bypassed
by userspace wrappers that simply retry until the system calls return without
interruption; however, current standards curiously do not require such
wrappers, which is one reason why Daniel J.\ Bernstein created
his own interface set (\cf~Section~\ref{sec:devel}).}.

Gabriel compared Lisp with Unix and concluded that, basically, when simplicity
of the interface and simplicity of the implementation conflict\footnote{Richard
P.\ Gabriel later noted in \emph{Worse is Better is Worse} that people often
ignore this central premise, and instead just blindly aim to produce software
that only implements 50\% of the requirements.  Another sign of ignoring the
premise, I believe, is the objection to refactoring when attempting to fulfill
the complete requirements, with ``worse is better'' as an excuse\cupercite%
{chiusano2014}.}, Lisp would choose the former (``\stress{the right thing}'' or
the MIT~/ Stanford style), while Unix would choose the latter (``\stress{worse
is better}'' or the New Jersey style).  Apart from C, another main manifestation
of ``worse is better'' in Unix is the preference of textual interfaces by
traditional Unix tools\footnote{In addition to the plain text \vs~S-expressions
debate, there is also the text \vs~binary debate; in my opinion, from cases
like the use of CDB in qmail and s6-rc, we can see that binary files are not
always avoided, but only when there are simple ways to use text files without
compromising the requirements (\eg~performance and security).} (\cf~Section~%
\ref{sec:mcilroy}); and just like C, textual interfaces are often criticised in
the Lisp circle, because plain text is unstructured unlike homoiconic formats
(\eg~S-expressions).  However, from the perspective of minimising the system's
total complexity which covers both the interface and the implementation, I
believe that \stress{the choice between plain text and S-expressions is not
a black-or-white problem}: when processing data with simple structures, using
plain text is usually better because the interface is still easy enough to use;
in contrast, when processing data with complicated structures, the decrease in
interfacial complexity of using S-expressions often outweighs the increase
in implementational complexity.  When dealing with languages, extensive
processing of data with deeply nested and often self-referencing
structures are necessary, so S-expressions are undoubtedly preferable.

Another common criticism against Unix from the Lisp circle is that the former
relentlessly exposes low-level details to the user, and that instead these
details should be hidden from the user by means of encapsulation\footnote{From
this criticism, we can also understand why Lisp focuses more on the interfacial
complexity.}; however, a common problem with encapsulation is \stress{leaky
abstractions}, where customisation often has to be achieved by working around
the encapsulation.  systemd and Linux distributions from Red Hat, examined
in the first part of this document, are the more severe examples; actually
I believe there are few abstractions that are satisfactorily airtight,
and among them are certain well-designed programming languages as well
as kernels of Unix-like operating systems.  Even when we distinguish
between ``normal'' and ``advanced'' users, providing encapsulation
to the former without interfering with the latter's convenience
in customising and debugging does not seem like a solved problem.

\section{Benefits of reconciling Unix and Lisp}\label{sec:benefits}

As was noted in last section, C is an inferior language to Lisp, most
importantly due to its lack of expressiveness: for example, had it used a macro
system (like that in Dale\cupercite{github:dale}) that could modify ASTs, then
features like object-oriented programming would be implementable using macros,
and C++ would perhaps have been unnecessary.  Another prominent weakness of C,
widely noted both inside and outside the Lisp circle, is its memory unsafety
which results in buffer overflows, null-pointer dereferences \etc; alternative
C libraries like skalibs (\cf~Section~\ref{sec:devel}) surely help to reduce
this kind of bugs, but are far from able to reducing them to the minimum,
and I will mention a possible strategy for this in the next section.

However, to be fair, Lisp also has its weaknesses, among which a best-known is
the performance cost of dynamic type checking, especially in scenarios like
numerical computation; automatic type inference, even in its advanced form in
\eg~Chez Scheme, is not a universal solution to this problem.  Another main
problem is the necessity of garbage collection in Lisp implementations, which
makes compiled executables larger in size and often unsuitable for use in
real-time environments; furthermore, advanced requirements for low-level
development, for instance cryptography (\cf~NaCl and BearSSL) which often
requires both constant-time execution and high performance (often involving
assembly), seem largely ignored in the Lisp circle. To summarise them up,
from what I know, I feel that while Lisp is good at implementing complicated
application requirements through abstractions, it is less involved
in low-level development, where it has big potentials in fact.

Something interesting lies in the observations above -- the pros and cons
of Lisp and C seem to be complementary; this naturally leads to the guess
that if we somehow manage to design \stress{a minimalist homoiconic language
that combines their strengths while avoiding their weaknesses}, it would be,
in Tony Hoare's words\cupercite{hoare1981}\footnote{A most important lesson we
have to learn from the speech, as Tony Hoare put it, is that simplicity must
be taken as the first priority when pursuing an ultimate language.},
\begin{quoting}
	\emph{[...]} a language to end all languages, designed to meet the needs
	of all computer applications, both commercial and scientific, \emph{[...]}
\end{quoting}
But is that achievable?  If yes, how to do it, and what would we get?
If no, would the attempt be worthwhile?  My guess for the first question
is ``yes'', while the second and the fourth will be respectively
explored in the next section and Section~\ref{sec:toe}; in the rest
of this section, I will give some examples for the third question.

As was mentioned in Section~\ref{sec:exec}, Laurent Bercot implemented the unit
operations in chainloading as a set of command-line tools; in order to implement
unit operations involving two commands (\eg~loops and pipelines), he designed
a special quoting syntax for command line arguments, and wrapped it up as
``blocks''\cupercite{ska:elblocks} in his language called execline\footnote{Its
design is similar to the initial shell in Unix, the Thompson shell\cupercite%
{wiki:thompson}, which was substituted by the Bourne shell in Unix v7 due to
its inadequacy for more complex programming.}.  Nevertheless, chainloading
does not necessarily imply \verb|exec()|, and instead can be done in a
shell-like language\cupercite{vector2016a} (\cf~shell commands like \verb|cd|
and \verb|umask|); based on the model of scsh\cupercite{scsh:home}, the execline
language can be replaced with scsh-like Scheme, with chainloaders replaced by
scsh-like Scheme programs analogous to the following shell reimplementation of
the \verb|cd| chainloader provided by execline\cupercite{vector2018c}:
\begin{wquoting}
\begin{Verbatim}
#!/bin/rc -e
cd $1; shift; exec $*
\end{Verbatim}
\end{wquoting}

Following this line of thought, it is not unimaginable to replace traditional
Unix tools with Scheme programs as well; considering the expressiveness of
Scheme and the existence of elegant Scheme compilers like Chez Scheme, this
would surely help to reduce the total complexity of the system.  So now we
see that by migrating to Lisp for system programming, even these simple
tools can be further simplified; and as was noted before, Lisp is probably
even more powerful for application programming, so I find it undoubted
that \stress{by embracing homoiconicity, we will be able to build
systems that are more Unix-ish than was possible before}.

Now that we have seen the power of homoiconicity in system programming, it is
appropriate to revisit the Trusting Trust issue in Section~\ref{sec:security};
at that time I noted that one method against Trusting Trust is to construct the
compiler from the machine code in multiple steps, and it should be self-evident
that the auditability of this procedure directly depends on the latter's total
complexity.  It was also noted in Section~\ref{sec:lisp} that Steve Russell
implemented the first Lisp interpreter in assembly by hand, which in combination
with the elegance of Chez Scheme tells us that \stress{homoiconicity will
dramatically reduce the total complexity of bootstrapping from machine code},
and therefore strengthen our defence against Trusting Trust\footnote{Another
potential problem is hardware backdoors, and I think a way to deter them is to
leave adequate room for variation in every step of the bootstrapping procedure:
because the semantics of low-level code is difficult to analyse (which results
in the importance of open source), any attempt at mechanically injecting
malicious code may trigger false positives, which may expose the backdoor.}.

\section{Lisp~/ C reconciliation: how to?}\label{sec:howto}

As was emphasised in Section~\ref{sec:devel}, we should analyse specific issues
specifically, and while the disappearance of resource limitations does not imply
simplicity was no longer important, it surely motivates us to rethink previous
compromises made due to these limitations.  We are well past the era where
garbage collection was prohibitively expensive for regular computers, and now
for devices with severely limited resource we generally prefer cross-compilation
over native compilation.  Given this observation while considering the issue
of big executables and real-time requirements in last section, the proposed
language (I give it the codename ``Nil'', for uNIx plus Lisp) should be able
to use GC for its interpreter and compiler, but \stress{executables produced
by the compiler might need to avoid using GC whenever reasonable}\footnote%
{And the programmer should be aware of how to avoid GC when implementing
special requirements, or alternatively we can perhaps consider (optional and
configurable) real-time GC\cupercite{bernstein2013}.  Furtherly, considering
the inherent pros and cons of different methods for memory management (GC, RAII,
manual management \etc), we probably need a minimal mechanism where multiple
memory-management methods can be used at the same time without conflicts.}.

In last section, we revisited the issue of bootstrapping, and I hinted about
a procedure where a minimal interpreter is somehow built, and then in a later
step a production-ready compiler is produced; a first point to note is that
this deviates from today's common practice of using a compiler to build an
interpreter, and instead constructs an interpreter first.  However, as can be
guessed, Nil interpreters would probably be easier to write in assembly than
Nil compilers are, just as with Lisp which Nil is modeled upon, so from the
viewpoint of complexity it would be better to generate the compiler from a
primitive interpreter\footnote{Probably in multiple steps, involving more and
more powerful compilers, interpreters and even assemblers, and the assemblers
would probably somehow resemble the proposed Nil-powered assembly; to facilitate
auditing, a smaller number of intermediate steps should probably be preferred,
as long as the total size of the codebase involved is close to the minimum.
Besides, on a more theoretical level, I find the notion of Futamura projections
(essentially \stress{partial evaluation})\cupercite{wiki:parteval} highly
interesting.}.  Similarly, noticing the expressiveness of Nil, it would
be natural to use a self-bootstrappable Nil compiler as the base
compiler in production systems, from which other compilers (if
still necessary, and perhaps including one for C) are produced.

Hitherto in this section, we have been examining the Lisp-like aspects of Nil,
but what about the C-like aspects?  I consider Dale, mentioned in last section,
a possible prototype for a C-like layer, upon which a Lisp-like layer would
be implemented using macros, and many other languages (\eg~shell and Makefile)
would be emulated in turn on the Lisp-like layer, accessible to the user via
something like \hologo{LaTeX}'s \stress{macro packages}.  Another approach I
have thought of, which I give the codename Nil-powered assembly, is based on the
notion of a portable assembly\footnote{Since the C-like layer would essentially
be a machine code generator, similar generators like Chez Scheme's built-in
assembler and Daniel J.\ Bernstein's qhasm might be highly instructive
references.} (\cf~Section~\ref{sec:wib}): the C-like layer would be implemented
based on the Lisp-like layer as most other languages would be, and it
would be a markup-like ``reverse-macro'' system which provides primitive
procedures that when called emit assembly instructions to the output.

In addition, as was noted in last section, Nil needs a type system stronger than
that of Lisp, for which I find Yin Wang's design base on \stress{contracts}%
\cupercite{wangyin2013a, wangyin2013b} a very thought-provoking reference;
it is worth noting that this design helps to boost memory safety of the C-like
layer, and even facilitates the formal verification of written programs (\cf~%
Footnote~\ref{fn:formal}).  The foreign function interface between the Lisp-like
and C-like layers will also be an issue, which I am not yet knowledgeable enough
to comment on.  Finally, before ending this section, I need to stress the
non-technical issue of inertia, which troubles Scheme (\cf~Footnote~%
\ref{fn:r6rs}), Plan~9 (\cf~Footnote~\ref{fn:plan9}) as well as qmail and
other excellent (or not) software projects: apart from the technical challenges
Nil will inevitably encounter, it will also have to attract some attention
from both academia and industry to gain enough momentum (there is surely the
possibility that the latter simply does not care, but see the next section);
and even if Nil might have some success, getting rid of historical burdens
while adapting to new requirements\footnote{For programming languages, one
of its most important aspects is the (careful) standardisation of additional
language features and libraries, which is in my opinion done terribly by
the Scheme community.} would not be easy for it, as is for other projects.

\section{Toward a ``theory of everything''}\label{sec:toe}

As was noted in last section and Section~\ref{sec:benefits}, Nil might be a
language that is impossible even in the theoretical sense, or might not attract
adequate attention from the industry, so would the exploration on Nil still be
worthwhile in such cases?  In this final section, I will give my answer
to this question based on the analogy I made in \parencite{vector2018c}:
\begin{quoting}
	I guess reconciling Lisp and Unix would be much easier than
	reconciling quantum mechanics and general relativity; and
	it would be, in a perhaps exaggerated sense, as meaningful.
\end{quoting}

Theoretical physicists and high-energy physicists have long pursued a theory
of everything that can reconcile quantum field theory and general relativity,
because the theory would provide a unified basis for all low-level physical
phenomena.  To my knowledge, there does not seem to be a firm guarantee such
a theory can be successfully achieved by humans: for example, the best-known
candidate, string theory, still appears far from testable, even though it does
agree with observed facts.  On the other hand, there is not a proof that such
a theory is unachievable, either; and apart from the theoretical promises,
research on it has always been giving rise to exciting advancement in diverse
fields ranging from pure mathematics (profoundly connected to theoretical
physics) to civil engineering (involved in the construction of large
facilities for physical experiments).  For these two reasons,
a ToE is still the lifelong pursuit to many physicists.

Similarly, although the efforts at Lisp~/ C reconciliation are not guaranteed
to really result in an ultimate language, it would surely be rewarding to
explore \stress{the best way the two languages can collaborate}, so that the
system's complexity is minimised and the programmer's productivity is maximised:
as has already been seen in Section~\ref{sec:benefits}, the reconciliation, even
in a very primitive form, can already contribute greatly to the reduction in the
complexity of Unix systems; I believe that further simplification of these
systems will attract more people to explore the fundamental aspects of computer
systems, just like how the Raspberry Pi reignited the enthusiasm for low-level
development.  And even if our efforts might not result in production-ready
Nil-based systems finally, I am completely convinced that insightful
communication between the Unix and Lisp circles will, as was explained in
Section~\ref{sec:worklife}, definitely result in a lot of \stress{byproducts
that are both interesting and meaningful}, therefore I conclude this document
with two quotations respectively from Rob Pike\cupercite{pike2000}%
\footnote{The description is, ironically, applicable to himself as well
regarding programming languages.} and Hal Abelson\cupercite{abelson2008}:
\begin{quoting}
	Narrowness of experience leads to narrowness of imagination.
\end{quoting}
\colskipc
\begin{quoting}
	If you \emph{[carefully study the example interpreters in this book]},
	you will change your view of your programming, and your view of
	yourself as a programmer.  You'll come to see yourself as a designer
	of languages rather than only a user of languages, as a person
	who chooses the rules by which languages are put together, rather
	than only a follower of rules that other people have chosen.
\end{quoting}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% UMB-CS110-2015S: Introduction to Computing
% Copyright 2015 Pejman Ghorbanzade <pejman@ghorbanzade.com>
% Creative Commons Attribution-ShareAlike 4.0 International License
% More info: https://github.com/ghorbanzade/UMB-CS110-2015S
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def \topDirectory {../..}
\def \texDirectory {\topDirectory/src/main/tex}

\documentclass[10pt, compress]{beamer}

\usepackage{\texDirectory/template/style/directives}
\input{\texDirectory/template/config}
\usepackage{\texDirectory/template/style/beamerthemeUmassLecture}
\doc{number}{16}
%\setbeamertemplate{footline}[text line]{}

\begin{document}
\prepareCover

\section{Course Administration}

\begin{frame}[fragile]
\frametitle{Course Administration}
Deadline for Assignment 5 extended to May 3, 2015 at 11:59 PM.
\end{frame}

\begin{frame}[fragile]
	\frametitle{Overview}
	\begin{itemize}
		\item[] Class BigInteger
		\item[] Recursion
	\end{itemize}
\end{frame}

\section{Class BigInteger}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Objective}
		Write an algorithm that asks user for a number $x$ and gives as output the value of $x!$ where $x$ is any number between 0 to 50.
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Factorial.java} (v1.0) (Page 1)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=1]{java}
import java.util.InputMismatchException;
import java.util.Scanner;
public class Factorial1 {
	public static long calculateFactorial(int num)
			throws OutOfRangeException {
		if (num > 50 || num < 0)
			throw new OutOfRangeException("Out of Range");
		long result = num;
		for (int i = num-1; i >= 1; i--)
			 result *= i;
		return result;
	}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Factorial.java} (v1.0) (Page 2)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=13]{java}
	public static void main(String[] args) {
		System.out.print("Enter number: ");
		Scanner input = new Scanner(System.in);
		try {
			int num = input.nextInt();
			System.out.println(num+"! is: "
					+calculateFactorial(num));
		}
		catch (InputMismatchException|OutOfRangeException e) {
			e.getMessage();
			e.printStackTrace();
		}
		input.close();
	}
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{\texttt{OutOfRangeException.java}}
		\begin{minted}[fontsize=\small,linenos,firstnumber=1]{java}
@SuppressWarnings("serial")
public class OutOfRangeException extends Exception {
	private String message;
	public OutOfRangeException(String message) {
		 this.message = message;
	}
	public String getMessage() {
		return message;
	}
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Problem Statement}
		No primitive data type can represent $x!$ when $x > 20$. Using primitive data types will lead to data overflow runtime error.
	\end{block}
	\begin{block}{Output}
	\begin{verbatim}
	> Enter number: 20
	20! is: 2432902008176640000
	> Enter number: 21
	21! is: -4249290049419214848
	\end{verbatim}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Proposed Solution}
		Class \textbf{BigInteger} is provided for handling extremely large numbers whose size exceeds that of primitive data types.
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Drawbacks}
		\begin{itemize}
			\item[] Java does not support operation overloading. All arithmetic operations to be carried out by provided methods.
			\item[] Objects of type BigInteger are immutable. Stored value of an object can never be changed.
			\item[] Arithmetic operations are substantially slower.
			\item[] Memory requirements are substantially higher.
		\end{itemize}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{\texttt{BigInt.java}}
		\begin{minted}[fontsize=\small,linenos,firstnumber=1]{java}
import java.math.BigInteger;
public class BigInt {
	public static void main(String[] args) {
		BigInteger b1 = new BigInteger(
				String.valueOf(Integer.MAX_VALUE));
		BigInteger b2 = new BigInteger(
				String.valueOf(Integer.MAX_VALUE));
		System.out.println(b1.multiply(b2));
		System.out.println(b1.divide(b2));
		System.out.println(b1.pow(500));
	}
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Methods}
		\begin{columns}
			\begin{column}{0.3\textwidth}
				\begin{itemize}
					\item[] abs()
					\item[] not()
					\item[] add()
					\item[] divide()
					\item[] multiple()
					\item[] subtract()
				\end{itemize}
			\end{column}
			\begin{column}{0.3\textwidth}
				\begin{itemize}
					\item[] pow()
					\item[] mod()
					\item[] max()
					\item[] min()
					\item[] compareTo()
					\item[] remainder()
				\end{itemize}
			\end{column}
			\begin{column}{0.3\textwidth}
				\begin{itemize}
					\item[] gcd()
					\item[] signum()
					\item[] clearBit()
					\item[] setBit()
					\item[] testBit()
					\item[] toByteArray()
				\end{itemize}
			\end{column}
		\end{columns}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Factorial.java} (v2.0) (Page 1)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=1]{java}
import java.util.InputMismatchException;
import java.util.Scanner;
import java.math.BigInteger;
public class Factorial2 {
	public static BigInteger calculateFactorial(int num)
			throws OutOfRangeException {
		if (num > 50 || num < 0)
			throw new OutOfRangeException("Out of Range");
		BigInteger result = BigInteger.ONE;
		for (int i=1; i<=num; i++)
			result = result.multiply(BigInteger.valueOf(i));
		return result;
	}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Factorial.java} (v2.0) (Page 2)}		\begin{minted}[fontsize=\small,linenos,firstnumber=14]{java}
	public static void main(String[] args) {
		System.out.print("Enter number: ");
		Scanner input = new Scanner(System.in);
		try {
			int num = input.nextInt();
			System.out.println(num + "! = "
					+calculateFactorial(num));
		}
		catch (InputMismatchException|OutOfRangeException e) {
			e.getMessage();
			e.printStackTrace();
		}
		input.close();
	}
}
		\end{minted}
	\end{block}
\end{frame}

\section{Recursion}

\begin{frame}[fragile]
\frametitle{Recursion}
\begin{quote}
To understand what recursion is, you must first understand recursion.
\end{quote}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Objective}
		Write a program \texttt{Factorial.java} that asks user for a number $x$ and gives as output the value of $x!$ where $x$ is any number between 0 to 50.
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Alternative Solution}
		Calculating factorial for any positive number $x$ ($x \neq 1$) requires multiplication of $x$ with factorial of $x-1$.
		\begin{equation}
		n! = n \times (n-1)!
		\end{equation}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Factorial.java} (v3.0) (Page 1)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=1]{java}
import java.util.InputMismatchException;
import java.util.Scanner;
import java.math.BigInteger;
public class Factorial3 {
	public static BigInteger calculateFactorial(int num) {
		if (num == 0)
			return BigInteger.ONE;
		else
			return BigInteger.valueOf(num).multiply(
					calculateFactorial(num-1));
	}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Factorial.java} (v3.0) (Page 2)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=12]{java}
	public static void main(String[] args) {
		System.out.print("Enter number: ");
		Scanner input = new Scanner(System.in);
		try {
			int num = input.nextInt();
			if (num > 50 || num < 0)
				throw new OutOfRangeException("Out of Range");
			System.out.println(num+"! = "+calculateFactorial(num));
		}
		catch (InputMismatchException|OutOfRangeException e) {
			e.getMessage();
			e.printStackTrace();
		}
		input.close();
	}
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
\begin{figure}[H]\centering
\newcounter{density}
\setcounter{density}{20}
\definecolor{turquoise}{HTML}{48D1CC}
\def\couleur{turquoise}
\begin{tikzpicture}
		\path[coordinate] (0,0) coordinate(A)
			++( 60:8cm) coordinate(B)
			++(-60:8cm) coordinate(C);
		\draw[fill=\couleur!\thedensity] (A) -- (B) -- (C) -- cycle;
		\foreach \x in {1,...,25}{%
				\pgfmathsetcounter{density}{\thedensity+10}
				\setcounter{density}{\thedensity}
				\path[coordinate] coordinate(X) at (A){};
				\path[coordinate] (A)
					-- (B) coordinate[pos=.10](A)
					-- (C) coordinate[pos=.10](B)
					-- (X) coordinate[pos=.10](C);
				\draw[fill=\couleur!\thedensity] (A)--(B)--(C)--cycle;
		}
\end{tikzpicture}
\end{figure}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Definition}
		Recursion is a function-call mechanism in which a method returns a call to itself, usually with a different input.
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Motivation}
		\begin{itemize}
			\item[] Recursive models make many real-life phenomena easy to explain.
			\item[] Recursive models make many computational problems easy to solve.
		\end{itemize}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Objective}
		Write a program \texttt{Fibonacci.java} that asks user for a number $x$ and gives as output the value of $x^{th}$ element of the Fibonacci series.
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Fibonacci.java} (Page 1)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=1]{java}
import java.util.InputMismatchException;
import java.util.Scanner;
public class Fibonacci {
	public static int fib(int n) {
		if (n < 2)
				return n;
			else
				return fib(n - 1) + fib(n - 2);
	}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Class BigInteger}
	\begin{block}{Class \texttt{Fibonacci.java} (Page 2)}
		\begin{minted}[fontsize=\small,linenos,firstnumber=10]{java}
	public static void main(String[] args) {
		System.out.print("Enter number: ");
		Scanner input = new Scanner(System.in);
		try {
			int num = input.nextInt();
			System.out.println(num+"! is: "+fib(num));
		}
		catch (InputMismatchException e) {
			e.getMessage();
			e.printStackTrace();
		}
		input.close();
	}
}
		\end{minted}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Conditions}
		\begin{itemize}
			\item[] \textbf{Base Case:}\\A recursive method must end calling itself at some point.
			\item[] \textbf{Convergence:}\\A recursive call must be computationally less complicated.
			\item[] \textbf{Overlapping:}\\No two recursive calls must overlap.
		\end{itemize}
	\end{block}
\end{frame}

\begin{frame}[fragile]
\frametitle{Recursion}
	\begin{block}{Caution}
		\begin{itemize}
			\item[] A recursive method must return before memory allocations become prohibitive causing \texttt{\small StackOverflowError}.
			\item[] Although easy to understand, a recursive method is not guaranteed to have reasonable run-time performance.
		\end{itemize}
	\end{block}
\end{frame}

\plain{}{Keep Calm\\and\\Enjoy Programming}

\end{document}


\documentclass[12pt, letterpaper]{article}
\include{eu}
\pagestyle{plain}

\begin{document}

\noindent
Name: \rule[-1ex]{0.60\textwidth}{0.1pt}
NetID: \rule[-1ex]{0.20\textwidth}{0.1pt}

\section*{\textsl{Einstein's Universe} Final Exam}
\setcounter{problem}{1}

\begin{problem}
(From Problem Set 1)
How many molecules of air are there in a cubic centimeter?
You will have to scale up your answer on the problem set, which
was for a cubic millimeter.
\end{problem}

\vfill ~

\begin{problem}
(From the reading)
Classical mechanics, or Newtonian mechanics, is only valid in certain
circumstances. When do the laws of classical mechanics, like $F =
m\,a$ for example, become wrong or break down? There are many answers
to this problem; I will take anything correct.
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 1)
A Joule is a unit of energy. What are the SI base units for 1\,J? That is,
express 1\,J in terms of kg, s, and m.
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 1)
What is the approximate thickness of a stack of 10,000 100-dollar bills?
That is, a million dollars!
No need to be precise, and use any units you like.
\end{problem}

\vfill ~

\clearpage

\begin{problem}
(From the Kinematics Lab)
Here is a data table of times, positions, and velocities in SI units:\\
\rule{1.0in}{0pt}\begin{tabular}{c|c|c}
time $t$ ($\s$) & position $x$ ($\m$) & velocity $v$ ($\m\,\s^{-1}$) \\
\hline
1.1 & 1.15 & 1.0 \\
2.3 & 1.51 & 1.6 \\
3.7 & 2.00 & 2.3 \\
\hline
\end{tabular}\\
What is the average acceleration in the time interval from $2.3\,\s$ to $3.7\,\s$?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 2)
Give a combination of a mass $M$, a length $L$, and a tension $T$ that will have
units of \emph{time}.
\end{problem}

\vfill ~

\begin{problem}
(From the reading)
What, roughly, is the principle of relativity? State it in 30 words or less!
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 2)
If the work function (binding energy) for an electron in some metal is 2\,eV, can
a photon of wavelength $0.5\,\mu\m$ unbind an electron from that metal?
\end{problem}

\vfill ~

\cleardoublepage

\begin{problem}
(From Lecture on 2019-09-26)
This wave on a string is moving to the left. The string is moving only
up and down. Draw arrows at points A, B, and C showing which way those
bits of string are moving.\\
\includegraphics{wavepulse.png}
\end{problem}

\vfill ~

\begin{problem}
(From the Newton's Second Law Lab)
A $100\,\g$ mass will have roughly what weight in $N$? Roughly!
\end{problem}

\vfill ~

\begin{problem}
(From the reading)
Muons live for a couple of milliseconds. Naively, they can't travel more than few hundred meters,
even traveling near the speed of light. And yet, they often are observed to travel many kilometers.
How is this possible?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 3, problem 2)
If something travels at 0.99\,c, what is the corresponding Lorentz factor?
\end{problem}

\vfill ~

\clearpage

\begin{problem}
(From the Photoelectric Effect Lab)
Which photons have more energy? Ultraviolet or Green?
\end{problem}

\vfill ~

\begin{problem}
(From the reading)
Why did Einstein want to have astronomers precisely observe a Solar eclipse?
What was he hoping they would see?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 4, problem 3)
Which produces more energy per unit mass of fuel: Nuclear fusion reactions or chemical reactions?
\end{problem}

\vfill ~

\begin{problem}
(From the reading)
If you are in a rocket that is moving in the $x$-direction with
respect to the Earth at $0.75\,c$ and, inside the rocket, you are
moving at $0.75\,c$ in the $x$ direction with respect to the rocket,
how fast are you moving with respect to the Earth? No need to
calculate. All I want to know is: Are you moving closer to $0.75\,c$,
$0.95\,c$, or $1.5\,c$?
\end{problem}

\vfill ~

\cleardoublepage

\begin{problem}
(From Lecture, 2019-10-31)
How does the vomit comet make everyone inside experience weightlessness?
What are the pilots doing to make that happen?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 5)
How long does it take light to travel a distance corresponding to the altitude of the mountain K2?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 5)
What is the Doppler factor corresponding to a velocity of $2\times 10^8\,\mps$?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 5)
What is the insolation on Jupiter in watts per square meter?
\end{problem}

\vfill ~

\clearpage

\begin{problem}
(From Lecture)
What is the age of the Universe?
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 6)
The star S2 orbits the black hole at the center of our Galaxy.
How fast is this star moving, on average or roughly?
Don't forget your units, here or elsewhere on the exam!
\end{problem}

\vfill ~

\begin{problem}
(From Lecture)
What is the relationship between an acceleration $a$, a change in velocity $\Delta v$ and a small time interval $\Delta t$? Give an equation.
\end{problem}

\vfill ~

\begin{problem}
(From Problem Set 6)
Why did the black hole merger discovered by \textsl{LIGO} produce a final black hole that is less massive than the sum of the masses of the two black holes that merged to make it? Or, where did the mass go?
\end{problem}

\vfill ~

\clearpage

\begin{problem}
State one true thing about the world that you learned in this class,
which you expect to remember for many years.
\end{problem}

\vfill ~

\begin{problem}
Einstein brought two changes to physics: relativity (special and general) and
quantization of energy and mass. Which do you think is more important, and why?
\end{problem}

\vfill ~

~

\vfill ~

~

\vfill ~

\end{document}


\documentclass{article}

\usepackage{fancyhdr}
\usepackage{extramarks}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{tikz}
\usepackage{physics}
\usepackage[plain]{algorithm}
\usepackage{algpseudocode}
\usepackage{hyperref}

\usetikzlibrary{automata,positioning}

%
% Basic Document Settings
%

\topmargin=-0.45in
\evensidemargin=0in
\oddsidemargin=0in
\textwidth=6.5in
\textheight=9.0in
\headsep=0.25in

\linespread{1.1}

\pagestyle{fancy}
%\lhead{\hmwkAuthorName}
\chead{\hmwkClass\ : \hmwkTitle}
\rhead{\firstxmark}
\lfoot{\lastxmark}
\cfoot{\thepage}

\renewcommand\headrulewidth{0.4pt}
\renewcommand\footrulewidth{0.4pt}

\setlength\parindent{0pt}

%
% Create Problem Sections
%
\newcommand{\be}{\begin{equation}}
\newcommand{\ee}{\end{equation}}
\newcommand{\bes}{\begin{equation*}}
\newcommand{\ees}{\end{equation*}}
\newcommand{\bea}{\begin{flalign*}}
\newcommand{\eea}{\end{flalign*}}

\newcommand{\enterProblemHeader}[1]{
    \nobreak\extramarks{}{Problem \arabic{#1} continued on next page\ldots}\nobreak{}
    \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{}
}

\newcommand{\exitProblemHeader}[1]{
    \nobreak\extramarks{Problem \arabic{#1} (continued)}{Problem \arabic{#1} continued on next page\ldots}\nobreak{}
    \stepcounter{#1}
    \nobreak\extramarks{Problem \arabic{#1}}{}\nobreak{}
}

\setcounter{secnumdepth}{0}
\newcounter{partCounter}
\newcounter{homeworkProblemCounter}
\setcounter{homeworkProblemCounter}{1}
\nobreak\extramarks{Problem \arabic{homeworkProblemCounter}}{}\nobreak{}

%
% Homework Problem Environment
%
% This environment takes an optional argument. When given, it will adjust the
% problem counter. This is useful for when the problems given for your
% assignment aren't sequential. See the last 3 problems of this template for an
% example.
%
\newenvironment{homeworkProblem}[1][-1]{
    \ifnum#1>0
        \setcounter{homeworkProblemCounter}{#1}
    \fi
    \section{Problem \arabic{homeworkProblemCounter}}
    \setcounter{partCounter}{1}
    \enterProblemHeader{homeworkProblemCounter}
}{
    \exitProblemHeader{homeworkProblemCounter}
}

%
% Homework Details
%   - Title
%   - Due date
%   - Class
%   - Section/Time
%   - Instructor
%   - Author
%

\newcommand{\hmwkTitle}{Tutorial\ \#3	}
\newcommand{\hmwkDueDate}{ICTS Summer School on Gravitational Wave Astronomy, 2019. }
\newcommand{\hmwkClass}{Advanced General Relativity}
\newcommand{\hmwkClassTime}{}
\newcommand{\hmwkClassInstructor}{Sudipta Sarkar}
\newcommand{\hmwkAuthorName}{\textbf{Tutorial Instructors : Aditya Vijaykumar, Md Arif Shaikh}}

%
% Title Page
%

\title{
    %\vspace{2in}
    \textmd{\textbf{\hmwkClass:\ \hmwkTitle}}\\
    \normalsize\vspace{0.1in}\small{\hmwkDueDate\ }\\
%    \vspace{3in}
}

\author{\hmwkAuthorName}
\date{}

\renewcommand{\part}[1]{\textbf{\large Part \Alph{partCounter}}\stepcounter{partCounter}\\}

%
% Various Helper Commands
%

% Useful for algorithms
\newcommand{\alg}[1]{\textsc{\bfseries \footnotesize #1}}

% For derivatives
\newcommand{\deriv}[1]{\frac{\mathrm{d}}{\mathrm{d}x} (#1)}

% For partial derivatives
\newcommand{\pderiv}[2]{\frac{\partial}{\partial #1} (#2)}

% Integral dx
\newcommand{\dx}{\mathrm{d}x}

% Alias for the Solution section header
\newcommand{\solution}{\textbf{\large Solution}}

% Probability commands: Expectation, Variance, Covariance, Bias
\newcommand{\E}{\mathrm{E}}
\newcommand{\Var}{\mathrm{Var}}
\newcommand{\Cov}{\mathrm{Cov}}
\newcommand{\Bias}{\mathrm{Bias}}

\begin{document}

\maketitle

\begin{homeworkProblem}
	\textbf{Part (a)}\\
	Given,
	\begin{equation}\label{e1}
	\dd{s}^2 = - \qty(1- \dfrac{2M}{r}) \dd{t}^2 + \qty(1 - \dfrac{2M}{r})^{-1} \dd{r}^2 + r^2 \qty(\dd{\theta}^2 + \sin^2 \theta \dd{\phi}^2)
	\end{equation}
	Using an affine parameter $ \lambda $, we can rewrite these equations as,
	\begin{equation}\label{e2}
	\kappa = \qty(\dv{s}{\lambda})^2 = - \qty(1- \dfrac{2M}{r}) \dot{t}^2 + \qty(1 - \dfrac{2M}{r})^{-1} \dot{r}^2 + r^2 \qty(\dot{\theta}^2 + \sin^2 \theta \dot{\phi}^2)
	\end{equation}
	where $ \kappa = -1,0,1 $ for timelike, null and spacelike geodesics respectively. Corresponding to the Killing vectors $ \partial_t $ and $ \partial_\phi $, we would have the following conserved quantities,
	\begin{equation}\label{e3}
	\tilde{E} = 2\qty(1 - \dfrac{2M}{r}) \dot{t} \qq{and} \tilde{L} = 2 r^2 \sin^2 \theta \dot{\phi}
	\end{equation}
	Substituting $\dot{t} $ and $ \dot{\phi} $ from (\ref{e3}) to (\ref{e2}) and assuming planar orbit ($ \theta = \pi/2 $), we get,
	\begin{align}\label{key}
	\kappa &= - \qty(1- \dfrac{2M}{r}) \dfrac{\tilde{E}^2}{4 \qty(1 - \dfrac{2M}{r})^2}+ \qty(1 - \dfrac{2M}{r})^{-1} \dot{r}^2 + r^2 \dfrac{\tilde{L}^2}{4 r^4 \sin^4 \theta} \\
	&= - \qty(1- \dfrac{2M}{r})^{-1} \dfrac{\tilde{E}^2}{4}+ \qty(1 - \dfrac{2M}{r})^{-1} \dot{r}^2 + \dfrac{\tilde{L}^2}{4 r^2}\\
	\kappa - \dfrac{2M\kappa}{r} &= -  \dfrac{\tilde{E}^2}{4}+  \dot{r}^2 + \dfrac{\tilde{L}^2}{4 r^2} \qty(1 - \dfrac{2M}{r})
	\end{align}
	\begin{equation}\label{key}
	\therefore \dfrac{\dot{r}^2}{2} - \dfrac{1}{2}\qty({\kappa} +\dfrac{\tilde{E}^2}{4} ) + \dfrac{M\kappa}{r} + \dfrac{\tilde{L}^2}{8r^2} - \dfrac{\tilde{L}^2 M}{4 r^3} = 0
	\end{equation}
	Defining $ E = \dfrac{\tilde{E}}{2} $ and $ L = \dfrac{\tilde{L}}{2} $, we have,
	\begin{equation}\label{e8}
	\dfrac{\dot{r}^2}{2} + V_{eff}(r) = 0
	\end{equation}
	where $ V_{eff}(r) = - \dfrac{E^2 + \kappa}{2} + \dfrac{M\kappa}{r} + \dfrac{{L}^2}{2r^2} - \dfrac{{L}^2 M}{ r^3}  $
	\\

	\textbf{Part (b)}\\
	Substituting $ \kappa = 0$ and $ \dot{r} = 0 $ in (\ref{e8}), and further using (\ref{e3}) we have,
	\begin{equation}\label{e9}
	E^2 = \dfrac{L^2}{ r^2} \qty(1 - \dfrac{2M}{r}) \implies \qty(\dv{t}{\phi})^2  = r^2 \qty(1 - \dfrac{2M}{r})^{-1}
	\end{equation}
	Now, writing down the radial geodesic for the Schwarzschild metric, we have,
	\begin{equation}\label{key}
	\dv{\tau} \qty[2\qty(1 - \dfrac{2M}{r})^{-1} \dot{r} ] = - \dfrac{2M}{r^2} \dot{t}^2  - \qty(1 - \dfrac{2M}{r})^{-2} \qty(\dfrac{2M}{r^2}) \dot{r}^2 + 2 r (\dot{\theta}^2 + \sin^2 \theta \dot{\phi}^2)
	\end{equation}
	Using $ \dot{r}=0 $, $ \theta = \pi/2 $, we get,
	\begin{equation}\label{key}
	\dfrac{2M}{r^2} \dot{t}^2 = 2 r \dot{\phi}^2 \implies \qty(\dv{t}{\phi})^2 = \dfrac{r^3}{M}
	\end{equation}
	Comparing with (\ref{e9}), we have,
	\begin{equation}\label{key}
	r^2 \qty(1 - \dfrac{2M}{r})^{-1} = \dfrac{r^3}{M} \implies 1 - \dfrac{2M}{r} = \dfrac{M}{r} \implies r = 3M
	\end{equation}
	Hence, there is a null circular orbit at $ r = 3M $. To decide stability, one needs to check the value of $ \pdv[2]{V_{eff}}{r} $ at $ r=r_p=3M $,
	\begin{equation}\label{key}
	\eval{\pdv[2]{V_{eff}}{r}}_{r=r_p} =  \dfrac{3L^2}{r_p^4} - 12\dfrac{L^2 M}{r_p^5} = - \dfrac{L^2}{(3M)^4} < 0
	\end{equation}
	Hence, this orbit is unstable.
	\\

	\textbf{Parts (c) and (d)}\\
	Radial null geodesics will have $ \kappa =0  $ and $ L=0 $. Hence, using (\ref{e8}),
	\begin{align}\label{key}
	\dot{r}^2 &= E^2  \\
	\implies \dv{r}{\lambda} &= - E \qq{for ingoing rays}\\
	\implies \int_{r_0}^{2M} \dd{r}  &= - E \int_{0}^{\lambda_0} \dd{\lambda} \\
	\implies \lambda_0 &= \dfrac{r_0 - 2M}{E} \implies \qq{finite}
	\end{align}

	Also, using (\ref{e2}), and assuming null radial orbits, we get,
	\begin{align}\label{key}
	\dfrac{\dot{t}^2}{\dot{r}^2} &= \qty(\dv{t}{r})^2 = \qty(1 - \dfrac{2M}{r})^{-2}\\
	\implies t &= \pm \int \dd{r}  \qty(1 - \dfrac{2M}{r})^{-1} + C \\
	\implies t &= \pm \qty[r - r_0 + 2M \log(\dfrac{r-2M}{r_0 - 2M})] + t_0
	\end{align}

	\textcolor{red}{Sketch the rays}
\end{homeworkProblem}

\begin{homeworkProblem}
	The area of a black hole $ A \propto M^2 $. The area theorem hence implies,
	\begin{equation}\label{ehawk}
	M_3^2 \ge M_1^2 + M_2^2
	\end{equation}
	Consider the two numbers $ M_1^2 $ and $ M_2^2 $. Let's write down the $ AM \ge GM $ inequality \textit{ie.},
	\begin{align}\label{e10}
	\dfrac{M_1^2 + M_2^2}{2} &\ge M_1 M_2\\
	\implies M_1^2 + M_2^2 &\ge \dfrac{M_1^2 + M_2^2}{2} + M_1 M_2 \\
	\implies M_1^2 + M_2^2 &\ge \dfrac{(M_1 + M_2)^2}{2}
	\end{align}

	Combining (\ref{ehawk}) and the last inequality, we have,
	\begin{equation}\label{key}
	M_3^2 \ge \dfrac{(M_1 + M_2)^2}{2} \implies \dfrac{M_3}{M_1 + M_2} \ge \dfrac{1}{\sqrt{2}}
	\end{equation}
	Hence,
	\begin{equation}\label{key}
 \eta \le 1 - \dfrac{1}{\sqrt{2}}
	\end{equation}
\end{homeworkProblem}
\end{document}