Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
MaxFlowGoldbergTarjan.h
Go to the documentation of this file.
1
33#pragma once
34
35#include <ogdf/basic/Array.h>
36#include <ogdf/basic/Graph.h>
38#include <ogdf/basic/List.h>
39#include <ogdf/basic/basic.h>
41
42#include <algorithm>
43
44//#define OGDF_GT_USE_GAP_RELABEL_HEURISTIC
45#define OGDF_GT_USE_MAX_ACTIVE_LABEL
46//#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
47//#define OGDF_GT_GRH_STEPS 1 // gap relabel frequency: call gapRelabel() after OGDF_GT_GRH_STEPS relabel() operations (1 == off)
48//#endif
49#define OGDF_GT_USE_PUSH_RELABEL_SECOND_STAGE
50
51// world666 is much better without OGDF_GT_USE_PUSH_RELABEL_SECOND_STAGE
52
53namespace ogdf {
54
56
59template<typename TCap>
62 NodeArray<TCap> m_ex; // ex_f(v) values will be saved here to save runtime
63#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
64 NodeArray<ListIterator<node>> m_activeLabelListPosition; // holds the iterator of every active node in the corresp. list of m_labeList
65 Array<List<node>> m_activeLabelList; // array indexed by label, contains list of active nodes with that label
66 int m_maxLabel = 0; // the maximum label among all active nodes
67#endif
68#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
69 NodeArray<ListIterator<node>> m_labelListPosition; // holds the iterator of every node in the corresp. list of m_labeList
70 Array<List<node>> m_labelList; // array indexed by label, contains list of nodes with that label
71#endif
72
75
76 inline TCap getCap(const edge e) const {
77 return e->target() == *this->m_s ? 0 : (*this->m_cap)[e];
78 }
79
80 inline bool isResidualEdge(const adjEntry adj) const {
81 const edge e = adj->theEdge();
82 if (adj->theNode() == e->source()) {
83 return this->m_et->less((*this->m_flow)[e], getCap(e));
84 }
85 return this->m_et->greater((*this->m_flow)[e], (TCap)0);
86 }
87
88 inline bool isAdmissible(const adjEntry adj) const {
89 OGDF_ASSERT(adj);
90 return isResidualEdge(adj) && m_label[adj->theNode()] == m_label[adj->twinNode()] + 1;
91 }
92
93 inline bool isActive(const node v) const {
94 OGDF_ASSERT((v != *this->m_s && v != *this->m_t)
95 || (m_label[*this->m_s] == this->m_G->numberOfNodes() && m_label[*this->m_t] == 0));
96 return this->m_et->greater(m_ex[v], (TCap)0) && this->m_G->numberOfNodes() > m_label[v]
97 && m_label[v] > 0;
98 }
99
100#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
101 inline void setActive(const node v) {
102 const int label = m_label[v];
103 OGDF_ASSERT(0 < label);
104 OGDF_ASSERT(label < this->m_G->numberOfNodes());
106 m_activeLabelListPosition[v] = m_activeLabelList[label].pushBack(v);
107 if (label > m_maxLabel) {
108 m_maxLabel = label;
109 }
110 }
111
112 inline void findNewMaxLabel() {
113 while (m_maxLabel > 0 && m_activeLabelList[m_maxLabel].empty()) {
114 --m_maxLabel;
115 }
116 }
117
118 inline void setInactive(const node v) {
121 m_activeLabelListPosition[v] = nullptr;
123 }
124#endif
125
126 // sets label of v, maintaining m_labelList (moves node v to the correct list in the array)
127 inline void setLabel(const node v, int label) {
128#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
129 if (m_labelListPosition[v].valid()) {
130 m_labelList[m_label[v]].del(
131 m_labelListPosition[v]); // delete node from old list using noted position
132 }
133 m_labelListPosition[v] =
134 m_labelList[label].pushBack(v); // push node to new list and update iterator
135#endif
136#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
137 if (m_activeLabelListPosition[v].valid()) {
138 OGDF_ASSERT(0 < m_label[v]);
139 OGDF_ASSERT(m_label[v] < this->m_G->numberOfNodes());
140 setInactive(v);
141 }
142 m_label[v] = label; // update label
143 if (v != *this->m_s && v != *this->m_t && isActive(v)) {
144 setActive(v);
145 }
146#else
147 m_label[v] = label; // update label
148#endif
149 }
150
151#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
152 void gapRelabel() {
153# ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
154 // XXX: this is a test but it seems to work and it seems to be fast!
155 const int n = m_maxLabel + 1;
156# else
157 const int n = this->m_G->numberOfNodes();
158# endif
159 for (int i = 1; i < n - 1; ++i) {
160 if (m_labelList[i].empty()) {
161 for (int j = i + 1; j < n; ++j) {
162 while (!m_labelList[j].empty()) {
163 setLabel(m_labelList[j].front(), this->m_G->numberOfNodes());
164 }
165 }
166 break;
167 }
168 }
169 }
170#endif
171
172 void push(const adjEntry adj) {
173 const edge e = adj->theEdge();
174 const node v = adj->theNode();
175 if (v == e->source()) {
176 const TCap value = min(m_ex[v], getCap(e) - (*this->m_flow)[e]);
177 OGDF_ASSERT(this->m_et->geq(value, (TCap)0));
178 (*this->m_flow)[e] += value;
179 m_ex[v] -= value;
180 m_ex[adj->twinNode()] += value;
181 } else {
182 const TCap value = min(m_ex[v], (*this->m_flow)[adj]);
183 OGDF_ASSERT(this->m_et->geq(value, (TCap)0));
184 (*this->m_flow)[adj] -= value;
185 m_ex[v] -= value;
186 m_ex[adj->twinNode()] += value;
187 }
188 }
189
191 // breadth-first search to relabel nodes with their respective distance to the sink in the residual graph
192 const int n = this->m_G->numberOfNodes();
193 NodeArray<int> dist(*this->m_G, n); // distance array
194 List<node> queue; // reachable, not processed nodes
195 dist[*this->m_t] = 0;
196 queue.pushBack(*this->m_t);
197 while (!queue.empty()) { // is there a node to check?
198 node w = queue.popFrontRet();
199 for (adjEntry adj : w->adjEntries) {
200 node x = adj->twinNode();
201 if (isResidualEdge(adj->twin()) && dist[x] == n) { // not already seen
202 dist[x] = dist[w] + 1; // set distance of node to sink
203 queue.pushBack(x);
204 }
205 }
206 }
207 // set distance of unreachable nodes to "number of nodes" thus making them inactive
208 for (node w : this->m_G->nodes) {
209 setLabel(w, dist[w]);
210 }
211 }
212
213 void relabel(const node v) {
214 int minLabel = this->m_G->numberOfNodes() - 1;
215 for (adjEntry adj : v->adjEntries) {
216 if (isResidualEdge(adj)) {
217 const int label = m_label[adj->twinNode()];
218 if (label < minLabel) {
219 minLabel = label;
220 }
221 }
222 }
223 if (minLabel + 1 != m_label[v]) { // == can happen after global relabel
224 setLabel(v, minLabel + 1);
225 }
226 }
227
228 void relabelStage2(const node v) {
229 int minLabel = this->m_G->numberOfNodes() - 1;
230 for (adjEntry adj : v->adjEntries) {
231 if (isResidualEdge(adj)) {
232 const int label = m_label[adj->twinNode()];
233 if (label < minLabel) {
234 minLabel = label;
235 }
236 }
237 }
238 OGDF_ASSERT(minLabel + 1 != m_label[v]);
239 m_label[v] = minLabel + 1;
240 }
241
242public:
243 // first stage: push excess towards sink
244 TCap computeValue(const EdgeArray<TCap>& cap, const node& s, const node& t) {
245 // TODO: init this stuff in the module?
246 this->m_s = &s;
247 this->m_t = &t;
248 this->m_cap = &cap;
249 this->m_flow->init(*this->m_G, (TCap)0);
251
252 m_label.init(*this->m_G);
253 m_ex.init(*this->m_G, 0);
254#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
255 m_activeLabelListPosition.init(*this->m_G, nullptr);
256 m_activeLabelList.init(1, this->m_G->numberOfNodes() - 1);
257 m_maxLabel = 0;
258#endif
259#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
260 m_labelListPosition.init(*this->m_G, nullptr);
261 m_labelList.init(this->m_G->numberOfNodes() + 1);
262#endif
263 m_cutNodes.clear();
264
265 // initialize residual graph for first preflow
266 for (edge e : this->m_G->edges) {
267 if (e->source() == *this->m_s && e->target() != *this->m_s) { // ignore loops
268 (*this->m_flow)[e] = getCap(e);
269 m_ex[e->target()] += getCap(e); // "+" needed for the case of multigraphs
270 }
271 }
272
273 if (*this->m_t == *this->m_s) {
274 return (TCap)0;
275 }
276
277 NodeArray<adjEntry> curr(*this->m_G);
278 for (node v = this->m_G->firstNode(); v; v = v->succ()) {
279 curr[v] = v->firstAdj();
280 }
281
282 globalRelabel(); // initialize distance labels
283
284 int relCount = 0; // counts the relabel operations for the global relabeling heuristic
285#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
286 while (m_maxLabel != 0) {
288 const node v = m_activeLabelList[m_maxLabel].front();
291#else
292 List<node> active;
293 for (adjEntry adj : (*this->m_s)->adjEntries) {
294 node w = adj->theEdge()->target();
295 if (w != *this->m_s) {
296 active.pushBack(w);
297 }
298 }
299 while (!active.empty()) {
300 const node v = active.front();
301#endif
302 adjEntry& adj = curr[v];
303 if (v == *this->m_s || v == *this->m_t || !isActive(v)) {
304 // source, sink or not active: remove activity status
305#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
306 setInactive(v);
307#else
308 active.popFront();
309#endif
310 } else {
311 while (this->m_et->greater(m_ex[v], (TCap)0)) {
312 if (isAdmissible(adj)) {
313 // push and adjacent node becomes active
314#ifdef OGDF_GT_USE_MAX_ACTIVE_LABEL
315 const node w = adj->twinNode();
316 if (w != *this->m_s && w != *this->m_t && !isActive(w)) {
317 // w will become active after push
318 setActive(w);
319 }
320 push(adj);
321 if (v != *this->m_s && !isActive(v)) {
322 setInactive(v);
323 }
324#else
325 push(adj);
326 active.pushBack(adj->twinNode());
327#endif
328 } else {
329 if (adj != v->lastAdj()) {
330 adj = adj->succ();
331 } else { // end of adjacency list
332 adj = v->firstAdj();
333 relabel(v);
334 ++relCount;
335#ifdef OGDF_GT_USE_GAP_RELABEL_HEURISTIC
336 // only gapRelabel if we do not do a globalRelabel directly afterwards
337 if (relCount != this->m_G->numberOfNodes()
338# if (OGDF_GT_GRH_STEPS > 1)
339 && relCount % OGDF_GT_GRH_STEPS
340 == 0 // obey frequency of gap relabel heuristic
341# endif
342 ) {
343 gapRelabel();
344 }
345#endif
346 break;
347 }
348 }
349 }
350 if (relCount == this->m_G->numberOfNodes()) {
351 relCount = 0;
353 }
354 }
355 }
356
357 TCap result = 0;
358 for (adjEntry adj : (*this->m_t)->adjEntries) {
359 edge e = adj->theEdge();
360 if (e->target() == *this->m_t) {
361 result += (*this->m_flow)[e];
362 } else {
363 result -= (*this->m_flow)[e];
364 }
365 }
366 return result;
367 }
368
369 // second stage: push excess that has not reached the sink back towards source
371 List<node> active;
372#ifdef OGDF_GT_USE_PUSH_RELABEL_SECOND_STAGE
373 NodeArray<adjEntry> curr(*this->m_G);
374 for (node v = this->m_G->firstNode(); v; v = v->succ()) {
375 curr[v] = v->firstAdj();
376 m_label[v] = 1;
377 if (this->m_et->greater(m_ex[v], (TCap)0) && v != *this->m_s && v != *this->m_t) {
378 active.pushBack(v);
379 }
380 }
381 if (active.empty()) {
382 return;
383 }
384
385 m_label[*this->m_s] = 0;
386 while (!active.empty()) {
387 node v = active.front();
388 if (v == *this->m_s || v == *this->m_t || !isActive(v)) {
389 active.popFront();
390 } else {
391 adjEntry& adj = curr[v];
392 if (isAdmissible(adj)) {
393 push(adj);
394 active.pushBack(adj->twinNode());
395 } else {
396 if (adj == v->lastAdj()) {
397 // no admissible outgoing edge found -> relabel node!
398 relabelStage2(v);
399 adj = v->firstAdj();
400# if 0
401 // node is still active but move it to the end of the queue
402 // (don't know if this is really necessary)
403 active.popFront();
404 active.pushBack(v);
405# endif
406 } else {
407 adj = adj->succ();
408 }
409 }
410 }
411 }
412#else // USE_PUSH_RELABEL_SECOND_STAGE
413 m_ex[*this->m_s] = m_ex[*this->m_t] = 0;
414 for (node v = this->m_G->firstNode(); v; v = v->succ()) {
415 if (this->m_et->greater(m_ex[v], (TCap)0)) {
416 active.pushBack(v);
417 }
418 }
419 while (!active.empty()) {
420 const node v = active.popFrontRet();
421 if (this->m_et->greater(m_ex[v], (TCap)0) && v != *this->m_s && v != *this->m_t) {
422 for (adjEntry adj = v->firstAdj(); adj; adj = adj->succ()) {
423 const edge e = adj->theEdge();
424 const node u = e->source();
425 if (u != v) { // e is incoming edge
426 if (this->m_et->greater(m_ex[v], (TCap)0) && isResidualEdge(adj)) {
427 push(adj);
428 if (u != *this->m_s) {
429 active.pushFront(u);
430 }
431 }
432 }
433 }
434 }
435 }
436#endif // USE_PUSH_RELABEL_SECOND_STAGE
437 }
438
440 using MaxFlowModule<TCap>::init;
441 using MaxFlowModule<TCap>::computeFlow;
444};
445
446}
Declaration and implementation of Array class and Array algorithms.
Includes declaration of graph class.
Decralation of GraphElement and GraphList classes.
Declaration of doubly linked lists and iterators.
Interface for Max Flow Algorithms.
Basic declarations, included by all source files.
Class for adjacency list elements.
Definition Graph_d.h:143
adjEntry succ() const
Returns the successor in the adjacency list.
Definition Graph_d.h:219
edge theEdge() const
Returns the edge associated with this adjacency entry.
Definition Graph_d.h:161
node twinNode() const
Returns the associated node of the corresponding adjacency entry (shorthand for twin()->theNode()).
Definition Graph_d.h:176
node theNode() const
Returns the node whose adjacency list contains this element.
Definition Graph_d.h:167
The parameterized class Array implements dynamic arrays of type E.
Definition Array.h:219
void init()
Reinitializes the array to an array with empty index set.
Definition Array.h:372
Class for the representation of edges.
Definition Graph_d.h:364
node target() const
Returns the target node of the edge.
Definition Graph_d.h:402
node source() const
Returns the source node of the edge.
Definition Graph_d.h:399
std::enable_if< std::is_integral< T >::value, bool >::type geq(const T &x, const T &y) const
Compare if x is GEQ to y for integral types.
std::enable_if< std::is_integral< T >::value, bool >::type less(const T &x, const T &y) const
Compare if x is LESS than y for integral types.
Definition EpsilonTest.h:55
std::enable_if< std::is_integral< T >::value, bool >::type greater(const T &x, const T &y) const
Compare if x is GREATER than y for integral types.
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition Graph_d.h:979
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition Graph_d.h:929
node firstNode() const
Returns the first node in the list of all nodes.
Definition Graph_d.h:994
internal::GraphObjectContainer< EdgeElement > edges
The container containing all edge objects.
Definition Graph_d.h:932
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
void popFront()
Removes the first element from the list.
Definition List.h:1585
void clear()
Removes all elements from the list.
Definition List.h:1626
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition List.h:1547
iterator pushFront(const E &x)
Adds element x at the beginning of the list.
Definition List.h:1534
E popFrontRet()
Removes the first element from the list and returns it.
Definition List.h:1591
const_reference front() const
Returns a const reference to the first element.
Definition List.h:305
bool empty() const
Returns true iff the list is empty.
Definition List.h:286
Computes a max flow via Preflow-Push (global relabeling and gap relabeling heuristic).
Array< List< node > > m_activeLabelList
bool isActive(const node v) const
void push(const adjEntry adj)
void setLabel(const node v, int label)
bool isAdmissible(const adjEntry adj) const
TCap computeValue(const EdgeArray< TCap > &cap, const node &s, const node &t)
Compute only the value of the flow.
NodeArray< ListIterator< node > > m_activeLabelListPosition
bool isResidualEdge(const adjEntry adj) const
TCap getCap(const edge e) const
void computeFlowAfterValue()
Compute the flow itself after the flow value is already computed. Only used in algorithms with 2 phas...
const node * m_t
Pointer to the sink node.
virtual void init(const Graph &graph, EdgeArray< TCap > *flow=nullptr)
Initialize the problem with a graph and optional flow array. If no flow array is given,...
EdgeArray< TCap > * m_flow
Pointer to (extern) flow array.
void useEpsilonTest(const double &eps)
Change the used EpsilonTest from StandardEpsilonTest to a user given EpsilonTest.
bool isFeasibleInstance() const
Return whether the instance is feasible, i.e. the capacities are non-negative.
const Graph * m_G
Pointer to the given graph.
const node * m_s
Pointer to the source node.
const EdgeArray< TCap > * m_cap
Pointer to the given capacity array.
MaxFlowModule()
Empty Constructor.
TCap computeFlow(EdgeArray< TCap > &cap, node &s, node &t, EdgeArray< TCap > &flow)
Only a shortcut for computeValue and computeFlowAfterValue.
EpsilonTest * m_et
Pointer to the used EpsilonTest.
Class for the representation of nodes.
Definition Graph_d.h:241
internal::GraphObjectContainer< AdjElement > adjEntries
The container containing all entries in the adjacency list of this node.
Definition Graph_d.h:272
adjEntry firstAdj() const
Returns the first entry in the adjaceny list.
Definition Graph_d.h:287
adjEntry lastAdj() const
Returns the last entry in the adjacency list.
Definition Graph_d.h:290
void init(const Base *base=nullptr)
Reinitializes the array. Associates the array with the matching registry of base.
RegisteredArray for edges of a graph, specialized for EdgeArray<edge>.
Definition Graph_d.h:717
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)