\documentclass{article} % For LaTeX2e
\usepackage[legalpaper, margin=0.5in]{geometry}
\usepackage{amsmath}
\usepackage{amsfonts,dsfont}
\usepackage{amssymb}
\usepackage[ruled,vlined]{algorithm2e}

\usepackage{graphicx}
\usepackage{caption}
\usepackage{subcaption}
\usepackage{xcolor}

\begin{document}

\section{Simple GAN vs. Unsupervised Conditional GAN}
\begin{figure}[h]
	\centering
	\captionsetup{labelformat=empty}
	\begin{subfigure}[b]{0.3\textwidth}
		\includegraphics[width=\textwidth]{2_gan_ls9_1000_1000.pdf}
		\caption{Simple GAN (2 modes)}
		\label{fig:gan_2}
	\end{subfigure}
	\begin{subfigure}[b]{0.3\textwidth}
		\includegraphics[width=\textwidth]{3_gan_ls9_1000_1000.pdf}
		\caption{Simple GAN (3 modes)}
		\label{fig:gan_3}
	\end{subfigure}
	\begin{subfigure}[b]{0.3\textwidth}
		\includegraphics[width=\textwidth]{4_gan_ls9_1000_1000.pdf}
		\caption{Simple GAN (4 modes)}
		\label{fig:gan_4}
	\end{subfigure} \\
	\begin{subfigure}[b]{0.3\textwidth}
		\includegraphics[width=\textwidth]{2_cond_gan_k2_ls9_1000_1000.pdf}
		\caption{Conditional GAN (2 modes)}
		\label{fig:cgan_2}
	\end{subfigure}
	\begin{subfigure}[b]{0.3\textwidth}
		\includegraphics[width=\textwidth]{3_cond_gan_k3_ls9_1000_1000.pdf}
		\caption{Conditional GAN (3 modes)}
		\label{fig:cgan_3}
	\end{subfigure}
	\begin{subfigure}[b]{0.3\textwidth}
		\includegraphics[width=\textwidth]{4_cond_gan_k4_ls9_1000_1000.pdf}
		\caption{Conditional GAN (4 modes)}
		\label{fig:cgan_4}
	\end{subfigure} \\[-1ex]
	\caption{Comparison between simple GAN and {\bf unsupervised} Conditional GAN (cGAN) for $1D$ data with multiple modes. The samples at $y=0$ are the real samples on which the GAN was trained. The samples at $y=0.5$ are synthetic samples generated by the GANs after training for $1000$ epochs. The {\em black} lines show the histogram of the original data. The \textit{\textcolor{red}{red}} lines show the histogram of the synthetic samples generated by the GAN. For the unsupervised cGAN, we first perform {\em unsupervised} clustering with Gaussian Mixture Models. The number of components were selected with {\em BIC}. The cluster labels are then assigned as the class labels. For the 1D data shown here, cluster information seems to help.}
	\label{fig:1d_gan}
\end{figure}

