%!TEX root = /home/renaud/Documents/EPL/tfe/latex/tfe.tex
\section{Discrete-time compartment model} \label{sec:dtcm(chapcomp)}
It is also possible to build a discrete-time compartment model, and this could even be more relevant than a continuous-time one in the context of numerical implementation. Consider equation~\eqref{eq:compartmentmatrix}. For a given time step $\Delta t > 0$, we would like to build a similar expression that would link $\b c(t+\Delta t)$ to $\b c(t)$. From the theory of ordinary differential equations~\cite{EDO}, we know that the general solution to that equation is
\begin{equation} \label{eq:generalODEsol}
	\b c(t) = \Exp^{\bs \Omega^{-1}\b A(t-t_0)} \b c(t_0) + \int_{t_0}^t \Exp^{\bs \Omega^{-1}\b A(t-s)} \b q(s) \rm ds.
\end{equation}
For a general source term $\b q$, it is not possible to write a matrix expression of the form $\b c(t+\Delta t) = \b A_{\Delta t} \b c(t) + \b B_{\Delta t} \b q(t)$, but it is possible under certain conditions on $\b q$. In this work, we won't need such conditions because we make the assumption that there is no source/sink term, i.e. we assume that $\b q = 0$. Let $t_0 < t_1 < t_2 < \dots$ be such that $t_{k+1} = t_k + \Delta t$. If $\b c(t_k)$ is known, $\b c(t_{k+1})$ can be computed using~\eqref{eq:generalODEsol} with $\b q = 0$:
\begin{equation}
	\b c(t_{k+1}) = \Exp^{\bs \Omega^{-1}\b A\Delta t} \b c(t_k).
\end{equation}
Doing this, we have found a matrix relation that links $\b c(t+\Delta t)$ to $\b c(t)$:
\begin{equation} \label{eq:generaldiscretecompartment}
	\b c(t + \Delta t) = \b A_{\Delta t} \b c(t),
\end{equation}
where $\b A_{\Delta t} = \Exp^{\bs \Omega^{-1}\b A\Delta t}$ is the \textit{discrete interaction matrix}. Notice that the discrete interaction matrix is closely related to the transition probability matrix introduced in chapter~\ref{chap:clustering}. Indeed, developing~\eqref{eq:generaldiscretecompartment} for $C_i(t)$ yields
\begin{equation} \label{eq:crapaud}
	C_i(t+\Delta t) = [\b A_{\Delta t}]_{i,1} C_{1}(t) + [\b A_{\Delta t}]_{i,2} C_{2}(t) + \ldots + [\b A_{\Delta t}]_{i,N} C_{N}(t).
\end{equation}
Let $P_i(t)$ denote the number of tracer's particles in compartment $i$ at time $t$, and let $P$ be the mass of one tracer's particle. Notice that
\begin{equation}
	C_i(t) = \frac{P_i(t) P}{|\Omega_i|}.
\end{equation}
Multiplying equation~\eqref{eq:crapaud} by $|\Omega_i|/P$ yields after some manipulations
\begin{equation}
	P_i(t) = [\b A_{\Delta t}]_{i,1} \frac{|\Omega_i|}{|\Omega_1|} P_{1}(t) + [\b A_{\Delta t}]_{i,2}\frac{|\Omega_i|}{|\Omega_2|} P_{2}(t) + \ldots + [\b A_{\Delta t}]_{i,N}\frac{|\Omega_i|}{|\Omega_N|} P_{N}(t).
\end{equation}
Hence, the factor $\frac{|\Omega_i|}{|\Omega_j|}[\b A_{\Delta t}]_{i,j}$ can be interpreted as the probability \label{page:probability_interpretation} for a tracer's particle to end up in compartment $i$ after a period $\Delta t$ if it was initially in compartment $j$. This consideration suggests that the entries of $\b A_{\Delta t}$ should be nonnegative: this is indeed an important property of the discrete interaction matrix that shall be proven shortly.
\begin{property} \label{prop1_discr_comp}
	The entries of the discrete interaction matrix are nonnegative:
	\begin{equation}
		[\b A_{\Delta t}]_{ij} \ge 0 \mbox{ for every } i,j = 1,\dots,N.
	\end{equation}
\end{property}
\begin{proof}
	Let $C_0 > 0$ be a positive constant, and fix $j \in \{1,\dots,N\}$. Suppose that
	\begin{equation}
		\b c(t) = \begin{pmatrix} c_1(t) \\ \vdots \\ c_{j-1}(t) \\ c_j(t) \\ c_{j+1}(t) \\ \vdots \\ c_N(t) \end{pmatrix}
				= \begin{pmatrix} 0 \\ \vdots \\ 0 \\ C_0 \\ 0 \\ \vdots \\ 0 \end{pmatrix}.
	\end{equation}
	By equation~\eqref{eq:generaldiscretecompartment},
	\begin{equation}
		\b c(t+\Delta t) = \b A_{\Delta t} \b c(t) = \begin{pmatrix} [\b A_{\Delta t}]_{1,j} C_0 \\ \vdots \\ [\b A_{\Delta t}]_{N,j} C_0 \end{pmatrix}.
	\end{equation}
	Since $\b c$ is a concentration, we must have that $\b c(t) \ge \b 0$ at any time $t$. Therefore, since $C_0 > 0$ we must have that
	\begin{equation}
		[\b A_{\Delta t}]_{i,j} \ge 0 \mbox{ for every } i = 1,\dots,N.
	\end{equation}
	Finally, as we have made no assumption on $j$, this must be true for any $j \in \{1,\dots,N\}$, which concludes the proof.
\end{proof}
The interpretation of $\frac{|\Omega_i|}{|\Omega_j|}[\b A_{\Delta t}]_{i,j}$ in terms of a transition probability of the tracer's particles between compartments suggests another important property of the discrete interaction matrix. Indeed, the tracer's particles can neither disappear nor be created, hence the sum of the probabilities over all possible destinations (i.e. over all compartments since we consider an isolated domain) must be equal to one:
\begin{equation}
	\sum_{i=1}^N \frac{|\Omega_i|}{|\Omega_j|}[\b A_{\Delta t}]_{i,j} = 1 \quad \mbox{for every } j=1,\dots,N.
\end{equation}
This property can be deduced from property~\ref{prop1_comp}:

\begin{property} \label{prop1ter_comp} \label{prop2_discr_comp}
	The columns of the discrete interaction matrix satisfy the following relation:
	\begin{equation}
		\sum_{i=1}^N |\Omega_i|  [\b A_{\Delta t}]_{ij} = |\Omega_j| \quad \mbox{for every } j=1,\dots,N.
	\end{equation}
	In matrix form:
	\begin{equation}
		\bs \omega^\t \b A_{\Delta t} = \bs \omega^\t .
	\end{equation}
\end{property}
\begin{proof}
	The expression of the mean concentration over $\Omega$ is the same as in the continuous case:
	\begin{equation}
		\bar C = \frac{1}{|\Omega|} \b 1^\t \bs \Omega \b c.
	\end{equation}
	Since $\bar C$ is constant, we must have that
	\begin{equation}
		|\Omega| \bar C(t+\Delta t) = |\Omega| \bar C(t) = \b1^\t \bs \Omega \b c(t) = \bs \omega^\t \b c(t),
	\end{equation}
	but by equation~\eqref{eq:generaldiscretecompartment} we also have that
	\begin{equation}
		|\Omega| \bar C(t+\Delta t) = \b1^\t \bs \Omega \b c(t+\Delta t) = \b1^\t \bs \Omega \b A_{\Delta t} \b c(t) = \bs \omega^\t \b A_{\Delta t} \b c(t).
	\end{equation}
	Hence, $\bs \omega^\t \b c(t) = \bs \omega^\t \b A_{\Delta t} \b c(t)$, and since this must be true for every possible value of $\b c(t)$, we must have that
	\begin{equation} \label{eq:prop1ter_comp}
		\bs \omega^\t = \bs \omega^\t \b A_{\Delta t},
	\end{equation}
	the desired result.
\end{proof}
\begin{corollary}{prop1ter_comp} \label{corollary2}
	If the compartments all have the same size, the discrete interaction matrix is  left stochastic:
	\begin{equation}
		\b 1^\t \b A_{\Delta t} = \b 1^\t.
	\end{equation}
\end{corollary}
\begin{proof}
	Let $|\Omega_0|$ be the size of the compartments. Then, $\bs \omega = |\Omega_0| \b 1$ and equation~\eqref{eq:prop1ter_comp} reduces to
	\begin{equation}
		|\Omega_0| \b 1^\t = |\Omega_0| \b 1^\t \b A_{\Delta t}.
	\end{equation}
\end{proof}
Property~\ref{prop2_comp} also has an interpretation in terms of the discrete interaction matrix:
\begin{property} \label{prop2ter_comp} \label{prop3_discr_comp}
	The discrete interaction matrix is right stochastic:
	\begin{equation}
		\b A_{\Delta t} \b 1 = \b 1.
	\end{equation}
\end{property}
\begin{proof}
	Let $C_0 > 0$ be a constant and $\b c(t) = C_0 \b 1$. Introducing the latter in~\eqref{eq:generaldiscretecompartment} yields
	\begin{equation}
		C_0 \b 1 = \b A_{\Delta t} C_0 \b 1 = C_0 \b A_{\Delta t} \b 1.
	\end{equation}
