Google OR-Tools v9.12
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-2025 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#ifndef OR_TOOLS_GRAPH_MAX_FLOW_H_
15#define OR_TOOLS_GRAPH_MAX_FLOW_H_
16
17#include <cstdint>
18#include <memory>
19#include <vector>
20
21#include "ortools/graph/flow_problem.pb.h"
23#include "ortools/graph/graph.h"
24
25namespace operations_research {
26
27// A simple and efficient max-cost flow interface. This is as fast as
28// GenericMaxFlow<ReverseArcStaticGraph>, which is the fastest, but uses
29// more memory in order to hide the somewhat involved construction of the
30// static graph.
31//
32// TODO(user): If the need arises, extend this interface to support warm start.
34 public:
35 typedef int32_t NodeIndex;
36 typedef int32_t ArcIndex;
37 typedef int64_t FlowQuantity;
38
39 // The constructor takes no size.
40 // New node indices will be created lazily by AddArcWithCapacity().
42
43#ifndef SWIG
44 // This type is neither copyable nor movable.
45 SimpleMaxFlow(const SimpleMaxFlow&) = delete;
47#endif
48
49 // Adds a directed arc with the given capacity from tail to head.
50 // * Node indices and capacity must be non-negative (>= 0).
51 // * Self-looping and duplicate arcs are supported.
52 // * After the method finishes, NumArcs() == the returned ArcIndex + 1.
54 FlowQuantity capacity);
55
56 // Returns the current number of nodes. This is one more than the largest
57 // node index seen so far in AddArcWithCapacity().
58 NodeIndex NumNodes() const;
59
60 // Returns the current number of arcs in the graph.
61 ArcIndex NumArcs() const;
62
63 // Returns user-provided data.
64 // The implementation will crash if "arc" is not in [0, NumArcs()).
65 NodeIndex Tail(ArcIndex arc) const;
66 NodeIndex Head(ArcIndex arc) const;
68
69 // Solves the problem (finds the maximum flow from the given source to the
70 // given sink), and returns the problem status.
71 enum Status {
72 // Solve() was called and found an optimal solution. Note that OptimalFlow()
73 // may be 0 which means that the sink is not reachable from the source.
75 // There is a flow > std::numeric_limits<FlowQuantity>::max(). Note that in
76 // this case, the class will contain a solution with a flow reaching that
77 // bound.
78 //
79 // TODO(user): rename POSSIBLE_OVERFLOW to INT_OVERFLOW and modify our
80 // clients.
82 // The input is inconsistent (bad tail/head/capacity values).
84 // This should not happen. There was an error in our code (i.e. file a bug).
86 };
87 Status Solve(NodeIndex source, NodeIndex sink);
88
89 // Returns the maximum flow we can send from the source to the sink in the
90 // last OPTIMAL Solve() context.
92
93 // Returns the flow on the given arc in the last OPTIMAL Solve() context.
94 //
95 // Note: It is possible that there is more than one optimal solution. The
96 // algorithm is deterministic so it will always return the same solution for
97 // a given problem. However, there is no guarantee of this from one code
98 // version to the next (but the code does not change often).
99 FlowQuantity Flow(ArcIndex arc) const;
100
101 // Returns the nodes reachable from the source by non-saturated arcs (.i.e.
102 // arc with Flow(arc) < Capacity(arc)), the outgoing arcs of this set form a
103 // minimum cut. This works only if Solve() returned OPTIMAL.
104 void GetSourceSideMinCut(std::vector<NodeIndex>* result);
105
106 // Returns the nodes that can reach the sink by non-saturated arcs, the
107 // outgoing arcs of this set form a minimum cut. Note that if this is the
108 // complement set of GetNodeReachableFromSource(), then the min-cut is unique.
109 // This works only if Solve() returned OPTIMAL.
110 void GetSinkSideMinCut(std::vector<NodeIndex>* result);
111
112 // Change the capacity of an arc.
113 //
114 // WARNING: This looks like it enables incremental solves, but as of 2018-02,
115 // the next Solve() will restart from scratch anyway.
116 // TODO(user): Support incrementality in the max flow implementation.
117 void SetArcCapacity(ArcIndex arc, FlowQuantity capacity);
118
119 // Creates the protocol buffer representation of the current problem.
120 FlowModelProto CreateFlowModelProto(NodeIndex source, NodeIndex sink) const;
121
122 private:
123 NodeIndex num_nodes_;
124 std::vector<NodeIndex> arc_tail_;
125 std::vector<NodeIndex> arc_head_;
126 std::vector<FlowQuantity> arc_capacity_;
127 std::vector<ArcIndex> arc_permutation_;
128 std::vector<FlowQuantity> arc_flow_;
129 FlowQuantity optimal_flow_;
130
131 // Note that we cannot free the graph before we stop using the max-flow
132 // instance that uses it.
133 typedef ::util::ReverseArcStaticGraph<NodeIndex, ArcIndex> Graph;
134 std::unique_ptr<Graph> underlying_graph_;
135 std::unique_ptr<GenericMaxFlow<Graph> > underlying_max_flow_;
136};
137
138} // namespace operations_research
139
140#endif // OR_TOOLS_GRAPH_MAX_FLOW_H_
SimpleMaxFlow & operator=(const SimpleMaxFlow &)=delete
FlowModelProto CreateFlowModelProto(NodeIndex source, NodeIndex sink) const
Creates the protocol buffer representation of the current problem.
Definition max_flow.cc:129
FlowQuantity OptimalFlow() const
Definition max_flow.cc:111
SimpleMaxFlow(const SimpleMaxFlow &)=delete
This type is neither copyable nor movable.
void SetArcCapacity(ArcIndex arc, FlowQuantity capacity)
Definition max_flow.cc:56
ArcIndex NumArcs() const
Returns the current number of arcs in the graph.
Definition max_flow.cc:40
void GetSinkSideMinCut(std::vector< NodeIndex > *result)
Definition max_flow.cc:124
NodeIndex Tail(ArcIndex arc) const
Definition max_flow.cc:44
ArcIndex AddArcWithCapacity(NodeIndex tail, NodeIndex head, FlowQuantity capacity)
Definition max_flow.cc:27
@ BAD_RESULT
This should not happen. There was an error in our code (i.e. file a bug).
Definition max_flow.h:85
@ BAD_INPUT
The input is inconsistent (bad tail/head/capacity values).
Definition max_flow.h:83
NodeIndex Head(ArcIndex arc) const
Definition max_flow.cc:48
Status Solve(NodeIndex source, NodeIndex sink)
Definition max_flow.cc:60
FlowQuantity Capacity(ArcIndex arc) const
Definition max_flow.cc:52
FlowQuantity Flow(ArcIndex arc) const
Definition max_flow.cc:115
void GetSourceSideMinCut(std::vector< NodeIndex > *result)
Definition max_flow.cc:119
In SWIG mode, we don't want anything besides these top-level includes.
util::ReverseArcStaticGraph Graph
Type of graph to use.