\section{AnoGAN}
\begin{figure}[h]
	\centering
	\captionsetup{labelformat=empty}
	\begin{subfigure}[b]{0.45\textwidth}
		\includegraphics[width=\textwidth]{toy2_ano_gan_ls9_2000.pdf}
		\caption{Toy data samples}
		\label{fig:toy}
	\end{subfigure}
	\begin{subfigure}[b]{0.45\textwidth}
		\includegraphics[width=\textwidth]{toy2_ano_gan_ls9_2000_test_ano_50.pdf}
		\caption{{\em AnoGAN} with simple GAN}
		\label{fig:gan_ano}
	\end{subfigure} \\
	\begin{subfigure}[b]{0.45\textwidth}
		\includegraphics[width=\textwidth]{toy2_cond_ano_gan_k3_ls9_2000.pdf}
		\caption{Clusters for cGAN}
		\label{fig:cgan_k}
	\end{subfigure}
	\begin{subfigure}[b]{0.45\textwidth}
		\includegraphics[width=\textwidth]{toy2_cond_ano_gan_k3_ls9_2000_test_ano_50.pdf}
		\caption{{\em AnoGAN} with cGAN}
		\label{fig:cgan_ano}
	\end{subfigure} \\[-1ex]
	\caption{Illustration of {\bf AnoGAN}. {\bf (a)} shows the $2D$ {\em Toy} data. All GANs were trained for $2000$ epochs. {\bf (b)} shows the AnoGAN results with a simple GAN. {\bf (c)} shows the unsupervised clustering of the {\em Toy} dataset. The number of components in the Gaussian Mixture Model was found to be $3$ using the $BIC$ model selection criteria. {\bf (d)} shows the AnoGAN results with a cGAN where the labels were assigned according to the clusters shown in {\bf (c)}. In {\bf (b)} and {\bf (d)} the points marked in {\em black} are test data points which were not available during training. Each test point has a corresponding colored point (marked with a \textit{\textcolor{red}{red `$\times$'}}) that represents its synthetic image reconstructed by AnoGAN. In simplistic terms, the distance between a test point and its reconstructed image can be considered a measure of anomalousness. {\bf (b)} and {\bf (d)} show that the points in the dense regions (e.g., $2, 3, 4, 7$) generally have low reconstruction loss. However, points in low-density regions (e.g., $1, 5, 6, 8$) give mixed results: while the reconstruction loss for $1$ is low, it is high for $5, 6, 8$. {\bf (b)} and {\bf (d)} also show the trace of reconstruction for each data point. AnoGAN computes the reconstructed image iteratively. For example, with test point $5$, the initial random latent representation $z_0$ corresponds to a point in the middle. After optimizing the AnoGAN loss, a new latent representation $z_1$ is found which corresponds to a point slightly closer to $5$. Then, using $z_1$ and optimizing, the next latent representation $z_2$ is found. Over the several iterations, the reconstructed image for $5$ moved along the \textcolor{brown}{brown} line until it finally reached the point marked with \textcolor{red}{$\times$}. The traces are useful for debug: we can see that all reconstructed points move closer to the target test points irrespective of where they start. It is hard to see whether a cGAN performs better than a simple GAN in this case. Moreover, the AnoGAN loss should be averaged over multiple runs for each test point because there is stochasticity in the initial latent representation.}
	\label{fig:ano_gan}
\end{figure}

\end{document}


\documentclass[english]{beamer}
\input{preamble.tex}
\begin{document}

\title{Estimation of DP Models}

\subtitle{ScPo CompEcon}

\frame{\titlepage}

\frame{\frametitle{Table of contents}\tableofcontents}

\section{Rust Bus Replacement}

\begin{frame}
\tableofcontents[currentsection]
\end{frame}

\begin{frame}{Estimation of Dynamic Programming Models}
\begin{midi}
\item Now that we know how to solve them, how do we estimate DP models?
\item Examples
\begin{itemize}
\item \cite{rustbus}
\item \cite{BLP}
\end{itemize}
\item There are many different methods. We will introduce just a few. Look at the survey \cite{Aguirre} for more details.
\end{midi}
\end{frame}

\begin{frame}{\cite{rustbus}}
\begin{itemize}
\item Each Bus comes in once a month for repair
\begin{itemize}
\item Harold Zurcher decides after observing mileage $x_t$ since last engine replacment \bred{and} some other unobserved variable $\varepsilon$ whether to replace or not:
\begin{equation*}
u(x+t,d_t,\red{\theta^c},\red{RC}) = \begin{cases}-c(x_t,\red{\theta^c}) & \text{if }d_t=0 \\
                                                  -(\red{RC} + c(0,\red{\theta^c}) & \text{if }d_t=1
  \end{cases}
\end{equation*}

\item He solves the DP
\begin{equation*}
V_\red{\theta}(x_t) = \sup_{d_t} \mathbb{E}\left\{ \sum_{j=t}^\infty \beta^{j-t} u(x_j,d_j,\red{\theta}) + \varepsilon_t(d_t) |x_t \right\}
\end{equation*}
\end{itemize}
\item Parameters to be estimated: $\red{\theta} = \red{(\theta^c,RC,\theta^p)}$
\item This formulation results after making a set of simplifying assumptions.
\end{itemize}
\end{frame}

\begin{frame}{\cite{rustbus}}
\begin{midi}
\item To simplify, the odometer progress is assumed to be a random process.
\item that is, $x_t$ evolves stochastically.
\item The assumption is that $x_{t+1}\in\{s,s+1,s+2,s+3\}$ where $s$ is the state of $x_t$, i.e. the bin it lies in.
\end{midi}

\end{frame}

\begin{frame}{Model and Data}
\begin{midi}
\item Data: a time series $\{x_t,d_t \}_{t=1}^T$
\item Likelihood function is
\begin{equation*}
\mathcal{L}(\red{\theta}) = \Pi_{t=2}^T P(d_t|x_t,\red{\theta^c},\red{RC})p(x_t|x_{t-1},d_{t-1},\red{\theta^p})
\end{equation*}
where the conditional choice probabilities are given by
\begin{equation*}
P(d_t|x_t,\red{\theta^c},\red{RC}) = \frac{\exp[u(x,d,\red{\theta^c},\red{RC}) + \beta\blue{EV}_\red{\theta}(x,d)]}{\sum_{d'\in\{0,1\}}\exp[u(x,d',\red{\theta^c},\red{RC}) + \beta\blue{EV}_\red{\theta}(x',d')]}
\end{equation*}
and, importantly, $\blue{EV}$ is the solution to

\begin{align*}
\blue{EV}_\red{\theta}(x,d) =& T_\red{\theta}(\blue{EV}_\red{\theta})(x,d) \\
                       \equiv&\int_{x'=0}^\infty \log \left( \sum_{d'\in{0,1}}\exp[u(x,d',\red{\theta^c},\red{RC}) + \beta\blue{EV}_\red{\theta}(x',d')] \right)
\end{align*}
\end{midi}
\end{frame}

\begin{frame}{Nested Fixed Point Algorithm (NXFP)}
\begin{widee}
\item \bred{Outer Loop}: Solve the Likelihood function
\begin{equation*}
\max_{\red{\theta}>0} \mathcal{L}(\red{\theta}) = \Pi_{t=2}^T P(d_t|x_t,\red{\theta^c},\red{RC})p(x_t|x_{t-1},d_{t-1},\red{\theta^p})
\end{equation*}
\item \bblue{Inner Loop}: Compute Expected value function $\blue{EV}_\red{\theta}$ for a given guess $\red{\theta}$
\begin{equation*}
\blue{EV}_\red{\theta} = T_\red{\theta}(\blue{EV}_\red{\theta})(x,d)
\end{equation*}
\end{widee}
\end{frame}

\begin{frame}{Potential Issues with NXFP}
\begin{midi}
\item We need a stopping rule for the likelihood function.
\item We need one for the inner loop as well.
\item Errors will propagate from the inner loop to the outer loop.
\item Given that the search direction on $\mathcal{L}(\red{\theta})$ depends on it's gradient, errors will matter a lot.
\item the tolerance on the inner loop needs to be \bred{tight}, like $1.0e^{-13}$
\end{midi}
\end{frame}

\begin{frame}{MPEC}{Mathematical Programming with Equality constraints}

\begin{midi}
\item We can turn the problem around.
\item Instead of asking \emph{Whats the \blue{EV} compatible with my guess $\red{\theta}$?}, we could directly attack the likelihood:
\item Maximize $\mathcal{L}(\red{\theta})$ \bred{subject to} the constraint, that behavior is \bblue{optimal} according to the model.
\item in other words, augment the likelihood:
\end{midi}

\begin{align*}
\mathcal{L}(\red{\theta},\blue{EV};X) &= \Pi_{t=2}^T P(d_t|x_t,\red{\theta^c},\red{RC})p(x_t|x_{t-1},d_{t-1},\red{\theta^p}) \\
P(d_t|x_t,\red{\theta^c},\red{RC}) &= \frac{\exp[u(x,d,\red{\theta^c},\red{RC}) + \beta\blue{EV}(x,d)]}{\sum_{d'\in\{0,1\}}\exp[u(x,d',\red{\theta^c},\red{RC}) + \beta\blue{EV}(x',d')]}
\end{align*}

\end{frame}

\begin{frame}{Different Optimization problems}
\bred{NXFP} solves the unconstrained optimization problem:
\begin{equation*}
\max_{\red{\theta}} \mathcal{L}(\red{\theta},\blue{EV}_\red{\theta})
\end{equation*}
\bblue{MPEC} solves the constrained optimization problem:
\begin{align*}
\max_{\red{\theta},\blue{EV}} & \mathcal{L}(\red{\theta},\blue{EV};X) \\
\text{subject to} & \blue{EV} = T(\blue{EV},\red{\theta})
\end{align*}
\end{frame}

\begin{frame}{\cite{juddsu}}

\begin{midi}
\item \cite{juddsu} perform MPEC on the bus model.
\item the key difference to note is that $\blue{EV}$ now becomes a choice variable.
\item In fact, the optimizer will be fed a vector
\begin{equation*}
x = [RC,\theta^c,\mathbf{EV}]
\end{equation*}
where $\mathbf{EV}$ is an approximation to $\blue{EV}$. In \cite{juddsu}, this is just going to be
\begin{equation*}
\mathbf{EV} \equiv [EV(x_1),EV(x_2),\dots,EV(x_n)]
\end{equation*}
i.e. the approximation needs to hold pointwise.
\end{midi}
\end{frame}

\begin{frame}{\cite{juddsu}}
\includegraphics[width=11cm]{su-2.png}

\end{frame}

\begin{frame}{Performance}
\begin{midi}
\item In \emph{general}, NXFP is a computationally expensive operation.
\begin{itemize}
\item you have to solve a DP for many many many times in order to find your $\red{\theta}$.
\end{itemize}
\item However, there is much to qualify about this statement. The \bred{details} matter here.
\item For example, \cite{juddsu} are very critical about NXFP in the Bus Model. They compare it to the performance of \bblue{MPEC}.
\item But \citet{iskhakov2016comment} redo the exercise with Rust's original method to solve $\blue{EV}$ and show that NXFP is still a very strong contender in this example.
\end{midi}
\end{frame}

\section{Berry, Levinsohn and Pakes (BLP) as MPEC}

\begin{frame}
\tableofcontents[currentsection]
\end{frame}

\begin{frame}{BLP after \cite{dube2012improving}}
\begin{midi}
\item \cite{BLP} is a model for automobile sales.
\item It has become a very widely applied model and estimation technique, short: \bred{BLP}.
\item The original paper performs demand estimation with a large number of differentiated products:
\begin{itemize}
\item characteristics approach
\item useful when only aggregate data are available
\item allows for flexible substitition patterns
\item controls for price endogeneity
\end{itemize}
\item The computational algorithm derives moment conditions from a non-linear model
\item The method is also known as \bblue{Random Coefficients Logit Demand}
\end{midi}
\end{frame}

\begin{frame}{Random Coefficients Logit Demand}
\begin{midi}
\item The Utility of $i$ from purchasing product $j$ in market $t$ is
\begin{equation}
u_{ijt} = \red{\beta_i^0} + x_{jt}\red{\beta_i^x} - \red{\beta_i^p} p_{jt} + \blue{\xi_{jt}} + \varepsilon_{ijt} \label{eq:demand}
\end{equation}
\item with product characteristics $x_{jt},p_{jt},\blue{\xi_{jt}}$
\begin{itemize}
\item $x_{jt},p_{jt}$: ovserved with $cov(p_{jt},\blue{\xi_{jt}})\neq 0$
\item $\blue{\xi_{jt}}$: unovserved to econometrician.
\end{itemize}
\item $\red{\beta_i} \equiv [\red{\beta_i^0},\red{\beta_i^x},\red{\beta_i^p}]$: random coefficients or individual specific tastes to be estimated.
\begin{itemize}
\item We posit a distribution: $\red{\beta_i} \sim F_\beta(\beta,\red{\theta})$
\item \redbox{Goal of BLP}: estimate $\red{\theta}$ in the above parametric distribution.
\item errors are assumed type 1 EV
\item Consumer picks product $j$ if $u_{ijt}\geq u_{ij't}$
\end{itemize}
\end{midi}
\end{frame}

\begin{frame}{The Model: Market Shares}
\begin{midi}
\item The model predicts \cyanbox{market shares}:
\begin{equation}
s_j(x_t,p_t,\blue{x_{it}};\red{\theta}) = \int_{\{\beta_i,\varepsilon_i | u_{ijt}\geq u_{ij't},\forall j'\neq j\}} dF_\beta(\beta,\red{\theta}) dF_\varepsilon(\varepsilon)
\end{equation}
\item with type 1 EV shocks $\varepsilon$, there is an analytical solution to one of those integrals:
\begin{equation}
s_j(x_t,p_t,\blue{x_{it}};\red{\theta})  = \int_\beta \frac{\exp(\beta^0 + x_{jt}\beta^x - \beta^p p_{jt} + \blue{\xi_{jt}})}{1+\sum_{k=1}^J \exp(\beta^0 + x_{kt}\beta^x - \beta^p p_{kt} + \blue{\xi_{kt}})} dF_\beta(\beta,\red{\theta})
\end{equation}
\end{midi}
\end{frame}

\begin{frame}{The Model: Market Shares}
They use numerical integration:
\begin{equation}
\hat{s}_j(x_t,p_t,\blue{x_{it}};\red{\theta})  = \frac{1}{ns} \sum_{r=1}^{ns} \frac{\exp(\beta^{0r} + x_{jt}\beta^{xr} - \beta^{pr} p_{jt} + \blue{\xi_{jt}})}{1+\sum_{k=1}^J \exp(\beta^{0r} + x_{kt}\beta^{xr} - \beta^{pr} p_{kt} + \blue{\xi_{kt}})} dF_\beta(\beta,\red{\theta})
\end{equation}
to arrive at the market share (moment) conditions:
\begin{equation}
\hat{s}_j(x_t,p_t,\blue{\xi_{it}};\red{\theta}) = S_{jt},\forall j \in J,t\in T  \label{eq:shares}
\end{equation}
where $S_{jt}$ is data.
\end{frame}

\begin{frame}{GMM Estimator}
\begin{midi}
\item If firms can observe demand shocks $\blue{\xi_t}$, they will set prices accordingly.
\item There will be correlation between $p_t$ and $\blue{\xi_t}$ $\Rightarrow$ Endogeneity Bias!
\item BLP solve endogeneity of prices with a vector $z_{jt}$ of IVs, which are \bred{excluded} from the demand equation \eqref{eq:demand}
\item they propose a moment condition $E[\blue{\xi_{jt}}|z_{jt},x_{jt}] = 0 $
\item $z_{jt}$: e.g. product-specific cost shifters, or $K$ non-price characteristics in $x_{j,t}$ (assumed mean independent of $\blue{\xi_t}$)
\item We often form $E[\xi_{jt} \cdot h(z_{jt},x_{jt})] = 0 $ for some known function $h$.
\end{midi}
\end{frame}

\begin{frame}{Getting moment equations}
\begin{midi}
\item To get the sample analog of $E[\blue{\xi_{jt}}|z_{jt},x_{jt}] = 0$, we need to find $\blue{\xi_{jt}}$ corresponding to $\red{\theta}$
\item System \eqref{eq:shares} defines a mapping $\blue{\xi_{jt}}$ and $S_t$
\item Berry proved that $s$ has an inverse, hence any observed $S_t$ can be explained by a \bblue{unique} $\blue{\xi_{jt}}(\red{\theta}) = s^{-1}(S_t,\red{\theta})$
\item Sample analog of $E[\blue{\xi_{jt}}|z_{jt},x_{jt}] = 0$ is thus
\begin{equation*}
g(\red{\theta}) = \frac{1}{TJ}\sum_{t,j} \blue{\xi_{jt}}(\red{\theta})' z_{jt}
\end{equation*}
\end{midi}
\end{frame}

\begin{frame}{GMM Estimator}
\begin{widei}
\item Data are $\{(x_{jt},p_{jt},S_{jt},z_{jt})_{j\in J,t\in T}\}$
\item We want to minimize the GMM objective
\begin{equation*}
Q(\red{\theta}) = g(\red{\theta})' W g(\red{\theta})
\end{equation*}
\item There is no analytic form for $\blue{\xi_{jt}}(\red{\theta})$, see previous slide
\end{widei}
\end{frame}

\begin{frame}{\cite{BLP} Estimation Algorithm - NFXP}
\begin{midi}
\item \bred{Outer} Loop: $\min_{\red{\theta}} g(\red{\theta})' W g(\red{\theta})$
\begin{enumerate}
\item Guess vector $\red{\theta}$ to get $g(\red{\theta}) = \frac{1}{TJ}\sum_t \sum_j\blue{\xi_{jt}}(\red{\theta})' z_{jt}$
\item Stop whenever $|| \nabla_\theta(g(\red{\theta})' W g(\red{\theta})) || \leq \red{\epsilon_\text{out}}$
\end{enumerate}
\pause
\item \bblue{Inner} loop: compute $\blue{\xi_{jt}}(\red{\theta})$ given $\red{\theta}$
\begin{enumerate}
\item Solve system $s_j(x_t,p_t,\blue{x_{it}};\red{\theta}) = S_{\cdot t}$ by \bblue{Berry} constraction:
\begin{equation*}
\xi_t^{h+1} = \xi_t^{h} + \log S_t - \log s_j(x_t,p_t,\blue{\xi_{t}^h};\red{\theta})
\end{equation*}
\item Stop whenever $|| \xi_{\cdot t}^{h+1} - \xi_{\cdot t}^{h}  || \leq \red{\epsilon_\text{in}}$
\item Call resulting demand shock $\blue{\xi_{jt}}(\red{\theta},\red{\epsilon_\text{in}})$
\end{enumerate}
\item Clearly, need to choose \bred{both stopping rules} for inner and outer loop.
\end{midi}
\end{frame}

\begin{frame}{\cite{knittel2014estimation}}

\begin{midi}
\item They perform an extensive investigation into BLP on two widely used datasets: cars and cereals.
\item They use 10 free solvers and 50 starting points for each.
\item Find: convergence occurs at several local extrema, saddles, and in regions where the FOC is not satisfied.
\item Resulting parameter estimates of economic variables (market shares, price elasticiteis) exhibit \bred{huge} variation depending on solver/starting point.
\item All in all, they found 400 local solutions.
\end{midi}
\end{frame}

\begin{frame}{\cite{dube2012improving}'s concerns}
\begin{mide}
\item Too much computation
\begin{itemize}
\item need to know $\xi(\theta)$ only at true $\theta$.
\item NFXP solves for $\xi(\theta)$ at each stage.
\end{itemize}
\item Stopping criteria
\begin{itemize}
\item inner loop can be slow to converge
\item it's tempting to loosen $\red{\epsilon_\text{in}}$ (often see $\red{\epsilon_\text{in}}=1e^{-6}$ or higher!)
\item outer loop may not converge with loose inner criterion
\end{itemize}
\item Inner loop error propagates to outer loop.
\end{mide}
\end{frame}

\begin{frame}{Errors from loose stopping}
\begin{align*}
\theta^* = & \arg \max_{\theta} Q(\xi(\theta,0)) \\
\hat{\theta} = & \arg \max_{\theta} Q(\xi(\theta,\red{\epsilon_\text{in}}))
\end{align*}
\begin{midi}
\item \cite{dube2012improving} derive bounds on the order of estimatin error as a function of $\red{\epsilon_\text{in}}$
\item Consider \cite{knittel2014estimation} for numerical experiments.
\end{midi}
\end{frame}

\begin{frame}{BLP as an MPEC}
\begin{midi}
\item \cite{dube2012improving} cast this as an MPEC:
\begin{align*}
\min_{\red{\theta},\blue{\xi}} & \blue{\xi}^T ZWZ^T\blue{\xi} \\
\text{subject to } & s(\blue{\xi},\red{\theta}) = S
\end{align*}
\item Advantages:
\begin{enumerate}
\item No need to set up 2 tolerances
\item no inner errors propagated
\item easy to code in AMPL
\item fewer iterations, given that AMPL provides analytic gradients/hessian
\end{enumerate}
\end{midi}
\end{frame}

\begin{frame}{Exploring Sparsity in BLP}
\begin{midi}
\item The way this is formulated now, the Hessian of objective is dense. :-(
\item They add an additional variable $\blue{r}$ and associated constraint $Z^T \blue{\xi}=\blue{r}$
\begin{align*}
\min_{\red{\theta},\blue{\xi},\blue{r}} & \blue{r}^T W \blue{r} \\
\text{subject to } & s(\blue{\xi},\red{\theta}) = S \\
\text{ and       } & Z^T \blue{\xi}=\blue{r}
\end{align*}
\item advantages:
\begin{enumerate}
\item Hessian of objective function is now sparse
\item Very big saving in memory requirements.
\end{enumerate}
\end{midi}
\end{frame}

\begin{frame}{Convergence and Loose vs Tight}
\includegraphics[width=10cm]{dube-2.png}

\end{frame}

\begin{frame}{Speed}
\includegraphics[width=10cm]{dube-3.png}

\end{frame}

\begin{frame}[allowframebreaks]{References}

        % \frametitle{References}
		\bibliographystyle{unsrtnat}
		\bibliography{../../references/references.bib}
\end{frame}

\end{document}


\documentclass[a4paper]{article}

\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage{times}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{float}
\usepackage[colorinlistoftodos]{todonotes}
\usepackage{hyperref}
\usepackage{listings}

\setlength{\parskip}{\baselineskip}%
\setlength{\parindent}{0pt}%
\frenchspacing

\lstset{
    frame=single,
    basicstyle=\footnotesize\ttfamily
}

\title{Experimental data transmission method using sound}

\author{FÁBIÁN Tamás László}

\date{\today}

\begin{document}
\maketitle

\section{Introduction}

A method for transmitting and receiving 20 bytes long data packets
using sound is described. The method uses continuous-phase multiple frequency-shift keying (CPFSK), and a robust synchronization method. A Reed-Solomon code is used for forward error correction.

A software was written in the Python language for experimental and
demonstration purposes. Scripts are provided to send and receive short
text messages using the computer's audio devices, or to read/write the
audio to/from data files. The files can be played back, or converted
into more traditional audio formats using sox\cite{sox1}.

A framework was established to gauge the performance of the software. A
script can generate random messages and save them into audio files with
various levels of white noise. An other script then can be used to
attempt decoding these files. Various statistics are shown after the
script finished decoding the files.

Experiments show that this method can transmit data 99.9\% accurately
at a carrier to noise ratio (CNR) of -11dB (or at about 10dB
$E_b/N_0$) measured over 22.05 KHz bandwidth, and with 83.4\% accuracy
at -12dB CNR (about 9dB $E_b/N_0$).

In real-world experiments using a small set of consumer-grade computer
audio devices reliable data transfer could be achieved over 1 meter
in a quiet room at quite low volume levels. Noisy environments mandate
higher volume setting and/or shorter distances. Interference due to
multipath propagation probably is the main performance bottleneck.

\section{Theory of Operation}

I provide a summary on the operation of the software. See the in-line
code documentation for implementation details.

\subsection{Modulation}

The data has to be transmitted and received with equipments designed to
produce and record audio. Since little was known about the working
environment, an Additive Gaussian White Noise (AGWN) channel was used
as the channel model. In real life however, it is likely that noise
bursts will occur frequently.

Audio sampling rate was determined to be 44.1KHz. This sampling rate
along with 48KHz is the most frequently supported one, and 48KHz audio
can easily be downsampled on devices only supporting that.

The channel properties were chosen so that the transmitting device
could be a low-quality piezoelectric speaker. A carrier frequency of
about 4KHz, and a maximum bandwidth of also 4KHz was determined. The
bandwidth were kept lower than the carrier frequency, to prevent
harmonics interfering with the reception, so the transmitter can drive
the speaker with a square wave.

Using 44100 samples per second sampling rate, a 200 sample DFT will have
a bucket size of 220.5 Hz. To keep the modulation process simple, one
transmitted symbol will contain 4 bits, or half a byte of information.
To encode 4 bits, a symbol must communicate 16 separate states.

The modulation uses 17 frequencies in the form of $4410 + n*220.5$ Hz
where $n \in [0..16] \cap \mathbb{Z}$. About half of the time the
carrier ($n=0$) is transmitted, and no actual data is sent. This is for
synchronization. When this tone is off, one of the other 16 frequencies
($n \in [1..16] \cup \mathbb{Z}$) is transmitted, this is when data is
actually being transmitted. So instead of 16 symbols, a 17 symbol
alphabet is being used, out of which the carrier or zero symbol is used
for frame synchronization.

The carrier is turned on-off in a way so it can easily be found using
correlation. The exact sequence of on-off states affect how easily it
may be spotted by correlating a potentially noisy and arbitrary
time-shifted signal with a known, clean synchronization sequence.

Good sync sequences were found using gradient descent with random
restarts: essentially by checking random sequences, and looking for
neighbors with increasingly better properties, until the process
stuck in a local optimum, after which it is restarted from an other
random vector.

A total of 200 symbols are transmitted, out of those 108 are used to
transmit data, and 92 used for synchronization only. Transmitting one
frame takes about 0.907 seconds. \textbf{The effective bit rate is
176.4bps.}

\subsection{Demodulation}

Demodulation begins by recording a chunk of audio longer than a single
frame. After normalizing the received data and correlating it with the
synchronization sequence, a decision is made whether there is a signal
present. The correlation will return the position where the sync signal
matches the audio the most.

Using the position information 108 DFTs at positions where the first
tone is off. The received power in each bin is observed, and a hard
decision is made about what symbol the particular 200-sample audio data
might encode. Only the DFTs encoding the 108 data nibbles are kept.

\subsection{Forward Error Correction}

A Reed-Solomon code RS(54,20) were chosen for forward error correction,
mainly because implementations were readily available, and of course
because of their good performance.

The error correcting code takes 20 byte payload, and produces a 54 byte
codeword. The code is capable of correcting 17 errors or 34 erasures.
Currently the software does not signal erasure towards the decoder,
but there are methods\cite{ft1} for doing so.

\section{The Software}

This section describes how the software should be operated to run
demonstrations and experiments.

\subsection{Prerequisites}

The demonstration software requires a functional Python 3.6
installation, and a machine with enough resources. The following
configuration \textit{before} Python installation is recommended:

\begin{itemize}
\item Intel Core i5 processor, or better
\item 4GB RAM
\item 6GB of free disk space
\item Speakers
\item Microphone
\item Ubuntu Linux 17.04 or newer is recommended, a recent Windows or
macOS should also work
\end{itemize}

It is recommended to install a Python distribution called Anaconda
\cite{ana1}. Anaconda a contains stable and fast Python build along
with several important libraries.

\subsection{Installation}

Anaconda 5.0.1 with Python 3.6 can be downloaded from:

\url{https://www.anaconda.com/download}.

There are installers for Linux, Windows and macOS operating system. Any
of those systems should be able to run the demo software, but it had
only been tested throughly on Ubuntu Linux "zesty" 17.04.

The scripts \texttt{send.py} and \texttt{receive.py} use
\textit{pyaudio}, a Python binding for an audio library called
\textit{portaudio}. The portaudio library (.so, .dll, or .dynlib) and
header files need to be installed. The installation process differs
across operating systems, and can be as simple as issuing a command
(Linux and maxOS), or having to install Visual Studio and compile the
library by hand (Windows)\footnote{This is why the .dll-s and headers
bundled with the pyaudio Python library for Windows}.

\subsubsection{Installation on Ubuntu Linux "zesty" 17.04}

The \texttt{portaudio19-dev} package need to be installed with the
package manager \texttt{apt}:

\begin{lstlisting}
$ sudo apt install portaudio19-dev
$ cd <path-to-demo-software>
$ pip install -r requirements.txt
\end{lstlisting}

\subsubsection{Installation on Apple macOS}

Portaudio need to be installed using \texttt{brew}:

\begin{lstlisting}
$ brew install portaudio
$ cd <path-to-demo-software>
$ pip install -r requirements.txt
\end{lstlisting}

\subsubsection{Installation on Microsoft Windows}

On Windows, the portaudio binaries are included in the pyaudio wheel,
so separate installation should not be necessary (make sure
\texttt{pip} and \texttt{python} are on the \texttt{PATH}):

\begin{lstlisting}
C:\> cd <path-to-demo-software>
C:\> pip install -r requirements.txt
\end{lstlisting}

\subsection{Usage}

The scripts \texttt{test-gen.py} and \texttt{text-score.py} can
generate a large set of audio files, and run a decoding benchmark on
them respectively. Any computer capable of running Python properly may
be used to run the benchmark. Since the process involves generating
14000 files consuming about 1.2GB space, this should be done on a fast
machine.

The scripts \texttt{send.py} and \texttt{receive.py} use audio devices
to play and record audio. They use the default system device, but they
can set up to use any device with the \texttt{-d <number>} or
\texttt{--device <number>} parameter. Use \texttt{devices.py} to view a
list of audio devices.

All command examples assume Linux operating system, but they should
work with no or only minor modifications on macOS and Windows too.
Commands should be executed in the directory where the scripts are
located.

\subsubsection{Listing audio devices}

The \texttt{devices.py} script shows a list of audio devices available.
On some systems error messages may occur on the first few lines. These
can be ignored.

Since \texttt{send.py} and \texttt{receive.py} are using the default
audio device, this list will probably rarely be needed.

\newpage

\begin{lstlisting}
$ ./devices.py
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM
cards.pcm.center_lfe
ALSA lib pcm.c:2495:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching
channel map
0 HDA Intel PCH: ALC898 Analog (hw:0,0)
1 HDA Intel PCH: ALC898 Digital (hw:0,1)
2 HDA Intel PCH: ALC898 Alt Analog (hw:0,2)
3 USB Audio CODEC: - (hw:1,0)
4 HDA NVidia: HDMI 0 (hw:2,3)
5 HDA NVidia: HDMI 1 (hw:2,7)
6 HDA NVidia: HDMI 2 (hw:2,8)
7 HDA NVidia: HDMI 3 (hw:2,9)
8 sysdefault
9 front
10 surround21
11 surround40
12 surround41
13 surround50
14 surround51
15 surround71
16 iec958
17 spdif
18 pulse
19 dmix
20 default
$
\end{lstlisting}

\subsubsection{Sending or saving messages}

The \texttt{send.py} script can send a message by playing the modulated
audio carrier on an audio device, or saving and audio file.

In it's simplest form it's just called with a short text to send:

\begin{lstlisting}
$ ./send.py test
CNR (dB):    inf
Eb/N0 (dB):  inf
Peak:        0.252437119188
$
\end{lstlisting}

The command always displays the estimated carrier to noise power ratio
and $E_b/N_0$ in decibels. Since there is no noise added by default,
both figures are displayed as being infinite.

Adding noise, distortion and saving the audio into a file:

\begin{lstlisting}
$ ./send.py -f test.s16 -c -11 -d 10000 test
CNR (dB):    -11.0397105534
Eb/N0 (dB):  9.92938957672
Peak:        0.742417642773
$
\end{lstlisting}

The files store a single audio channel at a sampling rate of 44100 KHz.
Each sample is a signed 16 bit little endian integer. The files contain
no header or any kind of metadata.

One can specify a string of hexadecimal digits to send with the
\texttt{-x} or \texttt{--hex} flag:

\begin{lstlisting}
$ ./send.py -f test.s16 -c -11 -d 10000 -x \
  9d7133b7f07274a5be88a06f7b5ae2914822c008

CNR (dB):    -11.0397105534
Eb/N0 (dB):  9.92938957672
Peak:        0.742417642773
$
\end{lstlisting}

For a brief description of usage and parameters, issue
\texttt{./send.py -h}.

\subsubsection{Receiving or loading messages}

The script \texttt{receive.py} can be used to load audio files, or
decode audio read from an audio device in real-time. The test.s16 file
created above can (very likely) be decoded with the following
command:

\begin{lstlisting}
$ ./receive.py -f test.s16 -x
Got sync signal, decoding...
DECODED: >>> 9d7133b7f07274a5be88a06f7b5ae2914822c008 <<<
End of data stream reached, terminating
$
\end{lstlisting}

Without the \texttt{-f} parameter the script listens on the default
audio device. The \texttt{-x} flag is useful for printing arbitrary
binary data. Without this flag the script tries to convert the received
data to ASCII strings, and print that instead of hex digits. Call the
script with the \texttt{-h} parameter to get a list of usable flags
and parameters and their descriptions.

\subsubsection{Recording audio}

A short script is provided for Linux using the SoX command
\texttt{rec}, and providing it with the necessary parameters, so only
the file name has to be given:

\begin{lstlisting}
$ ./rec.sh test.s16

Input File     : 'default' (alsa)
Channels       : 1
Sample Rate    : 44100
Precision      : 16-bit
Sample Encoding: 16-bit Signed Integer PCM

In:0.00% 00:00:05.20 [00:00:00.00] Out:221k  [ -====|====- ]     Clip:0
Aborted.
$
\end{lstlisting}

The recording can be stopped by hitting CTRL+C. It is worth keeping an
eye on the "Clip" indicator at the end of the last line. If this
counter starts growing then the audio level is too high.

\subsubsection{Playing saved audio}

Playing audio is also handled by SoX via a Linux shell script:

\begin{lstlisting}
$ ./play.sh test.s16

test.s16:

 File Size: 459k      Bit Rate: 706k
  Encoding: Signed PCM
  Channels: 1 @ 16-bit
Samplerate: 44100Hz
Replaygain: off
  Duration: 00:00:05.20

In:100%  00:00:05.20 [00:00:00.00] Out:229k  [      |      ]     Clip:0
Done.
$
\end{lstlisting}

\subsubsection{Generating test files}

The test set generator script will generate one thousand random test
files for each CNR level. The tested levels are between and including
-14dB and -1 dB.

The \texttt{test-gen.py} script accepts no arguments, and calling it
will start generating test files right away:

\begin{lstlisting}
$ ./test-gen.py
  0%|                              | 5/14000 [00:01<1:06:18,  3.52it/s]
$
\end{lstlisting}

During test set generation a progress bar with the speed and ETA is
displayed. Before generating a test set, make sure the \texttt{data}
directory only contains a \texttt{.gitignore} file, and no *.s16 audio
files. These are not removed automatically, and new files will have
different names every time.

Every file is exactly 1 second, or 44100 samples -- 88200 bytes --
long. The signal is right in the middle of every file at offset 2050.

\subsubsection{Scoring performance on a test file set}

The \texttt{test-score.py} script will read any .s16 files from the
data directory and will attempt to demodulate and decode them. It will
record any success or failure in finding the synchronization signal or
decoding the actual message.

Before exiting, the script will print out a rather dense representation
of the results. It looks like this:

\begin{lstlisting}
FILES:         {-5: 1000, -3: 1000, -4: 1000, -14: 1000, ...
GOOD DECODES:  {-5: 1000, -3: 1000, -4: 1000, -12: 834, ...
NO DECODES:    {-14: 1000, -13: 897, -12: 166, -11: 1}
BAD DECODES:   {}
GOOD SYNCS:    {-5: 1000, -3: 1000, -4: 1000, -14: 980, ...
BAD SYNCS:     {-13: 10, -14: 20, -12: 1, -11: 1}
BAD SYNC SET:  {2040, 2060}
\end{lstlisting}

Each line shows a metric. The number before the colons are specific CNR
values, the number after the colons are the number of occurrences.

For example the ,,FILES'' line shows the number of files. It can be
seen that for the CNR level of -5(dB) there were ,,1000'' files in the
data directory.

It can also be seen that for levels -5, -3 and -4 ever file was decoded
OK, and only 834 ,,GOOD DECODES'' were possible at CNR level -12.

,,NO DECODES'' counts files that could not be decoded at all, ,,BAD
DECODES'' count files that could be decoded, but the results were
different from the originally encoded data. ,,GOOD SYNCS'' show the
number of files where the synchronization signal could be recovered
with utmost precision. ,,BAD SYNCS'' counts ill-identified sync
vectors. ,,BAD SYNC SET'' shows all the offsets where a sync vector was
found, except the correct 2050 offset.

\subsubsection{Generating synchronization vectors}

The synchronization vector has to have a special property: it must have
low aperiodic autocorrelation. Such vectors are rare, and long vectors
are hard to find. The script \texttt{syncvec-search.py} tries to find
such vectors using gradient descent with random restarts. This script
was used design/development time, and can be used again if (when)
changing the modulation becomes necessary.

\subsubsection{Observing saved audio waveforms and spectra}

A script named \texttt{scope.py} is provided for graphically displaying
waveforms stored in s16 files. The script accepts a file name as a
single mandatory positional parameter, and various flags that control
what should be displayed. By default a simple waveform is displayed.

The following flags are available:

\begin{description}
\item[\texttt{-h}] Show help and exit.
\item[\texttt{-s}] Show spectrum.
\item[\texttt{-c}] Show correlation vector.
\item[\texttt{-w}] Show waterfall.
\item[\texttt{-o}] Offset: skip this many samples.
\item[\texttt{-y}] Synchronize: try to find a packet, cut it out, and.
  display only that
\end{description}

Some examples follow showing clean and noisy signals.

\begin{lstlisting}
$ ./scope.py clean.s16
...
$ ./scope.py noisy.s16
...
\end{lstlisting}

\begin{figure}[H]
    \centering
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=\textwidth]{scope_clean.png}
        \caption{Clean waveform}
    \end{subfigure}
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=\textwidth]{scope_noisy.png}
        \caption{Noisy waveform}
    \end{subfigure}
\end{figure}

\begin{lstlisting}
$ ./scope.py -s clean.s16
...
$ ./scope.py -s noisy.s16
...
\end{lstlisting}

\begin{figure}[H]
    \centering
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=1\textwidth]{dft_clean.png}
        \caption{Clean DFT}
    \end{subfigure}
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=1\textwidth]{dft_noisy.png}
        \caption{Noisy DFT}
    \end{subfigure}
\end{figure}

\begin{lstlisting}
$ ./scope.py -c clean.s16
...
$ ./scope.py -c noisy.s16
...
\end{lstlisting}

\begin{figure}[H]
    \centering
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=1\textwidth]{correlation_clean.png}
        \caption{Correlation vector, clean signal}
    \end{subfigure}
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=1\textwidth]{correlation_noisy.png}
        \caption{Correlation vector, noisy signal}
    \end{subfigure}
\end{figure}

\begin{lstlisting}
$ ./scope.py -y -w clean.s16
...
$ ./scope.py -y -w noisy.s16
...
\end{lstlisting}

\begin{figure}[H]
    \centering
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=1\textwidth]{waterfall_sync_clean.png}
        \caption{Clean signal, synchronized}
    \end{subfigure}
    \begin{subfigure}[b]{0.45\textwidth}
        \includegraphics[width=1\textwidth]{waterfall_sync_noisy.png}
        \caption{Noisy signal, synchronized}
    \end{subfigure}
\end{figure}

\section{Experimental results}

A large number of simulations, and some real-world experiments were
conducted. These are described below.

\subsection{Real-World Experiments}

Real-world experiments in the given time frame could only yield a
modest number of data points. The following description focuses more on
usability and other practical aspects, and does not try to communicate
precise figures.

\subsubsection{Single PC setup}

A single desktop personal computer with a high quality speaker and
microphone were used to test performance at the early stages of
development.

\textbf{With this setup I could easily achieve reliable data transfer
at distances slightly over 1 meter even when music played, or people
were talking if the microphone and speaker were facing each other.}

Performance was heavily dependent on the microphone setup and volume
setting. Too high volume causes clipping and destroys the signal, to
low volume hides the signal in the noise of the recording equipment. If
the microphone were facing in a direction other than the speaker,
\emph{multipath propagation} was found to interfere with reception.

\subsubsection{Single notebook setup}

A single laptop computer was used to try and replicate the results. The
notebook had a built-in microphone with lots of noise, since it was
equipped with forced air cooling, and the fan was on most of the time.

The built-in microphone and the speaker were about 12cm close together.
The received signals weren't as high quality as with the PC setup. This
was due not to the distance, but to the fact that the speakers and the
microphone were deliberately placed and insulated so that the audio
feedback is as little as possible.

The microphone in this setup faces away from the speakers, and picks
other sounds up easily, including the sound of the speakers bouncing
off objects, and arriving from the front. Because of this, the signal
gets back to the receiver multiple times with some delay.
This can easily confuse the demodulator.

\subsubsection{Notebook-PC setup}

To rule out any problem with the laptop's microphone and audio
circuitry, several experiments were conducted with the PC set being the
transmitter, and it being the receiver.

A performance similar to the PC-only setup were measured: signals could
easily be picked up from about 1 meter even when the laptop's fan were
on, or when some music or noise could be heard in the room. The
experiments were repeated with reversed roles, and performance remained
similar.

\subsubsection{Conclusions}

Experiments showed that the software worked beyond expectations, but also
revealed performance bottlenecks. The sensitivity to multipath in
particular needs to be addressed. Ambient noise will of course interfere
with the reception, but the volume of the transmitted signal could always
be set high enough to ensure success, and not be particularly annoying
(although this is highly subjective, and should carefully be considered
while developing the product). Multipath in contrast mostly dependent on
the paths, and not the volume, so increasing volume it has little
benefit in combating multipath.

\subsection{Benchmarks}

Using the \texttt{test-gen.py} script, 14000 audio files were
generated, from and including -14dB CNR to and including -1dB CNR. The
files contained randomly generated binary data. All the files were
exactly 1 second long, and every file had the encoded data right in the
middle, at offset 2050. The decoding benchmark does not ,,know'' about
this convention, and has to guess the position correctly in every file.

\textbf{It was found the decoding is possible 99.9\% of the time at
-11dB CNR under 22.05 KHz band-limited white noise.} Performance were
quickly falling under that: about 83.4\% good decodes were logged at
-12dB, and none at -13db.

\textbf{It is also worth mentioning that no false decodes were ever
observed. The messages either decoded correctly, or didn't at all.}

The synchronization method was found out to have been a very good
choice, might even have been an overkill. \textbf{In the vast majority
of the cases, the positions of the data frames were precisely
identified, even in cases where decoding was impossible.} Even when the
algorithm made errors finding frames, it only missed 10 samples in
either direction, so instead of one, only 3 positions were ever
identified. This is a useful property, and worth noting it in case the
synchronization precision would need to be improved for some reason.

\section{Implementation Challenges, Possible Improvements}

The work I've done on this project so far is rather experimental. The
finished product has to work in different environments, with various
noise sources, and a large variety of devices with different
properties.

I hereby attempt to address a few problems that might come up during
the deployment of this -- or similar -- solution.

\subsection{Parameters, Tuning}

The performance of the components of the system is not well balanced.
The synchronization works very well, but also takes about the half of
the bandwidth away. It's possible to make a trade-off between the
effectiveness of the synchronization algorithm and the bandwidth it
uses. Bandwidth then can be used to increase symbol time and combat
noise and multipath, and/or to decrease code rate, and have more
immunity to momentarily signal dropout and similar burst errors.

There is a trade-off between the code rate and the symbol time even when
we consider the sync vector to be constant. A longer symbol time and
higher code rate might provide better white noise and multipath
immunity. The possible set of parameters can be explored automatically
with machine learning algorithms, similarly to how good synchronization
vectors were found in the first place.

\subsection{Processing power}

In the current form, the software consumes quite a lot of CPU. The
implementation of the decoding algorithm must be chosen carefully, and
well-optimized native code will probably be needed for acceptable
performance.

\subsection{Channel model}

The simulations use a simple Additive Gaussian White Noise channel.
Real-world noise will very likely to be different. Any further
development would benefit from a noise model that is more faithful to
the environments in which the solution will be deployed.

\subsection{Choice of FEC, Implementation, Performance}

The Franke-Taylor algorithm\cite{ft1} can be adapted for RS(54,20).
This could provide as much as 2dB improvement over the hard-decision
algebraic decoding that were used in the software.

Other modern codes, like LDPC codes could be used instead of
Reed-Solomon codes. Because the lack of ready-to-use implementations,
using such codes was not attempted.

\subsection{Multipath}

Currently this is one of the major factors that limit the performance
of this solution. It can confuse the receiver even when noise and
distance are not problems. It is also not obvious what is happening,
and multipath can cause seemingly random, frustrating packet loss.

On the following waterfall charts a clean and a multipath-affected
signal can be seen:

\begin{figure}[H]
    \centering
    \begin{subfigure}{0.45\textwidth}
        \includegraphics[width=\textwidth]{waterfall_sync_clean.png}
        \caption{Clean signal}
    \end{subfigure}
    \begin{subfigure}{0.45\textwidth}
        \includegraphics[width=1\textwidth]{waterfall_sync_multipath.png}
        \caption{Multipath-affected signal}
    \end{subfigure}
\end{figure}

Notice how the power creeps from one symbol to the next few one, and
blur the image, making correct demodulation impossible. This signal
cannot be decoded, despite having no significant noise in it.

The next images show correlation vectors of the same signals. The
correlation vector contains information about the position of the
received frame. The clean signal has a sharp, single spike with small
side lobes, whereas the multipath-affected signal has multiple large
bumps near the main spike that also looks flattened. This is a sign of
multiple synchronization vectors in the same audio. During the
experiment only one transmitter was used, so these must be different
copies of the very same signal bouncing around the room, and getting
back into the microphone.

\begin{figure}[H]
    \centering
    \begin{subfigure}{0.45\textwidth}
        \includegraphics[width=1\textwidth]{correlation_clean.png}
        \caption{Correlation vector of a reasonably clean signal}
    \end{subfigure}
    \begin{subfigure}{0.45\textwidth}
        \includegraphics[width=1\textwidth]{correlation_multipath.png}
        \caption{Correlation vector of a signal affected by multipath}
    \end{subfigure}
\end{figure}

This problem were almost only encountered when the transmitting speaker
and the receiving microphone weren't facing each other. Microphones and
speakers tend to be directional \emph{by design}. If they are facing
each other, they amplify the signal, and signals coming from other
directions are attenuated. If they are facing away each other, stray
signals are amplified, and the original one gets attenuated.

This phenomenon can be mitigated by increasing the symbol time, and
even by introducing guard intervals. This decreases symbol rate, and
makes synchronization harder. Using frequency hopping spread spectrum
(FHSS) is an other effective way to combat this issue.

\textbf{To tackle this problem efficiently, more information on the
transmitting equipment and the working environments is needed, because
the carrier frequency, bandwidth, noise, and multipath models need to be
gotten right for the design of the system to be optimal.}

\begin{thebibliography}{9}
\bibitem{sox1}
  SoX, \url{http://sox.sourceforge.net/}
\bibitem{ana1}
  Anaconda, \url{https://www.anaconda.com/download}
\bibitem{ft1}
  Steven J. Franke, K9AN and Joseph H. Taylor, K1JT
  \emph{Open Source Soft-Decision Decoder for the JT65 (63,12) Reed-Solomon
  Code}, QEX, 2016
\end{thebibliography}

\end{document}


\documentclass[../Notes/main.tex]{subfiles}

\begin{document}
\section{Dynamic Programming}

\subsection{Knapsack}
\lstinputlisting[firstline=2]{Knapsack/Knapsack.cpp}

\subsection{Matrix Chain Multiplication}
\lstinputlisting[firstline=2]{Matrix_Chain_Multiplication/MCM.cpp}

\subsection{Longest Increasing Subsequence}
\lstinputlisting[firstline=2]{LIS/LIS.cpp}
\end{document}