Content deleted Content added
m →Example: added link to interactiv example |
{{MOS|article|date=July 2025| MOS:FORMULA - avoid mixing {{tag|math}} and {{tl|math}} in the same expression}} |
||
(84 intermediate revisions by 53 users not shown) | |||
Line 1:
{{Short description|Algorithm in mathematical optimization}}
In [[mathematical optimization]], the '''push–relabel algorithm''' (alternatively, '''preflow–push algorithm''') is an algorithm for computing [[maximum flow]]s. The name "push–relabel" comes from the two basic operations used in the algorithm. Throughout its execution, the algorithm maintains a "preflow" and gradually converts it into a maximum flow by moving flow locally between neighboring vertices using ''push'' operations under the guidance of an admissible network maintained by ''relabel'' operations. In comparison, the [[Ford–Fulkerson algorithm]] performs global augmentations that send flow following paths from the source all the way to the sink.<ref name="clrs26"/>▼
{{MOS|article|date=July 2025| [[MOS:FORMULA]] - avoid mixing {{tag|math}} and {{tl|math}} in the same expression}}
▲In [[mathematical optimization]], the '''push–relabel algorithm''' (alternatively, '''preflow–push algorithm''') is an algorithm for computing [[maximum flow]]s in a [[flow network]]. The name "push–relabel" comes from the two basic operations used in the algorithm. Throughout its execution, the algorithm maintains a "preflow" and gradually converts it into a maximum flow by moving flow locally between neighboring
The push–relabel algorithm is considered one of the most efficient maximum flow algorithms. The generic algorithm has a [[strongly polynomial]] {{
The push–relabel algorithm has been extended to compute [[minimum cost flow]]s.<ref name="goldberg97"/> The idea of distance labels has led to a more efficient augmenting path algorithm, which in turn can be incorporated back into the push–relabel algorithm to create a variant with even higher empirical performance.<ref name="goldberg08"/><ref name="ahuja91"/>
Line 7 ⟶ 9:
==History==
The concept of a preflow was originally designed by [[Alexander V. Karzanov]] and was published in 1974 in Soviet Mathematical Dokladi 15. This
The push-relabel algorithm was designed by [[Andrew V. Goldberg]] and [[Robert Tarjan]]. The algorithm was initially
==Concepts==
Line 16 ⟶ 18:
{{main|Flow network}}
Let:
*{{math|''G'' {{=}} (''V'', ''E'')}} be a ''network'' with ''capacity function'' {{math|''c'': ''V'' × ''V'' → <math>\mathbb{R}</math><sub>∞</sub>}},
*{{math|''F'' {{=}} (''G'', ''c'', ''s'', ''t'')}} a ''flow network'', where {{math|''s'' ∈ ''V''}} and {{math|''t'' ∈ ''V''}} are chosen ''source'' and ''sink'' vertices respectively,
*{{math|''f'' : ''V'' × ''V'' → <math>\mathbb{R}</math>}} denote a [[Flow network#Flows|''pre-flow'']] in {{mvar|F}},
*{{math|''x''<sub>''f''</sub> : ''V'' → <math>\mathbb{R}</math>}} denote the ''excess'' function with respect to the flow {{mvar|f}}, defined by {{math|''x''<sub>''f''</sub> (''u'') {{=}} Σ<sub>''v'' ∈ ''V''</sub> ''f'' (''v'', ''u'') − Σ<sub>''v'' ∈ ''V''</sub> ''f'' (''u'', ''v'')}},
*{{math|''c''<sub>''f''</sub> : ''V'' × ''V'' → <math>\mathbb{R}</math><sub>∞</sub>}} denote the ''residual capacity function'' with respect to the flow {{mvar|f}}, defined by {{math|''c''<sub>''f''</sub> (''e'') {{=}} ''c''(''e'') − ''f'' (''e'')}},
*{{math|''E''<sub>''f''</sub> ⊂ ''E''}} being the edges where {{math|''f'' < ''c''}},
and
*{{math|''G''<sub>''f''</sub> (''V'', ''E''<sub>''f'' </sub>)}} denote the [[Flow network#Residuals|''residual network'']] of {{mvar|G}} with respect to the flow {{mvar|f}}.
The push–relabel algorithm uses a nonnegative integer
:'''Valid labeling''':
::{{math|𝓁(''u'') ≤ 𝓁(''v'') + 1}} for all {{math|(''u'', ''v'') ∈ ''E''<sub>''f''</sub>}}
::{{math|𝓁(''s'') {{=}} {{!}} ''V'' {{!}}}}
::{{math|𝓁(''t'') {{=}} 0}}
In the algorithm, the
▲The push–relabel algorithm uses a nonnegative integer ''valid labeling'' function which makes use of ''distance labels'', or ''heights'', on vertices to determine which vertex pair should be selected for the push operation. This labeling function is denoted by <math>h(v), v \in V</math>. This function must satisfy the following conditions in order to be considered valid:
▲| '''Source condition''': || <math>h(s) = |V|</math>
▲| '''Sink conservation''': || <math>h(t) = 0</math>
An arc {{math|(''u'', ''v'') ∈ ''E''<sub>''f''</sub>}} is called '''admissible''' if {{math|𝓁(''u'') {{=}} 𝓁(''v'') + 1}}. The '''admissible network''' {{math|''G̃''<sub>''f''</sub> (''V'', ''Ẽ''<sub>''f''</sub> )}} is composed of the set of arcs {{math|''e'' ∈ ''E''<sub>''f''</sub>}} that are admissible. The admissible network is acyclic.
▲In the algorithm, the height values of ''s'' and ''t'' are fixed. <math>h(u)</math> is a lower bound of the unweighted distance from ''u'' to ''t'' in <math>G_f</math> if ''t'' is reachable from ''u''. If ''u'' has been disconnected from ''t'', then <math>h(u) - |V|</math> is a lower bound of the unweighted distance from ''u'' to ''s''. As a result, if a valid height function exists, there are no ''s''-''t'' paths in <math>G_f</math> because no such paths can be longer than <math>|V| - 1</math>.
For a fixed flow {{math|''f''}}, a vertex {{math|''v ∉ ''{''s, t''} }} is called '''active''' if it has positive excess with respect to {{math|''f''}}, i.e., {{math|''x''<sub>''f''</sub> (''u'') > 0}}.
===Operations===
Line 60 ⟶ 47:
====Initialization====
The algorithm starts by creating a residual graph, initializing the preflow values to zero and performing a set of saturating push operations on residual
====Push====
The push operation applies on an admissible out-
push(u, v):
assert
Δ = min(
f[u][v] += Δ
f[v][u] -= Δ
A push operation that causes {{
====Relabel====
The relabel operation applies on an active
relabel(u):
assert
====Effects of push and relabel====
After a push or relabel operation,
For a push operation on an admissible
To see that a relabel operation on
==The generic push–relabel algorithm==
The
▲The following algorithm is a generic version of the push–relabel algorithm. It is used as a proof of concept and does not contain implementation details on how to select an active vertex for the push and relabel operations. This generic version of the algorithm will terminate in {{nowrap|''O''(''V''<sup>2</sup>''E'')}}.
Since {{
generic-push-relabel(G
create a
'''let'''
'''let'''
'''while''' there is an applicable push or relabel operation '''do'''
execute the operation
===Correctness===
The algorithm maintains the condition that
If a preflow
Therefore, the algorithm will return the maximum flow upon termination.
===Time complexity===
In order to
In the algorithm, the relabel operation can be performed at most {{
Each saturating push on an admissible
Bounding the number of nonsaturating pushes can be achieved via a [[Potential method|potential argument]]. We use the potential function {{
The relabel operation can increase {{math|Φ}} by at most {{
In sum, the algorithm executes {{
▲The relabel operation can increase Φ by at most {{nowrap| (2{{!}}''V''{{!}} - 1)({{!}}''V''{{!}} - 2)}}. A saturating push on {{nowrap|(''u'', ''v'')}} activates ''v'' if it was inactive before the push, increasing Φ by at most {{nowrap| 2{{!}}''V''{{!}} - 1}}. Hence, the total contribution of all saturating pushes operations to Φ is at most {{nowrap| (2{{!}}''V''{{!}} - 1)(2{{!}}''V''{{!}}{{!}}''E''{{!}})}}. A nonsaturating push on {{nowrap|(''u'', ''v'')}} always deactivates ''u'', but it can also activate ''v'' as in a saturating push. As a result, it decreases Φ by at least {{nowrap|''h''(''u'') − ''h''(''v'') {{=}} 1}}. Since relabels and saturating pushes increase Φ, the total number of nonsaturating pushes must make up the difference of {{nowrap| (2{{!}}''V''{{!}} - 1)({{!}}''V''{{!}} - 2) + (2{{!}}''V''{{!}} - 1)(2{{!}}''V''{{!}}{{!}}''E''{{!}}) ≤ 4{{!}}''V''{{!}}<sup>2</sup>{{!}}''E''{{!}}}}. This results in a time bound of {{nowrap|''O''(''V''<sup>2</sup>''E'')}} for the nonsaturating push operations.
▲In sum, the algorithm executes {{nowrap|''O''(''V''<sup>2</sup>)}} relabels, {{nowrap|''O''(''VE'')}} saturating pushes and {{nowrap|''O''(''V''<sup>2</sup>''E'')}} nonsaturating pushes. Data structures can be designed to pick and execute an applicable operation in {{nowrap|''O''(1)}} time. Therefore, the time complexity of the algorithm is {{nowrap|''O''(''V''<sup>2</sup>''E'')}}. <ref name="clrs26"/><ref name="goldberg88"/>
===Example===
Line 139 ⟶ 124:
{{clear}}
In the example, the {{nowrap|''h''}} and {{nowrap|''e''}} values denote the
{{clear}}
Line 147 ⟶ 132:
! Algorithm Operation(s) !! Residual Graph
|-
|
|-
| Initial saturating push is performed across all preflow
|-
|rowspan="2"|
The excess at {{
|-
| [[File:Push-Relabel Algorithm Example - Step 3.svg|Step 3|350px]]
|-
|rowspan="2"| Once again, {{
The
|-
| [[File:Push-Relabel Algorithm Example - Step 4.svg|Step 4|350px]]
|-
| Relabel {{
|-
| Relabel {{
|-
| Relabel {{
|-
|rowspan="2"| This leaves the
Relabel {{
|-
| [[File:Push-Relabel Algorithm Example - Step 8.svg|Step 8|350px]]
|-
|rowspan="2"| Push the last bit of excess at {{
There are no remaining active
|-
| [[File:Push-Relabel Algorithm Example - Step 9.svg|Step 9|350px]]
|}
The example (but with
==Practical implementations==
While the generic push–relabel algorithm has {{
==="Current-
The "current-
Based on the "current-
discharge(u):
'''while'''
'''if''' current-
relabel(u)
rewind current-
'''else'''
'''let''' (u, v) = current-
'''if''' (u, v) is admissible '''then'''
push(u, v)
Finding the next admissible edge to push on has <math>O(1)</math> [[amortized complexity]]. The current-arc pointer only moves to the next neighbor when the edge to the current neighbor is saturated or non-admissible, and neither of these two properties can change until the active node <math>u</math> is relabelled. Therefore, when the pointer runs off, there are no admissible unsaturated edges and we have to relabel the active node <math>u</math>, so having moved the pointer <math>O(V)</math> times is paid for by the <math>O(V)</math> relabel operation.<ref name="goldberg88" />
▲ let current-edge[u] point to the next neighbor of u
===Active
Definition of the discharge operation reduces the push–relabel algorithm to repeatedly selecting an active node to discharge. Depending on the selection rule, the algorithm exhibits different time complexities. For the sake of brevity, we ignore
====FIFO selection rule====
The [[FIFO (computing and electronics)|FIFO]] push–relabel algorithm<ref name="goldberg86"/> organizes the active
The algorithm has {{
====Relabel-to-front selection rule====
The relabel-to-front push–relabel algorithm<ref name="clrs26"/> organizes all
The algorithm also has {{
====Highest label selection rule====
The highest-label push–relabel algorithm<ref name="cheriyan88"/> organizes all
The algorithm has {{
===Implementation techniques===
Although in the description of the generic push–relabel algorithm above, {{
The algorithm is typically separated into two phases. Phase one computes a maximum
Heuristics are crucial to improving the empirical performance of the algorithm.<ref name="cherkassky95"/> Two commonly used heuristics are the gap heuristic and the global relabeling heuristic.<ref name="goldberg86"/><ref name="derigs89"/> The gap heuristic detects gaps in the
==Sample implementations==
{{hidden begin|border=1px #aaa solid|titlestyle=text-align:center|title=[[C (programming language)|C]] implementation}}
<
#include <stdlib.h>
#include <stdio.h>
Line 258 ⟶ 243:
if (seen[u] < NODES) {
int v = seen[u];
if ((C[u][v] - F[u][v] > 0) && (height[u] > height[v])) {
push(C, F, excess, u, v);
} else {▼
seen[u] += 1;▼
}
▲ else
▲ seen[u] += 1;
} else {
relabel(C, F, height, u);
Line 273 ⟶ 258:
int temp = A[i];
int n;
for (n = i; n > 0; n--) {
A[n] = A[n-1];
}
Line 289 ⟶ 274:
for (i = 0, p = 0; i < NODES; i++){
if ((i != source) && (i != sink)) {
list[p] = i;
p++;
Line 306 ⟶ 291:
discharge(C, F, excess, height, seen, u);
if (height[u] > old_height) {
moveToFront(p, list);
p = 0;
} else {
else▼
p += 1;
}
int maxflow = 0;
Line 326 ⟶ 311:
void printMatrix(const int * const * M) {
int i, j;
for (i = 0; i < NODES; i++) {
for (j = 0; j < NODES; j++)
Line 343 ⟶ 328:
}
// Sample graph
capacities[0][1] = 2;
capacities[0][2] = 9;
Line 363 ⟶ 348:
return 0;
}
</syntaxhighlight>
{{hidden end}}
{{hidden begin|border=1px #aaa solid|titlestyle=text-align:center|title=[[Python (programming language)|Python]] implementation}}
<
</syntaxhighlight>
{{hidden end}}
== References ==
{{reflist|2|refs=
<ref name="clrs26">{{Cite book | isbn = 978-0262032933 | title = Introduction to Algorithms | edition = 2nd | last1 = Cormen | first1 = T. H. | author-link1 = Thomas H. Cormen | year = 2001 | publisher = The MIT Press | last2 = Leiserson | first2 = C. E. | author-link2 = Charles E. Leiserson | last3 = Rivest | first3 = R. L. | author-link3 = Ron Rivest | last4 = Stein | first4 = C. | author-link4 = Clifford Stein | chapter = §26 Maximum flow | pages = [https://archive.org/details/introductiontoal00corm_691/page/n665 643]–698| title-link = Introduction to Algorithms }}</ref>
<ref name="goldberg86">{{cite book|doi=10.1145/12130.12144|chapter=A new approach to the maximum flow problem|title=Proceedings of the eighteenth annual ACM symposium on Theory of computing
<ref name="goldberg88">{{cite journal|doi=10.1145/48014.61051|title=A new approach to the maximum-flow problem|journal=Journal of the ACM|volume=35|issue=4|pages=921|year=1988|last1=Goldberg|first1=Andrew V.|last2=Tarjan|first2=Robert E.|s2cid=52152408|doi-access=free}}</ref>
<ref name="sv82">{{cite journal|doi=10.1016/0196-6774(82)90013-X|title=An O(n2log n) parallel max-flow algorithm|journal=Journal of Algorithms|volume=3|issue=2|pages=128–146|year=1982|last1=Shiloach|first1=Yossi|last2=Vishkin|first2=Uzi}}</ref>
<ref name="cheriyan88">{{cite book|doi=10.1007/3-540-50517-2_69|chapter=Analysis of preflow push algorithms for maximum network flow|title=Foundations of Software Technology and Theoretical Computer Science|volume=338|pages=30|series=Lecture Notes in Computer Science|year=1988|last1=Cheriyan|first1=J.|last2=Maheshwari|first2=S. N.|isbn=978-3-540-50517-4}}</ref>
<ref name="derigs89">{{cite journal|doi=10.1007/BF01415937|title=Implementing Goldberg's max-flow-algorithm ? A computational investigation|journal=
<ref name="ahuja91">{{cite journal|doi=10.1002/1520-6750(199106)38:3<413::AID-NAV3220380310>3.0.CO;2-J|title=Distance-directed augmenting path algorithms for maximum flow and parametric maximum flow problems|journal=Naval Research Logistics|volume=38|issue=3|pages=413|year=1991|last1=Ahuja|first1=Ravindra K.|last2=Orlin|first2=James B.|citeseerx=10.1.1.297.5698}}</ref>
<ref name="amo93">{{Cite book | isbn = 978-0136175490 | title = Network Flows: Theory, Algorithms, and Applications | edition = 1st | last1 = Ahuja | first1 = R. K. | year = 1993 | publisher = Prentice Hall | last2 = Magnanti | first2 = T. L. | last3 = Orlin | first3 = J. B. }}</ref>
<ref name="cherkassky95">{{cite book|doi=10.1007/3-540-59408-6_49|chapter=On implementing push-relabel method for the maximum flow problem|title=Integer Programming and Combinatorial Optimization|volume=920|pages=157|series=Lecture Notes in Computer Science|year=1995|last1=Cherkassky|first1=Boris V.|last2=Goldberg|first2=Andrew V.|isbn=978-3-540-59408-6|citeseerx=10.1.1.150.3609}}</ref>
<ref name="ahuja97">{{cite journal|doi=10.1016/S0377-2217(96)00269-X|title=Computational investigations of maximum flow algorithms|journal=European Journal of Operational Research|volume=97|issue=3|pages=509|year=1997|last1=Ahuja|first1=Ravindra K.|last2=Kodialam|first2=Murali|last3=Mishra|first3=Ajay K.|last4=Orlin|first4=James B.|citeseerx=10.1.1.297.2945}}</ref>
<ref name="goldberg97">{{cite journal|doi=10.1006/jagm.1995.0805|title=An Efficient Implementation of a Scaling Minimum-Cost Flow Algorithm|journal=Journal of Algorithms|volume=22|pages=
<ref name="goldberg08">{{cite book|doi=10.1007/978-3-540-87744-8_39|chapter=The Partial Augment–Relabel Algorithm for the Maximum Flow Problem|title=Algorithms
<ref name="goldberg2014">{{cite journal|doi=10.1145/2628036|title=Efficient maximum flow algorithms|journal=Communications of the ACM|volume=57|issue=8|pages=82|year=2014|last1=Goldberg|first1=Andrew V.|last2=Tarjan|first2=Robert E.|s2cid=17014879}}</ref>
}}
{{optimization algorithms|combinatorial|state=expanded}}
[[Category:Network flow problem]]
[[Category:Graph algorithms]]
[[Category:Articles with example C code]]
[[Category:Articles with example Python (programming language) code]]
|