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