Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
min_cost_flow.cc
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
15
16#include <algorithm>
17#include <cmath>
18#include <cstdint>
19#include <cstdlib>
20#include <limits>
21#include <string>
22#include <vector>
23
24#include "absl/flags/flag.h"
25#include "absl/strings/str_format.h"
26#include "absl/strings/string_view.h"
29#include "ortools/graph/graph.h"
33
34// TODO(user): Remove these flags and expose the parameters in the API.
35// New clients, please do not use these flags!
36ABSL_FLAG(int64_t, min_cost_flow_alpha, 5,
37 "Divide factor for epsilon at each refine step.");
38ABSL_FLAG(bool, min_cost_flow_check_feasibility, true,
39 "Check that the graph has enough capacity to send all supplies "
40 "and serve all demands. Also check that the sum of supplies "
41 "is equal to the sum of demands.");
42ABSL_FLAG(bool, min_cost_flow_check_balance, true,
43 "Check that the sum of supplies is equal to the sum of demands.");
44ABSL_FLAG(bool, min_cost_flow_check_result, true,
45 "Check that the result is valid.");
46
47namespace operations_research {
48
49template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
51 const Graph* graph)
52 : graph_(graph),
53 alpha_(absl::GetFlag(FLAGS_min_cost_flow_alpha)),
54 stats_("MinCostFlow"),
55 check_feasibility_(absl::GetFlag(FLAGS_min_cost_flow_check_feasibility)) {
56 const NodeIndex max_num_nodes = Graphs<Graph>::NodeReservation(*graph_);
57 if (max_num_nodes > 0) {
58 first_admissible_arc_.assign(max_num_nodes, Graph::kNilArc);
59 node_potential_.assign(max_num_nodes, 0);
60 node_excess_.assign(max_num_nodes, 0);
61 initial_node_excess_.assign(max_num_nodes, 0);
62 feasible_node_excess_.assign(max_num_nodes, 0);
63 }
64 const ArcIndex max_num_arcs = Graphs<Graph>::ArcReservation(*graph_);
65 if (max_num_arcs > 0) {
66 residual_arc_capacity_.Reserve(-max_num_arcs, max_num_arcs - 1);
67 residual_arc_capacity_.SetAll(0);
68 scaled_arc_unit_cost_.Reserve(-max_num_arcs, max_num_arcs - 1);
69 scaled_arc_unit_cost_.SetAll(0);
70 }
71}
72
73template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
75 NodeIndex node, FlowQuantity supply) {
76 DCHECK(graph_->IsNodeValid(node));
77 node_excess_[node] = supply;
78 initial_node_excess_[node] = supply;
79 status_ = NOT_SOLVED;
80 feasibility_checked_ = false;
81}
82
83template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
85 ArcIndex arc, ArcScaledCostType unit_cost) {
86 DCHECK(IsArcDirect(arc));
87 scaled_arc_unit_cost_.Set(arc, unit_cost);
88 scaled_arc_unit_cost_.Set(Opposite(arc), -scaled_arc_unit_cost_[arc]);
89 status_ = NOT_SOLVED;
90 feasibility_checked_ = false;
91}
92
93template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
95 ArcIndex arc, ArcFlowType new_capacity) {
96 DCHECK_LE(0, new_capacity);
97 DCHECK(IsArcDirect(arc));
98 const FlowQuantity free_capacity = residual_arc_capacity_[arc];
99 const FlowQuantity capacity_delta = new_capacity - Capacity(arc);
100 if (capacity_delta == 0) {
101 return; // Nothing to do.
102 }
103 status_ = NOT_SOLVED;
104 feasibility_checked_ = false;
105 const FlowQuantity new_availability = free_capacity + capacity_delta;
106 if (new_availability >= 0) {
107 // The above condition is true when one of two following holds:
108 // 1/ (capacity_delta > 0), meaning we are increasing the capacity
109 // 2/ (capacity_delta < 0 && free_capacity + capacity_delta >= 0)
110 // meaning we are reducing the capacity, but that the capacity
111 // reduction is not larger than the free capacity.
112 DCHECK((capacity_delta > 0) ||
113 (capacity_delta < 0 && new_availability >= 0));
114 residual_arc_capacity_.Set(arc, new_availability);
115 DCHECK_LE(0, residual_arc_capacity_[arc]);
116 } else {
117 // We have to reduce the flow on the arc, and update the excesses
118 // accordingly.
119 const FlowQuantity flow = residual_arc_capacity_[Opposite(arc)];
120 const FlowQuantity flow_excess = flow - new_capacity;
121 residual_arc_capacity_.Set(arc, 0);
122 residual_arc_capacity_.Set(Opposite(arc), new_capacity);
123 node_excess_[Tail(arc)] += flow_excess;
124 node_excess_[Head(arc)] -= flow_excess;
125 DCHECK_LE(0, residual_arc_capacity_[arc]);
126 DCHECK_LE(0, residual_arc_capacity_[Opposite(arc)]);
127 }
128}
129
130template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
132 ArcIndex arc, ArcFlowType new_flow) {
133 DCHECK(IsArcValid(arc));
134 const FlowQuantity capacity = Capacity(arc);
135 DCHECK_GE(capacity, new_flow);
136 residual_arc_capacity_.Set(Opposite(arc), new_flow);
137 residual_arc_capacity_.Set(arc, capacity - new_flow);
138 status_ = NOT_SOLVED;
139 feasibility_checked_ = false;
140}
141
142template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
143bool GenericMinCostFlow<Graph, ArcFlowType,
144 ArcScaledCostType>::CheckInputConsistency() {
145 FlowQuantity total_supply = 0;
146 uint64_t max_capacity = 0; // uint64_t because it is positive and will be
147 // used to check against FlowQuantity overflows.
148 for (ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
149 const uint64_t capacity =
150 static_cast<uint64_t>(residual_arc_capacity_[arc]);
151 max_capacity = std::max(capacity, max_capacity);
152 }
153 uint64_t total_flow = 0; // uint64_t for the same reason as max_capacity.
154 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
155 const FlowQuantity excess = node_excess_[node];
156 total_supply += excess;
157 if (excess > 0) {
158 total_flow += excess;
159 if (std::numeric_limits<FlowQuantity>::max() <
160 max_capacity + total_flow) {
161 status_ = BAD_COST_RANGE;
162 LOG(ERROR) << "Input consistency error: max capacity + flow exceed "
163 << "precision";
164 return false;
165 }
166 }
167 }
168 if (total_supply != 0) {
169 status_ = UNBALANCED;
170 LOG(ERROR) << "Input consistency error: unbalanced problem";
171 return false;
172 }
173 return true;
174}
175
176template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
177bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckResult()
178 const {
179 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
180 if (node_excess_[node] != 0) {
181 LOG(DFATAL) << "node_excess_[" << node << "] != 0";
182 return false;
183 }
184 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
185 it.Next()) {
186 const ArcIndex arc = it.Index();
187 bool ok = true;
188 if (residual_arc_capacity_[arc] < 0) {
189 LOG(DFATAL) << "residual_arc_capacity_[" << arc << "] < 0";
190 ok = false;
191 }
192 if (residual_arc_capacity_[arc] > 0 && ReducedCost(arc) < -epsilon_) {
193 LOG(DFATAL) << "residual_arc_capacity_[" << arc
194 << "] > 0 && ReducedCost(" << arc << ") < " << -epsilon_
195 << ". (epsilon_ = " << epsilon_ << ").";
196 ok = false;
197 }
198 if (!ok) {
199 LOG(DFATAL) << DebugString("CheckResult ", arc);
200 return false;
201 }
202 }
203 }
204 return true;
205}
206
207template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
208bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
209 CheckRelabelPrecondition(NodeIndex node) const {
210 // Note that the classical Relabel precondition assumes IsActive(node), i.e.,
211 // the node_excess_[node] > 0. However, to implement the Push Look-Ahead
212 // heuristic, we can relax this condition as explained in the section 4.3 of
213 // the article "An Efficient Implementation of a Scaling Minimum-Cost Flow
214 // Algorithm", A.V. Goldberg, Journal of Algorithms 22(1), January 1997, pp.
215 // 1-29.
216 DCHECK_GE(node_excess_[node], 0);
217 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
218 it.Next()) {
219 const ArcIndex arc = it.Index();
220 DCHECK(!IsAdmissible(arc)) << DebugString("CheckRelabelPrecondition:", arc);
221 }
222 return true;
223}
224
225template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
226std::string
227GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::DebugString(
228 absl::string_view context, ArcIndex arc) const {
229 const NodeIndex tail = Tail(arc);
230 const NodeIndex head = Head(arc);
231 // Reduced cost is computed directly without calling ReducedCost to avoid
232 // recursive calls between ReducedCost and DebugString in case a DCHECK in
233 // ReducedCost fails.
234 const CostValue reduced_cost = scaled_arc_unit_cost_[arc] +
235 node_potential_[tail] - node_potential_[head];
236 return absl::StrFormat(
237 "%s Arc %d, from %d to %d, "
238 "Capacity = %d, Residual capacity = %d, "
239 "Flow = residual capacity for reverse arc = %d, "
240 "Height(tail) = %d, Height(head) = %d, "
241 "Excess(tail) = %d, Excess(head) = %d, "
242 "Cost = %d, Reduced cost = %d, ",
243 context, arc, tail, head, Capacity(arc),
244 static_cast<FlowQuantity>(residual_arc_capacity_[arc]), Flow(arc),
245 node_potential_[tail], node_potential_[head], node_excess_[tail],
246 node_excess_[head], static_cast<CostValue>(scaled_arc_unit_cost_[arc]),
247 reduced_cost);
248}
249
250template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
252 CheckFeasibility(std::vector<NodeIndex>* const infeasible_supply_node,
253 std::vector<NodeIndex>* const infeasible_demand_node) {
254 SCOPED_TIME_STAT(&stats_);
255 // Create a new graph, which is a copy of graph_, with the following
256 // modifications:
257 // Two nodes are added: a source and a sink.
258 // The source is linked to each supply node (whose supply > 0) by an arc whose
259 // capacity is equal to the supply at the supply node.
260 // The sink is linked to each demand node (whose supply < 0) by an arc whose
261 // capacity is the demand (-supply) at the demand node.
262 // There are no supplies or demands or costs in the graph, as we will run
263 // max-flow.
264 // TODO(user): make it possible to share a graph by MaxFlow and MinCostFlow.
265 // For this it is necessary to make StarGraph resizable.
266 feasibility_checked_ = false;
267 ArcIndex num_extra_arcs = 0;
268 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
269 if (initial_node_excess_[node] != 0) {
270 ++num_extra_arcs;
271 }
272 }
273 const NodeIndex num_nodes_in_max_flow = graph_->num_nodes() + 2;
274 const ArcIndex num_arcs_in_max_flow = graph_->num_arcs() + num_extra_arcs;
275 const NodeIndex source = num_nodes_in_max_flow - 2;
276 const NodeIndex sink = num_nodes_in_max_flow - 1;
277 StarGraph checker_graph(num_nodes_in_max_flow, num_arcs_in_max_flow);
278 MaxFlow checker(&checker_graph, source, sink);
279 checker.SetCheckInput(false);
280 checker.SetCheckResult(false);
281 // Copy graph_ to checker_graph.
282 for (ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
283 const ArcIndex new_arc =
284 checker_graph.AddArc(graph_->Tail(arc), graph_->Head(arc));
285 DCHECK_EQ(arc, new_arc);
286 checker.SetArcCapacity(new_arc, Capacity(arc));
287 }
288 FlowQuantity total_demand = 0;
289 FlowQuantity total_supply = 0;
290 // Create the source-to-supply node arcs and the demand-node-to-sink arcs.
291 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
292 const FlowQuantity supply = initial_node_excess_[node];
293 if (supply > 0) {
294 const ArcIndex new_arc = checker_graph.AddArc(source, node);
295 checker.SetArcCapacity(new_arc, supply);
296 total_supply += supply;
297 } else if (supply < 0) {
298 const ArcIndex new_arc = checker_graph.AddArc(node, sink);
299 checker.SetArcCapacity(new_arc, -supply);
300 total_demand -= supply;
301 }
302 }
303 if (total_supply != total_demand) {
304 LOG(DFATAL) << "total_supply(" << total_supply << ") != total_demand("
305 << total_demand << ").";
306 return false;
307 }
308 if (!checker.Solve()) {
309 LOG(DFATAL) << "Max flow could not be computed.";
310 return false;
311 }
312 const FlowQuantity optimal_max_flow = checker.GetOptimalFlow();
313 feasible_node_excess_.assign(checker_graph.num_nodes(), 0);
314 for (StarGraph::OutgoingArcIterator it(checker_graph, source); it.Ok();
315 it.Next()) {
316 const ArcIndex arc = it.Index();
317 const NodeIndex node = checker_graph.Head(arc);
318 const FlowQuantity flow = checker.Flow(arc);
319 feasible_node_excess_[node] = flow;
320 if (infeasible_supply_node != nullptr) {
321 infeasible_supply_node->push_back(node);
322 }
323 }
324 for (StarGraph::IncomingArcIterator it(checker_graph, sink); it.Ok();
325 it.Next()) {
326 const ArcIndex arc = it.Index();
327 const NodeIndex node = checker_graph.Tail(arc);
328 const FlowQuantity flow = checker.Flow(arc);
329 feasible_node_excess_[node] = -flow;
330 if (infeasible_demand_node != nullptr) {
331 infeasible_demand_node->push_back(node);
332 }
333 }
334 feasibility_checked_ = true;
335 return optimal_max_flow == total_supply;
336}
337
338template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
340 if (!feasibility_checked_) {
341 return false;
342 }
343 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
344 const FlowQuantity excess = feasible_node_excess_[node];
345 node_excess_[node] = excess;
346 initial_node_excess_[node] = excess;
347 }
348 return true;
349}
350
351template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
353 ArcIndex arc) const {
354 if (IsArcDirect(arc)) {
355 return residual_arc_capacity_[Opposite(arc)];
356 } else {
357 return -residual_arc_capacity_[arc];
358 }
359}
360
361// We use the equations given in the comment of residual_arc_capacity_.
362template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
365 ArcIndex arc) const {
366 if (IsArcDirect(arc)) {
367 return residual_arc_capacity_[arc] + residual_arc_capacity_[Opposite(arc)];
368 } else {
369 return 0;
370 }
371}
372
373template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
375 ArcIndex arc) const {
376 DCHECK(IsArcValid(arc));
377 DCHECK_EQ(uint64_t{1}, cost_scaling_factor_);
378 return scaled_arc_unit_cost_[arc];
379}
380
381template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
383 NodeIndex node) const {
384 DCHECK(graph_->IsNodeValid(node));
385 return node_excess_[node];
386}
387
388template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
391 NodeIndex node) const {
392 return initial_node_excess_[node];
393}
394
395template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
398 NodeIndex node) const {
399 return feasible_node_excess_[node];
400}
401
402template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
404 ArcIndex arc) const {
405 return FastIsAdmissible(arc, node_potential_[Tail(arc)]);
406}
407
408template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
410 FastIsAdmissible(ArcIndex arc, CostValue tail_potential) const {
411 DCHECK_EQ(node_potential_[Tail(arc)], tail_potential);
412 return residual_arc_capacity_[arc] > 0 &&
413 FastReducedCost(arc, tail_potential) < 0;
415
416template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
418 NodeIndex node) const {
419 return node_excess_[node] > 0;
420}
422template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
425 ArcIndex arc) const {
426 return FastReducedCost(arc, node_potential_[Tail(arc)]);
427}
428
429template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
432 ArcIndex arc, CostValue tail_potential) const {
433 DCHECK_EQ(node_potential_[Tail(arc)], tail_potential);
434 DCHECK(graph_->IsNodeValid(Tail(arc)));
435 DCHECK(graph_->IsNodeValid(Head(arc)));
436 DCHECK_LE(node_potential_[Tail(arc)], 0) << DebugString("ReducedCost:", arc);
437 DCHECK_LE(node_potential_[Head(arc)], 0) << DebugString("ReducedCost:", arc);
438
439 // Note that there should be no overflow independently of the order of
440 // operations if potentials are in [overflow_threshold_, 0].
441 return scaled_arc_unit_cost_[arc] + tail_potential -
442 node_potential_[Head(arc)];
443}
444
445template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
449 OutgoingOrOppositeIncomingArcIterator arc_it(*graph_, node);
450 return arc_it.Index();
451}
452
453template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
455 if (absl::GetFlag(FLAGS_min_cost_flow_check_balance) &&
456 !CheckInputConsistency()) {
457 return false;
458 }
459 if (check_feasibility_ && !CheckFeasibility(nullptr, nullptr)) {
460 status_ = INFEASIBLE;
461 return false;
462 }
464 status_ = NOT_SOLVED;
465 node_potential_.assign(node_potential_.size(), 0);
466 ResetFirstAdmissibleArcs();
467 if (!ScaleCosts()) return false;
468 if (!Optimize()) return false;
469 DCHECK_EQ(status_, NOT_SOLVED);
470 status_ = OPTIMAL;
471
472 if (absl::GetFlag(FLAGS_min_cost_flow_check_result) && !CheckResult()) {
473 status_ = BAD_RESULT;
474 UnscaleCosts();
475 return false;
476 }
477 UnscaleCosts();
478
479 IF_STATS_ENABLED(VLOG(1) << stats_.StatString());
480 return true;
481}
482
483template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
486 if (status_ != OPTIMAL) {
487 return 0;
488 }
489
490 // The total cost of the flow.
491 // We cap the result if its overflow.
492 CostValue total_flow_cost = 0;
493 const CostValue kMaxCost = std::numeric_limits<CostValue>::max();
494 const CostValue kMinCost = std::numeric_limits<CostValue>::min();
495 for (ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
496 const CostValue flow_on_arc = residual_arc_capacity_[Opposite(arc)];
497 const CostValue flow_cost =
498 CapProd(scaled_arc_unit_cost_[arc], flow_on_arc);
499 if (flow_cost == kMaxCost || flow_cost == kMinCost) return kMaxCost;
500 total_flow_cost = CapAdd(flow_cost, total_flow_cost);
501 if (total_flow_cost == kMaxCost || total_flow_cost == kMinCost) {
502 return kMaxCost;
503 }
504 }
505 return total_flow_cost;
506}
507
508template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
509void GenericMinCostFlow<Graph, ArcFlowType,
510 ArcScaledCostType>::ResetFirstAdmissibleArcs() {
511 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
512 first_admissible_arc_[node] = GetFirstOutgoingOrOppositeIncomingArc(node);
513 }
514}
515
516template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
517bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ScaleCosts() {
518 SCOPED_TIME_STAT(&stats_);
519 cost_scaling_factor_ = scale_prices_ ? graph_->num_nodes() + 1 : 1;
520 epsilon_ = 1LL;
521 VLOG(3) << "Number of nodes in the graph = " << graph_->num_nodes();
522 VLOG(3) << "Number of arcs in the graph = " << graph_->num_arcs();
523 const CostValue threshold =
524 std::numeric_limits<CostValue>::max() / (2 * cost_scaling_factor_);
525 for (ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
526 if (scaled_arc_unit_cost_[arc] > threshold ||
527 scaled_arc_unit_cost_[arc] < -threshold) {
528 status_ = BAD_COST_RANGE;
529 return false;
530 }
531 const CostValue cost = scaled_arc_unit_cost_[arc] * cost_scaling_factor_;
532 scaled_arc_unit_cost_.Set(arc, cost);
533 scaled_arc_unit_cost_.Set(Opposite(arc), -cost);
534 epsilon_ = std::max(epsilon_, MathUtil::Abs(cost));
535 }
536
537 // Since epsilon_ is currently the largest scaled cost, as long as our
538 // node potentials stay above this threshold, we can correctly compute
539 // potential - epsilon or cost + potential_diff.
540 overflow_threshold_ = std::numeric_limits<CostValue>::min() + epsilon_;
541
542 VLOG(3) << "Initial epsilon = " << epsilon_;
543 VLOG(3) << "Cost scaling factor = " << cost_scaling_factor_;
544 return true;
545}
546
547template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
548void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UnscaleCosts() {
549 SCOPED_TIME_STAT(&stats_);
550 for (ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
551 const CostValue cost = scaled_arc_unit_cost_[arc] / cost_scaling_factor_;
552 scaled_arc_unit_cost_.Set(arc, cost);
553 scaled_arc_unit_cost_.Set(Opposite(arc), -cost);
554 }
555 cost_scaling_factor_ = 1;
556}
557
558template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
559bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Optimize() {
560 const CostValue kEpsilonMin = 1LL;
561 num_relabels_since_last_price_update_ = 0;
562 do {
563 // Avoid epsilon_ == 0.
564 epsilon_ = std::max(epsilon_ / alpha_, kEpsilonMin);
565 VLOG(3) << "Epsilon changed to: " << epsilon_;
566 if (!Refine()) return false;
567 } while (epsilon_ != 1LL);
568 return true;
569}
570
571template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
572void GenericMinCostFlow<Graph, ArcFlowType,
573 ArcScaledCostType>::SaturateAdmissibleArcs() {
574 SCOPED_TIME_STAT(&stats_);
575 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
576 const CostValue tail_potential = node_potential_[node];
577 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
578 first_admissible_arc_[node]);
579 it.Ok(); it.Next()) {
580 const ArcIndex arc = it.Index();
581 if (FastIsAdmissible(arc, tail_potential)) {
582 FastPushFlow(residual_arc_capacity_[arc], arc, node);
583 }
584 }
585
586 // We just saturated all the admissible arcs, so there are no arcs with a
587 // positive residual capacity that are incident to the current node.
588 // Moreover, during the course of the algorithm, if the residual capacity of
589 // such an arc becomes positive again, then the arc is still not admissible
590 // until we relabel the node (because the reverse arc was admissible for
591 // this to happen). In conclusion, the optimization below is correct.
592 first_admissible_arc_[node] = Graph::kNilArc;
593 }
594}
595
596template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
597void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::PushFlow(
598 FlowQuantity flow, ArcIndex arc) {
599 SCOPED_TIME_STAT(&stats_);
600 FastPushFlow(flow, arc, Tail(arc));
601}
602
603template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
604void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastPushFlow(
606 SCOPED_TIME_STAT(&stats_);
607 DCHECK_EQ(Tail(arc), tail);
608 DCHECK_GT(residual_arc_capacity_[arc], 0);
609 DCHECK_LE(flow, residual_arc_capacity_[arc]);
610 // Reduce the residual capacity on the arc by flow.
611 residual_arc_capacity_.Set(arc, residual_arc_capacity_[arc] - flow);
612 // Increase the residual capacity on the opposite arc by flow.
613 const ArcIndex opposite = Opposite(arc);
614 residual_arc_capacity_.Set(opposite, residual_arc_capacity_[opposite] + flow);
615 // Update the excesses at the tail and head of the arc.
616 node_excess_[tail] -= flow;
617 node_excess_[Head(arc)] += flow;
618}
619
620template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
621void GenericMinCostFlow<Graph, ArcFlowType,
622 ArcScaledCostType>::InitializeActiveNodeStack() {
623 SCOPED_TIME_STAT(&stats_);
624 DCHECK(active_nodes_.empty());
625 for (NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
626 if (IsActive(node)) {
627 active_nodes_.push(node);
628 }
629 }
630}
631
632template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
633bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UpdatePrices() {
634 SCOPED_TIME_STAT(&stats_);
635
636 // The algorithm works as follows. Start with a set of nodes S containing all
637 // the nodes with negative excess. Expand the set along reverse admissible
638 // arcs. If at the end, the complement of S contains at least one node with
639 // positive excess, relabel all the nodes in the complement of S by
640 // subtracting epsilon from their current potential. See the paper cited in
641 // the .h file.
642 //
643 // After this relabeling is done, the heuristic is reapplied by extending S as
644 // much as possible, relabeling the complement of S, and so on until there is
645 // no node with positive excess that is not in S. Note that this is not
646 // described in the paper.
647 //
648 // Note(user): The triggering mechanism of this UpdatePrices() is really
649 // important; if it is not done properly it may degrade performance!
650
651 // This represents the set S.
652 const NodeIndex num_nodes = graph_->num_nodes();
653 std::vector<NodeIndex> bfs_queue;
654 std::vector<bool> node_in_queue(num_nodes, false);
655
656 // This is used to update the potential of the nodes not in S.
657 const CostValue kMinCostValue = std::numeric_limits<CostValue>::min();
658 std::vector<CostValue> min_non_admissible_potential(num_nodes, kMinCostValue);
659 std::vector<NodeIndex> nodes_to_process;
660
661 // Sum of the positive excesses out of S, used for early exit.
662 FlowQuantity remaining_excess = 0;
663
664 // First consider the nodes which have a negative excess.
665 for (NodeIndex node = 0; node < num_nodes; ++node) {
666 if (node_excess_[node] < 0) {
667 bfs_queue.push_back(node);
668 node_in_queue[node] = true;
669
670 // This uses the fact that the sum of excesses is always 0.
671 remaining_excess -= node_excess_[node];
672 }
673 }
674
675 // All the nodes not yet in the bfs_queue will have their potential changed by
676 // +potential_delta (which becomes more and more negative at each pass). This
677 // update is applied when a node is pushed into the queue and at the end of
678 // the function for the nodes that are still unprocessed.
679 CostValue potential_delta = 0;
680
681 int queue_index = 0;
682 while (remaining_excess > 0) {
683 // Reverse BFS that expands S as much as possible in the reverse admissible
684 // graph. Once S cannot be expanded anymore, perform a relabeling on the
685 // nodes not in S but that can reach it in one arc and try to expand S
686 // again.
687 for (; queue_index < bfs_queue.size(); ++queue_index) {
688 DCHECK_GE(num_nodes, bfs_queue.size());
689 const NodeIndex node = bfs_queue[queue_index];
690 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
691 it.Next()) {
692 const NodeIndex head = Head(it.Index());
693 if (node_in_queue[head]) continue;
694 const ArcIndex opposite_arc = Opposite(it.Index());
695 if (residual_arc_capacity_[opposite_arc] > 0) {
696 node_potential_[head] += potential_delta;
697 if (node_potential_[head] < overflow_threshold_) {
698 status_ = BAD_COST_RANGE;
699 return false;
700 }
701 if (ReducedCost(opposite_arc) < 0) {
702 DCHECK(IsAdmissible(opposite_arc));
703
704 // TODO(user): Try to steal flow if node_excess_[head] > 0.
705 // An initial experiment didn't show a big speedup though.
706
707 remaining_excess -= node_excess_[head];
708 if (remaining_excess == 0) {
709 node_potential_[head] -= potential_delta;
710 break;
711 }
712 bfs_queue.push_back(head);
713 node_in_queue[head] = true;
714 if (potential_delta < 0) {
715 first_admissible_arc_[head] =
716 GetFirstOutgoingOrOppositeIncomingArc(head);
717 }
718 } else {
719 // The opposite_arc is not admissible but is in the residual graph;
720 // this updates its min_non_admissible_potential.
721 node_potential_[head] -= potential_delta;
722 if (min_non_admissible_potential[head] == kMinCostValue) {
723 nodes_to_process.push_back(head);
724 }
725 min_non_admissible_potential[head] = std::max(
726 min_non_admissible_potential[head],
727 node_potential_[node] - scaled_arc_unit_cost_[opposite_arc]);
728 }
729 }
730 }
731 if (remaining_excess == 0) break;
732 }
733 if (remaining_excess == 0) break;
734
735 // Decrease by as much as possible instead of decreasing by epsilon.
736 // TODO(user): Is it worth the extra loop?
737 CostValue max_potential_diff = kMinCostValue;
738 for (int i = 0; i < nodes_to_process.size(); ++i) {
739 const NodeIndex node = nodes_to_process[i];
740 if (node_in_queue[node]) continue;
741 max_potential_diff =
742 std::max(max_potential_diff,
743 min_non_admissible_potential[node] - node_potential_[node]);
744 if (max_potential_diff == potential_delta) break;
745 }
746 DCHECK_LE(max_potential_diff, potential_delta);
747 potential_delta = max_potential_diff - epsilon_;
748
749 // Loop over nodes_to_process_ and for each node, apply the first of the
750 // rules below that match or leave it in the queue for later iteration:
751 // - Remove it if it is already in the queue.
752 // - If the node is connected to S by an admissible arc after it is
753 // relabeled by +potential_delta, add it to bfs_queue_ and remove it from
754 // nodes_to_process.
755 int index = 0;
756 for (int i = 0; i < nodes_to_process.size(); ++i) {
757 const NodeIndex node = nodes_to_process[i];
758 if (node_in_queue[node]) continue;
759 if (node_potential_[node] + potential_delta <
760 min_non_admissible_potential[node]) {
761 node_potential_[node] += potential_delta;
762 if (node_potential_[node] < overflow_threshold_) {
763 status_ = BAD_COST_RANGE;
764 return false;
765 }
766 first_admissible_arc_[node] =
767 GetFirstOutgoingOrOppositeIncomingArc(node);
768 bfs_queue.push_back(node);
769 node_in_queue[node] = true;
770 remaining_excess -= node_excess_[node];
771 continue;
772 }
773
774 // Keep the node for later iteration.
775 nodes_to_process[index] = node;
776 ++index;
777 }
778 nodes_to_process.resize(index);
779 }
780
781 // Update the potentials of the nodes not yet processed.
782 if (potential_delta == 0) return true;
783 for (NodeIndex node = 0; node < num_nodes; ++node) {
784 if (!node_in_queue[node]) {
785 node_potential_[node] += potential_delta;
786 if (node_potential_[node] < overflow_threshold_) {
787 status_ = BAD_COST_RANGE;
788 return false;
789 }
790 first_admissible_arc_[node] = GetFirstOutgoingOrOppositeIncomingArc(node);
791 }
792 }
793 return true;
794}
795
796template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
797bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Refine() {
798 SCOPED_TIME_STAT(&stats_);
799 SaturateAdmissibleArcs();
800 InitializeActiveNodeStack();
801
802 const NodeIndex num_nodes = graph_->num_nodes();
803 while (!active_nodes_.empty()) {
804 // TODO(user): Experiment with different factors in front of num_nodes.
805 if (num_relabels_since_last_price_update_ >= num_nodes) {
806 num_relabels_since_last_price_update_ = 0;
807 if (use_price_update_) {
808 if (!UpdatePrices()) return false;
809 }
810 }
811 const NodeIndex node = active_nodes_.top();
812 active_nodes_.pop();
813 DCHECK(IsActive(node));
814 if (!Discharge(node)) return false;
815 }
816 return true;
817}
818
819template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
820bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Discharge(
821 NodeIndex node) {
822 SCOPED_TIME_STAT(&stats_);
823 while (true) {
824 // The node is initially active, and we exit as soon as it becomes
825 // inactive.
826 DCHECK(IsActive(node));
827 const CostValue tail_potential = node_potential_[node];
828 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
829 first_admissible_arc_[node]);
830 it.Ok(); it.Next()) {
831 const ArcIndex arc = it.Index();
832 if (!FastIsAdmissible(arc, tail_potential)) continue;
833
834 // We look ahead to see if this node can accept the flow or will need
835 // to be relabeled later in which case we do it now. Note that this will
836 // just be skipped for self-loop so it is fine.
837 const NodeIndex head = Head(arc);
838 if (node_excess_[head] >= 0 && !NodeHasAdmissibleArc(head)) {
839 // Relabel head and skip if the arc is not admissible anymore.
840 if (!Relabel(head)) return false;
841 if (!FastIsAdmissible(arc, tail_potential)) continue;
842 }
843
844 const FlowQuantity delta =
845 std::min(node_excess_[node],
846 static_cast<FlowQuantity>(residual_arc_capacity_[arc]));
847 const bool head_active_before_push = IsActive(head);
848 FastPushFlow(delta, arc, node);
849 if (IsActive(head) && !head_active_before_push) {
850 active_nodes_.push(head);
851 }
852
853 if (node_excess_[node] == 0) {
854 // arc may still be admissible.
855 first_admissible_arc_[node] = arc;
856 return true;
857 }
858 }
859 if (!Relabel(node)) return false;
860 }
861}
862
863template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
864bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
865 NodeHasAdmissibleArc(NodeIndex node) {
866 SCOPED_TIME_STAT(&stats_);
867 const CostValue tail_potential = node_potential_[node];
868 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
869 first_admissible_arc_[node]);
870 it.Ok(); it.Next()) {
871 const ArcIndex arc = it.Index();
872 if (FastIsAdmissible(arc, tail_potential)) {
873 first_admissible_arc_[node] = arc;
874 return true;
875 }
876 }
877 return false;
878}
879
880// Note that we only relabel if there is no leaving admissible arc.
881template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
882bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Relabel(
883 NodeIndex node) {
884 SCOPED_TIME_STAT(&stats_);
885 DCHECK(CheckRelabelPrecondition(node));
886 ++num_relabels_since_last_price_update_;
887
888 // By setting node_potential_[node] to the guaranteed_new_potential we are
889 // sure to keep epsilon-optimality of the pseudo-flow. Note that we could
890 // return right away with this value, but we prefer to check that this value
891 // will lead to at least one admissible arc, and if not, to decrease the
892 // potential as much as possible.
893 const CostValue guaranteed_new_potential = node_potential_[node] - epsilon_;
894 if (guaranteed_new_potential < overflow_threshold_) {
895 status_ = BAD_COST_RANGE;
896 return false;
897 }
898
899 // This will be updated to contain the minimum node potential for which
900 // the node has no admissible arc. We know that:
901 // - min_non_admissible_potential <= node_potential_[node]
902 // - We can set the new node potential to min_non_admissible_potential -
903 // epsilon_ and still keep the epsilon-optimality of the pseudo flow.
904 const CostValue kMinCostValue = std::numeric_limits<CostValue>::min();
905 CostValue min_non_admissible_potential = kMinCostValue;
906
907 // The following variables help setting the first_admissible_arc_[node] to a
908 // value different from GetFirstOutgoingOrOppositeIncomingArc(node) which
909 // avoids looking again at some arcs.
910 CostValue previous_min_non_admissible_potential = kMinCostValue;
911 ArcIndex first_arc = Graph::kNilArc;
912
913 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
914 it.Next()) {
915 const ArcIndex arc = it.Index();
916 if (residual_arc_capacity_[arc] > 0) {
917 const CostValue min_non_admissible_potential_for_arc =
918 node_potential_[Head(arc)] - scaled_arc_unit_cost_[arc];
919 // We test this condition first as it is more probable that the first arc
920 // with residual capacity will be admissible if we reduce the node
921 // potential by epsilon.
922 if (min_non_admissible_potential_for_arc > guaranteed_new_potential) {
923 // We found an admissible arc for the guaranteed_new_potential. We
924 // stop right now instead of trying to compute the minimum possible
925 // new potential that keeps the epsilon-optimality of the pseudo flow.
926 node_potential_[node] = guaranteed_new_potential;
927 first_admissible_arc_[node] = arc;
928 return true;
929 }
930 if (min_non_admissible_potential_for_arc > min_non_admissible_potential) {
931 previous_min_non_admissible_potential = min_non_admissible_potential;
932 min_non_admissible_potential = min_non_admissible_potential_for_arc;
933 first_arc = arc;
934 }
935 }
936 }
937
938 // No residual arc leaves this node!
939 //
940 // TODO(user): This can be dealt with before the aglorithm start so that we
941 // do not need to test it here.
942 if (min_non_admissible_potential == kMinCostValue) {
943 if (node_excess_[node] != 0) {
944 // Note that this infeasibility detection is incomplete.
945 // Only max flow can detect that a min-cost flow problem is infeasible.
946 status_ = INFEASIBLE;
947 return false;
948 } else {
949 // This source saturates all its arcs, we can actually decrease the
950 // potential by as much as we want.
951 //
952 // TODO(user): Set it to a minimum value? but be careful of overflow.
953 node_potential_[node] = guaranteed_new_potential;
954 first_admissible_arc_[node] = Graph::kNilArc;
955 }
956 return true;
957 }
958
959 // We decrease the potential as much as possible, but we do not know the first
960 // admissible arc (most of the time). Keeping the
961 // previous_min_non_admissible_potential makes it faster by a few percent.
962 if (min_non_admissible_potential < overflow_threshold_) {
963 status_ = BAD_COST_RANGE;
964 return false;
965 }
966 const CostValue new_potential = min_non_admissible_potential - epsilon_;
967 if (new_potential < overflow_threshold_) {
968 status_ = BAD_COST_RANGE;
969 return false;
970 }
971 node_potential_[node] = new_potential;
972 if (previous_min_non_admissible_potential <= new_potential) {
973 first_admissible_arc_[node] = first_arc;
974 } else {
975 // We have no indication of what may be the first admissible arc.
976 first_admissible_arc_[node] = GetFirstOutgoingOrOppositeIncomingArc(node);
977 }
978 return true;
979}
980
981template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
982typename Graph::ArcIndex
983GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Opposite(
984 ArcIndex arc) const {
985 return Graphs<Graph>::OppositeArc(*graph_, arc);
986}
987
988template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
989bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcValid(
990 ArcIndex arc) const {
991 return Graphs<Graph>::IsArcValid(*graph_, arc);
992}
993
994template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
995bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcDirect(
996 ArcIndex arc) const {
997 DCHECK(IsArcValid(arc));
998 return arc >= 0;
999}
1000
1001// Explicit instantiations that can be used by a client.
1002//
1003// TODO(user): Move this code out of a .cc file and include it at the end of
1004// the header so it can work with any graph implementation?
1005template class GenericMinCostFlow<StarGraph>;
1006template class GenericMinCostFlow<::util::ReverseArcListGraph<>>;
1007template class GenericMinCostFlow<::util::ReverseArcStaticGraph<>>;
1008template class GenericMinCostFlow<::util::ReverseArcMixedGraph<>>;
1009template class GenericMinCostFlow<
1011template class GenericMinCostFlow<::util::ReverseArcListGraph<int64_t, int64_t>,
1012 int64_t, int64_t>;
1013
1014// A more memory-efficient version for large graphs.
1015template class GenericMinCostFlow<
1017 /*ArcFlowType=*/int16_t,
1018 /*ArcScaledCostType=*/int32_t>;
1019
1021 ArcIndex reserve_num_arcs) {
1022 if (reserve_num_nodes > 0) {
1023 node_supply_.reserve(reserve_num_nodes);
1024 }
1025 if (reserve_num_arcs > 0) {
1026 arc_tail_.reserve(reserve_num_arcs);
1027 arc_head_.reserve(reserve_num_arcs);
1028 arc_capacity_.reserve(reserve_num_arcs);
1029 arc_cost_.reserve(reserve_num_arcs);
1030 arc_permutation_.reserve(reserve_num_arcs);
1031 arc_flow_.reserve(reserve_num_arcs);
1032 }
1033}
1034
1036 ResizeNodeVectors(node);
1037 node_supply_[node] = supply;
1038}
1039
1042 FlowQuantity capacity,
1043 CostValue unit_cost) {
1044 ResizeNodeVectors(std::max(tail, head));
1045 const ArcIndex arc = arc_tail_.size();
1046 arc_tail_.push_back(tail);
1047 arc_head_.push_back(head);
1048 arc_capacity_.push_back(capacity);
1049 arc_cost_.push_back(unit_cost);
1050 return arc;
1051}
1052
1053ArcIndex SimpleMinCostFlow::PermutedArc(ArcIndex arc) {
1054 return arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
1055}
1056
1057SimpleMinCostFlow::Status SimpleMinCostFlow::SolveWithPossibleAdjustment(
1058 SupplyAdjustment adjustment) {
1059 optimal_cost_ = 0;
1060 maximum_flow_ = 0;
1061 arc_flow_.clear();
1062 const NodeIndex num_nodes = node_supply_.size();
1063 const ArcIndex num_arcs = arc_capacity_.size();
1064 if (num_nodes == 0) return OPTIMAL;
1065
1066 int supply_node_count = 0, demand_node_count = 0;
1067 FlowQuantity total_supply = 0, total_demand = 0;
1068 for (NodeIndex node = 0; node < num_nodes; ++node) {
1069 if (node_supply_[node] > 0) {
1070 ++supply_node_count;
1071 total_supply += node_supply_[node];
1072 } else if (node_supply_[node] < 0) {
1073 ++demand_node_count;
1074 total_demand -= node_supply_[node];
1075 }
1076 }
1077 if (adjustment == DONT_ADJUST && total_supply != total_demand) {
1078 return UNBALANCED;
1079 }
1080
1081 // Feasibility checking, and possible supply/demand adjustment, is done by:
1082 // 1. Creating a new source and sink node.
1083 // 2. Taking all nodes that have a non-zero supply or demand and
1084 // connecting them to the source or sink respectively. The arc thus
1085 // added has a capacity of the supply or demand.
1086 // 3. Computing the max flow between the new source and sink.
1087 // 4. If adjustment isn't being done, checking that the max flow is equal
1088 // to the total supply/demand (and returning INFEASIBLE if it isn't).
1089 // 5. Running min-cost max-flow on this augmented graph, using the max
1090 // flow computed in step 3 as the supply of the source and demand of
1091 // the sink.
1092 const ArcIndex augmented_num_arcs =
1093 num_arcs + supply_node_count + demand_node_count;
1094 const NodeIndex source = num_nodes;
1095 const NodeIndex sink = num_nodes + 1;
1096 const NodeIndex augmented_num_nodes = num_nodes + 2;
1097
1098 Graph graph(augmented_num_nodes, augmented_num_arcs);
1099 for (ArcIndex arc = 0; arc < num_arcs; ++arc) {
1100 graph.AddArc(arc_tail_[arc], arc_head_[arc]);
1101 }
1102
1103 for (NodeIndex node = 0; node < num_nodes; ++node) {
1104 if (node_supply_[node] > 0) {
1105 graph.AddArc(source, node);
1106 } else if (node_supply_[node] < 0) {
1107 graph.AddArc(node, sink);
1108 }
1109 }
1110
1111 graph.Build(&arc_permutation_);
1112
1113 {
1114 GenericMaxFlow<Graph> max_flow(&graph, source, sink);
1115 ArcIndex arc;
1116 for (arc = 0; arc < num_arcs; ++arc) {
1117 max_flow.SetArcCapacity(PermutedArc(arc), arc_capacity_[arc]);
1118 }
1119 for (NodeIndex node = 0; node < num_nodes; ++node) {
1120 if (node_supply_[node] != 0) {
1121 max_flow.SetArcCapacity(PermutedArc(arc), std::abs(node_supply_[node]));
1122 ++arc;
1123 }
1124 }
1125 CHECK_EQ(arc, augmented_num_arcs);
1126 if (!max_flow.Solve()) {
1127 LOG(ERROR) << "Max flow could not be computed.";
1128 switch (max_flow.status()) {
1130 return NOT_SOLVED;
1132 LOG(ERROR)
1133 << "Max flow failed but claimed to have an optimal solution";
1134 ABSL_FALLTHROUGH_INTENDED;
1135 default:
1136 return BAD_RESULT;
1137 }
1138 }
1139 maximum_flow_ = max_flow.GetOptimalFlow();
1140 }
1141
1142 if (adjustment == DONT_ADJUST && maximum_flow_ != total_supply) {
1143 return INFEASIBLE;
1144 }
1145
1146 GenericMinCostFlow<Graph> min_cost_flow(&graph);
1147 ArcIndex arc;
1148 for (arc = 0; arc < num_arcs; ++arc) {
1149 ArcIndex permuted_arc = PermutedArc(arc);
1150 min_cost_flow.SetArcUnitCost(permuted_arc, arc_cost_[arc]);
1151 min_cost_flow.SetArcCapacity(permuted_arc, arc_capacity_[arc]);
1152 }
1153 for (NodeIndex node = 0; node < num_nodes; ++node) {
1154 if (node_supply_[node] != 0) {
1155 ArcIndex permuted_arc = PermutedArc(arc);
1156 min_cost_flow.SetArcCapacity(permuted_arc, std::abs(node_supply_[node]));
1157 min_cost_flow.SetArcUnitCost(permuted_arc, 0);
1158 ++arc;
1159 }
1160 }
1161 min_cost_flow.SetNodeSupply(source, maximum_flow_);
1162 min_cost_flow.SetNodeSupply(sink, -maximum_flow_);
1163 min_cost_flow.SetCheckFeasibility(false);
1164 min_cost_flow.SetPriceScaling(scale_prices_);
1165
1166 arc_flow_.resize(num_arcs);
1167 if (min_cost_flow.Solve()) {
1168 optimal_cost_ = min_cost_flow.GetOptimalCost();
1169 for (arc = 0; arc < num_arcs; ++arc) {
1170 arc_flow_[arc] = min_cost_flow.Flow(PermutedArc(arc));
1171 }
1172 }
1173 return min_cost_flow.status();
1174}
1175
1176CostValue SimpleMinCostFlow::OptimalCost() const { return optimal_cost_; }
1177
1178FlowQuantity SimpleMinCostFlow::MaximumFlow() const { return maximum_flow_; }
1179
1181 return arc_flow_[arc];
1182}
1183
1184NodeIndex SimpleMinCostFlow::NumNodes() const { return node_supply_.size(); }
1185
1186ArcIndex SimpleMinCostFlow::NumArcs() const { return arc_tail_.size(); }
1187
1188ArcIndex SimpleMinCostFlow::Tail(ArcIndex arc) const { return arc_tail_[arc]; }
1189
1190ArcIndex SimpleMinCostFlow::Head(ArcIndex arc) const { return arc_head_[arc]; }
1191
1193 return arc_capacity_[arc];
1194}
1195
1197 return arc_cost_[arc];
1198}
1199
1201 return node_supply_[node];
1202}
1203
1204void SimpleMinCostFlow::ResizeNodeVectors(NodeIndex node) {
1205 if (node < node_supply_.size()) return;
1206 node_supply_.resize(node + 1);
1207}
1208
1209} // namespace operations_research
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Iterator class for traversing the incoming arcs associated to a given node.
bool Ok() const
Returns true unless all the incoming arcs have been traversed.
ArcIndexType Index() const
Returns the index of the arc currently pointed to by the iterator.
NodeIndexType Tail(const ArcIndexType arc) const
Returns the tail or start-node of arc.
void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity)
Sets the capacity for arc to new_capacity.
Definition max_flow.cc:194
bool Solve()
Returns true if a maximum flow was solved.
Definition max_flow.cc:353
FlowQuantity GetOptimalFlow() const
Returns the total flow found by the algorithm.
Definition max_flow.h:377
FlowQuantity Flow(ArcIndex arc) const
Definition max_flow.h:381
void SetArcUnitCost(ArcIndex arc, ArcScaledCostType unit_cost)
Sets the unit cost for the given arc.
FlowQuantity InitialSupply(NodeIndex node) const
Returns the initial supply at a given node.
bool Solve()
Solves the problem, returning true if a min-cost flow could be found.
bool CheckFeasibility(std::vector< NodeIndex > *infeasible_supply_node, std::vector< NodeIndex > *infeasible_demand_node)
void SetArcCapacity(ArcIndex arc, ArcFlowType new_capacity)
Sets the capacity for the given arc.
FlowQuantity Capacity(ArcIndex arc) const
Returns the capacity of the given arc.
void SetArcFlow(ArcIndex arc, ArcFlowType new_flow)
FlowQuantity Supply(NodeIndex node) const
void SetNodeSupply(NodeIndex node, FlowQuantity supply)
FlowQuantity Flow(ArcIndex arc) const
CostValue UnitCost(ArcIndex arc) const
Returns the unscaled cost for the given arc.
FlowQuantity FeasibleSupply(NodeIndex node) const
static T Abs(const T x)
Definition mathutil.h:96
FlowQuantity Supply(NodeIndex node) const
ArcIndex AddArcWithCapacityAndUnitCost(NodeIndex tail, NodeIndex head, FlowQuantity capacity, CostValue unit_cost)
FlowQuantity Capacity(ArcIndex arc) const
void SetNodeSupply(NodeIndex node, FlowQuantity supply)
CostValue UnitCost(ArcIndex arc) const
NodeIndex Tail(ArcIndex arc) const
FlowQuantity Flow(ArcIndex arc) const
SimpleMinCostFlow(NodeIndex reserve_num_nodes=0, ArcIndex reserve_num_arcs=0)
NodeIndex Head(ArcIndex arc) const
NodeIndexType num_nodes() const
Returns the number of nodes in the graph.
NodeIndexType Head(const ArcIndexType arc) const
Returns the head or end-node of arc.
GraphType graph
GurobiMPCallbackContext * context
int arc
int index
ABSL_FLAG(int64_t, min_cost_flow_alpha, 5, "Divide factor for epsilon at each refine step.")
In SWIG mode, we don't want anything besides these top-level includes.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapProd(int64_t x, int64_t y)
util::ReverseArcStaticGraph Graph
Type of graph to use.
ListGraph Graph
Defining the simplest Graph interface as Graph for convenience.
Definition graph.h:2407
int64_t delta
Definition resource.cc:1709
int head
int tail
#define IF_STATS_ENABLED(instructions)
Definition stats.h:417
#define SCOPED_TIME_STAT(stats)
Definition stats.h:418
static ArcIndex ArcReservation(const Graph &graph)
Definition graphs.h:41
static bool IsArcValid(const Graph &graph, ArcIndex arc)
Definition graphs.h:35
static ArcIndex OppositeArc(const Graph &graph, ArcIndex arc)
Definition graphs.h:32
static NodeIndex NodeReservation(const Graph &graph)
Definition graphs.h:38