21#include "absl/strings/str_format.h"
31 "Divide factor for epsilon at each refine step.");
32ABSL_FLAG(
bool, min_cost_flow_check_feasibility,
true,
33 "Check that the graph has enough capacity to send all supplies "
34 "and serve all demands. Also check that the sum of supplies "
35 "is equal to the sum of demands.");
37 "Check that the sum of supplies is equal to the sum of demands.");
39 "Check that the magnitude of the costs will not exceed the "
40 "precision of the machine when scaled (multiplied) by the number "
43 "Check that the result is valid.");
47template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
53 residual_arc_capacity_(),
54 first_admissible_arc_(),
57 alpha_(
absl::GetFlag(FLAGS_min_cost_flow_alpha)),
58 cost_scaling_factor_(1),
59 scaled_arc_unit_cost_(),
62 initial_node_excess_(),
63 feasible_node_excess_(),
64 stats_(
"MinCostFlow"),
65 feasibility_checked_(false),
66 use_price_update_(false),
67 check_feasibility_(
absl::GetFlag(FLAGS_min_cost_flow_check_feasibility)) {
69 if (max_num_nodes > 0) {
70 node_excess_.
Reserve(0, max_num_nodes - 1);
72 node_potential_.
Reserve(0, max_num_nodes - 1);
74 first_admissible_arc_.
Reserve(0, max_num_nodes - 1);
75 first_admissible_arc_.
SetAll(Graph::kNilArc);
76 initial_node_excess_.
Reserve(0, max_num_nodes - 1);
77 initial_node_excess_.
SetAll(0);
78 feasible_node_excess_.
Reserve(0, max_num_nodes - 1);
79 feasible_node_excess_.
SetAll(0);
82 if (max_num_arcs > 0) {
83 residual_arc_capacity_.Reserve(-max_num_arcs, max_num_arcs - 1);
84 residual_arc_capacity_.SetAll(0);
85 scaled_arc_unit_cost_.Reserve(-max_num_arcs, max_num_arcs - 1);
86 scaled_arc_unit_cost_.SetAll(0);
90template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
93 DCHECK(graph_->IsNodeValid(node));
94 node_excess_.Set(node, supply);
95 initial_node_excess_.Set(node, supply);
97 feasibility_checked_ =
false;
100template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
104 scaled_arc_unit_cost_.Set(
arc, unit_cost);
105 scaled_arc_unit_cost_.Set(Opposite(
arc), -scaled_arc_unit_cost_[
arc]);
106 status_ = NOT_SOLVED;
107 feasibility_checked_ =
false;
110template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
117 if (capacity_delta == 0) {
120 status_ = NOT_SOLVED;
121 feasibility_checked_ =
false;
122 const FlowQuantity new_availability = free_capacity + capacity_delta;
123 if (new_availability >= 0) {
129 DCHECK((capacity_delta > 0) ||
130 (capacity_delta < 0 && new_availability >= 0));
131 residual_arc_capacity_.Set(
arc, new_availability);
138 residual_arc_capacity_.Set(
arc, 0);
139 residual_arc_capacity_.Set(Opposite(
arc), new_capacity);
141 node_excess_.Set(
tail, node_excess_[
tail] + flow_excess);
143 node_excess_.Set(
head, node_excess_[
head] - flow_excess);
149template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
155 residual_arc_capacity_.Set(Opposite(
arc), new_flow);
156 residual_arc_capacity_.Set(
arc,
capacity - new_flow);
157 status_ = NOT_SOLVED;
158 feasibility_checked_ =
false;
161template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
163 ArcScaledCostType>::CheckInputConsistency()
const {
165 uint64_t max_capacity = 0;
169 static_cast<uint64_t
>(residual_arc_capacity_[
arc]);
172 uint64_t total_flow = 0;
173 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
175 total_supply += excess;
177 total_flow += excess;
179 max_capacity + total_flow) {
180 LOG(DFATAL) <<
"Input consistency error: max capacity + flow exceed "
186 if (total_supply != 0) {
187 LOG(DFATAL) <<
"Input consistency error: unbalanced problem";
193template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
194bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckResult()
196 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
197 if (node_excess_[node] != 0) {
198 LOG(DFATAL) <<
"node_excess_[" << node <<
"] != 0";
201 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
205 if (residual_arc_capacity_[
arc] < 0) {
206 LOG(DFATAL) <<
"residual_arc_capacity_[" <<
arc <<
"] < 0";
209 if (residual_arc_capacity_[
arc] > 0 && ReducedCost(
arc) < -epsilon_) {
210 LOG(DFATAL) <<
"residual_arc_capacity_[" <<
arc
211 <<
"] > 0 && ReducedCost(" <<
arc <<
") < " << -epsilon_
212 <<
". (epsilon_ = " << epsilon_ <<
").";
216 LOG(DFATAL) << DebugString(
"CheckResult ",
arc);
224template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
225bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::CheckCostRange()
232 max_cost_magnitude =
std::max(max_cost_magnitude, cost_magnitude);
233 if (cost_magnitude != 0.0) {
234 min_cost_magnitude =
std::min(min_cost_magnitude, cost_magnitude);
237 VLOG(3) <<
"Min cost magnitude = " << min_cost_magnitude
238 <<
", Max cost magnitude = " << max_cost_magnitude;
239#if !defined(_MSC_VER)
241 log(max_cost_magnitude + 1) + log(graph_->num_nodes() + 1)) {
242 LOG(DFATAL) <<
"Maximum cost magnitude " << max_cost_magnitude <<
" is too "
243 <<
"high for the number of nodes. Try changing the data.";
250template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
251bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
252 CheckRelabelPrecondition(
NodeIndex node)
const {
260 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
263 DCHECK(!IsAdmissible(
arc)) << DebugString(
"CheckRelabelPrecondition:",
arc);
268template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
270GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::DebugString(
277 const CostValue reduced_cost = scaled_arc_unit_cost_[
arc] +
278 node_potential_[
tail] - node_potential_[
head];
279 return absl::StrFormat(
280 "%s Arc %d, from %d to %d, "
281 "Capacity = %d, Residual capacity = %d, "
282 "Flow = residual capacity for reverse arc = %d, "
283 "Height(tail) = %d, Height(head) = %d, "
284 "Excess(tail) = %d, Excess(head) = %d, "
285 "Cost = %d, Reduced cost = %d, ",
288 node_potential_[
tail], node_potential_[
head], node_excess_[
tail],
293template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
296 std::vector<NodeIndex>*
const infeasible_demand_node) {
309 feasibility_checked_ =
false;
311 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
312 if (initial_node_excess_[node] != 0) {
316 const NodeIndex num_nodes_in_max_flow = graph_->num_nodes() + 2;
317 const ArcIndex num_arcs_in_max_flow = graph_->num_arcs() + num_extra_arcs;
318 const NodeIndex source = num_nodes_in_max_flow - 2;
319 const NodeIndex sink = num_nodes_in_max_flow - 1;
320 StarGraph checker_graph(num_nodes_in_max_flow, num_arcs_in_max_flow);
321 MaxFlow checker(&checker_graph, source, sink);
327 checker_graph.
AddArc(graph_->Tail(
arc), graph_->Head(
arc));
334 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
339 total_supply += supply;
340 }
else if (supply < 0) {
343 total_demand -= supply;
346 if (total_supply != total_demand) {
347 LOG(DFATAL) <<
"total_supply(" << total_supply <<
") != total_demand("
348 << total_demand <<
").";
352 LOG(DFATAL) <<
"Max flow could not be computed.";
356 feasible_node_excess_.SetAll(0);
357 for (StarGraph::OutgoingArcIterator it(checker_graph, source); it.Ok();
362 feasible_node_excess_.Set(node, flow);
363 if (infeasible_supply_node !=
nullptr) {
364 infeasible_supply_node->push_back(node);
367 for (StarGraph::IncomingArcIterator it(checker_graph, sink); it.Ok();
372 feasible_node_excess_.Set(node, -flow);
373 if (infeasible_demand_node !=
nullptr) {
374 infeasible_demand_node->push_back(node);
377 feasibility_checked_ =
true;
378 return optimal_max_flow == total_supply;
381template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
383 if (!feasibility_checked_) {
386 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
387 const FlowQuantity excess = feasible_node_excess_[node];
388 node_excess_.Set(node, excess);
389 initial_node_excess_.Set(node, excess);
394template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
397 if (IsArcDirect(
arc)) {
398 return residual_arc_capacity_[Opposite(
arc)];
400 return -residual_arc_capacity_[
arc];
405template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
409 if (IsArcDirect(
arc)) {
410 return residual_arc_capacity_[
arc] + residual_arc_capacity_[Opposite(
arc)];
416template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
420 DCHECK_EQ(uint64_t{1}, cost_scaling_factor_);
421 return scaled_arc_unit_cost_[
arc];
424template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
427 DCHECK(graph_->IsNodeValid(node));
428 return node_excess_[node];
431template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
435 return initial_node_excess_[node];
438template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
442 return feasible_node_excess_[node];
445template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
448 return FastIsAdmissible(
arc, node_potential_[Tail(
arc)]);
451template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
452bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
455 return residual_arc_capacity_[
arc] > 0 &&
456 FastReducedCost(
arc, tail_potential) < 0;
459template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
460bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsActive(
462 return node_excess_[node] > 0;
465template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
467GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ReducedCost(
469 return FastReducedCost(
arc, node_potential_[Tail(
arc)]);
472template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
474GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastReducedCost(
479 DCHECK_LE(node_potential_[Tail(
arc)], 0) << DebugString(
"ReducedCost:",
arc);
480 DCHECK_LE(node_potential_[Head(
arc)], 0) << DebugString(
"ReducedCost:",
arc);
481 return scaled_arc_unit_cost_[
arc] + tail_potential -
482 node_potential_[Head(
arc)];
485template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
487GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::
488 GetFirstOutgoingOrOppositeIncomingArc(
NodeIndex node)
const {
489 OutgoingOrOppositeIncomingArcIterator arc_it(*graph_, node);
490 return arc_it.Index();
493template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
495 status_ = NOT_SOLVED;
496 if (absl::GetFlag(FLAGS_min_cost_flow_check_balance) &&
497 !CheckInputConsistency()) {
498 status_ = UNBALANCED;
501 if (absl::GetFlag(FLAGS_min_cost_flow_check_costs) && !CheckCostRange()) {
502 status_ = BAD_COST_RANGE;
505 if (check_feasibility_ && !CheckFeasibility(
nullptr,
nullptr)) {
509 node_potential_.SetAll(0);
510 ResetFirstAdmissibleArcs();
513 if (absl::GetFlag(FLAGS_min_cost_flow_check_result) && !CheckResult()) {
514 status_ = BAD_RESULT;
520 LOG(DFATAL) <<
"Status != OPTIMAL";
521 total_flow_cost_ = 0;
524 total_flow_cost_ = 0;
526 const FlowQuantity flow_on_arc = residual_arc_capacity_[Opposite(
arc)];
527 total_flow_cost_ += scaled_arc_unit_cost_[
arc] * flow_on_arc;
534template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
536 ArcScaledCostType>::ResetFirstAdmissibleArcs() {
537 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
538 first_admissible_arc_.Set(node,
539 GetFirstOutgoingOrOppositeIncomingArc(node));
543template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
544void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::ScaleCosts() {
546 cost_scaling_factor_ = graph_->num_nodes() + 1;
548 VLOG(3) <<
"Number of nodes in the graph = " << graph_->num_nodes();
549 VLOG(3) <<
"Number of arcs in the graph = " << graph_->num_arcs();
552 scaled_arc_unit_cost_.Set(
arc,
cost);
553 scaled_arc_unit_cost_.Set(Opposite(
arc), -
cost);
556 VLOG(3) <<
"Initial epsilon = " << epsilon_;
557 VLOG(3) <<
"Cost scaling factor = " << cost_scaling_factor_;
560template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
561void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UnscaleCosts() {
565 scaled_arc_unit_cost_.Set(
arc,
cost);
566 scaled_arc_unit_cost_.Set(Opposite(
arc), -
cost);
568 cost_scaling_factor_ = 1;
571template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
572void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Optimize() {
574 num_relabels_since_last_price_update_ = 0;
577 epsilon_ =
std::max(epsilon_ / alpha_, kEpsilonMin);
578 VLOG(3) <<
"Epsilon changed to: " << epsilon_;
580 }
while (epsilon_ != 1LL && status_ != INFEASIBLE);
581 if (status_ == NOT_SOLVED) {
586template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
587void GenericMinCostFlow<
Graph, ArcFlowType,
588 ArcScaledCostType>::SaturateAdmissibleArcs() {
590 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
591 const CostValue tail_potential = node_potential_[node];
592 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
593 first_admissible_arc_[node]);
594 it.Ok(); it.Next()) {
596 if (FastIsAdmissible(
arc, tail_potential)) {
597 FastPushFlow(residual_arc_capacity_[
arc],
arc, node);
607 first_admissible_arc_[node] = Graph::kNilArc;
611template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
612void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::PushFlow(
615 FastPushFlow(flow,
arc, Tail(
arc));
618template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
619void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::FastPushFlow(
626 residual_arc_capacity_.Set(
arc, residual_arc_capacity_[
arc] - flow);
629 residual_arc_capacity_.Set(opposite, residual_arc_capacity_[opposite] + flow);
631 node_excess_.Set(
tail, node_excess_[
tail] - flow);
633 node_excess_.Set(
head, node_excess_[
head] + flow);
636template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
637void GenericMinCostFlow<
Graph, ArcFlowType,
638 ArcScaledCostType>::InitializeActiveNodeStack() {
640 DCHECK(active_nodes_.empty());
641 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
642 if (IsActive(node)) {
643 active_nodes_.push(node);
648template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
649void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::UpdatePrices() {
668 const NodeIndex num_nodes = graph_->num_nodes();
669 std::vector<NodeIndex> bfs_queue;
670 std::vector<bool> node_in_queue(num_nodes,
false);
674 std::vector<CostValue> min_non_admissible_potential(num_nodes, kMinCostValue);
675 std::vector<NodeIndex> nodes_to_process;
681 for (
NodeIndex node = 0; node < num_nodes; ++node) {
682 if (node_excess_[node] < 0) {
683 bfs_queue.push_back(node);
684 node_in_queue[node] =
true;
687 remaining_excess -= node_excess_[node];
698 while (remaining_excess > 0) {
703 for (; queue_index < bfs_queue.size(); ++queue_index) {
705 const NodeIndex node = bfs_queue[queue_index];
706 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
709 if (node_in_queue[
head])
continue;
710 const ArcIndex opposite_arc = Opposite(it.Index());
711 if (residual_arc_capacity_[opposite_arc] > 0) {
712 node_potential_[
head] += potential_delta;
713 if (ReducedCost(opposite_arc) < 0) {
714 DCHECK(IsAdmissible(opposite_arc));
719 remaining_excess -= node_excess_[
head];
720 if (remaining_excess == 0) {
721 node_potential_[
head] -= potential_delta;
724 bfs_queue.push_back(
head);
725 node_in_queue[
head] =
true;
726 if (potential_delta < 0) {
727 first_admissible_arc_[
head] =
728 GetFirstOutgoingOrOppositeIncomingArc(
head);
733 node_potential_[
head] -= potential_delta;
734 if (min_non_admissible_potential[
head] == kMinCostValue) {
735 nodes_to_process.push_back(
head);
738 min_non_admissible_potential[
head],
739 node_potential_[node] - scaled_arc_unit_cost_[opposite_arc]);
743 if (remaining_excess == 0)
break;
745 if (remaining_excess == 0)
break;
749 CostValue max_potential_diff = kMinCostValue;
750 for (
int i = 0; i < nodes_to_process.size(); ++i) {
751 const NodeIndex node = nodes_to_process[i];
752 if (node_in_queue[node])
continue;
755 min_non_admissible_potential[node] - node_potential_[node]);
756 if (max_potential_diff == potential_delta)
break;
758 DCHECK_LE(max_potential_diff, potential_delta);
759 potential_delta = max_potential_diff - epsilon_;
768 for (
int i = 0; i < nodes_to_process.size(); ++i) {
769 const NodeIndex node = nodes_to_process[i];
770 if (node_in_queue[node])
continue;
771 if (node_potential_[node] + potential_delta <
772 min_non_admissible_potential[node]) {
773 node_potential_[node] += potential_delta;
774 first_admissible_arc_[node] =
775 GetFirstOutgoingOrOppositeIncomingArc(node);
776 bfs_queue.push_back(node);
777 node_in_queue[node] =
true;
778 remaining_excess -= node_excess_[node];
783 nodes_to_process[
index] = node;
786 nodes_to_process.resize(
index);
790 if (potential_delta == 0)
return;
791 for (
NodeIndex node = 0; node < num_nodes; ++node) {
792 if (!node_in_queue[node]) {
793 node_potential_[node] += potential_delta;
794 first_admissible_arc_[node] = GetFirstOutgoingOrOppositeIncomingArc(node);
799template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
800void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Refine() {
802 SaturateAdmissibleArcs();
803 InitializeActiveNodeStack();
805 const NodeIndex num_nodes = graph_->num_nodes();
806 while (status_ != INFEASIBLE && !active_nodes_.empty()) {
808 if (num_relabels_since_last_price_update_ >= num_nodes) {
809 num_relabels_since_last_price_update_ = 0;
810 if (use_price_update_) {
814 const NodeIndex node = active_nodes_.top();
821template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
822void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Discharge(
829 const CostValue tail_potential = node_potential_[node];
830 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
831 first_admissible_arc_[node]);
832 it.Ok(); it.Next()) {
834 if (FastIsAdmissible(
arc, tail_potential)) {
836 if (!LookAhead(
arc, tail_potential,
head))
continue;
837 const bool head_active_before_push = IsActive(
head);
842 if (IsActive(
head) && !head_active_before_push) {
843 active_nodes_.push(
head);
845 if (node_excess_[node] == 0) {
847 first_admissible_arc_.Set(node,
arc);
853 }
while (status_ != INFEASIBLE);
856template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
857bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::LookAhead(
861 DCHECK_EQ(node_potential_[Tail(in_arc)], in_tail_potential);
862 if (node_excess_[node] < 0)
return true;
863 const CostValue tail_potential = node_potential_[node];
864 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node,
865 first_admissible_arc_[node]);
866 it.Ok(); it.Next()) {
868 if (FastIsAdmissible(
arc, tail_potential)) {
869 first_admissible_arc_.Set(node,
arc);
877 return FastIsAdmissible(in_arc, in_tail_potential);
880template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
881void GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Relabel(
884 DCHECK(CheckRelabelPrecondition(node));
885 ++num_relabels_since_last_price_update_;
892 const CostValue guaranteed_new_potential = node_potential_[node] - epsilon_;
900 CostValue min_non_admissible_potential = kMinCostValue;
905 CostValue previous_min_non_admissible_potential = kMinCostValue;
906 ArcIndex first_arc = Graph::kNilArc;
908 for (OutgoingOrOppositeIncomingArcIterator it(*graph_, node); it.Ok();
911 if (residual_arc_capacity_[
arc] > 0) {
912 const CostValue min_non_admissible_potential_for_arc =
913 node_potential_[Head(
arc)] - scaled_arc_unit_cost_[
arc];
914 if (min_non_admissible_potential_for_arc > min_non_admissible_potential) {
915 if (min_non_admissible_potential_for_arc > guaranteed_new_potential) {
919 node_potential_.Set(node, guaranteed_new_potential);
920 first_admissible_arc_.Set(node,
arc);
923 previous_min_non_admissible_potential = min_non_admissible_potential;
924 min_non_admissible_potential = min_non_admissible_potential_for_arc;
931 if (min_non_admissible_potential == kMinCostValue) {
932 if (node_excess_[node] != 0) {
936 LOG(ERROR) <<
"Infeasible problem.";
941 node_potential_.Set(node, guaranteed_new_potential);
942 first_admissible_arc_.Set(node,
943 GetFirstOutgoingOrOppositeIncomingArc(node));
951 const CostValue new_potential = min_non_admissible_potential - epsilon_;
952 node_potential_.Set(node, new_potential);
953 if (previous_min_non_admissible_potential <= new_potential) {
954 first_admissible_arc_.Set(node, first_arc);
957 first_admissible_arc_.Set(node,
958 GetFirstOutgoingOrOppositeIncomingArc(node));
962template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
964GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::Opposite(
969template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
970bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcValid(
975template <
typename Graph,
typename ArcFlowType,
typename ArcScaledCostType>
976bool GenericMinCostFlow<Graph, ArcFlowType, ArcScaledCostType>::IsArcDirect(
986template class GenericMinCostFlow<StarGraph>;
987template class GenericMinCostFlow<::util::ReverseArcListGraph<>>;
988template class GenericMinCostFlow<::util::ReverseArcStaticGraph<>>;
989template class GenericMinCostFlow<::util::ReverseArcMixedGraph<>>;
990template class GenericMinCostFlow<
994template class GenericMinCostFlow<
1001 if (reserve_num_nodes > 0) {
1002 node_supply_.reserve(reserve_num_nodes);
1004 if (reserve_num_arcs > 0) {
1005 arc_tail_.reserve(reserve_num_arcs);
1006 arc_head_.reserve(reserve_num_arcs);
1007 arc_capacity_.reserve(reserve_num_arcs);
1008 arc_cost_.reserve(reserve_num_arcs);
1009 arc_permutation_.reserve(reserve_num_arcs);
1010 arc_flow_.reserve(reserve_num_arcs);
1015 ResizeNodeVectors(node);
1016 node_supply_[node] = supply;
1025 arc_tail_.push_back(
tail);
1026 arc_head_.push_back(
head);
1028 arc_cost_.push_back(unit_cost);
1033 return arc < arc_permutation_.size() ? arc_permutation_[
arc] :
arc;
1037 SupplyAdjustment adjustment) {
1041 const NodeIndex num_nodes = node_supply_.size();
1042 const ArcIndex num_arcs = arc_capacity_.size();
1043 if (num_nodes == 0)
return OPTIMAL;
1045 int supply_node_count = 0, demand_node_count = 0;
1047 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1048 if (node_supply_[node] > 0) {
1049 ++supply_node_count;
1050 total_supply += node_supply_[node];
1051 }
else if (node_supply_[node] < 0) {
1052 ++demand_node_count;
1053 total_demand -= node_supply_[node];
1056 if (adjustment == DONT_ADJUST && total_supply != total_demand) {
1071 const ArcIndex augmented_num_arcs =
1072 num_arcs + supply_node_count + demand_node_count;
1075 const NodeIndex augmented_num_nodes = num_nodes + 2;
1077 Graph graph(augmented_num_nodes, augmented_num_arcs);
1079 graph.AddArc(arc_tail_[
arc], arc_head_[
arc]);
1082 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1083 if (node_supply_[node] > 0) {
1084 graph.AddArc(source, node);
1085 }
else if (node_supply_[node] < 0) {
1086 graph.AddArc(node, sink);
1090 graph.Build(&arc_permutation_);
1093 GenericMaxFlow<Graph> max_flow(&graph, source, sink);
1096 max_flow.SetArcCapacity(PermutedArc(
arc), arc_capacity_[
arc]);
1098 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1099 if (node_supply_[node] != 0) {
1100 max_flow.SetArcCapacity(PermutedArc(
arc), std::abs(node_supply_[node]));
1105 if (!max_flow.Solve()) {
1106 LOG(ERROR) <<
"Max flow could not be computed.";
1107 switch (max_flow.status()) {
1112 <<
"Max flow failed but claimed to have an optimal solution";
1113 ABSL_FALLTHROUGH_INTENDED;
1118 maximum_flow_ = max_flow.GetOptimalFlow();
1121 if (adjustment == DONT_ADJUST && maximum_flow_ != total_supply) {
1125 GenericMinCostFlow<Graph> min_cost_flow(&graph);
1129 min_cost_flow.SetArcUnitCost(permuted_arc, arc_cost_[
arc]);
1130 min_cost_flow.SetArcCapacity(permuted_arc, arc_capacity_[
arc]);
1132 for (
NodeIndex node = 0; node < num_nodes; ++node) {
1133 if (node_supply_[node] != 0) {
1135 min_cost_flow.SetArcCapacity(permuted_arc, std::abs(node_supply_[node]));
1136 min_cost_flow.SetArcUnitCost(permuted_arc, 0);
1140 min_cost_flow.SetNodeSupply(source, maximum_flow_);
1141 min_cost_flow.SetNodeSupply(sink, -maximum_flow_);
1142 min_cost_flow.SetCheckFeasibility(
false);
1144 arc_flow_.resize(num_arcs);
1145 if (min_cost_flow.Solve()) {
1146 optimal_cost_ = min_cost_flow.GetOptimalCost();
1148 arc_flow_[
arc] = min_cost_flow.Flow(PermutedArc(
arc));
1151 return min_cost_flow.status();
1159 return arc_flow_[
arc];
1171 return arc_capacity_[
arc];
1175 return arc_cost_[
arc];
1179 return node_supply_[node];
1182void SimpleMinCostFlow::ResizeNodeVectors(
NodeIndex node) {
1183 if (node < node_supply_.size())
return;
1184 node_supply_.resize(node + 1);
#define DCHECK_LE(val1, val2)
#define CHECK_EQ(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
ArcIndexType AddArc(NodeIndexType tail, NodeIndexType head)
NodeIndexType Tail(const ArcIndexType arc) const
FlowQuantity GetOptimalFlow() const
void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity)
FlowQuantity Flow(ArcIndex arc) const
void SetCheckResult(bool value)
void SetCheckInput(bool value)
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)
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
NodeIndexType Head(const ArcIndexType arc) 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.
#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)