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