23 #include "absl/flags/flag.h"
24 #include "absl/strings/str_format.h"
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.");
41 "Check that the sum of supplies is equal to the sum of demands.");
43 "Check that the magnitude of the costs will not exceed the "
44 "precision of the machine when scaled (multiplied) by the number "
47 "Check that the result is valid.");
51 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
57 residual_arc_capacity_(),
58 first_admissible_arc_(),
61 alpha_(
absl::GetFlag(FLAGS_min_cost_flow_alpha)),
62 cost_scaling_factor_(1),
63 scaled_arc_unit_cost_(),
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)) {
72 if (max_num_nodes > 0) {
73 node_excess_.
Reserve(0, max_num_nodes - 1);
75 node_potential_.
Reserve(0, max_num_nodes - 1);
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);
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);
93 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
96 DCHECK(graph_->IsNodeValid(node));
97 node_excess_.Set(node, supply);
98 initial_node_excess_.Set(node, supply);
100 feasibility_checked_ =
false;
103 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
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]);
110 feasibility_checked_ =
false;
113 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
116 DCHECK_LE(0, new_capacity);
117 DCHECK(IsArcDirect(
arc));
120 if (capacity_delta == 0) {
124 feasibility_checked_ =
false;
125 const FlowQuantity new_availability = free_capacity + capacity_delta;
126 if (new_availability >= 0) {
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]);
141 residual_arc_capacity_.Set(
arc, 0);
142 residual_arc_capacity_.Set(Opposite(
arc), new_capacity);
144 node_excess_.Set(
tail, node_excess_[
tail] + flow_excess);
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)]);
152 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
155 DCHECK(IsArcValid(
arc));
158 residual_arc_capacity_.Set(Opposite(
arc), new_flow);
159 residual_arc_capacity_.Set(
arc,
capacity - new_flow);
161 feasibility_checked_ =
false;
164 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
166 ArcScaledCostType>::CheckInputConsistency()
const {
168 uint64_t max_capacity = 0;
172 static_cast<uint64_t
>(residual_arc_capacity_[
arc]);
175 uint64_t total_flow = 0;
176 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
178 total_supply += excess;
180 total_flow += excess;
182 max_capacity + total_flow) {
183 LOG(DFATAL) <<
"Input consistency error: max capacity + flow exceed "
189 if (total_supply != 0) {
190 LOG(DFATAL) <<
"Input consistency error: unbalanced problem";
196 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
197 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckResult()
199 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
200 if (node_excess_[node] != 0) {
201 LOG(DFATAL) <<
"node_excess_[" << node <<
"] != 0";
204 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
208 if (residual_arc_capacity_[
arc] < 0) {
209 LOG(DFATAL) <<
"residual_arc_capacity_[" <<
arc <<
"] < 0";
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_ <<
").";
219 LOG(DFATAL) << DebugString(
"CheckResult ",
arc);
227 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
228 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckCostRange()
230 using UnsignedCostValue = uint64_t;
231 static_assert(
sizeof(UnsignedCostValue) >=
sizeof(
CostValue),
"");
232 UnsignedCostValue max_cost_magnitude = 0;
233 UnsignedCostValue min_cost_magnitude =
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);
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();
257 if (num_nodes == 0)
return true;
258 const UnsignedCostValue quotient = kMaxCost / num_nodes;
259 const UnsignedCostValue remainder = kMaxCost % num_nodes;
261 if (max_cost_magnitude > kMaxCost / 3)
return false;
262 if (3 * max_cost_magnitude < quotient)
return true;
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);
269 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
270 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
271 CheckRelabelPrecondition(
NodeIndex node)
const {
278 DCHECK_GE(node_excess_[node], 0);
279 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
282 DCHECK(!IsAdmissible(
arc)) << DebugString(
"CheckRelabelPrecondition:",
arc);
287 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
289 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::DebugString(
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, ",
307 node_potential_[
tail], node_potential_[
head], node_excess_[
tail],
312 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
315 std::vector<NodeIndex>*
const infeasible_demand_node) {
328 feasibility_checked_ =
false;
330 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
331 if (initial_node_excess_[node] != 0) {
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);
346 checker_graph.AddArc(graph_->Tail(
arc), graph_->Head(
arc));
347 DCHECK_EQ(
arc, new_arc);
348 checker.SetArcCapacity(new_arc, Capacity(
arc));
353 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
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;
365 if (total_supply != total_demand) {
366 LOG(DFATAL) <<
"total_supply(" << total_supply <<
") != total_demand("
367 << total_demand <<
").";
370 if (!checker.Solve()) {
371 LOG(DFATAL) <<
"Max flow could not be computed.";
375 feasible_node_excess_.SetAll(0);
376 for (StarGraph::OutgoingArcIterator it(checker_graph, source); it.Ok();
381 feasible_node_excess_.Set(node, flow);
382 if (infeasible_supply_node !=
nullptr) {
383 infeasible_supply_node->push_back(node);
386 for (StarGraph::IncomingArcIterator it(checker_graph, sink); it.Ok();
391 feasible_node_excess_.Set(node, -flow);
392 if (infeasible_demand_node !=
nullptr) {
393 infeasible_demand_node->push_back(node);
396 feasibility_checked_ =
true;
397 return optimal_max_flow == total_supply;
400 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
402 if (!feasibility_checked_) {
405 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
407 node_excess_.Set(node, excess);
408 initial_node_excess_.Set(node, excess);
413 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
416 if (IsArcDirect(
arc)) {
417 return residual_arc_capacity_[Opposite(
arc)];
419 return -residual_arc_capacity_[
arc];
424 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
428 if (IsArcDirect(
arc)) {
429 return residual_arc_capacity_[
arc] + residual_arc_capacity_[Opposite(
arc)];
435 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
438 DCHECK(IsArcValid(
arc));
439 DCHECK_EQ(uint64_t{1}, cost_scaling_factor_);
440 return scaled_arc_unit_cost_[
arc];
443 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
446 DCHECK(graph_->IsNodeValid(node));
447 return node_excess_[node];
450 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
454 return initial_node_excess_[node];
457 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
461 return feasible_node_excess_[node];
464 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
467 return FastIsAdmissible(
arc, node_potential_[Tail(
arc)]);
470 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
471 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
473 DCHECK_EQ(node_potential_[Tail(
arc)], tail_potential);
474 return residual_arc_capacity_[
arc] > 0 &&
475 FastReducedCost(
arc, tail_potential) < 0;
478 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
479 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsActive(
481 return node_excess_[node] > 0;
484 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
486 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ReducedCost(
488 return FastReducedCost(
arc, node_potential_[Tail(
arc)]);
491 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
493 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastReducedCost(
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)];
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();
512 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
515 if (absl::GetFlag(FLAGS_min_cost_flow_check_balance) &&
516 !CheckInputConsistency()) {
517 status_ = UNBALANCED;
520 if (absl::GetFlag(FLAGS_min_cost_flow_check_costs) && !CheckCostRange()) {
521 status_ = BAD_COST_RANGE;
524 if (check_feasibility_ && !CheckFeasibility(
nullptr,
nullptr)) {
528 node_potential_.SetAll(0);
529 ResetFirstAdmissibleArcs();
532 if (absl::GetFlag(FLAGS_min_cost_flow_check_result) && !CheckResult()) {
533 status_ = BAD_RESULT;
539 LOG(DFATAL) <<
"Status != OPTIMAL";
547 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
560 const CostValue flow_on_arc = residual_arc_capacity_[Opposite(
arc)];
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) {
569 return total_flow_cost;
572 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
574 ArcScaledCostType>::ResetFirstAdmissibleArcs() {
575 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
576 first_admissible_arc_.Set(node,
577 GetFirstOutgoingOrOppositeIncomingArc(node));
581 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
582 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ScaleCosts() {
584 cost_scaling_factor_ = graph_->num_nodes() + 1;
586 VLOG(3) <<
"Number of nodes in the graph = " << graph_->num_nodes();
587 VLOG(3) <<
"Number of arcs in the graph = " << graph_->num_arcs();
590 scaled_arc_unit_cost_.Set(
arc,
cost);
591 scaled_arc_unit_cost_.Set(Opposite(
arc), -
cost);
594 VLOG(3) <<
"Initial epsilon = " << epsilon_;
595 VLOG(3) <<
"Cost scaling factor = " << cost_scaling_factor_;
598 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
599 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UnscaleCosts() {
603 scaled_arc_unit_cost_.Set(
arc,
cost);
604 scaled_arc_unit_cost_.Set(Opposite(
arc), -
cost);
606 cost_scaling_factor_ = 1;
609 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
610 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Optimize() {
612 num_relabels_since_last_price_update_ = 0;
615 epsilon_ =
std::max(epsilon_ / alpha_, kEpsilonMin);
616 VLOG(3) <<
"Epsilon changed to: " << epsilon_;
618 }
while (epsilon_ != 1LL && status_ !=
INFEASIBLE);
624 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
625 void GenericMinCostFlow<
Graph, ArcFlowType,
626 ArcScaledCostType>::SaturateAdmissibleArcs() {
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()) {
634 if (FastIsAdmissible(
arc, tail_potential)) {
635 FastPushFlow(residual_arc_capacity_[
arc],
arc, node);
645 first_admissible_arc_[node] = Graph::kNilArc;
649 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
650 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::PushFlow(
653 FastPushFlow(flow,
arc, Tail(
arc));
656 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
657 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastPushFlow(
661 DCHECK_GT(residual_arc_capacity_[
arc], 0);
662 DCHECK_LE(flow, residual_arc_capacity_[
arc]);
664 residual_arc_capacity_.Set(
arc, residual_arc_capacity_[
arc] - flow);
667 residual_arc_capacity_.Set(opposite, residual_arc_capacity_[opposite] + flow);
669 node_excess_.Set(
tail, node_excess_[
tail] - flow);
671 node_excess_.Set(
head, node_excess_[
head] + flow);
674 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
675 void GenericMinCostFlow<
Graph, ArcFlowType,
676 ArcScaledCostType>::InitializeActiveNodeStack() {
678 DCHECK(active_nodes_.empty());
679 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
680 if (IsActive(node)) {
681 active_nodes_.push(node);
686 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
687 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UpdatePrices() {
706 const NodeIndex num_nodes = graph_->num_nodes();
707 std::vector<NodeIndex> bfs_queue;
708 std::vector<bool> node_in_queue(num_nodes,
false);
712 std::vector<CostValue> min_non_admissible_potential(num_nodes, kMinCostValue);
713 std::vector<NodeIndex> nodes_to_process;
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;
725 remaining_excess -= node_excess_[node];
736 while (remaining_excess > 0) {
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();
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));
757 remaining_excess -= node_excess_[
head];
758 if (remaining_excess == 0) {
759 node_potential_[
head] -= potential_delta;
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);
771 node_potential_[
head] -= potential_delta;
772 if (min_non_admissible_potential[
head] == kMinCostValue) {
773 nodes_to_process.push_back(
head);
776 min_non_admissible_potential[
head],
777 node_potential_[node] - scaled_arc_unit_cost_[opposite_arc]);
781 if (remaining_excess == 0)
break;
783 if (remaining_excess == 0)
break;
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;
793 min_non_admissible_potential[node] - node_potential_[node]);
794 if (max_potential_diff == potential_delta)
break;
796 DCHECK_LE(max_potential_diff, potential_delta);
797 potential_delta = max_potential_diff - epsilon_;
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];
821 nodes_to_process[
index] = node;
824 nodes_to_process.resize(
index);
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);
837 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
838 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Refine() {
840 SaturateAdmissibleArcs();
841 InitializeActiveNodeStack();
843 const NodeIndex num_nodes = graph_->num_nodes();
844 while (status_ !=
INFEASIBLE && !active_nodes_.empty()) {
846 if (num_relabels_since_last_price_update_ >= num_nodes) {
847 num_relabels_since_last_price_update_ = 0;
848 if (use_price_update_) {
852 const NodeIndex node = active_nodes_.top();
854 DCHECK(IsActive(node));
859 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
860 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Discharge(
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()) {
872 if (FastIsAdmissible(
arc, tail_potential)) {
874 if (!LookAhead(
arc, tail_potential,
head))
continue;
875 const bool head_active_before_push = IsActive(
head);
880 if (IsActive(
head) && !head_active_before_push) {
881 active_nodes_.push(
head);
883 if (node_excess_[node] == 0) {
885 first_admissible_arc_.Set(node,
arc);
894 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
895 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::LookAhead(
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()) {
906 if (FastIsAdmissible(
arc, tail_potential)) {
907 first_admissible_arc_.Set(node,
arc);
915 return FastIsAdmissible(in_arc, in_tail_potential);
918 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
919 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Relabel(
922 DCHECK(CheckRelabelPrecondition(node));
923 ++num_relabels_since_last_price_update_;
930 const CostValue guaranteed_new_potential = node_potential_[node] - epsilon_;
938 CostValue min_non_admissible_potential = kMinCostValue;
943 CostValue previous_min_non_admissible_potential = kMinCostValue;
944 ArcIndex first_arc = Graph::kNilArc;
946 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
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) {
957 node_potential_.Set(node, guaranteed_new_potential);
958 first_admissible_arc_.Set(node,
arc);
961 previous_min_non_admissible_potential = min_non_admissible_potential;
962 min_non_admissible_potential = min_non_admissible_potential_for_arc;
969 if (min_non_admissible_potential == kMinCostValue) {
970 if (node_excess_[node] != 0) {
974 LOG(ERROR) <<
"Infeasible problem.";
979 node_potential_.Set(node, guaranteed_new_potential);
980 first_admissible_arc_.Set(node,
981 GetFirstOutgoingOrOppositeIncomingArc(node));
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);
995 first_admissible_arc_.Set(node,
996 GetFirstOutgoingOrOppositeIncomingArc(node));
1000 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
1002 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Opposite(
1007 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
1008 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcValid(
1013 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
1014 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcDirect(
1016 DCHECK(IsArcValid(
arc));
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<
1032 template class GenericMinCostFlow<
1039 if (reserve_num_nodes > 0) {
1040 node_supply_.reserve(reserve_num_nodes);
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);
1053 ResizeNodeVectors(node);
1054 node_supply_[node] = supply;
1063 arc_tail_.push_back(
tail);
1064 arc_head_.push_back(
head);
1066 arc_cost_.push_back(unit_cost);
1071 return arc < arc_permutation_.size() ? arc_permutation_[
arc] :
arc;
1075 SupplyAdjustment adjustment) {
1079 const NodeIndex num_nodes = node_supply_.size();
1080 const ArcIndex num_arcs = arc_capacity_.size();
1081 if (num_nodes == 0)
return OPTIMAL;
1083 int supply_node_count = 0, demand_node_count = 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];
1094 if (adjustment == DONT_ADJUST && total_supply != total_demand) {
1109 const ArcIndex augmented_num_arcs =
1110 num_arcs + supply_node_count + demand_node_count;
1113 const NodeIndex augmented_num_nodes = num_nodes + 2;
1115 Graph graph(augmented_num_nodes, augmented_num_arcs);
1117 graph.AddArc(arc_tail_[
arc], arc_head_[
arc]);
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);
1128 graph.Build(&arc_permutation_);
1131 GenericMaxFlow<Graph> max_flow(&graph, source, sink);
1134 max_flow.SetArcCapacity(PermutedArc(
arc), arc_capacity_[
arc]);
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]));
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()) {
1150 <<
"Max flow failed but claimed to have an optimal solution";
1151 ABSL_FALLTHROUGH_INTENDED;
1156 maximum_flow_ = max_flow.GetOptimalFlow();
1159 if (adjustment == DONT_ADJUST && maximum_flow_ != total_supply) {
1163 GenericMinCostFlow<Graph> min_cost_flow(&graph);
1167 min_cost_flow.SetArcUnitCost(permuted_arc, arc_cost_[
arc]);
1168 min_cost_flow.SetArcCapacity(permuted_arc, arc_capacity_[
arc]);
1170 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1171 if (node_supply_[node] != 0) {
1173 min_cost_flow.SetArcCapacity(permuted_arc, std::abs(node_supply_[node]));
1174 min_cost_flow.SetArcUnitCost(permuted_arc, 0);
1178 min_cost_flow.SetNodeSupply(source, maximum_flow_);
1179 min_cost_flow.SetNodeSupply(sink, -maximum_flow_);
1180 min_cost_flow.SetCheckFeasibility(
false);
1182 arc_flow_.resize(num_arcs);
1183 if (min_cost_flow.Solve()) {
1184 optimal_cost_ = min_cost_flow.GetOptimalCost();
1186 arc_flow_[
arc] = min_cost_flow.Flow(PermutedArc(
arc));
1189 return min_cost_flow.status();
1197 return arc_flow_[
arc];
1209 return arc_capacity_[
arc];
1213 return arc_cost_[
arc];
1217 return node_supply_[node];
1220 void SimpleMinCostFlow::ResizeNodeVectors(
NodeIndex node) {
1221 if (node < node_supply_.size())
return;
1222 node_supply_.resize(node + 1);
CostValue UnitCost(ArcIndex arc) const
FlowQuantity FeasibleSupply(NodeIndex node) const
FlowQuantity Flow(ArcIndex arc) const
GenericMinCostFlow(const Graph *graph)
Graph::NodeIndex NodeIndex
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)
CostValue GetOptimalCost()
void SetArcCapacity(ArcIndex arc, ArcFlowType new_capacity)
CostValue UnitCost(ArcIndex arc) const
ArcIndex AddArcWithCapacityAndUnitCost(NodeIndex tail, NodeIndex head, FlowQuantity capacity, CostValue unit_cost)
FlowQuantity Flow(ArcIndex arc) const
FlowQuantity MaximumFlow() const
NodeIndex NumNodes() 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
CostValue OptimalCost() const
bool Reserve(int64_t new_min_index, int64_t new_max_index)
GurobiMPCallbackContext * context
ABSL_FLAG(int64_t, min_cost_flow_alpha, 5, "Divide factor for epsilon at each refine step.")
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)
#define IF_STATS_ENABLED(instructions)
#define SCOPED_TIME_STAT(stats)
static ArcIndex ArcReservation(const Graph &graph)
static NodeIndex NodeReservation(const Graph &graph)
static bool IsArcValid(const Graph &graph, ArcIndex arc)
static ArcIndex OppositeArc(const Graph &graph, ArcIndex arc)
#define VLOG(verboselevel)