Ford-Fulkerson algorithm

This commit is contained in:
Antti H S Laaksonen 2017-01-10 22:33:14 +02:00
parent 801ee43ca8
commit 99c1706277
1 changed files with 209 additions and 204 deletions

View File

@ -1,24 +1,26 @@
\chapter{Network flows} \chapter{Flows and cuts}
Annettuna on suunnattu, painotettu verkko, In this chapter, we will focus on the following
josta on valittu tietty alkusolmu ja loppusolmu. problems in a directed, weighted graph
Tarkastelemme seuraavia ongelmia: where a starting node and a ending node is given:
\begin{itemize} \begin{itemize}
\item \key{Maksimivirtauksen etsiminen}: \item \key{Finding a maximum flow}:
Kuinka paljon virtausta on mahdollista kuljettaa What is the maximum amount of flow we can
verkon alkusolmusta loppusolmuun kaaria pitkin? deliver
\item \key{Minimileikkauksen etsiminen}: from the starting node to the ending node?
Mikä on yhteispainoltaan pienin joukko kaaria, \item \key{Finding a minimum cut}:
joiden poistaminen erottaa alkusolmun loppusolmusta? What is a minimum-weight set of edges
that separates the starting node and the ending node?
\end{itemize} \end{itemize}
Osoittautuu, että nämä ongelmat vastaavat toisiaan It turns out that these problems correspond to
ja ne on mahdollista ratkaista samanaikaisesti each other, and we can solve them simultaneously
toistensa avulla. using the same algorithm.
Käytämme esimerkkinä seuraavaa verkkoa, As an example, we will use the following graph
jossa solmu 1 on alkusolmu ja solmu 6 on loppusolmu: where node 1 is the starting node and node 6
is the ending node:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -39,23 +41,24 @@ jossa solmu 1 on alkusolmu ja solmu 6 on loppusolmu:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
\subsubsection{Maksimivirtaus} \subsubsection{Maximum flow}
\index{virtaus@virtaus} \index{flow}
\index{maksimivirtaus@maksimivirtaus} \index{maximum flow}
\key{Maksimivirtaus} on suurin A \key{maximum flow} is a flow from the
mahdollinen verkossa kulkeva virtaus, starting node to the ending node whose
joka lähtee liikkeelle alkusolmusta ja total amount is as large as possible.
päätyy loppusolmuun. The weight of each edge is a capacity that
Kunkin kaaren paino on kapasiteetti, determines the maximum amount of flow that
joka ilmaisee, kuinka paljon virtausta kaaren can go through the edge.
kautta voi kulkea. In all nodes, except for the starting node
Kaikissa verkon solmuissa alku- and the ending node,
ja loppusolmua lukuun ottamatta the amount of incoming and outgoing flow
lähtevän ja tulevan virtauksen on oltava yhtä suuri. must be the same.
Esimerkkiverkon maksimivirtaus on seuraava: A maximum flow for the example graph
is as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -76,35 +79,33 @@ Esimerkkiverkon maksimivirtaus on seuraava:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Merkintä $v/k$ kaaressa tarkoittaa, The notation $v/k$ means
että kaaressa kulkee virtausta $v$ that amount of the flow through the edge is $v$
ja kaaren kapasiteetti on $k$. and the capacity of the edge is $k$.
Jokaiselle kaarelle tulee päteä $v \le k$. For each edge, it is required that $v \le k$.
Tässä verkossa In this graph, the size of a maximum flow is 7
maksimivirtauksen suuruus on 7, koska alkusolmusta because the outgoing flow from the starting node is $3+4=7$,
lähtevä virtaus on $3+4=7$ ja loppusolmuun and the incoming flow to the ending node is $5+2=7$.
tuleva virtaus on $5+2=7$.
Huomaa, että jokaisessa välisolmussa tulevan ja Note that in each intermediate node,
lähtevän virtauksen määrä on yhtä suuri. the incoming flow and the outgoing flow are equally large.
Esimerkiksi solmuun 2 tulee virtausta $3+3=6$ yksikköä solmuista 1 ja 4 For example, in node 2, the incoming flow is $3+3=6$
ja siitä lähtee virtausta $6$ yksikköä solmuun 3. from nodes 1 and 4,
and the outgoing flow is $6$ to node 3.
\subsubsection{Minimileikkaus} \subsubsection{Minimum cut}
\index{leikkaus@leikkaus} \index{cut}
\index{minimileikkaus@minimileikkaus} \index{minimum cut}
\key{Minimileikkaus} on yhteispainoltaan A \key{minimum cut} is a set of edges
pienin mahdollinen joukko verkon kaaria, whose removal separates the starting node from the ending node,
joiden poistaminen estää kulkemisen and whose total weight is as small as possible.
alkusolmusta loppusolmuun. A cut divides the graph into two components,
Leikkauksen jälkeen alkuosaan kuuluvat one containing the starting node and the other
solmut, joihin pääsee alkusolmusta, containing the ending node.
ja loppuosaan kuuluvat muut verkon solmut,
mukaan lukien loppusolmu.
Esimerkkiverkon minimileikkaus on seuraava: A minimum cut for the example graph is as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -130,53 +131,50 @@ Esimerkkiverkon minimileikkaus on seuraava:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Tässä leikkauksessa alkuosassa ovat solmut $\{1,2,4\}$ In this cut, the first component contains nodes $\{1,2,4\}$,
ja loppuosassa ovat solmut $\{3,5,6\}$. and the second component contains nodes $\{3,5,6\}$.
Minimileikkauksen paino on 7, The weight of the cut is 7,
koska alkuosasta loppuosaan kulkevat because it consists of edges
kaaret $2 \rightarrow 3$ ja $4 \rightarrow 5$, $2 \rightarrow 3$ and $4 \rightarrow 5$,
joiden yhteispaino on $6+1=7$. and the total weight of the edges is $6+1=7$.
\\\\ \\\\
Ei ole sattumaa, että esimerkkiverkossa It is not a coincidence that
sekä maksimivirtauksen suuruus both the size of the maximum flow and
että minimileikkauksen paino on 7. the weight of the minimum cut is 7
Virtauslaskennan keskeinen tulos on, in the example graph.
että verkon maksimivirtaus ja It turns out that a maximum flow and
minimileikkaus a minimum cut are \emph{always} of equal size,
ovat \textit{aina} yhtä suuret, so the concepts are two sides of the same coin.
eli käsitteet kuvaavat saman asian
kahta eri puolta.
Seuraavaksi tutustumme FordFulkersonin Next we will discuss the FordFulkerson
algoritmiin, jolla voi etsiä verkon algorithm that can be used for finding
maksimivirtauksen ja a maximum flow and a minimum cut in a graph.
minimileikkauksen. The algorithm also helps us to understand
Algoritmi auttaa myös ymmärtämään, \emph{why} they are equally large.
\textit{miksi} maksimivirtaus ja
minimileikkaus ovat yhtä suuret.
\section{FordFulkersonin algoritmi} \section{FordFulkerson algorithm}
\index{FordFulkersonin algoritmi} \index{FordFulkerson algorithm}
\key{FordFulkersonin algoritmi} etsii verkon maksimivirtauksen. The \key{FordFulkerson algorithm} finds
Algoritmi aloittaa tilanteesta, a maximum flow in a graph.
jossa virtaus on 0, ja alkaa sitten etsiä verkosta polkuja, The algorithm begins with an empty flow,
jotka tuottavat siihen lisää virtausta. and at each step finds a path in the graph
Kun mitään polkua ei enää pysty muodostamaan, that generates more flow.
maksimivirtaus on tullut valmiiksi. Finally, when the algorithm can't extend the flow
anymore, it terminates and a maximum flow has been found.
Algoritmi käsittelee verkkoa muodossa, The algorithm uses a special representation
jossa jokaiselle kaarelle on vastakkaiseen for the graph where each original edge has a reverse
suuntaan kulkeva pari. edge in another direction.
Kaaren paino kuvastaa, miten paljon The weight of each edge indicates how much more flow
lisää virtausta sen kautta pystyy vielä kulkemaan. we could route through it.
Aluksi alkuperäisen verkon kaarilla on Initially, the weight of each original edge
painona niiden kapasiteetti equals the capacity of the edge,
ja käänteisillä kaarilla on painona 0. and the weight of each reverse edge is zero.
\begin{samepage} \begin{samepage}
Esimerkkiverkosta syntyy seuraava verkko: The new representation for the example graph is as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -209,13 +207,13 @@ Esimerkkiverkosta syntyy seuraava verkko:
\subsubsection{Algoritmin toiminta} \subsubsection{Algoritmin toiminta}
FordFulkersonin algoritmi etsii verkosta joka vaiheessa polun, The FordFulkerson algorithm finds at each step
joka alkaa alkusolmusta, a path from the starting node to the ending node
päättyy loppusolmuun ja jossa jokaisen kaaren where each edge has a positive weight.
paino on positiivinen. If there are more than one possible paths,
Jos vaihtoehtoja on useita, mikä tahansa valinta kelpaa. we can choose any of them.
Esimerkkiverkossa voimme valita vaikkapa seuraavan polun: In the example graph, we can choose, say, the following path:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -250,16 +248,17 @@ Esimerkkiverkossa voimme valita vaikkapa seuraavan polun:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Polun valinnan jälkeen virtaus lisääntyy $x$ yksikköä, After choosing the path, the flow increases by $x$ units
jossa $x$ on pienin kaaren kapasiteetti polulla. where $x$ is the smallest weight of an edge in the path.
Samalla jokaisen polulla olevan kaaren kapasiteetti In addition, the weight of each edge in the path
vähenee $x$:llä ja jokaisen käänteisen kaaren kapasiteetti kasvaa $x$:llä. decreases by $x$, and the weight of each reverse edge
increases by $x$.
Yllä valitussa polussa In the above path, the weights of the
kaarten kapasiteetit ovat 5, 6, 8 ja 2. edges are 5, 6, 8 and 2.
Pienin kapasiteetti on 2, The minimum weight is 2,
joten virtaus kasvaa 2:lla so the flow increases by 2
ja verkko muuttuu seuraavasti: and the new graph is as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -289,17 +288,17 @@ ja verkko muuttuu seuraavasti:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Muutoksessa on ideana, että virtauksen lisääminen The idea is that increasing the flow decreases the amount of
vähentää polkuun kuuluvien kaarten kykyä välittää virtausta. flow that can go through the edges in the future.
Toisaalta virtausta on mahdollista peruuttaa myöhemmin On the other hand, it is possible to adjust the
käyttämällä käänteisiä kaaria, jos osoittautuu, että amount of the flow later
virtausta on järkevää reitittää verkossa toisella tavalla. using the reverse edges if it turns out that
we should route the flow in another way.
Algoritmi kasvattaa virtausta The algorithm increases the flow as long as
niin kauan, kuin verkossa on olemassa polku there is a path from the starting node
alkusolmusta loppusolmuun positiivisia kaaria pitkin. to the ending node through positive edges.
Tässä tapauksessa In the current example, our next path can be as follows:
voimme valita seuraavan polun vaikkapa näin:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -334,12 +333,13 @@ voimme valita seuraavan polun vaikkapa näin:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Tämän polun pienin kapasiteetti on 3, The minimum weight in this path is 3,
joten polku kasvattaa virtausta 3:lla so the path increases the flow by 3,
ja kokonaisvirtaus polun käsittelyn jälkeen on 5. and the total amount of the flow after
processing the path is 5.
\begin{samepage} \begin{samepage}
Nyt verkko muuttuu seuraavasti: The new graph will be as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -370,11 +370,12 @@ Nyt verkko muuttuu seuraavasti:
\end{center} \end{center}
\end{samepage} \end{samepage}
Maksimivirtaus tulee valmiiksi We still need two more steps before we have reached a maximum flow.
lisäämällä virtausta vielä polkujen $1 \rightarrow 2 \rightarrow 3 \rightarrow 6$ ja For example, we can choose the paths
$1 \rightarrow 4 \rightarrow 5 \rightarrow 3 \rightarrow 6$ avulla. $1 \rightarrow 2 \rightarrow 3 \rightarrow 6$ and
Molemmat polut tuottavat 1 yksikön lisää virtausta, $1 \rightarrow 4 \rightarrow 5 \rightarrow 3 \rightarrow 6$.
ja lopullinen verkko on seuraava: Both paths increase the flow by 1,
and the final graph is as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -404,68 +405,69 @@ ja lopullinen verkko on seuraava:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Nyt virtausta ei pysty enää kasvattamaan, It's not possible to increase the flow anymore,
koska verkossa ei ole mitään polkua because there is no path from the starting node
alkusolmusta loppusolmuun, to the ending node with positive edge weights.
jossa jokaisen kaaren paino olisi positiivinen. Thus, the algorithm terminates and the maximum flow is 7.
Niinpä algoritmi pysähtyy ja verkon maksimivirtaus on 7.
\subsubsection{Polun valinta} \subsubsection{Finding paths}
FordFulkersonin algoritmi ei ota kantaa siihen, The FordFulkerson algorithm doesn't specify
millä tavoin virtausta kasvattava polku valitaan verkossa. how the path that increases the flow should be chosen.
Valintatavasta riippumatta algoritmi pysähtyy In any case, the algorithm will stop sooner or later
ja tuottaa maksimivirtauksen ennemmin tai myöhemmin, and produce a maximum flow.
mutta polun valinnalla on vaikutusta algoritmin tehokkuuteen. However, the efficiency of the algorithm depends on
the way the paths are chosen.
Yksinkertainen tapa on valita virtausta kasvattava A simple way to find paths is to use depth-first search.
polku syvyyshaulla. Usually, this works well, but the worst case is that
Tämä toimii usein hyvin, mutta pahin tapaus on, each path only increases the flow by 1, and the algorithm becomes slow.
että jokainen polku Fortunately, we can avoid this by using one of the following
kasvattaa virtausta vain 1:llä ja algoritmi toimii hitaasti. algorithms:
Onneksi tämän ilmiön pystyy estämään käyttämällä
jompaakumpaa seuraavaa algoritmia:
\index{EdmondsKarpin algoritmi} \index{EdmondsKarp algorithm}
\key{EdmondsKarpin algoritmi} on The \key{EdmondsKarp algorithm}
FordFulkersonin algoritmin toteutus, is an implementation of the
jossa virtausta kasvattava polku valitaan FordFulkerson algorithm where
aina niin, että siinä on mahdollisimman vähän kaaria. each path that increases the flow
Tämä onnistuu etsimällä polku syvyyshaun is chosen so that the number of edges
sijasta leveyshaulla. in the path is minimum.
Osoittautuu, että tämä varmistaa virtauksen This can be done by using breadth-first search
kasvamisen nopeasti ja instead of depth-first search.
maksimivirtauksen etsiminen vie aikaa $O(m^2 n)$. It turns out that this guarantees that
flow increases quickly, and the time complexity
of the algorithm is $O(m^2 n)$.
\index{skaalaava algoritmi@skaalaava algoritmi} \index{scaling algorithm}
\key{Skaalaava algoritmi} The \key{scaling algorithm} uses depth-first
asettaa minimiarvon, joka on ensin alkusolmusta search to find paths where the weight of each edge is
lähtevien kaarten kapasiteettien summa $c$. at least a minimum value.
Joka vaiheessa verkosta etsitään Initially, the minimum value is $c$,
syvyyshaulla polku, jonka jokaisen kaaren kapasiteetti the sum of capacities of the edges that
on vähintään minimiarvo. begin at the starting edge.
Aina jos kelvollista polkua ei löydy, If the algorithm can't find a path,
minimiarvo jaetaan 2:lla, the minimum value is divided by 2,
kunnes lopuksi minimiarvo on 1. and finally it will be 1.
Algoritmin aikavaativuus on $O(m^2 \log c)$. The time complexity of the algorithm is $O(m^2 \log c)$.
Käytännössä skaalaava algoritmi on mukavampi koodattava, In practice, the scaling algorithm is easier to code
koska siinä riittää etsiä polku syvyyshaulla. because we can use depth-first search to find paths.
Molemmat algoritmit ovat yleensä aina riittävän Both algorithms are efficient enough for problems
nopeita ohjelmointikisoissa esiintyviin tehtäviin. that typically appear in programming contests.
\subsubsection{Minimileikkaus} \subsubsection{Minimum cut}
\index{minimileikkaus@minimileikkaus} \index{minimum cut}
Osoittautuu, että kun FordFulkersonin algoritmi on saanut valmiiksi It turns out that once the FordFulkerson algorithm
maksimivirtauksen, se on tuottanut samalla minimileikkauksen. has found a maximum flow,
Olkoon $A$ niiden solmujen joukko, it has also produced a minimum cut.
joihin verkossa pääsee Let $A$ be the set of nodes
alkusolmusta positiivisia kaaria pitkin. that can be reached from the starting node
Esimerkkiverkossa $A$ sisältää solmut 1, 2 ja 4: using positive edges.
In the example graph, $A$ contains nodes 1, 2 and 4:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9,label distance=-2mm] \begin{tikzpicture}[scale=0.9,label distance=-2mm]
@ -495,25 +497,26 @@ Esimerkkiverkossa $A$ sisältää solmut 1, 2 ja 4:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Nyt minimileikkauksen muodostavat ne alkuperäisen verkon kaaret, Now the minimum cut consists of the edges in the original graph
jotka kulkevat joukosta $A$ joukon $A$ ulkopuolelle that begin at a node in $A$ and end at a node outside $A$,
ja joiden kapasiteetti on täysin käytetty and whose capacity is fully
maksimivirtauksessa. used in the maximum flow.
Tässä verkossa kyseiset kaaret ovat $2 \rightarrow 3$ In the above graph, such edges are
ja $4 \rightarrow 5$, jotka tuottavat minimileikkauksen $6+1=7$. $2 \rightarrow 3$ and $4 \rightarrow 5$,
that correspond to the minimum cut $6+1=7$.
Miksi sitten algoritmin tuottama virtaus ja leikkaus ovat Why is the flow produced by the algorithm maximum,
varmasti maksimivirtaus ja minimileikkaus? and why is the cut minimum?
Syynä tähän on, että verkossa ei voi olla virtausta, The reason for this is that a graph never
jonka suuruus ylittäisi yhdenkään contains a flow whose size is larger
verkossa olevan leikkauksen painoa. than the weight of any cut in the graph.
Niinpä kun verkossa oleva Hence, always when a flow and a cut are equally large,
virtaus ja leikkaus ovat yhtä suuret, they are a maximum flow and a minimum cut.
ne ovat varmasti maksimivirtaus ja minimileikkaus.
Tarkastellaan mitä tahansa verkon leikkausta, Let's consider any cut in the graph
jossa alkusolmu kuuluu osaan $A$, where the starting node belongs to set $A$,
loppusolmu kuuluu osaan $B$ ja osien välillä kulkee kaaria: the ending node belongs to set $B$
and there are edges between the sets:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -537,17 +540,19 @@ loppusolmu kuuluu osaan $B$ ja osien välillä kulkee kaaria:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Leikkauksen paino on niiden kaarten painojen summa, The weight of the cut is the sum of those edges
jotka kulkevat osasta $A$ osaan $B$. that go from set $A$ to set $B$.
Tämä on yläraja sille, kuinka suuri verkossa oleva virtaus voi olla, This is an upper bound for the amount of flow
koska virtauksen täytyy edetä osasta $A$ osaan $B$. in the graph, because the flow has to proceed
Niinpä maksimivirtaus on pienempi tai yhtä suuri kuin from set $A$ to set $B$.
mikä tahansa verkon leikkaus. Thus, a maximum flow is smaller than or equal to
any cut in the graph.
Toisaalta FordFulkersonin algoritmi tuottaa virtauksen, On the other hand, the FordFulkerson algorithm
joka on \emph{tarkalleen} yhtä suuri kuin verkossa oleva leikkaus. produces a flow that is \emph{exactly} as large
Niinpä tämän virtauksen on oltava maksimivirtaus ja as a cut in the graph.
vastaavasti leikkauksen on oltava minimileikkaus. Thus, the flow has to be a maximum flow,
and the cut has to be a minimum cut.
\section{Rinnakkaiset polut} \section{Rinnakkaiset polut}