\end{proof}
Two last properties allow to bound the entries of the discrete interaction matrix:
\begin{property} \label{prop4_discr_comp}
	The entries of the discrete interaction matrix are smaller than one:
	\begin{equation}
	 		[\b A_{\Delta t}]_{i,j} \le 1 \mbox{ for every } i,j = 1,\dots,N.
	\end{equation}
\end{property}
\begin{proof}
	We proceed by contradiction. Suppose there exists $i,j \in \{1,\dots,N\}$ such that $[\b A_{\Delta t}]_{i,j} > 1$. By property~\ref{prop1_discr_comp}, all the entries of $\b A_{\Delta t}$ are nonnegative so that
	\begin{equation}
		\sum_{k = 1}^N [\b A_{\Delta t}]_{i,k} > 1,
	\end{equation}
	in contradiction with property~\ref{prop2ter_comp}.
\end{proof}
\begin{property} \label{prop5_discr_comp}
	The entries of the discrete interaction matrix satisfy
	\begin{equation}
		\frac{|\Omega_i|}{|\Omega_j|} [\b A_{\Delta t}]_{i,j} \le 1 \mbox{ for every } i,j = 1,\dots,N.
	\end{equation}
\end{property}
\begin{proof}
	We proceed again by contradiction. Suppose there exist $i,j \in \{1,\dots,N\}$ such that $\frac{|\Omega_i|}{|\Omega_j|} [\b A_{\Delta t}]_{i,j} > 1$. By property~\ref{prop1_discr_comp}, all the entries of $\b A_{\Delta t}$ are nonnegative so that
	\begin{equation}
		\sum_{k = 1}^N \frac{|\Omega_k|}{|\Omega_j|}[\b A_{\Delta t}]_{k,j} > 1,
	\end{equation}
	in contradiction with property~\ref{prop1ter_comp}.
\end{proof}
This last property is in agreement with the interpretation of the factors $\frac{|\Omega_i|}{|\Omega_j|} [\b A_{\Delta t}]_{i,j}$ as probabilities of transition between the compartments.


\documentclass[a4paper]{article}

\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{bbm}
\usepackage{color}
\usepackage{graphicx}
\usepackage{caption}
\usepackage{subcaption}

\newcommand{\X} {\mathbf{X}}

\newcommand{\todo}[1] { \emph{ {\color{red}TODO: #1} } }

\begin{document}

\section{Incremental calculation of a covariance matrix}
Given a $T\times N$ matrix $m$ of measurements in $N$ variables
at $T$ timesteps, the covariance matrix of all variables is given by
\begin{align}
  C_{ij} &= \left<\left(\X_i- \left<\X_i\right>\right) \left(\X_j-\left<\X_j\right>\right)\right>,
\end{align}
where $\X_i \in \mathbb{R}^T$ denotes column $i$ of matrix $m$ with all observations
of variable $i$ and $\left< \dots \right>$ is the average of the given observations.
Using the definition
\begin{align}
  \mu_i := \left< \X_i \right>,
\end{align}
the construction of the covariance matrix can be expressed as
\begin{align}
  C_{ij} &= \left<\left(\X_i - \mu_i\right) \left(\X_j - \mu_j\right)\right>\\
         &= \left<\X_i \X_j\right> - \left< \mu_i \X_j \right> - \left< \mu_j \X_i \right> + \left< \mu_i \mu_j \right>\\
         &= \left<\X_i \X_j\right> - \mu_i \left<\X_j \right> - \mu_j \left<\X_i\right> + \left< \mu_i \mu_j \right>\\
         &= \left<\X_i \X_j\right> - \mu_i \mu_j - \mu_j \mu_i + \mu_i \mu_j\\
         &= \left<\X_i \X_j\right> - \mu_i \mu_j\\
         &= \frac{1}{T} \sum_t m_{ti} m_{tj} - \mu_i \mu_j\\
         &= \frac{1}{T-1}\left( \sum_t m_{ti} m_{tj} - \frac{1}{T} \left(\sum_t m_{ti}\right) \left(\sum_t m_{tj}\right) \right)
            \label{eq:cov_standard}.
\end{align}
Following this expression, we see that the covariance matrix can be
constructed incrementally by summing over the observations with constant memory consumption.
The used memory will be of order
\begin{align}
  \mathcal{O}_M &= \mathcal{O}_C + N\mathcal{O}_\mu\\
                &= \mathcal{O}\left( (N-1)(N-2) / 2 \right) + N\mathcal{O}\left(1\right)\\
                &= \mathcal{O}\left( N^2 \right),
\end{align}
with the memory consumption $\mathcal{O}_C$ of the (symmetric) covariance matrix and
the memory consumption $\mathcal{O}_\mu$ per observable average.
The runtime behavior will be of order
\begin{align}
  \mathcal{O}_R &= \mathcal{O}\left(T N\left(N-1\right)\right).
\end{align}
Assuming the number of observations $T$ is much greater than the number of variables $N$, i.e. $T \gg N$,
the runtime behavior may be described as being linear in $T$:
\begin{align}
  \mathcal{O}_R &= \mathcal{O}\left(T\right).
\end{align}

\subsection{Weighted variables}
To construct a covariance matrix with weighted variables (e.g. a mass-weighted covariance of molecular coordinates),
one previously defines a set of $N$ weights $w_i$ and expands the given incremental form (\ref{eq:cov_standard}) to
\begin{align}
  \tilde{C}_{ij} &= \frac{1}{T}\left( \sum_t w_i m_{ti} w_j m_{tj} - \frac{1}{T} \left(\sum_t w_i m_{ti}\right) \left(\sum_t w_j m_{tj}\right) \right)\\
                 &= \frac{1}{T}\left( w_i w_j \sum_t m_{ti} m_{tj} - \frac{1}{T} \left(w_i \sum_t m_{ti}\right) \left(w_j \sum_t m_{tj}\right) \right)\\
                 &= \frac{w_i w_j}{T}\left(\sum_t m_{ti} m_{tj} - \frac{1}{T} \left(\sum_t m_{ti}\right) \left(\sum_t m_{tj}\right) \right).
\end{align}
Here, it is assumed that all the weights are normalized, i.e. that they fulfill the relation
\begin{align}
  \sum_i^N w_i = 1,
\end{align}
with $0 \le w_i \le 1$.
If this is not the case, one can trivially transform the set of weights to a normalized one by dividing the weights by their sum.

\subsection{Weighted observations}
To construct a covariance matrix based on observations of different quality, we introduce the weights $\nu\left(t\right)$, defined
for an observation at time $t$.
Again, one can extend eq. (\ref{eq:cov_standard}) to a weighted form:
\begin{align}
  \hat{C}_{ij} &= \frac{1}{\tau}\left( \sum_t \nu\left(t\right) m_{ti} m_{tj}
                   - \frac{1}{\tau} \left(\sum_t \nu\left(t\right) m_{ti}\right) \left(\sum_t \nu\left(t\right) m_{tj}\right) \right),
\end{align}
with $\tau = \sum_t \nu\left(t\right)$ being the total weight.
In the case of unweighted observations, i.e. for $\nu\left(t\right) = 1 \; \forall \; t$, this reduces to the standard definition
of a covariance matrix (eq. (\ref{eq:cov_standard})).

\end{document}


\section{Graph Algorithms}

Welcome to the new episode of PrinceOfPersia presents: Fun with algorithms ;)

You can find all the definitions here in the book "Introduction to graph theory", Douglas.B West. Important graph algorithms :
\subsection{DFS}
The most useful graph algorithms are search algorithms. DFS (Depth First Search) is one of them.

While running DFS, we assign colors to the vertices (initially white). Algorithm itself is really simple :
\begin{verbatim}
dfs (v):
        color[v] = gray
        for u in adj[v]:
                if color[u] == white
                        then dfs(u)
        color[v] = black
\end{verbatim}
Black color here is not used, but you can use it sometimes.

Time complexity : $O(n + m)$.
\subsubsection{DFS tree}
DFS tree is a rooted tree that is built like this :

\begin{verbatim}
let T be a new tree
dfs (v):
        color[v] = gray
        for u in adj[v]:
                if color[u] == white
                        then dfs(u) and par[u] = v (in T)

        color[v] = black
\end{verbatim}
Lemma: There is no cross edges, it means if there is an edge between v and u, then v = par[u] or u = par[v].
\subsubsection{Starting time, finishing time}
Starting time of a vertex is the time we enter it (the order we enter it) and its finishing time is the time we leave it. Calculating these are easy :
\begin{verbatim}
TIME = 0
dfs (v):
        st[v] = TIME ++
        color[v] = gray
        for u in adj[v]:
                if color[u] == white
                        then dfs(u)
        color[v] = black
        ft[v] = TIME // or we can use TIME ++
\end{verbatim}
It is useable in specially data structure problems (convert the tree into an array).

Lemma: If we run dfs(root) in a rooted tree, then v is an ancestor of u if and only if stv ≤ stu ≤ ftu ≤ ftv .

So, given arrays st and ft we can rebuild the tree.
\subsubsection{Finding cut edges}
The code below works properly because the lemma above (first lemma):
\begin{verbatim}
h[root] = 0
par[v] = -1
dfs (v):
        d[v] = h[v]
        color[v] = gray
        for u in adj[v]:
                if color[u] == white
                        then par[u] = v and dfs(u) and d[v] = min(d[v], d[u])
                        if d[u] > h[v]
                                then the edge v-u is a cut edge
                else if u != par[v])
                        then d[v] = min(d[v], h[u])
        color[v] = black
\end{verbatim}
In this code, h[v] =  height of vertex v in the DFS tree and d[v] = min(h[w] where there is at least vertex u in subtree of v in the DFS tree where there is an edge between u and w).
\subsubsection{Finding cut vertices}
The code below works properly because the lemma above (first lemma):
\begin{verbatim}
h[root] = 0
par[v] = -1
dfs (v):
        d[v] = h[v]
        color[v] = gray
        for u in adj[v]:
                if color[u] == white
                        then par[u] = v and dfs(u) and d[v] = min(d[v], d[u])
                        if d[u] >= h[v] and (v != root or number_of_children(v) > 1)
                                then the edge v is a cut vertex
                else if u != par[v])
                        then d[v] = min(d[v], h[u])
        color[v] = black
