
\section{Chapitre 7: Problème du flot maximum}
\label{sec:ch7}

Référence: \cite{papadimitriou2013combinatorial}

\subsection{Les graphes orientés}
\label{sec:graphesorientes}

\begin{itemize}
\item Un graphe est un tuple $(V,E)$ formé de \textbf{sommets} $V$ et d'\textbf{arêtes} $E \subseteq V \times V$.
\item Une arête est représentée par une paire de sommets. Ces sommets sont \textbf{adjacents}.
\item Un graphe peut avoir des \textbf{poids} sur ses arêtes.
\item Un \textbf{chemin} est une suite de sommets distincts. Il a une \textbf{origine} et une \textbf{destination}.
\item Un \textbf{cycle} est une suite de sommets distincts dont le dernier sommet est adjacent au premier.
\item Liste de proximité: Tableau $Adj$ dont chaque élément $Adj[i]$ pointe sur une liste qui contient les sommets adjacents. Cette liste peut être doublement chaînée
\end{itemize}

\subsection{Fouille en profondeur}
\label{sec:fouilleprofondeur}

\begin{itemize}
\item Code de couleurs: Blanc=non visité, Gris=visite non complétée, Noir=visite complétée
\item Vecteur parent: Encode une forêt. $u$ est le parent de $v$ = $Parent[v]=u$
\item Complexité:
\begin{table}[!ht]
  \centering
  \begin{tabular}{l|l}
    Étape & Complexité \\
    \hline
    Initialisation & $\mathcal{O}(|V|)$ \\
    Visite & $|V|$ \\
    Arête & $|E|$ \\
    \hline
    \textbf{Total} & $\mathcal{O}(|V|+|E|)$
  \end{tabular}
  \caption{Complexité de la fouille en profondeur}
  \label{tab:compfouilleprof}
\end{table}
\end{itemize}


\begin{algorithm}[!ht]
  \Deb{
    \PourTous{$u \in V$}{
      $Couleur[u] \leftarrow Blanc$ \;
      $Parent[u] \leftarrow Nul$ \;
    }
    \PourTous{$u \in V$}{
      \Si{$Couleur[u]=Blanc$}{
        Visite$(u,V,E)$ \;
      }
    }
  }
\caption{FouilleProfondeur$(V,E)$}
\end{algorithm}

\begin{algorithm}[!ht]
  \Deb{
    $Couleur[u]=Gris$ \;
    \Pour{$v \in Adj[u]$}{
      \Si{$Couleur[u]=Blanc$}{
        $Parent[v] \leftarrow u$ \;
        Visite$(v,V,E)$ \;
      }
    }
    $Couleur[u]=Noir$
  }
\caption{Visite$(u,V,E)$}
\end{algorithm}

Pour trouver un chemin entre $s$ et $t$, on exécute seulement la fouille en profondeur sur l'origine $s$. Si $t$ est nul, il n'y a pas de chemin de $s$ vers $t$.

\subsection{Problème du flot maximum}
\label{sec:flotmaximum}

Définition du problème:
\begin{itemize}
\item $s$: Source
\item $t$: Puits
\item $c(a,b)$: Capacité
\item $f(a,b)=-f(b,a)$: Flot
\item Instance: $FlotMaximum(G=(V,E),s,t,c)$
\end{itemize}

Contraintes: un flot valide satisfait ces contraintes
\begin{itemize}
\item Conservation du flot:
  \begin{align}
    \sum_{b \mid (b,a) \in E} f(b,a) &= \sum_{b \mid (a,b) \in E} f(a,b) & \forall a \in V \setminus \lbrace s,t \rbrace
  \end{align}
\item Ce qui équivaut à:
  \begin{align}
    \sum_{b \in V} f(a,b) &= 0 & \forall a \in V \setminus \lbrace s,t \rbrace
  \end{align}
\item Contrainte de capacité:
  \begin{align}
    f(a,b) &\leq c(a,b) & \forall (a,b) \in E \\
    f(a,b) &\leq 0 & \forall (a,b) \notin E
  \end{align}
\end{itemize}

Le problème du flot maximum consiste à trouver un flot valide dont la valeur est maximale
\begin{align}
  v(f) &= \sum_{a \in V}f(s,a)\\
       &= \sum_{a \in V} f(a,t)
\end{align}

Représentation graphique

