19#include "absl/memory/memory.h"
20#include "absl/strings/str_format.h"
30 const ArcIndex num_arcs = arc_tail_.size();
33 arc_tail_.push_back(
tail);
34 arc_head_.push_back(
head);
48 return arc_capacity_[arc];
56 const ArcIndex num_arcs = arc_capacity_.size();
57 arc_flow_.assign(num_arcs, 0);
58 underlying_max_flow_.reset();
59 underlying_graph_.reset();
61 if (source == sink || source < 0 || sink < 0) {
64 if (source >= num_nodes_ || sink >= num_nodes_) {
67 underlying_graph_ = absl::make_unique<Graph>(num_nodes_, num_arcs);
68 underlying_graph_->AddNode(source);
69 underlying_graph_->AddNode(sink);
70 for (
int arc = 0; arc < num_arcs; ++arc) {
71 underlying_graph_->AddArc(arc_tail_[arc], arc_head_[arc]);
73 underlying_graph_->Build(&arc_permutation_);
74 underlying_max_flow_ = absl::make_unique<GenericMaxFlow<Graph>>(
75 underlying_graph_.get(), source, sink);
76 for (
ArcIndex arc = 0; arc < num_arcs; ++arc) {
78 arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
79 underlying_max_flow_->SetArcCapacity(permuted_arc, arc_capacity_[arc]);
81 if (underlying_max_flow_->Solve()) {
82 optimal_flow_ = underlying_max_flow_->GetOptimalFlow();
83 for (
ArcIndex arc = 0; arc < num_arcs; ++arc) {
85 arc < arc_permutation_.size() ? arc_permutation_[arc] : arc;
86 arc_flow_[arc] = underlying_max_flow_->Flow(permuted_arc);
91 switch (underlying_max_flow_->status()) {
111 if (underlying_max_flow_ ==
nullptr)
return;
112 underlying_max_flow_->GetSourceSideMinCut(result);
116 if (underlying_max_flow_ ==
nullptr)
return;
117 underlying_max_flow_->GetSinkSideMinCut(result);
121 if (underlying_max_flow_ ==
nullptr)
return FlowModel();
122 return underlying_max_flow_->CreateFlowModel();
125template <
typename Graph>
131 residual_arc_capacity_(),
132 first_admissible_arc_(),
136 use_global_update_(true),
137 use_two_phase_algorithm_(true),
138 process_node_by_height_(true),
146 if (max_num_nodes > 0) {
157 if (max_num_arcs > 0) {
163template <
typename Graph>
167 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
168 if (residual_arc_capacity_[arc] < 0) {
175template <
typename Graph>
181 const FlowQuantity free_capacity = residual_arc_capacity_[arc];
182 const FlowQuantity capacity_delta = new_capacity - Capacity(arc);
183 if (capacity_delta == 0) {
186 status_ = NOT_SOLVED;
187 if (free_capacity + capacity_delta >= 0) {
193 DCHECK((capacity_delta > 0) ||
194 (capacity_delta < 0 && free_capacity + capacity_delta >= 0));
195 residual_arc_capacity_.Set(arc, free_capacity + capacity_delta);
196 DCHECK_LE(0, residual_arc_capacity_[arc]);
205 SetCapacityAndClearFlow(arc, new_capacity);
209template <
typename Graph>
220 residual_arc_capacity_.Set(Opposite(arc), -new_flow);
221 residual_arc_capacity_.Set(arc,
capacity - new_flow);
222 status_ = NOT_SOLVED;
225template <
typename Graph>
227 std::vector<NodeIndex>* result) {
228 ComputeReachableNodes<false>(source_, result);
231template <
typename Graph>
233 ComputeReachableNodes<true>(sink_, result);
236template <
typename Graph>
240 if (node_excess_[source_] != -node_excess_[sink_]) {
241 LOG(DFATAL) <<
"-node_excess_[source_] = " << -node_excess_[source_]
242 <<
" != node_excess_[sink_] = " << node_excess_[sink_];
245 for (
NodeIndex node = 0; node < graph_->num_nodes(); ++node) {
246 if (node != source_ && node != sink_) {
247 if (node_excess_[node] != 0) {
248 LOG(DFATAL) <<
"node_excess_[" << node <<
"] = " << node_excess_[node]
254 for (
ArcIndex arc = 0; arc < graph_->num_arcs(); ++arc) {
255 const ArcIndex opposite = Opposite(arc);
256 const FlowQuantity direct_capacity = residual_arc_capacity_[arc];
257 const FlowQuantity opposite_capacity = residual_arc_capacity_[opposite];
258 if (direct_capacity < 0) {
259 LOG(DFATAL) <<
"residual_arc_capacity_[" << arc
260 <<
"] = " << direct_capacity <<
" < 0";
263 if (opposite_capacity < 0) {
264 LOG(DFATAL) <<
"residual_arc_capacity_[" << opposite
265 <<
"] = " << opposite_capacity <<
" < 0";
269 if (direct_capacity + opposite_capacity < 0) {
270 LOG(DFATAL) <<
"initial capacity [" << arc
271 <<
"] = " << direct_capacity + opposite_capacity <<
" < 0";
278template <
typename Graph>
283 const NodeIndex num_nodes = graph_->num_nodes();
284 std::vector<bool> is_reached(num_nodes,
false);
285 std::vector<NodeIndex> to_process;
287 to_process.push_back(source_);
288 is_reached[source_] =
true;
289 while (!to_process.empty()) {
290 const NodeIndex node = to_process.back();
291 to_process.pop_back();
295 if (residual_arc_capacity_[arc] > 0) {
297 if (!is_reached[
head]) {
298 is_reached[
head] =
true;
299 to_process.push_back(
head);
304 return is_reached[sink_];
307template <
typename Graph>
313 DCHECK(!IsAdmissible(arc)) << DebugString(
"CheckRelabelPrecondition:", arc);
318template <
typename Graph>
323 return absl::StrFormat(
324 "%s Arc %d, from %d to %d, "
325 "Capacity = %d, Residual capacity = %d, "
326 "Flow = residual capacity for reverse arc = %d, "
327 "Height(tail) = %d, Height(head) = %d, "
328 "Excess(tail) = %d, Excess(head) = %d",
330 Flow(arc), node_potential_[
tail], node_potential_[
head],
331 node_excess_[
tail], node_excess_[
head]);
334template <
typename Graph>
336 status_ = NOT_SOLVED;
337 if (check_input_ && !CheckInputConsistency()) {
346 const NodeIndex num_nodes = graph_->num_nodes();
347 if (sink_ >= num_nodes || source_ >= num_nodes) {
353 if (use_global_update_) {
354 RefineWithGlobalUpdate();
359 if (!CheckResult()) {
360 status_ = BAD_RESULT;
363 if (GetOptimalFlow() < kMaxFlowQuantity && AugmentingPathExists()) {
364 LOG(
ERROR) <<
"The algorithm terminated, but the flow is not maximal!";
365 status_ = BAD_RESULT;
369 DCHECK_EQ(node_excess_[sink_], -node_excess_[source_]);
371 if (GetOptimalFlow() == kMaxFlowQuantity && AugmentingPathExists()) {
373 status_ = INT_OVERFLOW;
379template <
typename Graph>
386 node_excess_.SetAll(0);
387 const ArcIndex num_arcs = graph_->num_arcs();
388 for (
ArcIndex arc = 0; arc < num_arcs; ++arc) {
389 SetCapacityAndClearFlow(arc, Capacity(arc));
394 node_potential_.SetAll(0);
395 node_potential_.Set(source_, graph_->num_nodes());
400 const NodeIndex num_nodes = graph_->num_nodes();
401 for (
NodeIndex node = 0; node < num_nodes; ++node) {
402 first_admissible_arc_[node] = Graph::kNilArc;
410template <
typename Graph>
413 const NodeIndex num_nodes = graph_->num_nodes();
422 std::vector<bool> stored(num_nodes,
false);
423 stored[sink_] =
true;
427 std::vector<bool> visited(num_nodes,
false);
428 visited[sink_] =
true;
432 std::vector<ArcIndex> arc_stack;
436 std::vector<int> index_branch;
439 std::vector<NodeIndex> reverse_topological_order;
448 arc_stack.push_back(arc);
451 visited[source_] =
true;
454 while (!arc_stack.empty()) {
455 const NodeIndex node = Head(arc_stack.back());
463 reverse_topological_order.push_back(node);
464 DCHECK(!index_branch.empty());
465 index_branch.pop_back();
467 arc_stack.pop_back();
474 DCHECK(index_branch.empty() ||
475 (arc_stack.size() - 1 > index_branch.back()));
476 visited[node] =
true;
477 index_branch.push_back(arc_stack.size() - 1);
479 for (OutgoingArcIterator it(*graph_, node); it.Ok(); it.Next()) {
483 if (flow > 0 && !stored[
head]) {
484 if (!visited[
head]) {
485 arc_stack.push_back(arc);
491 int cycle_begin = index_branch.size();
492 while (cycle_begin > 0 &&
493 Head(arc_stack[index_branch[cycle_begin - 1]]) !=
head) {
500 int first_saturated_index = index_branch.size();
501 for (
int i = index_branch.size() - 1; i >= cycle_begin; --i) {
502 const ArcIndex arc_on_cycle = arc_stack[index_branch[i]];
503 if (Flow(arc_on_cycle) <= max_flow) {
504 max_flow = Flow(arc_on_cycle);
505 first_saturated_index = i;
514 PushFlow(-max_flow, arc);
515 for (
int i = index_branch.size() - 1; i >= cycle_begin; --i) {
516 const ArcIndex arc_on_cycle = arc_stack[index_branch[i]];
517 PushFlow(-max_flow, arc_on_cycle);
518 if (i >= first_saturated_index) {
519 DCHECK(visited[Head(arc_on_cycle)]);
520 visited[Head(arc_on_cycle)] =
false;
531 if (first_saturated_index < index_branch.size()) {
532 arc_stack.resize(index_branch[first_saturated_index]);
533 index_branch.resize(first_saturated_index);
543 DCHECK(arc_stack.empty());
544 DCHECK(index_branch.empty());
548 for (
int i = 0; i < reverse_topological_order.size(); i++) {
549 const NodeIndex node = reverse_topological_order[i];
550 if (node_excess_[node] == 0)
continue;
551 for (IncomingArcIterator it(*graph_, node); it.Ok(); it.Next()) {
552 const ArcIndex opposite_arc = Opposite(it.Index());
553 if (residual_arc_capacity_[opposite_arc] > 0) {
555 std::min(node_excess_[node], residual_arc_capacity_[opposite_arc]);
556 PushFlow(flow, opposite_arc);
557 if (node_excess_[node] == 0)
break;
562 DCHECK_EQ(-node_excess_[source_], node_excess_[sink_]);
565template <
typename Graph>
570 const NodeIndex num_nodes = graph_->num_nodes();
571 node_in_bfs_queue_.assign(num_nodes,
false);
572 node_in_bfs_queue_[sink_] =
true;
573 node_in_bfs_queue_[source_] =
true;
584 const int num_passes = use_two_phase_algorithm_ ? 1 : 2;
585 for (
int pass = 0; pass < num_passes; ++pass) {
587 bfs_queue_.push_back(sink_);
589 bfs_queue_.push_back(source_);
592 while (queue_index != bfs_queue_.size()) {
593 const NodeIndex node = bfs_queue_[queue_index];
595 const NodeIndex candidate_distance = node_potential_[node] + 1;
603 if (node_in_bfs_queue_[
head])
continue;
611 const ArcIndex opposite_arc = Opposite(arc);
612 if (residual_arc_capacity_[opposite_arc] > 0) {
626 if (node_excess_[
head] > 0) {
628 node_excess_[
head], residual_arc_capacity_[opposite_arc]);
629 PushFlow(flow, opposite_arc);
633 if (residual_arc_capacity_[opposite_arc] == 0)
continue;
638 node_potential_[
head] = candidate_distance;
639 node_in_bfs_queue_[
head] =
true;
640 bfs_queue_.push_back(
head);
657 for (
NodeIndex node = 0; node < num_nodes; ++node) {
658 if (!node_in_bfs_queue_[node]) {
659 node_potential_[node] = 2 * num_nodes - 1;
665 DCHECK(IsEmptyActiveNodeContainer());
666 for (
int i = 1; i < bfs_queue_.size(); ++i) {
668 if (node_excess_[node] > 0) {
670 PushActiveNode(node);
675template <
typename Graph>
678 const NodeIndex num_nodes = graph_->num_nodes();
682 if (node_excess_[sink_] == kMaxFlowQuantity)
return false;
683 if (node_excess_[source_] == -kMaxFlowQuantity)
return false;
685 bool flow_pushed =
false;
691 if (flow == 0 || node_potential_[Head(arc)] >= num_nodes)
continue;
695 const FlowQuantity current_flow_out_of_source = -node_excess_[source_];
697 DCHECK_GE(current_flow_out_of_source, 0) << current_flow_out_of_source;
699 kMaxFlowQuantity - current_flow_out_of_source;
700 if (capped_flow < flow) {
707 if (capped_flow == 0)
return true;
708 PushFlow(capped_flow, arc);
718template <
typename Graph>
722 DCHECK_GE(residual_arc_capacity_[Opposite(arc)] + flow, 0);
723 DCHECK_GE(residual_arc_capacity_[arc] - flow, 0);
732 residual_arc_capacity_[arc] -= flow;
733 residual_arc_capacity_[Opposite(arc)] += flow;
736 node_excess_[Tail(arc)] -= flow;
737 node_excess_[Head(arc)] += flow;
740template <
typename Graph>
743 DCHECK(IsEmptyActiveNodeContainer());
744 const NodeIndex num_nodes = graph_->num_nodes();
745 for (
NodeIndex node = 0; node < num_nodes; ++node) {
746 if (IsActive(node)) {
747 if (use_two_phase_algorithm_ && node_potential_[node] >= num_nodes) {
750 PushActiveNode(node);
755template <
typename Graph>
780 while (SaturateOutgoingArcsFromSource()) {
781 DCHECK(IsEmptyActiveNodeContainer());
782 InitializeActiveNodeContainer();
783 while (!IsEmptyActiveNodeContainer()) {
784 const NodeIndex node = GetAndRemoveFirstActiveNode();
785 if (node == source_ || node == sink_)
continue;
788 if (use_two_phase_algorithm_) {
789 PushFlowExcessBackToSource();
794template <
typename Graph>
801 std::vector<int> skip_active_node;
803 while (SaturateOutgoingArcsFromSource()) {
807 skip_active_node.assign(num_nodes, 0);
808 skip_active_node[sink_] = 2;
809 skip_active_node[source_] = 2;
811 while (!IsEmptyActiveNodeContainer()) {
812 const NodeIndex node = GetAndRemoveFirstActiveNode();
813 if (skip_active_node[node] > 1) {
814 if (node != sink_ && node != source_) ++num_skipped;
817 const NodeIndex old_height = node_potential_[node];
836 if (node_potential_[node] > old_height + 1) {
837 ++skip_active_node[node];
840 }
while (num_skipped > 0);
841 if (use_two_phase_algorithm_) {
842 PushFlowExcessBackToSource();
847template <
typename Graph>
850 const NodeIndex num_nodes = graph_->num_nodes();
854 first_admissible_arc_[node]);
855 it.Ok(); it.Next()) {
857 if (IsAdmissible(arc)) {
860 if (node_excess_[
head] == 0) {
863 PushActiveNode(
head);
866 std::min(node_excess_[node], residual_arc_capacity_[arc]);
867 PushFlow(
delta, arc);
868 if (node_excess_[node] == 0) {
869 first_admissible_arc_[node] = arc;
875 if (use_two_phase_algorithm_ && node_potential_[node] >= num_nodes)
break;
879template <
typename Graph>
886 ArcIndex first_admissible_arc = Graph::kNilArc;
890 if (residual_arc_capacity_[arc] > 0) {
892 NodeHeight head_height = node_potential_[Head(arc)];
893 if (head_height < min_height) {
894 min_height = head_height;
895 first_admissible_arc = arc;
899 if (min_height + 1 == node_potential_[node])
break;
903 DCHECK_NE(first_admissible_arc, Graph::kNilArc);
904 node_potential_[node] = min_height + 1;
909 first_admissible_arc_[node] = first_admissible_arc;
912template <
typename Graph>
917template <
typename Graph>
919 return IsArcValid(arc) && arc >= 0;
922template <
typename Graph>
927template <
typename Graph>
931template <
typename Graph>
932template <
bool reverse>
934 NodeIndex start, std::vector<NodeIndex>* result) {
938 const NodeIndex num_nodes = graph_->num_nodes();
939 if (start >= num_nodes) {
941 result->push_back(start);
945 node_in_bfs_queue_.assign(num_nodes,
false);
948 bfs_queue_.push_back(start);
949 node_in_bfs_queue_[start] =
true;
950 while (queue_index != bfs_queue_.size()) {
951 const NodeIndex node = bfs_queue_[queue_index];
957 if (node_in_bfs_queue_[
head])
continue;
958 if (residual_arc_capacity_[reverse ? Opposite(arc) : arc] == 0)
continue;
959 node_in_bfs_queue_[
head] =
true;
960 bfs_queue_.push_back(
head);
963 *result = bfs_queue_;
966template <
typename Graph>
970 for (
int n = 0; n < graph_->num_nodes(); ++n) {
976 for (
int a = 0;
a < graph_->num_arcs(); ++
a) {
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
void set_head_node_id(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_capacity(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_tail_node_id(::PROTOBUF_NAMESPACE_ID::int64 value)
static constexpr ProblemType MAX_FLOW
Graph::OutgoingArcIterator OutgoingArcIterator
bool CheckInputConsistency() const
void Relabel(NodeIndex node)
std::vector< NodeIndex > active_nodes_
void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity)
std::string DebugString(const std::string &context, ArcIndex arc) const
bool SaturateOutgoingArcsFromSource()
Graph::OutgoingOrOppositeIncomingArcIterator OutgoingOrOppositeIncomingArcIterator
bool CheckRelabelPrecondition(NodeIndex node) const
std::vector< NodeIndex > bfs_queue_
ArcIndexArray first_admissible_arc_
void SetArcFlow(ArcIndex arc, FlowQuantity new_flow)
void PushFlowExcessBackToSource()
Graph::NodeIndex NodeIndex
void GetSourceSideMinCut(std::vector< NodeIndex > *result)
NodeHeightArray node_potential_
void InitializeActiveNodeContainer()
const Graph * graph() const
QuantityArray residual_arc_capacity_
void PushFlow(FlowQuantity flow, ArcIndex arc)
void ComputeReachableNodes(NodeIndex start, std::vector< NodeIndex > *result)
bool IsArcValid(ArcIndex arc) const
GenericMaxFlow(const Graph *graph, NodeIndex source, NodeIndex sink)
void RefineWithGlobalUpdate()
bool AugmentingPathExists() const
void GetSinkSideMinCut(std::vector< NodeIndex > *result)
ArcIndex Opposite(ArcIndex arc) const
bool IsArcDirect(ArcIndex arc) const
void Discharge(NodeIndex node)
QuantityArray node_excess_
FlowModel CreateFlowModel()
void set_supply(::PROTOBUF_NAMESPACE_ID::int64 value)
void set_id(::PROTOBUF_NAMESPACE_ID::int64 value)
FlowQuantity Flow(ArcIndex arc) const
NodeIndex NumNodes() const
FlowModel CreateFlowModelOfLastSolve()
void GetSourceSideMinCut(std::vector< NodeIndex > *result)
Status Solve(NodeIndex source, NodeIndex sink)
FlowQuantity OptimalFlow() const
ArcIndex AddArcWithCapacity(NodeIndex tail, NodeIndex head, FlowQuantity capacity)
FlowQuantity Capacity(ArcIndex arc) const
NodeIndex Head(ArcIndex arc) const
NodeIndex Tail(ArcIndex arc) const
void SetArcCapacity(ArcIndex arc, FlowQuantity capacity)
void GetSinkSideMinCut(std::vector< NodeIndex > *result)
bool Reserve(int64_t new_min_index, int64_t new_max_index)
GurobiMPCallbackContext * context
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)