\end{verbatim}
In this code, h[v] =  height of vertex v in the DFS tree and d[v] = min(h[w] where there is at least vertex u in subtree of v in the DFS tree where there is an edge between u and w).
\subsubsection{Finding Eulerian tours}
It is quite like DFS, with a little change :
\begin{verbatim}
vector E
dfs (v):
        color[v] = gray
        for u in adj[v]:
                erase the edge v-u and dfs(u)
        color[v] = black
        push v at the end of e
\end{verbatim}
e is the answer.
\subsection{BFS}
BFS is another search algorithm (Breadth First Search). It is usually used to calculate the distances from a vertex v to all other vertices in unweighted graphs.

Code :
\begin{verbatim}
        BFS(v):
                for each vertex i
                        do d[i] = inf
                d[v] = 0
                queue q
                q.push(v)
                while q is not empty
                        u = q.front()
                        q.pop()
                        for each w in adj[u]
                                if d[w] == inf
                                        then d[w] = d[u] + 1, q.push(w)
\end{verbatim}
Distance of vertex u from v is d[u].

Time complexity : O(n + m).
\subsubsection{BFS tree}
BFS tree is a rooted tree that is built like this :
\begin{verbatim}
let T be a new tree
        BFS(v):
                for each vertex i
                        do d[i] = inf
                d[v] = 0
                queue q
                q.push(v)
                while q is not empty
                        u = q.front()
                        q.pop()
                        for each w in adj[u]
                                if d[w] == inf
                                        then d[w] = d[u] + 1, q.push(w) and par[w] = u (in T)
\end{verbatim}
\subsection{SCC}
The most useful and fast-coding algorithm for finding SCCs is Kosaraju.

In this algorithm, first of all we run DFS on the graph and sort the vertices in decreasing of their finishing time (we can use a stack).

Then, we start from the vertex with the greatest finishing time, and for each vertex v that is not yet in any SCC, do : for each u that v is reachable by u and u is not yet in any SCC, put it in the SCC of vertex v. The code is quite simple.

\subsection{Shortest path}
Shortest path algorithms are algorithms to find some shortest paths in directed or undirected graphs.
\subsubsection{Dijkstra}
This algorithm is a single source shortest path (from one source to any other vertices). Pay attention that you can't have edges with negative weight.

Pseudo code :
\begin{verbatim}
dijkstra(v) :
        d[i] = inf for each vertex i
        d[v] = 0
        s = new empty set
        while s.size() < n
                x = inf
                u = -1
                for each i in V-s //V is the set of vertices
                        if x >= d[i]
                                then x = d[i], u = i
                insert u into s
                // The process from now is called Relaxing
                for each i in adj[u]
                        d[i] = min(d[i], d[u] + w(u,i))
\end{verbatim}
There are two different implementations for this. Both are useful (C++11).

One) $O(n^2)$
\begin{verbatim}
int mark[MAXN];
void dijkstra(int v){
	fill(d,d + n, inf);
	fill(mark, mark + n, false);
	d[v] = 0;
	int u;
	while(true){
		int x = inf;
		u = -1;
		for(int i = 0;i < n;i ++)
			if(!mark[i] and x >= d[i])
				x = d[i], u = i;
		if(u == -1)	break;
		mark[u] = true;
		for(auto p : adj[u]) //adj[v][i] = pair(vertex, weight)
			if(d[p.first] > d[u] + p.second)
				d[p.first] = d[u] + p.second;
	}
}
\end{verbatim}
Two)

1) Using std :: set :
\begin{verbatim}
void dijkstra(int v){
	fill(d,d + n, inf);
	d[v] = 0;
	int u;
	set<pair<int,int> > s;
	s.insert({d[v], v});
	while(!s.empty()){
		u = s.begin() -> second;
		s.erase(s.begin());
		for(auto p : adj[u]) //adj[v][i] = pair(vertex, weight)
			if(d[p.first] > d[u] + p.second){
				s.erase({d[p.first], p.first});
				d[p.first] = d[u] + p.second;
				s.insert({d[p.first], p.first});
			}
	}
}
\end{verbatim}
2) Using std :: priority$\_$queue (better):
\begin{verbatim}
bool mark[MAXN];
void dijkstra(int v){
	fill(d,d + n, inf);
	fill(mark, mark + n, false);
	d[v] = 0;
	int u;
	priority_queue<pair<int,int>,vector<pair<int,int> >, less<pair<int,int> > > pq;
	pq.push({d[v], v});
	while(!pq.empty()){
		u = pq.top().second;
		pq.pop();
		if(mark[u])
			continue;
		mark[u] = true;
		for(auto p : adj[u]) //adj[v][i] = pair(vertex, weight)
			if(d[p.first] > d[u] + p.second){
				d[p.first] = d[u] + p.second;
				pq.push({d[p.first], p.first});
			}
	}
}
\end{verbatim}

\subsubsection{Floyd-Warshall}
Floyd-Warshal algorithm is an all-pairs shortest path algorithm using dynamic programming.

It is too simple and undrestandable :
\begin{verbatim}
Floyd-Warshal()
	d[v][u] = inf for each pair (v,u)
	d[v][v] = 0 for each vertex v
	for k = 1 to n
		for i = 1 to n
			for j = 1 to n
                d[i][j] = min(d[i][j], d[i][k] + d[k][j])
\end{verbatim}
Time complexity : $O(n^3)$.
\subsubsection{Bellman-Ford}
Bellman-Ford is an algorithm for single source shortest path where edges can be negative (but if there is a cycle with negative weight, then this problem will be NP).

The main idea is to relax all the edges exactly n - 1 times (read relaxation above in dijkstra). You can prove this algorithm using induction.

If in the n - th step, we relax an edge, then we have a negative cycle (this is if and only if).

Code :
\begin{verbatim}
Bellman-Ford(int v)
	d[i] = inf for each vertex i
	d[v] = 0
	for step = 1 to n
		for all edges like e
			i = e.first // first end
			j = e.second // second end
			w = e.weight
			if d[j] > d[i] + w
				if step == n
					then return "Negative cycle found"
                d[j] = d[i] + w
\end{verbatim}
Time complexity : $O(nm)$.
\subsubsection{SPFA}
SPFA (Shortest Path Faster Algorithm) is a fast and simple algorithm (single source) that its complexity is not calculated yet. But if m = O(n2) it's better to use the first implementation of Dijkstra.

The origin of this algorithm is unknown. It's said that at first Chinese coders used it in programming contests.

Its code looks like the combination of Dijkstra and BFS :
\begin{verbatim}
SPFA(v):
	d[i] = inf for each vertex i
	d[v] = 0
	queue q
	q.push(v)
	while q is not empty
		u = q.front()
		q.pop()
		for each i in adj[u]
			if d[i] > d[u] + w(u,i)
				then d[i] = d[u] + w(u,i)
				if i is not in q
                    then q.push(i)
\end{verbatim}
Time complexity : Unknown!.
\subsection{MST}
MST = Minimum Spanning Tree :) (if you don't know what it is, google it).

Best MST algorithms :
\subsubsection{Kruskal}
In this algorithm, first we sort the edges in ascending order of their weight in an array of edges.

Then in order of the sorted array, we add ech edge if and only if after adding it there won't be any cycle (check it using DSU).

Code :
\begin{verbatim}
Kruskal()
	solve all edges in ascending order of their weight in an array e
	ans = 0
	for i = 1 to m
		v = e.first
		u = e.second
		w = e.weight
		if merge(v,u) // there will be no cycle
            then ans += w
\end{verbatim}
Time complexity : $O(m\log{m})$.
\subsubsection{Prim}
In this approach, we act like Dijkstra. We have a set of vertices S, in each step we add the nearest vertex to S, in S (distance of v from $S = \min_{u \in S}(weight(u,v))$ where weight(i, j) is the weight of the edge from i to j) .

So, pseudo code will be like this:
\begin{verbatim}
Prim()
	S = new empty set
	for i = 1 to n
		d[i] = inf
	while S.size() < n
		x = inf
		v = -1
		for each i in V - S // V is the set of vertices
			if x >= d[v]
				then x = d[v], v = i
		d[v] = 0
		S.insert(v)
		for each u in adj[v]
            do d[u] = min(d[u], w(v,u))
\end{verbatim}
C++ code:
One) $O(n^2)$
\begin{verbatim}
bool mark[MAXN];
void prim(){
	fill(d, d + n, inf);
	fill(mark, mark + n, false);
	int x,v;
	while(true){
		x = inf;
		v = -1;
		for(int i = 0;i < n;i ++)
			if(!mark[i] and x >= d[i])
				x = d[i], v = i;
		if(v == -1)
			break;
		d[v] = 0;
		mark[v] = true;
		for(auto p : adj[v]){ //adj[v][i] = pair(vertex, weight)
			int u = p.first, w = p.second;
			d[u] = min(d[u], w);
		}
	}
}
\end{verbatim}
Two) $O(m\log{n})$
\begin{verbatim}
void prim(){
	fill(d, d + n, inf);
	set<pair<int,int> > s;
	for(int i = 0;i < n;i ++)
		s.insert({d[i],i});
	int v;
	while(!s.empty()){
		v = s.begin() -> second;
		s.erase(s.begin());
		for(auto p : adj[v]){
			int u = p.first, w = p.second;
			if(d[u] > w){
				s.erase({d[u], u});
				d[u] = w;
				s.insert({d[u], u});
			}
		}
	}
}
\end{verbatim}
As Dijkstra you can use std :: priority$\_$queue instead of std :: set.

