Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
max_flow.cc
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
15
16#include <algorithm>
17#include <memory>
18#include <vector>
19
21#include "ortools/graph/graph.h"
22
23namespace operations_research {
24
25SimpleMaxFlow::SimpleMaxFlow() : num_nodes_(0) {}
26
28 NodeIndex tail, NodeIndex head, FlowQuantity capacity) {
29 const ArcIndex num_arcs = arc_tail_.size();
30 num_nodes_ = std::max(num_nodes_, tail + 1);
31 num_nodes_ = std::max(num_nodes_, head + 1);
32 arc_tail_.push_back(tail);
33 arc_head_.push_back(head);
34 arc_capacity_.push_back(capacity);
35 return num_arcs;
36}
37
39
41 return arc_tail_.size();
42}
43
45 return arc_tail_[arc];
46}
47
49 return arc_head_[arc];
50}
51
53 return arc_capacity_[arc];
54}
55
57 arc_capacity_[arc] = capacity;
58}
59
61 const ArcIndex num_arcs = arc_capacity_.size();
62 arc_flow_.assign(num_arcs, 0);
63 underlying_max_flow_.reset();
64 underlying_graph_.reset();
65 optimal_flow_ = 0;
66 if (source == sink || source < 0 || sink < 0) {
67 return BAD_INPUT;
68 }
69 if (source >= num_nodes_ || sink >= num_nodes_) {
70 return OPTIMAL;
71 }
72 underlying_graph_ = std::make_unique<Graph>(num_nodes_, num_arcs);
73 underlying_graph_->AddNode(source);
74 underlying_graph_->AddNode(sink);
75 for (int arc = 0; arc < num_arcs; ++arc) {
76 underlying_graph_->AddArc(arc_tail_[arc], arc_head_[arc]);
77 }
78 underlying_graph_->Build(&arc_permutation_);
79 underlying_max_flow_ = std::make_unique<GenericMaxFlow<Graph>>(
80 underlying_graph_.get(), source, sink);
81 for (ArcIndex arc = 0; arc < num_arcs; ++arc) {
82 ArcIndex permuted_arc =
83 arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
84 underlying_max_flow_->SetArcCapacity(permuted_arc, arc_capacity_[arc]);
85 }
86 if (underlying_max_flow_->Solve()) {
87 optimal_flow_ = underlying_max_flow_->GetOptimalFlow();
88 for (ArcIndex arc = 0; arc < num_arcs; ++arc) {
89 ArcIndex permuted_arc =
90 arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
91 arc_flow_[arc] = underlying_max_flow_->Flow(permuted_arc);
92 }
93 }
94 // Translate the GenericMaxFlow::Status. It is different because NOT_SOLVED
95 // does not make sense in the simple api.
96 switch (underlying_max_flow_->status()) {
98 return BAD_RESULT;
100 return OPTIMAL;
102 return POSSIBLE_OVERFLOW;
104 return BAD_INPUT;
106 return BAD_RESULT;
107 }
108 return BAD_RESULT;
109}
110
112 return optimal_flow_;
113}
114
116 return arc_flow_[arc];
117}
118
119void SimpleMaxFlow::GetSourceSideMinCut(std::vector<NodeIndex>* result) {
120 if (underlying_max_flow_ == nullptr) return;
121 underlying_max_flow_->GetSourceSideMinCut(result);
122}
123
124void SimpleMaxFlow::GetSinkSideMinCut(std::vector<NodeIndex>* result) {
125 if (underlying_max_flow_ == nullptr) return;
126 underlying_max_flow_->GetSinkSideMinCut(result);
127}
128
130 NodeIndex sink) const {
131 FlowModelProto model;
132 model.set_problem_type(FlowModelProto::MAX_FLOW);
133 for (int n = 0; n < num_nodes_; ++n) {
134 FlowNodeProto* node = model.add_nodes();
135 node->set_id(n);
136 if (n == source) node->set_supply(1);
137 if (n == sink) node->set_supply(-1);
138 }
139 for (int a = 0; a < arc_tail_.size(); ++a) {
140 FlowArcProto* arc = model.add_arcs();
141 arc->set_tail(Tail(a));
142 arc->set_head(Head(a));
143 arc->set_capacity(Capacity(a));
144 }
145 return model;
146}
147
148} // namespace operations_research
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
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.