\input{template}
\input{macros}

\begin{document}
\lecture{32} {Network Flows
(contd.)}{Ankit Jain}

In this lecture we continue with the primal-dual algorithm for network flows.

\section{Primal Dual Algorithm}
The network flow problem as defined in the previous lecture is as follows :
\begin{align}
max\sum_u f_{su}   \notag \\
\text{s.t.    } \forall u,v \text{        } f_{uv} \leq C_{uv}    \\
\forall u,v \text{        } f_{uv} + f_{vu} =  \text{   0} \\
\forall u \neq s,t \text {      } \sum_v f_{uv} = 0 
\end{align}
\begin{center}
where $f_{uv}$ is the flow from vertex u to vertex v \\
and $C_{uv}$ is the (non negative) capacity of the link u - v
\end{center}

In this case, we will solve the primal itself rather than the corresponding dual.\\

\subsection{Initialization}  
\begin{center}
We begin with a feasible solution. \\
$\forall u,v \text{   }  f_{uv}$ = 0
\end{center}
Now, we need a piece of code that we can run again and again recursively, improving  the above solution till we find the optimal. The Primal-Dual algorithm helps us find just that. \\

\subsection{Recursion } 

The Primal Dual Algorithm

\begin{align}
max\sum_u f_{su}'   \notag \\
\text{s.t.    } \forall u,v \text{   where   ( } f_{uv} = C_{uv} \text{ )   } f_{uv}' \leq \text{  0}  \\
\forall u,v \text{        } f_{uv}' + f_{vu}' =  \text{   0} \\
\forall u \neq s,t \text {      } \sum_v f_{uv}' = 0 \\ \notag \\
\text{This is related to the original problem by the following equation} \notag \\
 \forall u,v \text {  }  f_{uv}^{old} + \epsilon f_{uv}' = f_{uv}^{new}
\end{align}

Our aim is to keep raising $\epsilon$ until we reach an equality of the form $f_{uv}^{new} = C_{uv}$
\newpage
\begin{align}
\text{If  } \sum_u f_{su}' = \text{ 1 } \notag 
\end{align}
the network flow must be of the form as shown in Figure1 since we have a net flow of 1 leaving from s which cannot disappear at any node except the destination.  \\ 
All these edges have $ f_{uv} < C_{uv}$ \\

\begin{figure} 
\centering
\includegraphics[scale=0.5]{Dia1.jpg}
\caption{Path from s to t}
\label{Figure 2}
\end{figure}

So all we need to do is to find one such path and raise the flow till one of the paths reaches its capacity. 
$ \text{For any path, maximum raise possible }  = C_{uv} - f_{uv} $ 
This tells us the new capacity if all the edges in the graph. So we construct a graph on same set of vertices with capacity  $= C_{uv} - f_{uv} $ \\

One interesting fact to note here is that the number of edges can infact increase on doing the above step. This can happen when we have a capacity of a edge = 0 and corresponding flow $(f_{uv} ) < $ 0. However there can only be a maximum of 2m edges. (where m is number of edges in input graph)

So given new capacities, we find any path from s to t. On the path, find the minimum capacity and keep $\epsilon = $ minimum capacity on that path. This will give us a new equality of the form $f_{uv} = C_{uv}$. Hence we have a required equality, and we move to the next recursion. \\

\subsection{Order of Algorithm} 

\begin{figure} 
\centering
\includegraphics[scale=0.5]{Dia2.jpg}
\caption{Example Graph}
\label{Figure 2}
\end{figure}

If in Figure 2 we choose the path containing edge with weight 1 in each iteration it will take O(W) time to complete the execution. However the input size is O( ln W ). (No of bytes required to represent total weight ). So clearly the runtime is exponential in size of input. Hence choosing the appropriate path is critical. However LP cannot help us with this and we must look for a combinatorial algorithm. One such algorithm has been discussed in the next section.

\subsection{Optimality} 
	Another step of algorithm is to check if we have reached the optimal solution after each recursion. For this purpose, we look at all vertices accessible from s. We then seperate the graph into 2 parts, s on one side and t on the other. This is also know as the \textit{cut}. In an optimal solution, we cannot have any flow through any cut. (The dual infact works by finding the cut of minimum capacity.)

\section{ Improved Algorithm}
\subsection{Algorithm to find optimal path}
The optimal path can be thought of as the path connecting s to t such that its minimum capacity edge is maximum among all paths from s to t. This can done with a simple modification to the Dijkstra's Algorithm (Tutorial 3 - Question 2).

\subsection{Order of Algorithm}
For calculating the order, we first make two important observations. \\ \\
\textbf{Observation 1} 
\begin{center}
Let $f$ be the current flow \\ 
and $f^{*}$ be a flow of maximum value. \\
\end{center}
\textit{Claim : } $ f^{*} - f $ is a flow in the graph \\
\textit{Proof : } 
Both $f$ and $f^{*}$ are flows in the original graph and hence must satisfy equations (1), (2) and (3). \\
Therefore we have, 
\begin{align}
\forall u,v \text{  } f_{uv}^* - f_{uv} \leq C_{uv} - f_{uv}   \\
\forall u,v \text{  } (f_{uv}^* - f_{uv}) + (f_{vu}^* - f_{vu}) =  \text{   0} \\
\forall u \neq s,t \text {  } \sum_v f_{uv}^* - f_{uv} = 0 
\end{align}
which satisfies all conditions ((4),(5) and (6)) required by the flow in new graph. \\

\textbf{Observation 2} \\ \\
\textit{Claim :} The above flow ($f^{*} - f$) can be written as a sum of \emph{atmost} 2m flows, where each of them is a path from s to t. \\
\textit{Proof :} This is simply because there can be a maximum of 2m different edges, and even if each represents a different flow we can only have 2m different flows from s to t.\\ \\
  
Using the second observation I can say that, in every iteration I increase my flow by atleast $ (|f^{*}| - |f|) / 2m$.
Hence
\begin{align}
|f^{new}| \geq |f^{old}| + (|f^{*}| - |f|) / 2m \notag \\
|f^{*}| - |f^{new}| \leq (|f^{*}| - |f^{old}|) (1 - 1/2m) \notag 
\end{align}
So, in t iterations 
\begin{align}
  |f^{*}| (1 - 1/2m)^{t} < 1 \notag \\
  \text{as we began with  } f^{old} = \text{ 0 } \notag
\end{align}
This gives us,
\begin{align}
t = 2m \text{  } ln|f^{*}| \notag 
\end{align}
which is polynomial in size of input
\end{document}