\subsection{Maximum Flow}
I only wanna put the source code here (EdmondsKarp):
\begin{verbatim}
algorithm EdmondsKarp
    input:
        C[1..n, 1..n] (Capacity matrix)
        E[1..n, 1..?] (Neighbour lists)
        s             (Source)
        t             (Sink)
    output:
        f             (Value of maximum flow)
        F             (A matrix giving a legal flow with the maximum value)
    f := 0 (Initial flow is zero)
    F := array(1..n, 1..n) (Residual capacity from u to v is C[u,v] - F[u,v])
    forever
        m, P := BreadthFirstSearch(C, E, s, t, F)
        if m = 0
            break
        f := f + m
        (Backtrack search, and write flow)
        v := t
        while v ≠ s
            u := P[v]
            F[u,v] := F[u,v] + m
            F[v,u] := F[v,u] - m
            v := u
    return (f, F)

algorithm BreadthFirstSearch
    input:
        C, E, s, t, F
    output:
        M[t]          (Capacity of path found)
        P             (Parent table)
    P := array(1..n)
    for u in 1..n
        P[u] := -1
    P[s] := -2 (make sure source is not rediscovered)
    M := array(1..n) (Capacity of found path to node)
    M[s] := ∞
    Q := queue()
    Q.offer(s)
    while Q.size() > 0
        u := Q.poll()
        for v in E[u]
            (If there is available capacity, and v is not seen before in search)
            if C[u,v] - F[u,v] > 0 and P[v] = -1
                P[v] := u
                M[v] := min(M[u], C[u,v] - F[u,v])
                if v ≠ t
                    Q.offer(v)
                else
                    return M[t], P
    return 0, P
\end{verbatim}

EdmondsKarp pseudo code using Adjacency nodes:
\begin{verbatim}
algorithm EdmondsKarp
    input:
        graph (Graph with list of Adjacency nodes with capacities,flow,reverse and destinations)
        s             (Source)
        t             (Sink)
    output:
        flow             (Value of maximum flow)
    flow := 0 (Initial flow to zero)
    q := array(1..n) (Initialize q to graph length)
    while true
        qt := 0            (Variable to iterate over all the corresponding edges for a source)
        q[qt++] := s    (initialize source array)
        pred := array(q.length)    (Initialize predecessor List with the graph length)
        for qh=0;qh < qt && pred[t] == null
            cur := q[qh]
            for (graph[cur]) (Iterate over list of Edges)
                 Edge[] e :=  graph[cur]  (Each edge should be associated with Capacity)
                 if pred[e.t] == null && e.cap > e.f
                    pred[e.t] := e
                    q[qt++] : = e.t
        if pred[t] == null
            break
        int df := MAX VALUE (Initialize to max integer value)
        for u = t; u != s; u = pred[u].s
            df := min(df, pred[u].cap - pred[u].f)
        for u = t; u != s; u = pred[u].s
            pred[u].f  := pred[u].f + df
            pEdge := array(PredEdge)
            pEdge := graph[pred[u].t]
            pEdge[pred[u].rev].f := pEdge[pred[u].rev].f - df;
        flow := flow + df
    return flow
\end{verbatim}
\subsubsection{Dinic's algorithm}
Here is Dinic's algorithm as you wanted.

Input: A network G = ((V, E), c, s, t).

Output: A max s - t flow.

1.set f(e) = 0 for each e in E

2.Construct G$\_$L from G$\_$f of G. if dist(t) == inf, then stop and output f

3.Find a blocking flow fp in G$\_$L

4.Augment flow f by fp  and go back to step 2.

Time complexity : $O(mm\log{n})$.

Theorem: Maximum flow = minimum cut.

\subsubsection{Maximum Matching in bipartite graphs}
Maximum matching in bipartite graphs is solvable also by maximum flow like below :

Add two vertices S, T to the graph, every edge from X to Y (graph parts) has capacity 1, add an edge from S with capacity 1 to every vertex in X, add an edge from every vertex in Y with capacity 1 to T.

Finally, answer = maximum matching from S to T .

But it can be done really easier using DFS.

As, you know, a bipartite matching is the maximum matching if and only if there is no augmenting path (read Introduction to graph theory).

The code below finds a augmenting path:
\begin{verbatim}
bool dfs(int v){// v is in X, it reaturns true if and only if there is an augmenting path starting from v
	if(mark[v])
		return false;
	mark[v] = true;
	for(auto &u : adj[v])
		if(match[u] == -1 or dfs(match[u])) // match[i] = the vertex i is matched with in the current matching, initially -1
			return match[v] = u, match[u] = v, true;
	return false;
}
\end{verbatim}
An easy way to solve the problem is:
\begin{verbatim}
for(int i = 0;i < n;i ++)if(match[i] == -1){
	memset(mark, false, sizeof mark);
	dfs(i);
}
\end{verbatim}
But there is a faster way:
\begin{verbatim}
while(true){
	memset(mark, false, sizeof mark);
	bool fnd = false;
	for(int i = 0;i < n;i ++) if(match[i] == -1 && !mark[i])
		fnd |= dfs(i);
	if(!fnd)
		break;
}
\end{verbatim}
In both cases, time complexity = $O(nm)$.

\subsection{Trees}
Trees are the most important graphs.

In the last lectures we talked about segment trees on trees and heavy-light decomposition.

\subsubsection{Partial sum on trees}
We can also use partial sum on trees.

Example: Having a rooted tree, each vertex has a value (initially 0), each query gives you numbers v and u (v is an ancestor of u) and asks you to increase the value of all vertices in the path from u to v by 1.

So, we have an array p, and for each query, we increase p[u] by 1 and decrease p[par[v]] by 1. The we run this (like a normal partial sum):
\begin{verbatim}
void dfs(int v){
	for(auto u : adj[v])
		if(u - par[v])
			dfs(u), p[v] += p[u];
}
\end{verbatim}
\subsubsection{DSU on trees}
We can use DSU on a rooted tree (not tree DSUs, DSUs like vectors).

For example, in each node, we have a vector, all nodes in its subtree (this can be used only for offline queries, because we may have to delete it for memory usage).

Here again we use DSU technique, we will have a vector V for every node. When we want to have V[v] we should merge the vectors of its children. I mean if its children are u1, u2, ..., uk where V[u1].size() ≤ V[u2].size() ≤ ... ≤ V[uk].size(), we will put all elements from V[ui] for every 1 ≤ i < k, in V[k] and then, V[v] = V[uk].

Using this trick, time complexity will be .

C++ example (it's a little complicated) :
\begin{verbatim}
typedef vector<int> vi;
vi *V[MAXN];
void dfs(int v, int par = -1){
	int mx = 0, chl = -1;
	for(auto u : adj[v])if(par - u){
		dfs(u,v);
		if(mx < V[u]->size()){
			mx = V[u]->size();
			chl = u;
		}
	}
	for(auto u : adj[v])if(par - u and chl - u){
		for(auto a : *V[u])
			V[chl]->push_back(a);
		delete V[u];
	}
	if(chl + 1)
		V[v] = V[chl];
	else{
		V[v] = new vi;
		V[v]->push_back(v);
	}
}
\end{verbatim}
\subsubsection{LCA}
LCA of two vertices in a rooted tree, is their lowest common ancestor.

There are so many algorithms for this, I will discuss the important ones.

Each algorithm has complexities  < O(f(n)), O(g(n)) > , it means that this algorithm's preprocess is O(f(n)) and answering a query is O(g(n)) .

In all algorithms, h[v] =  height of vertex v.
One) Brute force  < O(n), O(n) >

The simplest approach. We go up enough to achieve the goal.

Preproccess :
\begin{verbatim}
void dfs(int v,int p = -1){
	if(par + 1)
		h[v] = h[p] + 1;
	par[v] = p;
	for(auto u : adj[v])	if(p - u)
		dfs(u,v);
}
\end{verbatim}
Query :
\begin{verbatim}
int LCA(int v,int u){
	if(v == u)
		return v;
	if(h[v] < h[u])
		swap(v,u);
	return LCA(par[v], u);
}
\end{verbatim}
Two) SQRT decomposition

