20 #include "absl/strings/str_format.h"
30 "Divide factor for epsilon at each refine step.");
32 "Check that the graph has enough capacity to send all supplies "
33 "and serve all demands. Also check that the sum of supplies "
34 "is equal to the sum of demands.");
36 "Check that the sum of supplies is equal to the sum of demands.");
38 "Check that the magnitude of the costs will not exceed the "
39 "precision of the machine when scaled (multiplied) by the number "
42 "Check that the result is valid.");
46 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
52 residual_arc_capacity_(),
53 first_admissible_arc_(),
56 alpha_(FLAGS_min_cost_flow_alpha),
57 cost_scaling_factor_(1),
58 scaled_arc_unit_cost_(),
61 initial_node_excess_(),
62 feasible_node_excess_(),
63 stats_(
"MinCostFlow"),
64 feasibility_checked_(false),
65 use_price_update_(false),
66 check_feasibility_(FLAGS_min_cost_flow_check_feasibility) {
68 if (max_num_nodes > 0) {
69 node_excess_.
Reserve(0, max_num_nodes - 1);
71 node_potential_.
Reserve(0, max_num_nodes - 1);
73 first_admissible_arc_.
Reserve(0, max_num_nodes - 1);
74 first_admissible_arc_.
SetAll(Graph::kNilArc);
75 initial_node_excess_.
Reserve(0, max_num_nodes - 1);
76 initial_node_excess_.
SetAll(0);
77 feasible_node_excess_.
Reserve(0, max_num_nodes - 1);
78 feasible_node_excess_.
SetAll(0);
81 if (max_num_arcs > 0) {
82 residual_arc_capacity_.Reserve(-max_num_arcs, max_num_arcs - 1);
83 residual_arc_capacity_.SetAll(0);
84 scaled_arc_unit_cost_.Reserve(-max_num_arcs, max_num_arcs - 1);
85 scaled_arc_unit_cost_.SetAll(0);
89 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
92 DCHECK(graph_->IsNodeValid(node));
93 node_excess_.Set(node, supply);
94 initial_node_excess_.Set(node, supply);
96 feasibility_checked_ =
false;
99 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
101 ArcIndex arc, ArcScaledCostType unit_cost) {
102 DCHECK(IsArcDirect(arc));
103 scaled_arc_unit_cost_.Set(arc, unit_cost);
104 scaled_arc_unit_cost_.Set(Opposite(arc), -scaled_arc_unit_cost_[arc]);
105 status_ = NOT_SOLVED;
106 feasibility_checked_ =
false;
109 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
111 ArcIndex arc, ArcFlowType new_capacity) {
112 DCHECK_LE(0, new_capacity);
113 DCHECK(IsArcDirect(arc));
114 const FlowQuantity free_capacity = residual_arc_capacity_[arc];
115 const FlowQuantity capacity_delta = new_capacity - Capacity(arc);
116 if (capacity_delta == 0) {
119 status_ = NOT_SOLVED;
120 feasibility_checked_ =
false;
121 const FlowQuantity new_availability = free_capacity + capacity_delta;
122 if (new_availability >= 0) {
128 DCHECK((capacity_delta > 0) ||
129 (capacity_delta < 0 && new_availability >= 0));
130 residual_arc_capacity_.Set(arc, new_availability);
131 DCHECK_LE(0, residual_arc_capacity_[arc]);
135 const FlowQuantity flow = residual_arc_capacity_[Opposite(arc)];
137 residual_arc_capacity_.Set(arc, 0);
138 residual_arc_capacity_.Set(Opposite(arc), new_capacity);
140 node_excess_.Set(
tail, node_excess_[
tail] + flow_excess);
142 node_excess_.Set(
head, node_excess_[
head] - flow_excess);
143 DCHECK_LE(0, residual_arc_capacity_[arc]);
144 DCHECK_LE(0, residual_arc_capacity_[Opposite(arc)]);
148 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
150 ArcIndex arc, ArcFlowType new_flow) {
151 DCHECK(IsArcValid(arc));
154 residual_arc_capacity_.Set(Opposite(arc), new_flow);
155 residual_arc_capacity_.Set(arc,
capacity - new_flow);
156 status_ = NOT_SOLVED;
157 feasibility_checked_ =
false;
160 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
162 ArcScaledCostType>::CheckInputConsistency()
const {
166 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
171 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
173 total_supply += excess;
175 total_flow += excess;
177 max_capacity + total_flow) {
178 LOG(DFATAL) <<
"Input consistency error: max capacity + flow exceed "
184 if (total_supply != 0) {
185 LOG(DFATAL) <<
"Input consistency error: unbalanced problem";
191 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
192 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckResult()
194 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
195 if (node_excess_[node] != 0) {
196 LOG(DFATAL) <<
"node_excess_[" << node <<
"] != 0";
199 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
203 if (residual_arc_capacity_[arc] < 0) {
204 LOG(DFATAL) <<
"residual_arc_capacity_[" << arc <<
"] < 0";
207 if (residual_arc_capacity_[arc] > 0 && ReducedCost(arc) < -epsilon_) {
208 LOG(DFATAL) <<
"residual_arc_capacity_[" << arc
209 <<
"] > 0 && ReducedCost(" << arc <<
") < " << -epsilon_
210 <<
". (epsilon_ = " << epsilon_ <<
").";
214 LOG(DFATAL) << DebugString(
"CheckResult ", arc);
222 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
223 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckCostRange()
228 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
230 max_cost_magnitude =
std::max(max_cost_magnitude, cost_magnitude);
231 if (cost_magnitude != 0.0) {
232 min_cost_magnitude =
std::min(min_cost_magnitude, cost_magnitude);
235 VLOG(3) <<
"Min cost magnitude = " << min_cost_magnitude
236 <<
", Max cost magnitude = " << max_cost_magnitude;
237 #if !defined(_MSC_VER)
239 log(max_cost_magnitude + 1) + log(graph_->num_nodes() + 1)) {
240 LOG(DFATAL) <<
"Maximum cost magnitude " << max_cost_magnitude <<
" is too "
241 <<
"high for the number of nodes. Try changing the data.";
248 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
249 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
250 CheckRelabelPrecondition(
NodeIndex node)
const {
257 DCHECK_GE(node_excess_[node], 0);
258 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
261 DCHECK(!IsAdmissible(arc)) << DebugString(
"CheckRelabelPrecondition:", arc);
266 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
268 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::DebugString(
275 const CostValue reduced_cost = scaled_arc_unit_cost_[arc] +
276 node_potential_[
tail] - node_potential_[
head];
277 return absl::StrFormat(
278 "%s Arc %d, from %d to %d, "
279 "Capacity = %d, Residual capacity = %d, "
280 "Flow = residual capacity for reverse arc = %d, "
281 "Height(tail) = %d, Height(head) = %d, "
282 "Excess(tail) = %d, Excess(head) = %d, "
283 "Cost = %d, Reduced cost = %d, ",
285 static_cast<FlowQuantity>(residual_arc_capacity_[arc]), Flow(arc),
286 node_potential_[
tail], node_potential_[
head], node_excess_[
tail],
287 node_excess_[
head],
static_cast<CostValue>(scaled_arc_unit_cost_[arc]),
291 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
294 std::vector<NodeIndex>*
const infeasible_demand_node) {
307 feasibility_checked_ =
false;
309 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
310 if (initial_node_excess_[node] != 0) {
314 const NodeIndex num_nodes_in_max_flow = graph_->num_nodes() + 2;
315 const ArcIndex num_arcs_in_max_flow = graph_->num_arcs() + num_extra_arcs;
316 const NodeIndex source = num_nodes_in_max_flow - 2;
317 const NodeIndex sink = num_nodes_in_max_flow - 1;
318 StarGraph checker_graph(num_nodes_in_max_flow, num_arcs_in_max_flow);
319 MaxFlow checker(&checker_graph, source, sink);
323 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
325 checker_graph.AddArc(graph_->Tail(arc), graph_->Head(arc));
326 DCHECK_EQ(arc, new_arc);
332 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
335 const ArcIndex new_arc = checker_graph.AddArc(source, node);
337 total_supply += supply;
338 }
else if (supply < 0) {
339 const ArcIndex new_arc = checker_graph.AddArc(node, sink);
341 total_demand -= supply;
344 if (total_supply != total_demand) {
345 LOG(DFATAL) <<
"total_supply(" << total_supply <<
") != total_demand("
346 << total_demand <<
").";
349 if (!checker.
Solve()) {
350 LOG(DFATAL) <<
"Max flow could not be computed.";
354 feasible_node_excess_.SetAll(0);
355 for (StarGraph::OutgoingArcIterator it(checker_graph, source); it.Ok();
358 const NodeIndex node = checker_graph.Head(arc);
360 feasible_node_excess_.Set(node, flow);
361 if (infeasible_supply_node !=
nullptr) {
362 infeasible_supply_node->push_back(node);
365 for (StarGraph::IncomingArcIterator it(checker_graph, sink); it.Ok();
370 feasible_node_excess_.Set(node, -flow);
371 if (infeasible_demand_node !=
nullptr) {
372 infeasible_demand_node->push_back(node);
375 feasibility_checked_ =
true;
376 return optimal_max_flow == total_supply;
379 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
381 if (!feasibility_checked_) {
384 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
385 const FlowQuantity excess = feasible_node_excess_[node];
386 node_excess_.Set(node, excess);
387 initial_node_excess_.Set(node, excess);
392 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
395 if (IsArcDirect(arc)) {
396 return residual_arc_capacity_[Opposite(arc)];
398 return -residual_arc_capacity_[arc];
403 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
407 if (IsArcDirect(arc)) {
408 return residual_arc_capacity_[arc] + residual_arc_capacity_[Opposite(arc)];
414 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
417 DCHECK(IsArcValid(arc));
418 DCHECK_EQ(
uint64{1}, cost_scaling_factor_);
419 return scaled_arc_unit_cost_[arc];
422 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
425 DCHECK(graph_->IsNodeValid(node));
426 return node_excess_[node];
429 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
433 return initial_node_excess_[node];
436 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
440 return feasible_node_excess_[node];
443 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
446 return FastIsAdmissible(arc, node_potential_[Tail(arc)]);
449 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
450 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
452 DCHECK_EQ(node_potential_[Tail(arc)], tail_potential);
453 return residual_arc_capacity_[arc] > 0 &&
454 FastReducedCost(arc, tail_potential) < 0;
457 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
458 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsActive(
460 return node_excess_[node] > 0;
463 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
465 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ReducedCost(
467 return FastReducedCost(arc, node_potential_[Tail(arc)]);
470 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
472 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastReducedCost(
474 DCHECK_EQ(node_potential_[Tail(arc)], tail_potential);
475 DCHECK(graph_->IsNodeValid(Tail(arc)));
476 DCHECK(graph_->IsNodeValid(Head(arc)));
477 DCHECK_LE(node_potential_[Tail(arc)], 0) << DebugString(
"ReducedCost:", arc);
478 DCHECK_LE(node_potential_[Head(arc)], 0) << DebugString(
"ReducedCost:", arc);
479 return scaled_arc_unit_cost_[arc] + tail_potential -
480 node_potential_[Head(arc)];
483 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
485 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
486 GetFirstOutgoingOrOppositeIncomingArc(
NodeIndex node)
const {
487 OutgoingOrOppositeIncomingArcIterator arc_it(*graph_, node);
488 return arc_it.Index();
491 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
493 status_ = NOT_SOLVED;
494 if (FLAGS_min_cost_flow_check_balance && !CheckInputConsistency()) {
495 status_ = UNBALANCED;
498 if (FLAGS_min_cost_flow_check_costs && !CheckCostRange()) {
499 status_ = BAD_COST_RANGE;
502 if (check_feasibility_ && !CheckFeasibility(
nullptr,
nullptr)) {
503 status_ = INFEASIBLE;
506 node_potential_.SetAll(0);
507 ResetFirstAdmissibleArcs();
510 if (FLAGS_min_cost_flow_check_result && !CheckResult()) {
511 status_ = BAD_RESULT;
516 if (status_ != OPTIMAL) {
517 LOG(DFATAL) <<
"Status != OPTIMAL";
518 total_flow_cost_ = 0;
521 total_flow_cost_ = 0;
522 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
523 const FlowQuantity flow_on_arc = residual_arc_capacity_[Opposite(arc)];
524 total_flow_cost_ += scaled_arc_unit_cost_[arc] * flow_on_arc;
531 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
533 ArcScaledCostType>::ResetFirstAdmissibleArcs() {
534 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
535 first_admissible_arc_.Set(node,
536 GetFirstOutgoingOrOppositeIncomingArc(node));
540 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
541 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ScaleCosts() {
543 cost_scaling_factor_ = graph_->num_nodes() + 1;
545 VLOG(3) <<
"Number of nodes in the graph = " << graph_->num_nodes();
546 VLOG(3) <<
"Number of arcs in the graph = " << graph_->num_arcs();
547 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
548 const CostValue cost = scaled_arc_unit_cost_[arc] * cost_scaling_factor_;
549 scaled_arc_unit_cost_.Set(arc,
cost);
550 scaled_arc_unit_cost_.Set(Opposite(arc), -
cost);
553 VLOG(3) <<
"Initial epsilon = " << epsilon_;
554 VLOG(3) <<
"Cost scaling factor = " << cost_scaling_factor_;
557 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
558 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UnscaleCosts() {
560 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
561 const CostValue cost = scaled_arc_unit_cost_[arc] / cost_scaling_factor_;
562 scaled_arc_unit_cost_.Set(arc,
cost);
563 scaled_arc_unit_cost_.Set(Opposite(arc), -
cost);
565 cost_scaling_factor_ = 1;
568 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
569 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Optimize() {
571 num_relabels_since_last_price_update_ = 0;
574 epsilon_ =
std::max(epsilon_ / alpha_, kEpsilonMin);
575 VLOG(3) <<
"Epsilon changed to: " << epsilon_;
577 }
while (epsilon_ != 1LL && status_ != INFEASIBLE);
578 if (status_ == NOT_SOLVED) {
583 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
584 void GenericMinCostFlow<
Graph, ArcFlowType,
585 ArcScaledCostType>::SaturateAdmissibleArcs() {
587 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
588 const CostValue tail_potential = node_potential_[node];
589 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
590 first_admissible_arc_[node]);
591 it.Ok(); it.Next()) {
593 if (FastIsAdmissible(arc, tail_potential)) {
594 FastPushFlow(residual_arc_capacity_[arc], arc, node);
604 first_admissible_arc_[node] = Graph::kNilArc;
608 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
609 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::PushFlow(
612 FastPushFlow(flow, arc, Tail(arc));
615 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
616 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastPushFlow(
619 DCHECK_EQ(Tail(arc),
tail);
620 DCHECK_GT(residual_arc_capacity_[arc], 0);
621 DCHECK_LE(flow, residual_arc_capacity_[arc]);
623 residual_arc_capacity_.Set(arc, residual_arc_capacity_[arc] - flow);
625 const ArcIndex opposite = Opposite(arc);
626 residual_arc_capacity_.Set(opposite, residual_arc_capacity_[opposite] + flow);
628 node_excess_.Set(
tail, node_excess_[
tail] - flow);
630 node_excess_.Set(
head, node_excess_[
head] + flow);
633 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
634 void GenericMinCostFlow<
Graph, ArcFlowType,
635 ArcScaledCostType>::InitializeActiveNodeStack() {
637 DCHECK(active_nodes_.empty());
638 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
639 if (IsActive(node)) {
640 active_nodes_.push(node);
645 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
646 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UpdatePrices() {
665 const NodeIndex num_nodes = graph_->num_nodes();
666 std::vector<NodeIndex> bfs_queue;
667 std::vector<bool> node_in_queue(num_nodes,
false);
671 std::vector<CostValue> min_non_admissible_potential(num_nodes, kMinCostValue);
672 std::vector<NodeIndex> nodes_to_process;
678 for (
NodeIndex node = 0; node < num_nodes; ++node) {
679 if (node_excess_[node] < 0) {
680 bfs_queue.push_back(node);
681 node_in_queue[node] =
true;
684 remaining_excess -= node_excess_[node];
695 while (remaining_excess > 0) {
700 for (; queue_index < bfs_queue.size(); ++queue_index) {
701 DCHECK_GE(num_nodes, bfs_queue.size());
702 const NodeIndex node = bfs_queue[queue_index];
703 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
706 if (node_in_queue[
head])
continue;
707 const ArcIndex opposite_arc = Opposite(it.Index());
708 if (residual_arc_capacity_[opposite_arc] > 0) {
709 node_potential_[
head] += potential_delta;
710 if (ReducedCost(opposite_arc) < 0) {
711 DCHECK(IsAdmissible(opposite_arc));
716 remaining_excess -= node_excess_[
head];
717 if (remaining_excess == 0) {
718 node_potential_[
head] -= potential_delta;
721 bfs_queue.push_back(
head);
722 node_in_queue[
head] =
true;
723 if (potential_delta < 0) {
724 first_admissible_arc_[
head] =
725 GetFirstOutgoingOrOppositeIncomingArc(
head);
730 node_potential_[
head] -= potential_delta;
731 if (min_non_admissible_potential[
head] == kMinCostValue) {
732 nodes_to_process.push_back(
head);
735 min_non_admissible_potential[
head],
736 node_potential_[node] - scaled_arc_unit_cost_[opposite_arc]);
740 if (remaining_excess == 0)
break;
742 if (remaining_excess == 0)
break;
746 CostValue max_potential_diff = kMinCostValue;
747 for (
int i = 0; i < nodes_to_process.size(); ++i) {
748 const NodeIndex node = nodes_to_process[i];
749 if (node_in_queue[node])
continue;
752 min_non_admissible_potential[node] - node_potential_[node]);
753 if (max_potential_diff == potential_delta)
break;
755 DCHECK_LE(max_potential_diff, potential_delta);
756 potential_delta = max_potential_diff - epsilon_;
765 for (
int i = 0; i < nodes_to_process.size(); ++i) {
766 const NodeIndex node = nodes_to_process[i];
767 if (node_in_queue[node])
continue;
768 if (node_potential_[node] + potential_delta <
769 min_non_admissible_potential[node]) {
770 node_potential_[node] += potential_delta;
771 first_admissible_arc_[node] =
772 GetFirstOutgoingOrOppositeIncomingArc(node);
773 bfs_queue.push_back(node);
774 node_in_queue[node] =
true;
775 remaining_excess -= node_excess_[node];
780 nodes_to_process[
index] = node;
783 nodes_to_process.resize(
index);
787 if (potential_delta == 0)
return;
788 for (
NodeIndex node = 0; node < num_nodes; ++node) {
789 if (!node_in_queue[node]) {
790 node_potential_[node] += potential_delta;
791 first_admissible_arc_[node] = GetFirstOutgoingOrOppositeIncomingArc(node);
796 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
797 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Refine() {
799 SaturateAdmissibleArcs();
800 InitializeActiveNodeStack();
802 const NodeIndex num_nodes = graph_->num_nodes();
803 while (status_ != INFEASIBLE && !active_nodes_.empty()) {
805 if (num_relabels_since_last_price_update_ >= num_nodes) {
806 num_relabels_since_last_price_update_ = 0;
807 if (use_price_update_) {
811 const NodeIndex node = active_nodes_.top();
813 DCHECK(IsActive(node));
818 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
819 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Discharge(
825 DCHECK(IsActive(node));
826 const CostValue tail_potential = node_potential_[node];
827 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
828 first_admissible_arc_[node]);
829 it.Ok(); it.Next()) {
831 if (FastIsAdmissible(arc, tail_potential)) {
833 if (!LookAhead(arc, tail_potential,
head))
continue;
834 const bool head_active_before_push = IsActive(
head);
837 static_cast<FlowQuantity>(residual_arc_capacity_[arc]));
838 FastPushFlow(
delta, arc, node);
839 if (IsActive(
head) && !head_active_before_push) {
840 active_nodes_.push(
head);
842 if (node_excess_[node] == 0) {
844 first_admissible_arc_.Set(node, arc);
850 }
while (status_ != INFEASIBLE);
853 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
854 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::LookAhead(
857 DCHECK_EQ(Head(in_arc), node);
858 DCHECK_EQ(node_potential_[Tail(in_arc)], in_tail_potential);
859 if (node_excess_[node] < 0)
return true;
860 const CostValue tail_potential = node_potential_[node];
861 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
862 first_admissible_arc_[node]);
863 it.Ok(); it.Next()) {
865 if (FastIsAdmissible(arc, tail_potential)) {
866 first_admissible_arc_.Set(node, arc);
874 return FastIsAdmissible(in_arc, in_tail_potential);
877 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
878 void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Relabel(
881 DCHECK(CheckRelabelPrecondition(node));
882 ++num_relabels_since_last_price_update_;
889 const CostValue guaranteed_new_potential = node_potential_[node] - epsilon_;
897 CostValue min_non_admissible_potential = kMinCostValue;
902 CostValue previous_min_non_admissible_potential = kMinCostValue;
903 ArcIndex first_arc = Graph::kNilArc;
905 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
908 if (residual_arc_capacity_[arc] > 0) {
909 const CostValue min_non_admissible_potential_for_arc =
910 node_potential_[Head(arc)] - scaled_arc_unit_cost_[arc];
911 if (min_non_admissible_potential_for_arc > min_non_admissible_potential) {
912 if (min_non_admissible_potential_for_arc > guaranteed_new_potential) {
916 node_potential_.Set(node, guaranteed_new_potential);
917 first_admissible_arc_.Set(node, arc);
920 previous_min_non_admissible_potential = min_non_admissible_potential;
921 min_non_admissible_potential = min_non_admissible_potential_for_arc;
928 if (min_non_admissible_potential == kMinCostValue) {
929 if (node_excess_[node] != 0) {
933 LOG(ERROR) <<
"Infeasible problem.";
938 node_potential_.Set(node, guaranteed_new_potential);
939 first_admissible_arc_.Set(node,
940 GetFirstOutgoingOrOppositeIncomingArc(node));
948 const CostValue new_potential = min_non_admissible_potential - epsilon_;
949 node_potential_.Set(node, new_potential);
950 if (previous_min_non_admissible_potential <= new_potential) {
951 first_admissible_arc_.Set(node, first_arc);
954 first_admissible_arc_.Set(node,
955 GetFirstOutgoingOrOppositeIncomingArc(node));
959 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
961 GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Opposite(
966 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
967 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcValid(
972 template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
973 bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcDirect(
975 DCHECK(IsArcValid(arc));
983 template class GenericMinCostFlow<StarGraph>;
984 template class GenericMinCostFlow<::util::ReverseArcListGraph<>>;
985 template class GenericMinCostFlow<::util::ReverseArcStaticGraph<>>;
986 template class GenericMinCostFlow<::util::ReverseArcMixedGraph<>>;
987 template class GenericMinCostFlow<::util::ReverseArcStaticGraph<uint16, int32>>;
990 template class GenericMinCostFlow<::util::ReverseArcStaticGraph<uint16, int32>,
996 if (reserve_num_nodes > 0) {
997 node_supply_.reserve(reserve_num_nodes);
999 if (reserve_num_arcs > 0) {
1000 arc_tail_.reserve(reserve_num_arcs);
1001 arc_head_.reserve(reserve_num_arcs);
1002 arc_capacity_.reserve(reserve_num_arcs);
1003 arc_cost_.reserve(reserve_num_arcs);
1004 arc_permutation_.reserve(reserve_num_arcs);
1005 arc_flow_.reserve(reserve_num_arcs);
1010 ResizeNodeVectors(node);
1011 node_supply_[node] = supply;
1019 const ArcIndex arc = arc_tail_.size();
1020 arc_tail_.push_back(
tail);
1021 arc_head_.push_back(
head);
1023 arc_cost_.push_back(unit_cost);
1028 return arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
1032 SupplyAdjustment adjustment) {
1036 const NodeIndex num_nodes = node_supply_.size();
1037 const ArcIndex num_arcs = arc_capacity_.size();
1038 if (num_nodes == 0)
return OPTIMAL;
1040 int supply_node_count = 0, demand_node_count = 0;
1042 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1043 if (node_supply_[node] > 0) {
1044 ++supply_node_count;
1045 total_supply += node_supply_[node];
1046 }
else if (node_supply_[node] < 0) {
1047 ++demand_node_count;
1048 total_demand -= node_supply_[node];
1051 if (adjustment == DONT_ADJUST && total_supply != total_demand) {
1066 const ArcIndex augmented_num_arcs =
1067 num_arcs + supply_node_count + demand_node_count;
1070 const NodeIndex augmented_num_nodes = num_nodes + 2;
1072 Graph graph(augmented_num_nodes, augmented_num_arcs);
1073 for (
ArcIndex arc = 0; arc < num_arcs; ++arc) {
1074 graph.AddArc(arc_tail_[arc], arc_head_[arc]);
1077 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1078 if (node_supply_[node] > 0) {
1079 graph.AddArc(source, node);
1080 }
else if (node_supply_[node] < 0) {
1081 graph.AddArc(node, sink);
1085 graph.Build(&arc_permutation_);
1088 GenericMaxFlow<Graph> max_flow(&graph, source, sink);
1090 for (arc = 0; arc < num_arcs; ++arc) {
1091 max_flow.SetArcCapacity(PermutedArc(arc), arc_capacity_[arc]);
1093 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1094 if (node_supply_[node] != 0) {
1095 max_flow.SetArcCapacity(PermutedArc(arc), std::abs(node_supply_[node]));
1099 CHECK_EQ(arc, augmented_num_arcs);
1100 if (!max_flow.Solve()) {
1101 LOG(ERROR) <<
"Max flow could not be computed.";
1102 switch (max_flow.status()) {
1107 <<
"Max flow failed but claimed to have an optimal solution";
1108 ABSL_FALLTHROUGH_INTENDED;
1113 maximum_flow_ = max_flow.GetOptimalFlow();
1116 if (adjustment == DONT_ADJUST && maximum_flow_ != total_supply) {
1120 GenericMinCostFlow<Graph> min_cost_flow(&graph);
1122 for (arc = 0; arc < num_arcs; ++arc) {
1123 ArcIndex permuted_arc = PermutedArc(arc);
1124 min_cost_flow.SetArcUnitCost(permuted_arc, arc_cost_[arc]);
1125 min_cost_flow.SetArcCapacity(permuted_arc, arc_capacity_[arc]);
1127 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1128 if (node_supply_[node] != 0) {
1129 ArcIndex permuted_arc = PermutedArc(arc);
1130 min_cost_flow.SetArcCapacity(permuted_arc, std::abs(node_supply_[node]));
1131 min_cost_flow.SetArcUnitCost(permuted_arc, 0);
1135 min_cost_flow.SetNodeSupply(source, maximum_flow_);
1136 min_cost_flow.SetNodeSupply(sink, -maximum_flow_);
1137 min_cost_flow.SetCheckFeasibility(
false);
1139 arc_flow_.resize(num_arcs);
1140 if (min_cost_flow.Solve()) {
1141 optimal_cost_ = min_cost_flow.GetOptimalCost();
1142 for (arc = 0; arc < num_arcs; ++arc) {
1143 arc_flow_[arc] = min_cost_flow.Flow(PermutedArc(arc));
1146 return min_cost_flow.status();
1154 return arc_flow_[arc];
1166 return arc_capacity_[arc];
1170 return arc_cost_[arc];
1174 return node_supply_[node];
1177 void SimpleMinCostFlow::ResizeNodeVectors(
NodeIndex node) {
1178 if (node < node_supply_.size())
return;
1179 node_supply_.resize(node + 1);