\begin{figure}[!ht]
  \centering
  \includegraphics[width=12cm]{exemple_flot}
  \caption{Représentation graphique d'un flot}
  \label{fig:grapheflot}
\end{figure}

\subsection{Chemins augmentant}
\label{sec:cheminsaugmentant}

Objectif: Identifier les chemins augmentants dans le graphe résiduel

\paragraph{Graphe résiduel}
\begin{itemize}
\item Utilisé pour identifier les chemins reliant la source au puits
\item Mêmes noeuds que le graphe original, mais les arêtes peuvent avoir un poids et une orientation différente
\item Notation: $G_f = (V, E_f)$
\item Existence d'une arête dans le graphe résiduel
  \begin{align}
    (a,b) \in E_{f} \iff f(a,b) < c(a,b)
    c_f(a.b) = c(a,b) - f(a.b)
  \end{align}
\item Chemin augmentant: relie la source au puits dans le graphe résiduel. Non nul
\end{itemize}

Exemple de graphe résiduel (Figure \ref{fig:grapheresiduel})

\begin{figure}[h]
  \centering
  \includegraphics[width=7cm]{exemple_flot_residuel}
  \caption{Graphe résiduel}
  \label{fig:grapheresiduel}
\end{figure}

\clearpage

\subsection{Algorithme de Ford-Fulkerson}
\label{sec:fordfulkerson}

\begin{algorithm}[h]
  \Deb{
    \Pour{$i \in \binom{|V|}{2}$}{
      $f[i] \leftarrow 0$
    }
    \Repeter{aucun chemin entre $s$ et $t$ dans $G_f$}{
      Construire $G_f$ \;
      Trouver le chemin $C$ de $s$ à $t$ avec une fouille en profondeur \;
      \Si{$\exists C$}{
        $q=min(c_f(a,b)) | (a,b) \in C$ \;
        \PourTous{$(a,b) \in C$}{
          $f(a,b) \leftarrow f(a,b)+q$ \;
          $f(b,a) \leftarrow f(b,a)-q$ \;
        }
      }
    }
    \Retour{f} \;
  }
\caption{Algorithme de Ford-Fulkerson}
\end{algorithm}

Complexité:

\begin{table}[h]
  \centering
  \begin{tabular}{l|l}
    Étape & Complexité \\
    \hline
    Chemin dans le graphe résiduel & $\mathcal{O}(|V|+|E|), |V|-1 \leq |E| \rightarrow \mathcal{O}(|E|)$ \\
    Mise à jour du graphe résiduel & $\mathcal{O}(|V|)$ \\
    \hline
    \textbf{Total} & $\mathcal{O}(v(f)|E|)$
  \end{tabular}
  \caption{Complexité de l'algorithme de Ford-Fulkerson}
  \label{tab:compfouilleprofordfulkerson}
\end{table}

\subsection{Coupe minimale}
\label{sec:coupeminimale}

\begin{itemize}
\item Une coupe est une bipartition des noeuds tel que la source est dans $S$ et le puits dans $T$
\item Capacité d'une coupe
  \begin{align}
    c(S,T) &= \sum_{a \in S} \sum_{b \in T} c(a,b)
  \end{align}
\item Flot net d'une coupe: quantité de flot passant d'un noeud dans $S$ à un noeud dans $T$:
  \begin{align}
    f(S,T) &= \sum_{a\in S, b\in T} f(a,b)
  \end{align}
\item Théorème: Pour toute coupe $(S,T)$ et tout flot valide $f$: $v(f)=f(S,T)$
\end{itemize}

Trois affirmations équivalentes:

\begin{enumerate}
\item $f$ est un flot maximum dans $G$
\item Le graphe résiduel $G_f$ n'a pas de chemin augmentant
\item Il existe une coupe $(S,T)$ dont la capacité $c(S,T)$ est égale a $v(f)$
\end{enumerate}

\subsection{Types de problèmes}
\label{sec:flotproblemes}

\paragraph{Ordonnancement}

Source reliée aux personnes avec des arêtes de capacité 1.
Personnes reliées aux plages de disponibilité avec une capacité de 1
Plages de disponibilité reliées au puits avec capacité de 1.

La partie du graphe se nomme couplage: sous-ensemble d'arêtes non adjacentes.
On recherche un couplage maximum.

\paragraph{All-Different}

\begin{itemize}
\item Se résout aussi avec un couplage maximum.
\item On peut trouver un autre support de domaine en poussant une unité de flot sur un cycle.
\item La différence entre les deux flots valides est un ensemble de cycles disjoints.
\item La valeur $v$ a un support de domaine dans $dom(X_i)$ ssi. $(v,X_i)$ appartient au graphe résiduel ou $(v,X_i)$ appartient à un cycle du graphe résiduel.
\end{itemize}

\begin{figure}[!ht]
  \centering
  \includegraphics[width=6cm]{composantsfortementconnexes}
  \caption{Composants fortement connexes}
  \label{fig:composantfortement}
\end{figure}

\subsection{Algorithmes de Kosaraju et de Régin}
\label{sec:kosarajuregin}

\paragraph{Algorithme de Kosaraju}

Sert à identifier les composantes fortement connexes: ensembles de noeuds où chaque noeud peut rejoindre tous les autres noeuds. Cet ensemble est maximal.

\begin{enumerate}
\item Effectuer une fouille en profondeur
\item Ajouter les noeuds coloriés en noir à une pile
\item Construire le graphe transposé
\item Effectuer une fouille en profondeur sur le graphe transposé en dépilant les noeuds
\item Définir le vecteur parent de cette fouille. Chaque arbre est une composante fortement connexe
\end{enumerate}

\paragraph{Algorithme de Régin}

Filtrage pour All-Different
\begin{enumerate}
\item Calculer un couplage avec Ford-Fulkerson
\item Marquer toutes les arêtes faisant partie d'un cycle
\item Retirer $v$ du domaine de $X_i$ si le flot est nul sur $(X_i,v)$ ou si cette arête n'est pas marquée.
\end{enumerate}

\begin{algorithm}
  \Deb{
    Construire un graphe $G$ avec $V= \lbrace X_1,\ldots,X_n \rbrace \cup \bigcup_{i=1}^{n} dom(X_i) \cup \lbrace s,t \rbrace$ \;
    \Pour{$i \in \left[ 1,\ldots,n \right]$}{
      \Pour{$v \in dom(X_i)$}{
        Ajouter $(C_i,v)$ de capacité 1 à $G$ \;
      }
      Ajouter l'arête $(s,X_i)$ de capacité 1 à $G$ \;
    }
    \Pour{$v \in \bigcup_{i=1}^{n} dom(X_i)$}{
      Ajouter l'arête $(v,t)$ de capacité 1 à $G$ \;
    }
    $f \leftarrow$ Ford-Fulkerson($G$) \;
    \Si{$v(f) \neq n$}{
      $sat=Faux$ \;
    }
    composantes $\leftarrow$ Kosaraju(GrapheResiduel) \;
    \Pour{$i \in \left[ 1,\ldots,n \right]$}{
      \Pour{$v \in dom(X_i)$}{
        \Si{$f(X_i,v)=0 \wedge$ composante($X_i$) $\neq$ composante($v$)}{
          $dom(X_i) \leftarrow dom(X_i) \ \lbrace v \rbrace$
        }
      }
    }
  }
\caption{Algorithme de Régin}
\end{algorithm}

Complexité: (D=somme des cardinalité des domaines). Possible de ramener à $\mathcal{O}(\delta D)$ en pratique, où $\delta$ est le nombre de valeurs supprimées des domaines.

\begin{table}[h]
  \centering
  \begin{tabular}{l|l}
    Étape & Complexité \\
    \hline
    Calcul du flot&$\mathcal{O}(nD)$ \\
    Calcul des composantes fortement connexes&$\mathcal{O}(D)$ \\
    Boucles de l'algorithme&$\mathcal{O}(D)$ \\
    \hline
    \textbf{Total} & $\mathcal{O}(nD)$
  \end{tabular}
  \caption{Complexité de l'algorithme de Régin}
  \label{tab:compregin}
\end{table}

\subsection{Production et consommation de flot}
\label{sec:prodconsflot}

On associe $b_i$ pour chaque noeud $i$ du graphe.
\begin{itemize}
\item Si $b_i>0$, le noeud produit $b_i$ unités de flot et les injecte dans le graphe
\item Si $b_i<0$, le noeud absorbe $b_i$ unités de flot
\end{itemize}

La contrainte de conservation du flot devient:
\begin{align}
  \sum_{b \mid (a,b) \in E} f(a,b) - \sum_{b \mid (b,a) \in E} f(b,a) &= b_a &\forall a \in V
\end{align}

Exemple:
\begin{itemize}
\item Problème: Chaque noeud est soit un producteur ou un consommateur de marchandise, les arêtes représentent le réseau de transport.
\item Solution: Créer un noeud source et le relier à chaque producteur. Créer un noeud puits et l'ajouter à chaque consommateur.
\item Résoudre le flot maximum avec Ford-Fulkerson
\end{itemize}

\subsection{Capacités minimales}
\label{sec:capaciteminimale}

On ajoute une capacité minimale $l(a,b)$ sur chaque arête. On a maintenant cette contrainte:
\begin{align}
  l(a,b) &\leq f(a,b) \leq c(a,b)\\
  l(a,b) &= -c(b,a)
\end{align}

\begin{itemize}
\item Le graphe résiduel est inchangé. Si f(a,b)=l(a,b), l'arête n'apparaitra pas
\item On peut utiliser l'algorithme de Ford-Fulkerson sur ce graphe résiduel.
\item On doit identifier un flot valide initial
\end{itemize}

Résolution:

\begin{enumerate}
\item Ajouter (s,t) tel que $l(s,t)=0$ et $c(s,t)=\infty$
\item On effectue le changement de variable $f^{\prime}(a,b) = f(a,b) - l(a,b)$
\item On retrouve le problème de production et consommation de flot
\item On ajoute une source et un puits, puis on exécute l'algorithme de Ford-Fulkerson
\item Le flot maximum obtenu est un flot initial valide pour le problème des capacités minimales
\item On exécute l'algorithme de Ford-Fulkerson pour le problème initial
\end{enumerate}
















%%% Local Variables:
%%% mode: latex
%%% TeX-master: "notes_de_cours"
%%% End:
