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