I talked about SQRT decomposition in the first lecture.

Here, we will cut the tree into $\sqrt{H}$ (H = height of the tree), starting from 0, k - th of them contains all vertices with h in interval $[k\sqrt{H},(k+1)\sqrt{H}]$.

Also, for each vertex v in k - th piece, we store r[v] that is, its lowest ancestor in the piece number k - 1.

Preprocess:
\begin{verbatim}
void dfs(int v,int p = -1){
	if(par + 1)
		h[v] = h[p] + 1;
	par[v] = p;
	if(h[v] % SQRT == 0)
		r[v] = p;
	else
		r[v] = r[p];
	for(auto u : adj[v])	if(p - u)
		dfs(u,v);
}
\end{verbatim}
Query:
\begin{verbatim}
int LCA(int v,int u){
	if(v == u)
		return v;
	if(h[v] < h[u])
		swap(v,u);
	if(h[v] == h[u])
		return (r[v] == r[u] ? LCA(par[v], par[u]) : LCA(r[v], r[u]));
	if(h[v] - h[u] < SQRT)
		return LCA(par[v], u);
	return LCA(r[v], u);
}
\end{verbatim}
Three) Sparse table <$O(n\log{n})$, $O(1)$>

Let's introduce you an order of tree vertices, haas and I named it Euler order. It is like DFS order, but every time we enter a vertex, we write it's number down (even when we come from a child to this node in DFS).

Code for calculate this :
\begin{verbatim}
vector<int> euler;
void dfs(int v,int p = -1){
	euler.push_back(v);
	for(auto u : adj[v])	if(p - u)
		dfs(u,v), euler.push_back(v);
}
\end{verbatim}
If we have a vector<pair<int,int> > instead of this and push {h[v], v} in the vector, and the first time {h[v], v} is appeared is s[v] and s[v] < s[u] then LCA(v, u) = ($min_{i = s[v]}^{s[u]}euler[i]$).second.

For this propose we can use RMQ problem, and the best algorithm for that, is to use Sparse table.

Four) Something like Sparse table :) <$O(n\log{n})$,$O(\log{n})$>

This is the most useful and simple (among fast algorithms) algorithm.

For each vector v and number i, we store its $2^i$-th ancestor. This can be done in $O(n\log{n})$. Then, for each query, we find the lowest ancestors of them which are in the same height, but different (read the source code for understanding).

Preprocess:
\begin{verbatim}
int par[MAXN][MAXLOG]; // initially all -1
void dfs(int v,int p = -1){
	par[v][0] = p;
	if(p + 1)
		h[v] = h[p] + 1;
	for(int i = 1;i < MAXLOG;i ++)
		if(par[v][i-1] + 1)
			par[v][i] = par[par[v][i-1]][i-1];
	for(auto u : adj[v])	if(p - u)
		dfs(u,v);
}
\end{verbatim}
Query:
\begin{verbatim}
int LCA(int v,int u){
	if(h[v] < h[u])
		swap(v,u);
	for(int i = MAXLOG - 1;i >= 0;i --)
		if(par[v][i] + 1 and h[par[v][i]] >= h[u])
			v = par[v][i];
	// now h[v] = h[u]
	if(v == u)
		return v;
	for(int i = MAXLOG - 1;i >= 0;i --)
		if(par[v][i] - par[u][i])
			v = par[v][i], u = par[u][i];
	return par[v][0];
}
\end{verbatim}

Five) Advance RMQ  < O(n), O(1) >

In the third approach, we said that LCA can be solved by RMQ.

When you look at the vector euler you see that for each i that 1 ≤ i < euler.size(), |euler[i].first - euler[i + 1].first| = 1.

So, we can convert the euler from its size(we consider its size is n + 1) into a binary sequence of length n (if euler[i].first - euler[i + 1].first = 1 we put 1 otherwise 0).

So, we have to solve the problem on a binary sequence A .

To solve this restricted version of the problem we need to partition A into blocks of size . Let A'[i] be the minimum value for the i - th block in A and B[i] be the position of this minimum value in A. Both A and B are  long. Now, we preprocess A' using the Sparse Table algorithm described in lecture 1. This will take  time and space. After this preprocessing we can make queries that span over several blocks in O(1). It remains now to show how the in-block queries can be made. Note that the length of a block is , which is quite small. Also, note that A is a binary array. The total number of binary arrays of size l is . So, for each binary block of size l we need to lock up in a table P the value for RMQ between every pair of indices. This can be trivially computed in  time and space. To index table P, preprocess the type of each block in A and store it in array . The block type is a binary number obtained by replacing  - 1 with 0 and  + 1 with 1 (as described above).

Now, to answer RMQA(i, j) we have two cases:

i and j are in the same block, so we use the value computed in P and T

i and j are in different blocks, so we compute three values: the minimum from i to the end of i's block using P and T, the minimum of all blocks between i's and j's block using precomputed queries on A' and the minimum from the beginning of j's block to j, again using T and P; finally return the position where the overall minimum is using the three values you just computed.

Six) Tarjan's algorithm O(na(n)) (a(n) is the inverse ackermann function)

Tarjan's algorithm is offline; that is, unlike other lowest common ancestor algorithms, it requires that all pairs of nodes for which the lowest common ancestor is desired must be specified in advance. The simplest version of the algorithm uses the union-find data structure, which unlike other lowest common ancestor data structures can take more than constant time per operation when the number of pairs of nodes is similar in magnitude to the number of nodes. A later refinement by Gabow $\&$ Tarjan (1983) speeds the algorithm up to linear time.

The pseudocode below determines the lowest common ancestor of each pair in P, given the root r of a tree in which the children of node n are in the set n.children. For this offline algorithm, the set P must be specified in advance. It uses the MakeSet, Find, and Union functions of a disjoint-set forest. MakeSet(u) removes u to a singleton set, Find(u) returns the standard representative of the set containing u, and Union(u, v) merges the set containing u with the set containing v. TarjanOLCA(r) is first called on the root r.
\begin{verbatim}
 function TarjanOLCA(u)
     MakeSet(u);
     u.ancestor := u;
     for each v in u.children do
         TarjanOLCA(v);
         Union(u,v);
         Find(u).ancestor := u;
     u.colour := black;
     for each v such that {u,v} in P do
         if v.colour == black
             print "Tarjan's Lowest Common Ancestor of " + u +
                   " and " + v + " is " + Find(v).ancestor + ".";
\end{verbatim}
Each node is initially white, and is colored black after it and all its children have been visited. The lowest common ancestor of the pair {u, v} is available as Find(v).ancestor immediately (and only immediately) after u is colored black, provided v is already black. Otherwise, it will be available later as Find(u).ancestor, immediately after v is colored black.
\begin{verbatim}
 function MakeSet(x)
     x.parent := x
     x.rank   := 0

 function Union(x, y)
     xRoot := Find(x)
     yRoot := Find(y)
     if xRoot.rank > yRoot.rank
         yRoot.parent := xRoot
     else if xRoot.rank < yRoot.rank
         xRoot.parent := yRoot
     else if xRoot != yRoot
         yRoot.parent := xRoot
         xRoot.rank := xRoot.rank + 1

 function Find(x)
     if x.parent == x
        return x
     else
        x.parent := Find(x.parent)
        return x.parent
\end{verbatim}


\subsection{Ordering of the integers}

\subsubsection{Ordering integers}

Integers are an ordered pair of naturals.

\(\{\{x\},\{x,y\}\}\)

For example \(-4\) can be:

\(\{\{4\},\{4,8\}\}\)

\(\{\{0\},\{0,8\}\}\)

We extend the ordering to say:

\(\{\{x\},\{x,y\}\}\le \{\{s(x)\},\{s(x),y\}\}\)

\(\{\{x\},\{x,s(y)\}\}\le \{\{x\},\{x,y\}\}\)

So can we define this on an arbitrary pair:

\(\{\{a\},\{a,b\}\}\le \{\{c\},\{c,d\}\}\)

We know that:

\(\{\{a\},\{a,b\}\}=\{\{s(a)\},\{s(a),s(b)\}\}\)

And either of:

\(\{\{a\},\{a,b\}\}=\{\{0\},\{0,A\}\}\)

\(\{\{a\},\{a,b\}\}=\{\{B\},\{B,0\}\}\)

\(\{\{a\},\{a,b\}\}=\{\{0\},\{0,0\}\}\)

As the latter is a case of either of the other \(2\), we consider only the first \(2\).

So we can define:

\(\{\{a\},\{a,b\}\}\le \{\{c\},\{c,d\}\}\)

As any of:

\(1: \{\{0\},\{0,A\}\}\le \{\{0\},\{0,C\}\}\)

\(2: \{\{0\},\{0,A\}\}\le \{\{D\},\{D,0\}\}\)

\(3: \{\{B\},\{B,0\}\}\le \{\{0\},\{0,C\}\}\)

\(4: \{\{B\},\{B,0\}\}\le \{\{D\},\{D,0\}\}\)

Case 1:

\(\{\{0\},\{0,A\}\}\le \{\{0\},\{0,C\}\}\)

Trivial, depends on relative size of \(A\) and \(C\).

Case 2:

\(\{\{0\},\{0,A\}\}\le \{\{D\},\{D,0\}\}\)

We can see that:

\(\{\{D\},\{D,A\}\}\le \{\{D\},\{D,0\}\}\)

