Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
max_flow.h
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// An implementation of a push-relabel algorithm for the max flow problem.
15//
16// In the following, we consider a graph G = (V,E,s,t) where V denotes the set
17// of nodes (vertices) in the graph, E denotes the set of arcs (edges). s and t
18// denote distinguished nodes in G called source and target. n = |V| denotes the
19// number of nodes in the graph, and m = |E| denotes the number of arcs in the
20// graph.
21//
22// Each arc (v,w) is associated a capacity c(v,w).
23//
24// A flow is a function from E to R such that:
25//
26// a) f(v,w) <= c(v,w) for all (v,w) in E (capacity constraint.)
27//
28// b) f(v,w) = -f(w,v) for all (v,w) in E (flow antisymmetry constraint.)
29//
30// c) sum on v f(v,w) = 0 (flow conservation.)
31//
32// The goal of this algorithm is to find the maximum flow from s to t, i.e.
33// for example to maximize sum v f(s,v).
34//
35// The starting reference for this class of algorithms is:
36// A.V. Goldberg and R.E. Tarjan. A new approach to the maximum flow problem.
37// ACM Symposium on Theory of Computing, pp. 136-146.
38// http://portal.acm.org/citation.cfm?id=12144.
39//
40// The basic idea of the algorithm is to handle preflows instead of flows,
41// and to refine preflows until a maximum flow is obtained.
42// A preflow is like a flow, except that the inflow can be larger than the
43// outflow. If it is the case at a given node v, it is said that there is an
44// excess at node v, and inflow = outflow + excess.
45//
46// More formally, a preflow is a function f such that:
47//
48// 1) f(v,w) <= c(v,w) for all (v,w) in E (capacity constraint). c(v,w) is a
49// value representing the maximum capacity for arc (v,w).
50//
51// 2) f(v,w) = -f(w,v) for all (v,w) in E (flow antisymmetry constraint)
52//
53// 3) excess(v) = sum on u f(u,v) >= 0 is the excess at node v, the
54// algebraic sum of all the incoming preflows at this node.
55//
56// Each node has an associated "height", in addition to its excess. The
57// height of the source is defined to be equal to n, and cannot change. The
58// height of the target is defined to be zero, and cannot change either. The
59// height of all the other nodes is initialized at zero and is updated during
60// the algorithm (see below). For those who want to know the details, the height
61// of a node, corresponds to a reduced cost, and this enables one to prove that
62// the algorithm actually computes the max flow. Note that the height of a node
63// can be initialized to the distance to the target node in terms of number of
64// nodes. This has not been tried in this implementation.
65//
66// A node v is said to be *active* if excess(v) > 0.
67//
68// In this case the following operations can be applied to it:
69//
70// - if there are *admissible* incident arcs, i.e. arcs which are not saturated,
71// and whose head's height is lower than the height of the active node
72// considered, a PushFlow operation can be applied. It consists in sending as
73// much flow as both the excess at the node and the capacity of the arc
74// permit.
75// - if there are no admissible arcs, the active node considered is relabeled,
76// i.e. its height is increased to 1 + the minimum height of its neighboring
77// nodes on admissible arcs.
78// This is implemented in Discharge, which itself calls PushFlow and Relabel.
79//
80// Before running Discharge, it is necessary to initialize the algorithm with a
81// preflow. This is done in InitializePreflow, which saturates all the arcs
82// leaving the source node, and sets the excess at the heads of those arcs
83// accordingly.
84//
85// The algorithm terminates when there are no remaining active nodes, i.e. all
86// the excesses at all nodes are equal to zero. In this case, a maximum flow is
87// obtained.
88//
89// The complexity of this algorithm depends amongst other things on the choice
90// of the next active node. It has been shown, for example in:
91// L. Tuncel, "On the Complexity of Preflow-Push Algorithms for Maximum-Flow
92// Problems", Algorithmica 11(4): 353-359 (1994).
93// and
94// J. Cheriyan and K. Mehlhorn, "An analysis of the highest-level selection rule
95// in the preflow-push max-flow algorithm", Information processing letters,
96// 69(5):239-242 (1999).
97// http://www.math.uwaterloo.ca/~jcheriya/PS_files/me3.0.ps
98//
99// ...that choosing the active node with the highest level yields a
100// complexity of O(n^2 * sqrt(m)).
101//
102// TODO(user): implement the above active node choice rule.
103//
104// This has been validated experimentally in:
105// R.K. Ahuja, M. Kodialam, A.K. Mishra, and J.B. Orlin, "Computational
106// Investigations of Maximum Flow Algorithms", EJOR 97:509-542(1997).
107// http://jorlin.scripts.mit.edu/docs/publications/58-comput%20investigations%20of.pdf.
108//
109//
110// TODO(user): an alternative would be to evaluate:
111// A.V. Goldberg, "The Partial Augment-Relabel Algorithm for the Maximum Flow
112// Problem.” In Proceedings of Algorithms ESA, LNCS 5193:466-477, Springer 2008.
113// http://www.springerlink.com/index/5535k2j1mt646338.pdf
114//
115// An interesting general reference on network flows is:
116// R. K. Ahuja, T. L. Magnanti, J. B. Orlin, "Network Flows: Theory, Algorithms,
117// and Applications," Prentice Hall, 1993, ISBN: 978-0136175490,
118// http://www.amazon.com/dp/013617549X
119//
120// Keywords: Push-relabel, max-flow, network, graph, Goldberg, Tarjan, Dinic,
121// Dinitz.
122
123#ifndef OR_TOOLS_GRAPH_MAX_FLOW_H_
124#define OR_TOOLS_GRAPH_MAX_FLOW_H_
125
126#include <memory>
127#include <string>
128#include <utility>
129#include <vector>
130
131#include "absl/strings/string_view.h"
132#include "ortools/base/logging.h"
134#include "ortools/graph/flow_problem.pb.h"
135#include "ortools/graph/graph.h"
136#include "ortools/util/stats.h"
137#include "ortools/util/zvector.h"
138
139namespace operations_research {
140
141// Forward declaration.
142template <typename Graph>
143class GenericMaxFlow;
144
145// A simple and efficient max-cost flow interface. This is as fast as
146// GenericMaxFlow<ReverseArcStaticGraph>, which is the fastest, but uses
147// more memory in order to hide the somewhat involved construction of the
148// static graph.
149//
150// TODO(user): If the need arises, extend this interface to support warm start.
152 public:
153 // The constructor takes no size.
154 // New node indices will be created lazily by AddArcWithCapacity().
156
157#ifndef SWIG
158 // This type is neither copyable nor movable.
159 SimpleMaxFlow(const SimpleMaxFlow&) = delete;
161#endif
162
163 // Adds a directed arc with the given capacity from tail to head.
164 // * Node indices and capacity must be non-negative (>= 0).
165 // * Self-looping and duplicate arcs are supported.
166 // * After the method finishes, NumArcs() == the returned ArcIndex + 1.
168 FlowQuantity capacity);
169
170 // Returns the current number of nodes. This is one more than the largest
171 // node index seen so far in AddArcWithCapacity().
172 NodeIndex NumNodes() const;
173
174 // Returns the current number of arcs in the graph.
175 ArcIndex NumArcs() const;
176
177 // Returns user-provided data.
178 // The implementation will crash if "arc" is not in [0, NumArcs()).
179 NodeIndex Tail(ArcIndex arc) const;
180 NodeIndex Head(ArcIndex arc) const;
182
183 // Solves the problem (finds the maximum flow from the given source to the
184 // given sink), and returns the problem status.
185 enum Status {
186 // Solve() was called and found an optimal solution. Note that OptimalFlow()
187 // may be 0 which means that the sink is not reachable from the source.
189 // There is a flow > std::numeric_limits<FlowQuantity>::max(). Note that in
190 // this case, the class will contain a solution with a flow reaching that
191 // bound.
192 //
193 // TODO(user): rename POSSIBLE_OVERFLOW to INT_OVERFLOW and modify our
194 // clients.
196 // The input is inconsistent (bad tail/head/capacity values).
198 // This should not happen. There was an error in our code (i.e. file a bug).
200 };
201 Status Solve(NodeIndex source, NodeIndex sink);
202
203 // Returns the maximum flow we can send from the source to the sink in the
204 // last OPTIMAL Solve() context.
206
207 // Returns the flow on the given arc in the last OPTIMAL Solve() context.
208 //
209 // Note: It is possible that there is more than one optimal solution. The
210 // algorithm is deterministic so it will always return the same solution for
211 // a given problem. However, there is no guarantee of this from one code
212 // version to the next (but the code does not change often).
214
215 // Returns the nodes reachable from the source by non-saturated arcs (.i.e.
216 // arc with Flow(arc) < Capacity(arc)), the outgoing arcs of this set form a
217 // minimum cut. This works only if Solve() returned OPTIMAL.
218 void GetSourceSideMinCut(std::vector<NodeIndex>* result);
219
220 // Returns the nodes that can reach the sink by non-saturated arcs, the
221 // outgoing arcs of this set form a minimum cut. Note that if this is the
222 // complement set of GetNodeReachableFromSource(), then the min-cut is unique.
223 // This works only if Solve() returned OPTIMAL.
224 void GetSinkSideMinCut(std::vector<NodeIndex>* result);
225
226 // Change the capacity of an arc.
227 //
228 // WARNING: This looks like it enables incremental solves, but as of 2018-02,
229 // the next Solve() will restart from scratch anyway.
230 // TODO(user): Support incrementality in the max flow implementation.
231 void SetArcCapacity(ArcIndex arc, FlowQuantity capacity);
232
233 // Creates the protocol buffer representation of the current problem.
234 FlowModelProto CreateFlowModelProto(NodeIndex source, NodeIndex sink) const;
235
236 private:
237 NodeIndex num_nodes_;
238 std::vector<NodeIndex> arc_tail_;
239 std::vector<NodeIndex> arc_head_;
240 std::vector<FlowQuantity> arc_capacity_;
241 std::vector<ArcIndex> arc_permutation_;
242 std::vector<FlowQuantity> arc_flow_;
243 FlowQuantity optimal_flow_;
244
245 // Note that we cannot free the graph before we stop using the max-flow
246 // instance that uses it.
247 typedef ::util::ReverseArcStaticGraph<NodeIndex, ArcIndex> Graph;
248 std::unique_ptr<Graph> underlying_graph_;
249 std::unique_ptr<GenericMaxFlow<Graph>> underlying_max_flow_;
250};
251
252// Specific but efficient priority queue implementation. The priority type must
253// be an integer. The queue allows to retrieve the element with highest priority
254// but only allows pushes with a priority greater or equal to the highest
255// priority in the queue minus one. All operations are in O(1) and the memory is
256// in O(num elements in the queue). Elements with the same priority are
257// retrieved with LIFO order.
258//
259// Note(user): As far as I know, this is an original idea and is the only code
260// that use this in the Maximum Flow context. Papers usually refer to an
261// height-indexed array of simple linked lists of active node with the same
262// height. Even worse, sometimes they use double-linked list to allow arbitrary
263// height update in order to detect missing height (used for the Gap heuristic).
264// But this can actually be implemented a lot more efficiently by just
265// maintaining the height distribution of all the node in the graph.
266template <typename Element, typename IntegerPriority>
268 public:
269 PriorityQueueWithRestrictedPush() : even_queue_(), odd_queue_() {}
270
271#ifndef SWIG
272 // This type is neither copyable nor movable.
274 delete;
276 const PriorityQueueWithRestrictedPush&) = delete;
277#endif
278
279 // Is the queue empty?
280 bool IsEmpty() const;
281
282 // Clears the queue.
283 void Clear();
284
285 // Push a new element in the queue. Its priority must be greater or equal to
286 // the highest priority present in the queue, minus one. This condition is
287 // DCHECKed, and violating it yields erroneous queue behavior in NDEBUG mode.
288 void Push(Element element, IntegerPriority priority);
289
290 // Returns the element with highest priority and remove it from the queue.
291 // IsEmpty() must be false, this condition is DCHECKed.
292 Element Pop();
293
294 private:
295 // Helper function to get the last element of a vector and pop it.
296 Element PopBack(std::vector<std::pair<Element, IntegerPriority>>* queue);
297
298 // This is the heart of the algorithm. basically we split the elements by
299 // parity of their priority and the precondition on the Push() ensures that
300 // both vectors are always sorted by increasing priority.
301 std::vector<std::pair<Element, IntegerPriority>> even_queue_;
302 std::vector<std::pair<Element, IntegerPriority>> odd_queue_;
303};
304
305// We want an enum for the Status of a max flow run, and we want this
306// enum to be scoped under GenericMaxFlow<>. Unfortunately, swig
307// doesn't handle templated enums very well, so we need a base,
308// untemplated class to hold it.
310 public:
311 enum Status {
312 NOT_SOLVED, // The problem was not solved, or its data were edited.
313 OPTIMAL, // Solve() was called and found an optimal solution.
314 INT_OVERFLOW, // There is a feasible flow > max possible flow.
315 BAD_INPUT, // The input is inconsistent.
316 BAD_RESULT // There was an error.
317 };
318};
319
320// Generic MaxFlow (there is a default MaxFlow specialization defined below)
321// that works with StarGraph and all the reverse arc graphs from graph.h, see
322// the end of max_flow.cc for the exact types this class is compiled for.
323template <typename Graph>
325 public:
326 typedef typename Graph::NodeIndex NodeIndex;
327 typedef typename Graph::ArcIndex ArcIndex;
333
334 // The height of a node never excess 2 times the number of node, so we
335 // use the same type as a Node index.
338
339 // Initialize a MaxFlow instance on the given graph. The graph does not need
340 // to be fully built yet, but its capacity reservation are used to initialize
341 // the memory of this class. source and sink must also be valid node of
342 // graph.
343 GenericMaxFlow(const Graph* graph, NodeIndex source, NodeIndex sink);
344
345#ifndef SWIG
346 // This type is neither copyable nor movable.
349#endif
350
351 virtual ~GenericMaxFlow() {}
352
353 // Returns the graph associated to the current object.
354 const Graph* graph() const { return graph_; }
355
356 // Returns the status of last call to Solve(). NOT_SOLVED is returned if
357 // Solve() has never been called or if the problem has been modified in such a
358 // way that the previous solution becomes invalid.
359 Status status() const { return status_; }
360
361 // Returns the index of the node corresponding to the source of the network.
363
364 // Returns the index of the node corresponding to the sink of the network.
365 NodeIndex GetSinkNodeIndex() const { return sink_; }
366
367 // Sets the capacity for arc to new_capacity.
368 void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity);
369
370 // Sets the flow for arc.
371 void SetArcFlow(ArcIndex arc, FlowQuantity new_flow);
372
373 // Returns true if a maximum flow was solved.
374 bool Solve();
375
376 // Returns the total flow found by the algorithm.
378
379 // Returns the flow on arc using the equations given in the comment on
380 // residual_arc_capacity_.
382 if (IsArcDirect(arc)) {
384 } else {
386 }
387 }
388
389 // Returns the capacity of arc using the equations given in the comment on
390 // residual_arc_capacity_.
392 if (IsArcDirect(arc)) {
395 } else {
396 return 0;
397 }
398 }
399
400 // Returns the nodes reachable from the source in the residual graph, the
401 // outgoing arcs of this set form a minimum cut.
402 void GetSourceSideMinCut(std::vector<NodeIndex>* result);
403
404 // Returns the nodes that can reach the sink in the residual graph, the
405 // outgoing arcs of this set form a minimum cut. Note that if this is the
406 // complement of GetNodeReachableFromSource(), then the min-cut is unique.
407 //
408 // TODO(user): In the two-phases algorithm, we can get this minimum cut
409 // without doing the second phase. Add an option for this if there is a need
410 // to, note that the second phase is pretty fast so the gain will be small.
411 void GetSinkSideMinCut(std::vector<NodeIndex>* result);
412
413 // Checks the consistency of the input, i.e. that capacities on the arcs are
414 // non-negative or null.
415 bool CheckInputConsistency() const;
416
417 // Checks whether the result is valid, i.e. that node excesses are all equal
418 // to zero (we have a flow) and that residual capacities are all non-negative
419 // or zero.
420 bool CheckResult() const;
421
422 // Returns true if there exists a path from the source to the sink with
423 // remaining capacity. This allows us to easily check at the end that the flow
424 // we computed is indeed optimal (provided that all the conditions tested by
425 // CheckResult() also hold).
426 bool AugmentingPathExists() const;
427
428 // Sets the different algorithm options. All default to true.
429 // See the corresponding variable declaration below for more details.
440
441 // Returns the protocol buffer representation of the current problem.
442 FlowModelProto CreateFlowModel();
443
444 protected:
445 // Returns true if arc is admissible.
447 return residual_arc_capacity_[arc] > 0 &&
449 }
450
451 // Returns true if node is active, i.e. if its excess is positive and it
452 // is neither the source or the sink of the graph.
453 bool IsActive(NodeIndex node) const {
454 return (node != source_) && (node != sink_) && (node_excess_[node] > 0);
455 }
456
457 // Sets the capacity of arc to 'capacity' and clears the flow on arc.
462
463 // Returns true if a precondition for Relabel is met, i.e. the outgoing arcs
464 // of node are all either saturated or the heights of their heads are greater
465 // or equal to the height of node.
466 bool CheckRelabelPrecondition(NodeIndex node) const;
467
468 // Returns context concatenated with information about arc
469 // in a human-friendly way.
470 std::string DebugString(absl::string_view context, ArcIndex arc) const;
471
472 // Initializes the container active_nodes_.
474
475 // Get the first element from the active node container.
478 const NodeIndex node = active_nodes_.back();
479 active_nodes_.pop_back();
480 return node;
481 }
482
483 // Push element to the active node container.
484 void PushActiveNode(const NodeIndex& node) {
487 } else {
488 active_nodes_.push_back(node);
489 }
490 }
491
492 // Check the emptiness of the container.
496 } else {
497 return active_nodes_.empty();
498 }
499 }
500
501 // Performs optimization step.
502 void Refine();
504
505 // Discharges an active node node by saturating its admissible adjacent arcs,
506 // if any, and by relabelling it when it becomes inactive.
507 void Discharge(NodeIndex node);
508
509 // Initializes the preflow to a state that enables to run Refine.
510 void InitializePreflow();
511
512 // Clears the flow excess at each node by pushing the flow back to the source:
513 // - Do a depth-first search from the source in the direct graph to cancel
514 // flow cycles.
515 // - Then, return flow excess along the depth-first search tree (by pushing
516 // the flow in the reverse dfs topological order).
517 // The theoretical complexity is O(mn), but it is a lot faster in practice.
519
520 // Computes the best possible node potential given the current flow using a
521 // reverse breadth-first search from the sink in the reverse residual graph.
522 // This is an implementation of the global update heuristic mentioned in many
523 // max-flow papers. See for instance: B.V. Cherkassky, A.V. Goldberg, "On
524 // implementing push-relabel methods for the maximum flow problem",
525 // Algorithmica, 19:390-410, 1997.
526 // ftp://reports.stanford.edu/pub/cstr/reports/cs/tr/94/1523/CS-TR-94-1523.pdf
527 void GlobalUpdate();
528
529 // Tries to saturate all the outgoing arcs from the source that can reach the
530 // sink. Most of the time, we can do that in one go, except when more flow
531 // than kMaxFlowQuantity can be pushed out of the source in which case we
532 // have to be careful. Returns true if some flow was pushed.
534
535 // Pushes flow on arc, i.e. consumes flow on residual_arc_capacity_[arc],
536 // and consumes -flow on residual_arc_capacity_[Opposite(arc)]. Updates
537 // node_excess_ at the tail and head of arc accordingly.
538 void PushFlow(FlowQuantity flow, ArcIndex arc);
539
540 // Relabels a node, i.e. increases its height by the minimum necessary amount.
541 // This version of Relabel is relaxed in a way such that if an admissible arc
542 // exists at the current node height, then the node is not relabeled. This
543 // enables us to deal with wrong values of first_admissible_arc_[node] when
544 // updating it is too costly.
545 void Relabel(NodeIndex node);
546
547 // Handy member functions to make the code more compact.
548 NodeIndex Head(ArcIndex arc) const { return graph_->Head(arc); }
549 NodeIndex Tail(ArcIndex arc) const { return graph_->Tail(arc); }
551 bool IsArcDirect(ArcIndex arc) const;
552 bool IsArcValid(ArcIndex arc) const;
553
554 // Returns the set of nodes reachable from start in the residual graph or in
555 // the reverse residual graph (if reverse is true).
556 template <bool reverse>
557 void ComputeReachableNodes(NodeIndex start, std::vector<NodeIndex>* result);
558
559 // Maximum manageable flow.
561
562 // A pointer to the graph passed as argument.
563 const Graph* graph_;
564
565 // An array representing the excess for each node in graph_.
567
568 // An array representing the height function for each node in graph_. For a
569 // given node, this is a lower bound on the shortest path length from this
570 // node to the sink in the residual network. The height of a node always goes
571 // up during the course of a Solve().
572 //
573 // Since initially we saturate all the outgoing arcs of the source, we can
574 // never reach the sink from the source in the residual graph. Initially we
575 // set the height of the source to n (the number of node of the graph) and it
576 // never changes. If a node as an height >= n, then this node can't reach the
577 // sink and its height minus n is a lower bound on the shortest path length
578 // from this node to the source in the residual graph.
580
581 // An array representing the residual_capacity for each arc in graph_.
582 // Residual capacities enable one to represent the capacity and flow for all
583 // arcs in the graph in the following manner.
584 // For all arc, residual_arc_capacity_[arc] = capacity[arc] - flow[arc]
585 // Moreover, for reverse arcs, capacity[arc] = 0 by definition,
586 // Also flow[Opposite(arc)] = -flow[arc] by definition.
587 // Therefore:
588 // - for a direct arc:
589 // flow[arc] = 0 - flow[Opposite(arc)]
590 // = capacity[Opposite(arc)] - flow[Opposite(arc)]
591 // = residual_arc_capacity_[Opposite(arc)]
592 // - for a reverse arc:
593 // flow[arc] = -residual_arc_capacity_[arc]
594 // Using these facts enables one to only maintain residual_arc_capacity_,
595 // instead of both capacity and flow, for each direct and indirect arc. This
596 // reduces the amount of memory for this information by a factor 2.
598
599 // An array representing the first admissible arc for each node in graph_.
601
602 // A stack used for managing active nodes in the algorithm.
603 // Note that the papers cited above recommend the use of a queue, but
604 // benchmarking so far has not proved it is better. In particular, processing
605 // nodes in LIFO order has better cache locality.
606 std::vector<NodeIndex> active_nodes_;
607
608 // A priority queue used for managing active nodes in the algorithm. It allows
609 // to select the active node with highest height before each Discharge().
610 // Moreover, since all pushes from this node will be to nodes with height
611 // greater or equal to the initial discharged node height minus one, the
612 // PriorityQueueWithRestrictedPush is a perfect fit.
614
615 // The index of the source node in graph_.
617
618 // The index of the sink node in graph_.
620
621 // The status of the problem.
623
624 // BFS queue used by the GlobalUpdate() function. We do not use a C++ queue
625 // because we need access to the vector for different optimizations.
626 std::vector<bool> node_in_bfs_queue_;
627 std::vector<NodeIndex> bfs_queue_;
628
629 // Whether or not to use GlobalUpdate().
631
632 // Whether or not we use a two-phase algorithm:
633 // 1/ Only deal with nodes that can reach the sink. At the end we know the
634 // value of the maximum flow and we have a min-cut.
635 // 2/ Call PushFlowExcessBackToSource() to obtain a max-flow. This is usually
636 // a lot faster than the first phase.
638
639 // Whether or not we use the PriorityQueueWithRestrictedPush to process the
640 // active nodes rather than a simple queue. This can only be true if
641 // use_global_update_ is true.
642 //
643 // Note(user): using a template will be slightly faster, but since we test
644 // this in a non-critical path, this only has a minor impact.
646
647 // Whether or not we check the input, this is a small price to pay for
648 // robustness. Disable only if you know the input is valid because an invalid
649 // input can cause the algorithm to run into an infinite loop!
651
652 // Whether or not we check the result.
653 // TODO(user): Make the check more exhaustive by checking the optimality?
655
656 // Statistics about this class.
658};
659
660#if !SWIG
661
662// Note: SWIG does not seem to understand explicit template specialization and
663// instantiation declarations.
664
665template <>
667template <>
668const FlowQuantity
670template <>
671const FlowQuantity
673template <>
674const FlowQuantity
676
677extern template class GenericMaxFlow<StarGraph>;
681
682// Default instance MaxFlow that uses StarGraph. Note that we cannot just use a
683// typedef because of dependent code expecting MaxFlow to be a real class.
684// TODO(user): Modify this code and remove it.
685class MaxFlow : public GenericMaxFlow<StarGraph> {
686 public:
687 MaxFlow(const StarGraph* graph, NodeIndex source, NodeIndex target)
688 : GenericMaxFlow(graph, source, target) {}
689};
690
691#endif // SWIG
692
693template <typename Element, typename IntegerPriority>
695 const {
696 return even_queue_.empty() && odd_queue_.empty();
697}
698
699template <typename Element, typename IntegerPriority>
701 even_queue_.clear();
702 odd_queue_.clear();
703}
704
705template <typename Element, typename IntegerPriority>
707 Element element, IntegerPriority priority) {
708 // Since users may rely on it, we DCHECK the exact condition.
709 DCHECK(even_queue_.empty() || priority >= even_queue_.back().second - 1);
710 DCHECK(odd_queue_.empty() || priority >= odd_queue_.back().second - 1);
711
712 // Note that the DCHECK() below are less restrictive than the ones above but
713 // check a necessary and sufficient condition for the priority queue to behave
714 // as expected.
715 if (priority & 1) {
716 DCHECK(odd_queue_.empty() || priority >= odd_queue_.back().second);
717 odd_queue_.push_back(std::make_pair(element, priority));
718 } else {
719 DCHECK(even_queue_.empty() || priority >= even_queue_.back().second);
720 even_queue_.push_back(std::make_pair(element, priority));
721 }
722}
723
724template <typename Element, typename IntegerPriority>
726 DCHECK(!IsEmpty());
727 if (even_queue_.empty()) return PopBack(&odd_queue_);
728 if (odd_queue_.empty()) return PopBack(&even_queue_);
729 if (odd_queue_.back().second > even_queue_.back().second) {
730 return PopBack(&odd_queue_);
731 } else {
732 return PopBack(&even_queue_);
733 }
734}
735
736template <typename Element, typename IntegerPriority>
738 std::vector<std::pair<Element, IntegerPriority>>* queue) {
739 DCHECK(!queue->empty());
740 Element element = queue->back().first;
741 queue->pop_back();
742 return element;
743}
744
745} // namespace operations_research
746
747#endif // OR_TOOLS_GRAPH_MAX_FLOW_H_
void GetSourceSideMinCut(std::vector< NodeIndex > *result)
Definition max_flow.cc:244
void SetUseTwoPhaseAlgorithm(bool value)
Definition max_flow.h:434
GenericMaxFlow & operator=(const GenericMaxFlow &)=delete
void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity)
Sets the capacity for arc to new_capacity.
Definition max_flow.cc:194
void SetCapacityAndClearFlow(ArcIndex arc, FlowQuantity capacity)
Sets the capacity of arc to 'capacity' and clears the flow on arc.
Definition max_flow.h:458
void SetUseGlobalUpdate(bool value)
Definition max_flow.h:430
void Refine()
Performs optimization step.
Definition max_flow.cc:774
ZVector< ArcIndex > ArcIndexArray
Definition max_flow.h:332
void PushFlow(FlowQuantity flow, ArcIndex arc)
Definition max_flow.cc:737
bool Solve()
Returns true if a maximum flow was solved.
Definition max_flow.cc:353
Graph::OutgoingArcIterator OutgoingArcIterator
Definition max_flow.h:328
void InitializePreflow()
Initializes the preflow to a state that enables to run Refine.
Definition max_flow.cc:398
const Graph * graph_
A pointer to the graph passed as argument.
Definition max_flow.h:563
ZVector< NodeHeight > NodeHeightArray
Definition max_flow.h:337
bool IsEmptyActiveNodeContainer()
Check the emptiness of the container.
Definition max_flow.h:493
StatsGroup stats_
Statistics about this class.
Definition max_flow.h:657
void InitializeActiveNodeContainer()
Initializes the container active_nodes_.
Definition max_flow.cc:759
NodeIndex source_
The index of the source node in graph_.
Definition max_flow.h:616
void PushActiveNode(const NodeIndex &node)
Push element to the active node container.
Definition max_flow.h:484
Graph::IncomingArcIterator IncomingArcIterator
Definition max_flow.h:331
GenericMaxFlow(const GenericMaxFlow &)=delete
This type is neither copyable nor movable.
ArcIndexArray first_admissible_arc_
An array representing the first admissible arc for each node in graph_.
Definition max_flow.h:600
void Discharge(NodeIndex node)
Definition max_flow.cc:866
bool IsActive(NodeIndex node) const
Definition max_flow.h:453
FlowModelProto CreateFlowModel()
Returns the protocol buffer representation of the current problem.
Definition max_flow.cc:985
QuantityArray node_excess_
An array representing the excess for each node in graph_.
Definition max_flow.h:566
Status status_
The status of the problem.
Definition max_flow.h:622
PriorityQueueWithRestrictedPush< NodeIndex, NodeHeight > active_node_by_height_
Definition max_flow.h:613
NodeIndex sink_
The index of the sink node in graph_.
Definition max_flow.h:619
Graph::OutgoingOrOppositeIncomingArcIterator OutgoingOrOppositeIncomingArcIterator
Definition max_flow.h:330
const Graph * graph() const
Returns the graph associated to the current object.
Definition max_flow.h:354
NodeIndex GetSinkNodeIndex() const
Returns the index of the node corresponding to the sink of the network.
Definition max_flow.h:365
FlowQuantity GetOptimalFlow() const
Returns the total flow found by the algorithm.
Definition max_flow.h:377
void SetArcFlow(ArcIndex arc, FlowQuantity new_flow)
Sets the flow for arc.
Definition max_flow.cc:228
bool CheckRelabelPrecondition(NodeIndex node) const
Definition max_flow.cc:326
FlowQuantity Capacity(ArcIndex arc) const
Definition max_flow.h:391
bool IsArcDirect(ArcIndex arc) const
Definition max_flow.cc:936
std::vector< bool > node_in_bfs_queue_
Definition max_flow.h:626
bool use_global_update_
Whether or not to use GlobalUpdate().
Definition max_flow.h:630
ArcIndex Opposite(ArcIndex arc) const
Definition max_flow.cc:931
std::vector< NodeIndex > bfs_queue_
Definition max_flow.h:627
NodeIndex Tail(ArcIndex arc) const
Definition max_flow.h:549
static const FlowQuantity kMaxFlowQuantity
Maximum manageable flow.
Definition max_flow.h:560
std::string DebugString(absl::string_view context, ArcIndex arc) const
Definition max_flow.cc:337
void ProcessNodeByHeight(bool value)
Definition max_flow.h:437
bool IsArcValid(ArcIndex arc) const
Definition max_flow.cc:941
NodeIndex GetAndRemoveFirstActiveNode()
Get the first element from the active node container.
Definition max_flow.h:476
NodeIndex Head(ArcIndex arc) const
Handy member functions to make the code more compact.
Definition max_flow.h:548
std::vector< NodeIndex > active_nodes_
Definition max_flow.h:606
void GetSinkSideMinCut(std::vector< NodeIndex > *result)
Definition max_flow.cc:250
void ComputeReachableNodes(NodeIndex start, std::vector< NodeIndex > *result)
Definition max_flow.cc:951
GenericMaxFlow(const Graph *graph, NodeIndex source, NodeIndex sink)
Definition max_flow.cc:144
bool IsAdmissible(ArcIndex arc) const
Returns true if arc is admissible.
Definition max_flow.h:446
NodeIndex GetSourceNodeIndex() const
Returns the index of the node corresponding to the source of the network.
Definition max_flow.h:362
FlowQuantity Flow(ArcIndex arc) const
Definition max_flow.h:381
MaxFlow(const StarGraph *graph, NodeIndex source, NodeIndex target)
Definition max_flow.h:687
bool IsEmpty() const
Is the queue empty?
Definition max_flow.h:694
void Push(Element element, IntegerPriority priority)
Definition max_flow.h:706
PriorityQueueWithRestrictedPush & operator=(const PriorityQueueWithRestrictedPush &)=delete
PriorityQueueWithRestrictedPush(const PriorityQueueWithRestrictedPush &)=delete
This type is neither copyable nor movable.
SimpleMaxFlow & operator=(const SimpleMaxFlow &)=delete
ArcIndex NumArcs() const
Returns the current number of arcs in the graph.
Definition max_flow.cc:45
FlowModelProto CreateFlowModelProto(NodeIndex source, NodeIndex sink) const
Creates the protocol buffer representation of the current problem.
Definition max_flow.cc:124
SimpleMaxFlow(const SimpleMaxFlow &)=delete
This type is neither copyable nor movable.
FlowQuantity OptimalFlow() const
Definition max_flow.cc:110
void SetArcCapacity(ArcIndex arc, FlowQuantity capacity)
Definition max_flow.cc:55
ArcIndex AddArcWithCapacity(NodeIndex tail, NodeIndex head, FlowQuantity capacity)
Definition max_flow.cc:32
void GetSinkSideMinCut(std::vector< NodeIndex > *result)
Definition max_flow.cc:119
FlowQuantity Capacity(ArcIndex arc) const
Definition max_flow.cc:51
@ BAD_RESULT
This should not happen. There was an error in our code (i.e. file a bug).
Definition max_flow.h:199
@ BAD_INPUT
The input is inconsistent (bad tail/head/capacity values).
Definition max_flow.h:197
Status Solve(NodeIndex source, NodeIndex sink)
Definition max_flow.cc:59
NodeIndex Head(ArcIndex arc) const
Definition max_flow.cc:49
void GetSourceSideMinCut(std::vector< NodeIndex > *result)
Definition max_flow.cc:114
NodeIndex Tail(ArcIndex arc) const
Definition max_flow.cc:47
FlowQuantity Flow(ArcIndex arc) const
Definition max_flow.cc:112
Base class to print a nice summary of a group of statistics.
Definition stats.h:128
void Set(int64_t index, T value)
Sets to value the content of the array at index.
Definition zvector.h:86
NodeIndexType Tail(ArcIndexType arc) const
Definition graph.h:1771
NodeIndexType Head(ArcIndexType arc) const
Definition graph.h:1763
int64_t value
GurobiMPCallbackContext * context
int arc
In SWIG mode, we don't want anything besides these top-level includes.
int head
int tail
int64_t start