OR-Tools  9.1
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"
23 #include "ortools/base/mathutil.h"
24 #include "ortools/graph/graph.h"
25 #include "ortools/graph/graphs.h"
26 #include "ortools/graph/max_flow.h"
27 
28 // TODO(user): Remove these flags and expose the parameters in the API.
29 // New clients, please do not use these flags!
30 ABSL_FLAG(int64_t, min_cost_flow_alpha, 5,
31  "Divide factor for epsilon at each refine step.");
32 ABSL_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.");
36 ABSL_FLAG(bool, min_cost_flow_check_balance, true,
37  "Check that the sum of supplies is equal to the sum of demands.");
38 ABSL_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");
42 ABSL_FLAG(bool, min_cost_flow_check_result, true,
43  "Check that the result is valid.");
44 
45 namespace operations_research {
46 
47 template <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 
90 template <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 
100 template <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 
110 template <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 
149 template <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 
161 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
162 bool 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 
193 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
194 bool 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 
224 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
225 bool 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 
250 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
251 bool 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 
268 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
269 std::string
270 GenericMinCostFlow<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 
293 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
294 bool GenericMinCostFlow<Graph, ArcFlowType, 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;
354  }
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 
381 template <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;
392 }
393 
394 template <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  }
402 }
403 
404 // We use the equations given in the comment of residual_arc_capacity_.
405 template <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 
416 template <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 
424 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
426  NodeIndex node) const {
427  DCHECK(graph_->IsNodeValid(node));
428  return node_excess_[node];
429 }
430 
431 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
434  NodeIndex node) const {
435  return initial_node_excess_[node];
436 }
437 
438 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
441  NodeIndex node) const {
442  return feasible_node_excess_[node];
443 }
444 
445 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
447  ArcIndex arc) const {
448  return FastIsAdmissible(arc, node_potential_[Tail(arc)]);
449 }
450 
451 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
452 bool 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 
459 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
460 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsActive(
461  NodeIndex node) const {
462  return node_excess_[node] > 0;
463 }
464 
465 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
466 CostValue
467 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ReducedCost(
468  ArcIndex arc) const {
469  return FastReducedCost(arc, node_potential_[Tail(arc)]);
470 }
471 
472 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
473 CostValue
474 GenericMinCostFlow<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 
485 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
487 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
488  GetFirstOutgoingOrOppositeIncomingArc(NodeIndex node) const {
489  OutgoingOrOppositeIncomingArcIterator arc_it(*graph_, node);
490  return arc_it.Index();
491 }
492 
493 template <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 
534 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
535 void 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 
543 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
544 void 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 
560 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
561 void 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 
571 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
572 void 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 
586 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
587 void 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 
611 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
612 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::PushFlow(
613  FlowQuantity flow, ArcIndex arc) {
614  SCOPED_TIME_STAT(&stats_);
615  FastPushFlow(flow, arc, Tail(arc));
616 }
617 
618 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
619 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastPushFlow(
620  FlowQuantity flow, ArcIndex arc, NodeIndex tail) {
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 
636 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
637 void 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 
648 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
649 void 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 
799 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
800 void 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 
821 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
822 void 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 
856 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
857 bool 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 
880 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
881 void 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 
962 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
963 typename Graph::ArcIndex
964 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Opposite(
965  ArcIndex arc) const {
966  return Graphs<Graph>::OppositeArc(*graph_, arc);
967 }
968 
969 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
970 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcValid(
971  ArcIndex arc) const {
972  return Graphs<Graph>::IsArcValid(*graph_, arc);
973 }
974 
975 template <typename Graph, typename ArcFlowType, typename ArcScaledCostType>
976 bool 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?
986 template class GenericMinCostFlow<StarGraph>;
987 template class GenericMinCostFlow<::util::ReverseArcListGraph<>>;
988 template class GenericMinCostFlow<::util::ReverseArcStaticGraph<>>;
989 template class GenericMinCostFlow<::util::ReverseArcMixedGraph<>>;
990 template class GenericMinCostFlow<
992 
993 // A more memory-efficient version for large graphs.
994 template class GenericMinCostFlow<
996  /*ArcFlowType=*/int16_t,
997  /*ArcScaledCostType=*/int32_t>;
998 
999 SimpleMinCostFlow::SimpleMinCostFlow(NodeIndex reserve_num_nodes,
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 
1014 void SimpleMinCostFlow::SetNodeSupply(NodeIndex node, FlowQuantity supply) {
1015  ResizeNodeVectors(node);
1016  node_supply_[node] = supply;
1017 }
1018 
1019 ArcIndex SimpleMinCostFlow::AddArcWithCapacityAndUnitCost(NodeIndex tail,
1020  NodeIndex head,
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 
1032 ArcIndex SimpleMinCostFlow::PermutedArc(ArcIndex arc) {
1033  return arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
1034 }
1035 
1036 SimpleMinCostFlow::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()) {
1108  case MaxFlowStatusClass::NOT_SOLVED:
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 
1154 CostValue SimpleMinCostFlow::OptimalCost() const { return optimal_cost_; }
1155 
1156 FlowQuantity SimpleMinCostFlow::MaximumFlow() const { return maximum_flow_; }
1157 
1158 FlowQuantity SimpleMinCostFlow::Flow(ArcIndex arc) const {
1159  return arc_flow_[arc];
1160 }
1161 
1162 NodeIndex SimpleMinCostFlow::NumNodes() const { return node_supply_.size(); }
1163 
1164 ArcIndex SimpleMinCostFlow::NumArcs() const { return arc_tail_.size(); }
1165 
1166 ArcIndex SimpleMinCostFlow::Tail(ArcIndex arc) const { return arc_tail_[arc]; }
1167 
1168 ArcIndex SimpleMinCostFlow::Head(ArcIndex arc) const { return arc_head_[arc]; }
1169 
1170 FlowQuantity SimpleMinCostFlow::Capacity(ArcIndex arc) const {
1171  return arc_capacity_[arc];
1172 }
1173 
1174 CostValue SimpleMinCostFlow::UnitCost(ArcIndex arc) const {
1175  return arc_cost_[arc];
1176 }
1177 
1178 FlowQuantity SimpleMinCostFlow::Supply(NodeIndex node) const {
1179  return node_supply_[node];
1180 }
1181 
1182 void 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 head
FlowQuantity Flow(ArcIndex arc) const
Definition: max_flow.h:365
int64_t min
Definition: alldiff_cst.cc:139
#define VLOG(verboselevel)
Definition: base/logging.h:979
const int ERROR
Definition: log_severity.h:32
#define LOG(severity)
Definition: base/logging.h:416
#define SCOPED_TIME_STAT(stats)
Definition: stats.h:438
CpSolverResponse Solve(const CpModelProto &model_proto)
Solves the given CpModelProto and returns an instance of CpSolverResponse.
#define DCHECK_GT(val1, val2)
Definition: base/logging.h:891
int64_t tail
int64_t max
Definition: alldiff_cst.cc:140
Definition: cleanup.h:22
void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity)
Definition: max_flow.cc:176
int64_t capacity
int index
Definition: pack.cc:509
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:890
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
int64_t delta
Definition: resource.cc:1692
ListGraph Graph
Definition: graph.h:2361
int64_t cost
#define DCHECK(condition)
Definition: base/logging.h:885
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:886
NodeIndexType Head(const ArcIndexType arc) const
Definition: ebert_graph.h:298
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:888
ABSL_FLAG(int64_t, min_cost_flow_alpha, 5, "Divide factor for epsilon at each refine step.")
NodeIndexType Tail(const ArcIndexType arc) const
Definition: ebert_graph.h:1377
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
Definition: ebert_graph.h:1002
Collection of objects used to extend the Constraint Solver library.
GurobiMPCallbackContext * context
FlowQuantity GetOptimalFlow() const
Definition: max_flow.h:361
#define IF_STATS_ENABLED(instructions)
Definition: stats.h:437