And therefore this holds.

Case 3:

\(\{\{B\},\{B,0\}\}\le \{\{0\},\{0,C\}\}\)

We can see that:

\(\{\{B\},\{B,0\}\}\le \{\{B\},\{B,C\}\}\)

And therefore this does not hold.

Case 4:

\(\{\{B\},\{B,0\}\}\le \{\{D\},\{D,0\}\}\)

Trivial, like case 1.


\chapter{Proofs}
\label{chapter:proofs}
\section{Direct Proofs}
\marginurl{%
    What is a Mathematical Proof:\\\noindent
    Introduction to Mathematical Reasoning \#1
}{youtu.be/eJD0gGqveIE}

We start the discussion of the proofs in mathematics from an example of a proof
in ``everyday'' life. Assume that we know that the following statements are
true.
\begin{enumerate}
    \item If a salmon has fins and scales it is kosher,
    \item if a salmon has scales it has fins,
    \item any salmon has scales.
\end{enumerate}
Using these facts we may conclude that any salmon is kosher; indeed, any salmon
has scales by the third statement, hence, by the second statement any salmon has
fins, finally, by the first statement any salmon is kosher since it has fins and
scales.

One may notice that this explanation is a sequence of conclusions such that
each of them is true because the previous one is true.
Mathematical proof is also a sequence of statements such that every statement
is true if the previous statement is true. If $P$ and $Q$ are some statements
and $Q$ is always true when $P$ is true, then we say that $P$ implies $Q$.
We denote the statement that $P$ implies $Q$ by $P \implies Q$.

\nomenclature[L]{$P \implies Q$}{denotes the statement saying that
if $P$ is true, then $Q$ is true as well}

In order to define the implication formally let us consider the following table.
\begin{center}
  \begin{tabular}{ l l l }
      \toprule
      $P$ & $Q$ & $P \implies Q$ \\
      \midrule
      T   & T   & T \\
      T   & F   & F \\
      F   & T   & T \\
      F   & F   & T \\
      \bottomrule
  \end{tabular}
\end{center}
Let $P$ and $Q$ be some statements. Then this table says that if $P$ and $Q$
are both false, then $P \implies Q$ is true etc.

\begin{exercise}
  Let $n$ be an integer.
  \begin{enumerate}
    \item Is it always true that ``$n^2$ is positive''
      implies ``$n$ is not equal to $0$''?
    \item Is it always true that ``$n^2 - n - 2$ is equal to $0$'' implies
      ``$n$ is equal to $2$''?
  \end{enumerate}
\end{exercise}
In the example we gave at the beginning of the section we used some
\emph{known} facts. But what does it mean to know something? In math we
typically say that we know a statement if we can prove it. But in order to prove
this statement we need to know something again, which is a problem! In order to
solve it, mathematicians introduced the notion of an \emph{axiom}.
An axiom is a statement that is believed to be true and when we prove a statement
we prove it under the assumption that these axioms are true\footnote{Note that
in different parts of mathematics axioms may be different.}.

For example, we may consider axioms of inequalities for real numbers.
\begin{enumerate}
  \item Let $a$ and $b$ be real numbers. Only one of the following is true:
    \begin{itemize}
      \item $a < b$,
      \item $b < a$, or
      \item $a = b$.
    \end{itemize}
  \item Let $a$, $b$, and $c$ be real numbers. Then $a < b$ iff $a + c < b + c$
    (iff is an abbreviation for ``if and only if'').
  \item Let $a$, $b$, and $c$ be real numbers. Then $a < b$ iff $ac < bc$
    provided that $c > 0$ and $a < b$ iff $ac > bc$ if $c < 0$.
  \item Let $a$, $b$, $c$ be real numbers. If $a < b$ and $b < c$, then $a < c$.
\end{enumerate}

\marginurl{%
  What We Know and How to Find a Proof:\\\noindent
  Introduction to Mathematical Reasoning \#2
}{youtu.be/nBjJi6aTk2M}

Let us now try to prove something using these axioms, we prove that if $a > 0$,
then $a^2 > 0$. Note that $a > 0$, hence, by the third axiom $a^2 > 0$
(note that we also used an additional statement saying that $0 \cdot 0 = 0$).

Similarly, we may prove that if $a < 0$, then $a^2 > 0$. And combining these
two statements together we may prove that if $a \neq 0$, then $a^2 > 0$.

Proofs like this are called direct proofs.

\begin{exercise}
  Consider another set of axioms; these axioms describe some objects that look
  like geometrical obejects, so they are called axioms of four-point geometry.

  These aximoms are using three undefined terms: ``point'', ``line'', and ``is
  on''. The axioms are the following statements.
  \begin{itemize}
    \item For every pair of distinct points $x$ and $y$, there is a unique line
      $\ell$ such that x is on l and y is on l.
    \item Given a line $\ell$ and a point $x$ that is not on $\ell$, there is a
      unique line $m$ such that $x$ is on $m$ and no point on $\ell$ is also on
      $m$.
    \item There are exactly four points.
    \item It is impossible for three points to be on the same line.
  \end{itemize}

  Prove (using these axioms) that there are at least two distinct lines.
\end{exercise}

Let $n$ and $m$ be some integers. Using direct proofs we may prove the
following two statements.
\begin{itemize}
  \item if $n$ is even, then $nm$ is also even (a number $\ell$ is even
    if there is an integer $k$ such that $\ell = 2k$),
  \item if $n$ is even and $m$ is even, then $n + m$ is also even.
\end{itemize}

We start from proving the first statement. There is an integer $k$ such that
$n = 2k$ since $n$ is even. As a result, $nm = 2 (nk)$ so $nm$ is even.

Now we prove the second statement. Since $n$ and $m$ are even there are $k$ and
$\ell$ such that $n = 2k$ and $m = 2\ell$. Hence, $n + m = 2 (k + \ell)$ so
$n + m$ is even.

\section{Constructing Proofs Backwards}
However, sometimes it is not easy to find the proof. In this case one of the
possible methods to deal with this problem is to try to prove starting from
the end.

For example, we may consider the statement $(a + b)^2 = a^2 + 2ba + b^2$.
Imagine, for a second, that you have not learned about axioms.
In this case you would write something like this:
\begin{multline*}
    (a + b)^2 = (a + b) \cdot (a + b) = \\
    a (a + b) + b (a + b) = \\
    a^2 + ab + ba + b^2 = a^2 + 2ba + b^2.
\end{multline*}

Let us try to prove it completely formally using the following axioms.
\begin{enumerate}
  \item Let $a$, $b$, and $c$ be real number. If $a = b$ and $b = c$, then $a =
    c$.
  \item Let $a$, $b$, and $c$ be real numbers. If $a = b$, then $a + c = b + c$
    and $c + a = c + b$.
  \item Let $a$, $b$, and $c$ be real numbers. Then $a (b + c) = ab + ac$.
  \item Let $a$ and $b$ be real numbers. Then $ab = ba$.
  \item Let $a$ and $b$ be real numbers. Then $a + b = b + a$.
  \item Let $a$ be a real number. Then $a^2 = a \cdot a$ and $a \cdot a = a^2$.
  \item Let $a$ be a real number. Then $a + a = 2a$.
\end{enumerate}
So the formal proof of the statement $(a + b)^2 = a^2 + 2ab + b^2$ is as
follows. First note that $(a + b)^2 = (a + b) \cdot (a + b)$ (by axiom~6),
hence, by axiom~1, it is enough to show that
$(a + b) \cdot (a + b) = a^2 + 2ab + b^2$. By axiom~3,
$(a + b) \cdot (a + b) = (a + b) \cdot a + (a + b) \cdot b$. Axiom~4 implies
that $(a + b) \cdot a = a \cdot (a + b)$ and $(a + b) \cdot b = b \cdot (a + b)$
Hence, by axioms~1 and~2 applied twice
\[
  a \cdot (a + b) + b \cdot (a + b) =
  (a + b) \cdot a + b \cdot (a + b) =
  (a + b) \cdot a + (a + b) \cdot b.
\]
As a result,
\begin{multline*}
  (a + b) \cdot (a + b) =
  (a + b) \cdot a + (a + b) \cdot b = \\
  a \cdot (a + b) + b \cdot (a + b) =
  a \cdot a + a \cdot b + b \cdot a + b \cdot b;
\end{multline*}
so by axiom 1, it is enough
to show that $a \cdot a + a \cdot b + b \cdot a + b \cdot b = a^2 + 2ab + b^2$.
Additionally, by axiom~6, $a \cdot a = a^2$ and $b \cdot b = b^2$. Hence, by
axiom~2, it is enough to show that
$a^2 + a \cdot b + b \cdot a + b^2 = a^2 + 2ab + b^2$. By axiom~4,
$a \cdot b = b \cdot a$, hence, by axiom~2,
$a \cdot b + b \cdot a = b \cdot a + b \cdot a$. Therefore by axiom~7,
$a \cdot b + b \cdot a = 2 b \cdot a$. Finally, by axiom~2,
$a \cdot b + b \cdot a + a^2 + b^2 = 2b \cdot a + a^2 + b^2$ and by axiom~5,
$a \cdot b + b \cdot a + a^2 + b^2 = a^2 + a \cdot b + b \cdot a + b^2$ and
$2b \cdot a + a^2 + b^2 =  a^2 + 2b \cdot a + b^2$. Which finishes the proof by
axiom~1.

\section{Analysis of Simple Algorithms}
\label{section:simple-algorithm}
We can use this knowledge to analyze simple algorithms. For example, let us
consider the following algorithm.
\begin{algorithm}
  \begin{algorithmic}[1]
    \Function{Max}{$a$, $b$, $c$}
      \State $r \gets a$
      \If {$b > r$}
        \State $r \gets b$
      \EndIf

      \If {$c > r$}
        \State $r \gets c$
      \EndIf
      \State \Return $r$
    \EndFunction
  \end{algorithmic}
  \caption{The algorithm that finds the maximum element of $a$, $b$, $c$.}
\end{algorithm}
We may prove that it is correct; i.e. it returns the maximum of $a$, $b$, and
$c$. We need to consider the following cases.
\begin{itemize}
  \item If the maximum is equal to $a$. In this case, at line~2, we set $r = a$,
    at line~3 the inequality $b > r$ is false (since $a = r$ is the maximum) and
    at line~6 the inequality $c > r$ is also false (since $a = r$ is the
    maximum). Hence, we do not change the value of $r$ after line~2 and
    the returned value is $a$.
  \item If the maximum is equal to $b$. We set $r = a$ at line~2.
    The inequality $b > r$ at line~3 is true (since $b$ is the maximum) and
    we set $r$ to be equal to $b$.
    So at line~6, the inequality $c > r$ is false (since $b = r$ is the
    maximum). Hence, the returned value is $b$.
  \item If the maximum is equal to $c$. We set $r = a$ at line~2.
    If the inequality $b > r$ is true at line~3 we set $r$ to be equal to $b$.
    So at line~6 the inequality $c > r$ is true (since $c$ is the
    maximum). Hence, we set $r$ being equal to $c$ and the returned value is
    $c$.
\end{itemize}

\section{Proofs in Real-life Mathematics}
In this chapter in most of the cases we explicitly used axioms to prove
statements. However, the resulting proofs are really long and hard to understand
(the last example in the previous section is a good example of this phenomenon).
Because of this mathematicians tend to skip steps in the proofs when they
believe that they are clear. It is worth to mention a nice quotation of Scott
Aaronson about this problem
\begin{displayquote}
  When mathematicians say that a theorem has been ``proved,'' they still mean,
  as they always have, something more like: ``we’ve reached a social consensus
  that all the ideas are now in place for a strictly formal proof that could be
  verified by a machine \dots with the only task remaining being massive rote
  coding work that none of us has any intention of ever doing!''
\end{displayquote}
This is the reason why it is arduous to read mathematical texts and it
is very different from reading non-mathematical books.
A problem that arises because of this tendency is that some mistakes may happen
if we skip way too many steps. In the last two centuries there were several
attempts to solve this issue, one approach to this we are going to discuss in
Part~\ref{part:logic}.
\marginurl{%
  Death of proof greatly exaggerated
}{scottaaronson.com/blog/?p=4133}

\begin{chapterendexercises}
  \exercise Using the axioms of inequalities show that if $a$ is a non-zero
    real number, then $a^2 > 0$.
  \exercise Using the axioms of inequalities prove that for all real
    numbers $a$, $b$, and $c$,
    \[
      bc + ac + ab \le a^2 + b^2 + c^2.
    \]
  \exercise[recommended] Prove that for all integers $a$, $b$, and $c$,
    If $a$ divides $b$ and $b$ divides $c$, then $a$ divides $c$.
    Recall that an integer $m$ divides an integer $n$ if there is an integer
    $k$ such that $mk = n$.
  \exercise[recommended] Show that square of an even integer is even.
  \exercise Prove that $0$ divides an integer $a$ iff $a = 0$.
  \exercise Using the axioms of inequalities, show that if $a > 0$, $b$, and $c$
    are real numbers, then $b \ge c$ implies that $ab \ge ac$.
  \exercise Using the axioms of inequalities, show that if $a, b < 0$ are real
    numbers, then $a \le b$ implies that $a^2 \ge b^2$.
\end{chapterendexercises}


%!TEX root = ../CombinatoricsNotes.tex

\section{Incidence problems}
\lect{4}{4}
% \marginnote{Lecture X: Monday, April 4, 2016.}
\begin{theorem}[Euler's formula]
Let $G$ be a connected graph drawn in the plane without crossings. Then
\[
|V(G)| - |\edges (G)| + \reg (G) =2
\]
where $\reg (G)$ is the number of regions in which the drawing divides the plane.
\end{theorem}

\begin{corollary} \label{cor:bound_edges_of_planar_3VG}
Let $G$ be a graph drawn in the plane without crossings. Then
\[
|\edges (G) |\leq 3 |V(G)|.
\]
\end{corollary}
\begin{proof}
We assume $|V(G)|\geq 3$. By adding additional edges we can ensure that each region of the drawing has a cycle of length 3 as its boundary. Then
\[
3 \reg(G) = 2 |\edges (G)|
\]
by double counting pairs (edge, region) such that each edge belongs to two regions boundary. Substituting into Euler's formula, we have
\[
|V(G)| - |\edges (G)| + \frac{2}{3}|\edges (G)| = 2
\]
so
\[
|\edges (G)| = 3 | V(G)| - 6 \leq 3 |V(G)|.
\]
\end{proof}

Let $\crossings(G)$ denote the minimal number of pairs of crossing edges taken over all drawing of $G$ in the plane  where vertices are represented by points, edges by curves joining corresponding points, and the drawing of edges are allowed to intersect, and each intersection is a \emph{crossing}\sidenote{locally looks like an $X$, not two curves bouncing off each other.}.

Then $\crossings(G)=0$ iff $G$ can be drawn in the plane without crossings, and $\crossings(K_5)=1$, by the drawing
\begin{center}
\begin{tikzpicture}

\end{tikzpicture}
\end{center}

\begin{corollary} \label{cor:bound_crossings_planar_graph93}
$\crossings(G) \geq |\edges (G)| - 3 |V(G)|$.
\end{corollary}
\begin{proof}
Let $G$ be a graph with $\crossings(G) = c$. In a drawing of $G$ with $c$ pairs of crossing edges, remove $c$ edges to obtain a graph drawin without crossings. Then by \cref{cor:bound_edges_of_planar_3VG},
\[
|\edges (G)| - c \leq 3 |V(G)|
\]
as we wanted.
\end{proof}

\begin{theorem}[Crossing number lemma]
\label{thm:crossing_number_lemma}

\[
\crossings(G) \geq \frac{1}{64}\frac{m^3}{n^2}
\]
for every graph $G$ with $m$ edges and $n$ vertices such that $m\geq 4n$.
\end{theorem}
\begin{proof}
Let $p \in [0,1]$ which we will choose later. Let $X\subset V(G)$ be obtained by choosing to include each vertex independently at random with probability $p$. Let $G'$ be the random subgraph of $G$ induced by $X$, namely $V(G') = X$, $\edges(G') = \edges(G| X)$. Let $m = |\edges(G)|$, $n= |V(G)|$, $x= \crossings(G)$, $m' = |\edges(G')|$, $n' = |V(G')|$, $x' = \crossings(G')$. Then by construction $\E[n'] = np$. Since each edge of $G$ survives with probability $p^2$, by linearity $\E[m']= mp^2$. Next, $\E[x'] \leq xp^4$ because the probability that a particular pair of crossing edges survives is $p^4$.

By \cref{cor:bound_crossings_planar_graph93}, $x'\geq m' - 3n'$. Taking expectation values, we have the bound $x p^4 \geq mp^2 - 3np$. That is,
\[
x\geq \frac{m}{p^2} - 3 \frac{n}{p^3}.
\]
Now, we choose optimal $p$:
\begin{gather*}
 \frac{\partial}{\partial p} \left( \frac{m}{p^2}- \frac{3n}{ p^3} \right) = - \frac{2m}{p^3} + \frac{9n}{p^4} = 0 \\
 \implies p=\frac{1}{4.5}\frac{n}{m}.
\end{gather*}
Let us simply take $p = \frac{1}{4}\frac{n}{m}.$ Then
\begin{gather*}
\crossings (G):=x \geq \frac{m}{\frac{16 n^2}{m^2}} - \frac{3n}{\frac{64 n^3}{m^3}}p = \frac{m^3}{n^2} \left( \frac{1}{16} - \frac{3}{64} \right) = \frac{1}{64}\frac{m^3}{n^2}.
\end{gather*}
\end{proof}

Let $P$ be a set of points in the plane. Let $L$ be a set of lines. Then define
\[
I(P,L):= |\{ ( p,L ): p\in P, l\in L, p\in L \}|.
\]
Then $I(P,L)$ is the number of \emph{incidences} of $P$ and $L$. Let $I(m,n)$ denote the maximum $I(P,L)$ over sets $P,L$ with $|P| = m$, $|L| = n$. Clearly, $I(m,n)\leq mn$.
\begin{example} We see $I(3,3) \leq 6$ by considering cases: if the three lines are parallel, the number of incidences is at most three. If two lines are parallel, there are at most five incidences. If none of the lines are parallel, there are at most six incidences. On the other hand, \cref{fig:I33} shows $I(3,3)\geq 6$.
\begin{marginfigure}
\begin{center}
\begin{tikzpicture}[scale=.7,rotate=180]
\node (x) at (2,0) {$\bullet$};
\node (y) at (1,2) {$\bullet$};

\node (z) at (0,0) {$\bullet$};

% \node (w) at (1,0) {$w$};

\draw [shorten >=-1cm,shorten <=-1cm](x) -- (y);
\draw[shorten >=-1cm,shorten <=-1cm] (y) -- (z);
\draw[shorten >=-1cm,shorten <=-1cm] (z) -- (x);
\end{tikzpicture}
\vspace{1em}
\end{center}
\caption{We see $I(3,3)\geq 6$.} \label{fig:I33}
\end{marginfigure}
\end{example}

\begin{example}
Let $n=4k^3$. Set
\[
P = \{ (x,y): 0\leq x \leq k-1, 0 \leq y\leq 4k^2 - 1, x,y\in \Z\}
\]
and
\[
L = \{ y = ax+b: 0\leq a \leq 2k-1, 0\leq b\leq 2k^2-1, a,b\in \Z \}
\]
Then $|P| = |L| =n$. We have $I(P,L)= k \cdot |L|  = kn \geq \frac{1}{2}n^{4/3}$

every line in $L$ incident with $k$ points in $P$.

\begin{gather*}
(x,ax+b)\in P \\
\text{for } 0\leq x \leq k-1, 0\leq a \leq 2k-1, 0\leq b \leq 2k^2- 1
\end{gather*}
$ax+b \leq (k-1)(2k-1) + 2k^2 - 1 < 4k^2$. So $I(n,n) \geq c n^{4/3}$ for all $n$ and some $c>0$.
\end{example}

\begin{theorem}[\cite{Szemeredi-Trotter1983}] \label{thm:bound_I_m_n95} \label{thm:Szemerdi_Trotter}
\[
I(m,n) \leq 4 m^{2/3} n^{2/3} + 4m + n.
\]
\end{theorem}

\begin{proof}
Let $P,L$ be sets of points and lines such that $|P| = m$, $|L| = n$ and $I(P,L) = I(n,m)$. Let $G$ be a graph drawn in the plane with crossings such that $V(G)  = P$, and $\edges(G)$ are drawn as line segments joining consecutive points on lines in $L$. \marginnote{I.e., follow one line at a time, connecting consecutive points.}
Then
\[
\crossings(G)\leq n^2
\]
because every crossing in $G$ is an intersection of two lines in $L$ (loose estimate). Then
\[
I:=I(P,L) = |\edges(G)| + n
\]
if there is a point of $P$ on every line in $L$ (if not, delete that line). We see this by following each line in $L$, and noting between every two incidences, we have an edge: if there are $k$ points in $P$ on a single line, there are $k-1$ edges connecting them.

Then $|\edges(G)| = I -n$. We have $|\edges(G)|\leq 4 |V(G)|$ if $I - n \leq 4m$, that is $I\leq 4m + n$.

Otherwise,  by \cref{thm:crossing_number_lemma},
\[
n^2 \geq \crossings (G) \geq \frac{1}{64} \frac{|\edges(G)|^3}{|V(G)|^2} = \frac{1}{64} \frac{(I-n)^3}{m^2}.
\]
That is,
\begin{gather*}
64 m^2 n^2 \geq (I-n)^3\\
4 m^{2/3} n^{2/3}\geq I- n\\
I \leq 4m^{2/3}n^{2/3}+n.\qedhere
\end{gather*}
\end{proof}

\begin{conjecture*}[\cite{Erdos-Szemeredi-1983}]
For every $\epsilon>0$ there exists $c_{\epsilon} > 0$ s.t. for every $A\subset \Z$,
\[
|A+A| + |A\cdot A| \geq c_{\epsilon} |A|^{2 - \epsilon},
\]
where $A+A = \{a+b: a,b\in A\}$ and $A\cdot A = \{a\cdot b: a,b\in A\}$.
\end{conjecture*}

\begin{theorem}[\cite{elekes1997number}] \label{thm:96_elekes}
There exists $c>0$ such that for every $A\subset \Z$,
\[
|A+A|\cdot |A\cdot A| \geq c |A|^{5/2}.
\]
In particular, by the arithmetic-geometric inequality,
\[
|A+A| + |A\cdot A| \geq c |A|^{5/4}.
\]
\end{theorem}
\begin{proof}
Let
\[
 P = \{(a,b):a \in A+A, b\in A\cdot A\}.
 \] Then $|P| =|A+A|\cdot |A\cdot A| $.Choose
\[
L = \{y = a(x-b): a,b\in A\}.
\]
Then $|L| = |A|^2$. Next,
\[
 I(P,L) \geq |A|^3
 \] since each line in $L$ contains $|A|$ points in $P$ as follows: $y = a(x-b)$, so choose $x= b+a' \in A+A$ for any $a' \in A$. Then $y = aa' \in A\cdot A$, so $(x,y) \in P$.

Therefore, by \cref{thm:bound_I_m_n95},
\begin{align*}
|A|^3 &\leq I(P,L) \leq 4 |A|^{4/3} |A+A|^{2/3}|A\cdot A|^{2/3} + 4|A+A| \cdot |A\cdot A| + |A|^2.
\end{align*}
At least one of these three terms is $\frac{1}{3}$ of the LHS. Easy if it is not the first one. Otherwise: $\frac{1}{3}|A|^3 \leq 4 |A|^{4/3} |A+A|^{2/3} |A\cdot A|^{2/3}$, so
\[
\left(\frac{1}{12}\right)^{3/2}|A|^{5/2} \leq |A+A| \cdot |A\cdot A|. \qedhere
\]
\end{proof}


\subsection{Regular Polygon}
\subsubsection{Description of the Algorithm}
The main idea behind this algorithm is to rotate a vector around a point
\textit{n} times.

Following a detailed description of the algorithm:

\begin{enumerate}
  \item calculate the parameters
  \item from 1 .. node\_counts calculate the points
  \item reverse the order of points
\end{enumerate}

\subsubsection{Implementation description}
The calculation of the parameters is the first part to do. The
parameter characterize the regular polygon about the position on the
sampling grid, the radius, the winding number and the node count.
There is room for further improvements or more parameters, like to
set the segment length and calculate the possible radius and the
center.

Trigonometric functions like Sinus and Cosinus helps to calculate the points.

\begin{lstlisting}[basicstyle=\scriptsize]
  auto gamma = 2 * \pi * winding_number / node_count;
  auto rotation_angle = -gamma / 2;

  auto x = radius * std::cos(seg_counter * gamma + rotation_angle) + center.x();
  auto y = radius * std::sin(seg_counter * gamma + rotation_angle) + center.y();
\end{lstlisting}

The rotation angle is not necessary for the algorithm. But it helps to perform
calculations during other algorithms easier. The rotation angle $ - gamma / 2$
rotates the whole polygon in a way, that the first segment lies vertically.

The final step revers the order of the points. This is also not really necessary
for the algorithm, but it produces a polygon which has the same direction as the
polygons from all other algorithms.

\subsubsection{Complexity}
The $n$ in the complexity analysis stands for the node count.

\begin{enumerate}
  \item calculate the parameters $\bigO(1)$
  \item from 1 .. node\_counts calculate the points $\bigO(n)$
  \item reverse the order of points $\bigO(n)$
\end{enumerate}

This leads to the sum of $\bigO(1) + \bigO(n) + \bigO(n) \Rightarrow \bigO(n)$

\subsubsection{Parameters}
\begin{description}
  \item [--nodes] how many nodes the polygon has to have. [default: 100]
  \item [--sampling-grid] the area within the polygon could grow. [default: 1500x800]
  %% \item [--winding-number]
  \item [--segment-length] set the segment length. [default: 0]
  \item [--radius] the radius for regular polygon. [default: 60]
\end{description}

\subsubsection{Examples}
\begin{figure}[ht]
  \centering

  \begin{minipage}[t]{0.4\textwidth}
    \begin{tikzpicture}[yscale=0.05,xscale=0.05]

      \setcounter{i}{1}

      \draw[->] (0,0) -- (80,0) node[below] {$x$};
      \draw[->] (0,0) -- (0,70) node[left] {$y$};

      \foreach \p in {(40,80), (70,58), (70, 22), (40,0), (10,22), (10,58)} {
        \node[point] (\arabic{i}) at \p {};
        \stepcounter{i}
      }

      \draw (1) -- (2) -- (3) -- (4) -- (5) -- (6) -- (1);
    \end{tikzpicture}
    \caption{Regular polygon with 6 points}
    \label{fig:rp:points-6}
  \end{minipage}\hfill
  \begin{minipage}[t]{0.4\textwidth}
    \begin{tikzpicture}[yscale=0.05,xscale=0.05]

      \setcounter{i}{1}

      \draw[->] (0,0) -- (80,0) node[below] {$x$};
      \draw[->] (0,0) -- (0,70) node[left] {$y$};

      \foreach \p in {(33,70), (70,60), (70, 20), (33,10), (0,40)} {
        \node[point] (\arabic{i}) at \p {};
        \stepcounter{i}
      }

      \draw (1) -- (2) -- (3) -- (4) -- (5) -- (1);
    \end{tikzpicture}
    \caption{Regular polygon with 5 points}
    \label{fig:rp:points-5}
  \end{minipage}
\end{figure}

\FloatBarrier