00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "graph/max_flow.h"
00015
00016 #include <algorithm>
00017
00018 #include "base/commandlineflags.h"
00019 #include "base/stringprintf.h"
00020
00021 DEFINE_bool(max_flow_check_input, false,
00022 "Check that the input is consistent.");
00023 DEFINE_bool(max_flow_check_result, false,
00024 "Check that the result is valid.");
00025
00026 namespace operations_research {
00027
00028 MaxFlow::MaxFlow(const StarGraph* graph,
00029 NodeIndex source,
00030 NodeIndex sink)
00031 : graph_(graph),
00032 node_excess_(),
00033 node_potential_(),
00034 residual_arc_capacity_(),
00035 first_admissible_arc_(),
00036 active_nodes_(),
00037 source_(source),
00038 sink_(sink) {
00039 const NodeIndex max_num_nodes = graph_->max_num_nodes();
00040 if (max_num_nodes > 0) {
00041 node_excess_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00042 node_excess_.SetAll(0);
00043 node_potential_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00044 node_potential_.SetAll(0);
00045 first_admissible_arc_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00046 first_admissible_arc_.SetAll(StarGraph::kNilArc);
00047 }
00048 const ArcIndex max_num_arcs = graph_->max_num_arcs();
00049 if (max_num_arcs > 0) {
00050 residual_arc_capacity_.Reserve(-max_num_arcs, max_num_arcs - 1);
00051 residual_arc_capacity_.SetAll(0);
00052 }
00053 DCHECK(graph_->IsNodeValid(source_));
00054 DCHECK(graph_->IsNodeValid(sink_));
00055 }
00056
00057 bool MaxFlow::CheckInputConsistency() const {
00058 bool ok = true;
00059 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00060 const ArcIndex arc = arc_it.Index();
00061 if (residual_arc_capacity_[arc] < 0) {
00062 ok = false;
00063 }
00064 }
00065 return ok;
00066 }
00067
00068 void MaxFlow::SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity) {
00069 DCHECK_LE(0, new_capacity);
00070 DCHECK(graph_->CheckArcValidity(arc));
00071 const FlowQuantity free_capacity = residual_arc_capacity_[arc];
00072 const FlowQuantity capacity_delta = new_capacity - Capacity(arc);
00073 VLOG(2) << "Changing capacity on arc " << arc
00074 << " from " << Capacity(arc) << " to " << new_capacity
00075 << ". Current free capacity = " << free_capacity;
00076 if (capacity_delta == 0) {
00077 return;
00078 }
00079 status_ = NOT_SOLVED;
00080 if (free_capacity + capacity_delta >= 0) {
00081
00082
00083
00084
00085
00086 DCHECK((capacity_delta > 0) ||
00087 (capacity_delta < 0 && free_capacity + capacity_delta >= 0));
00088 residual_arc_capacity_.Set(arc, free_capacity + capacity_delta);
00089 DCHECK_LE(0, residual_arc_capacity_[arc]);
00090 VLOG(2) << "Now: capacity = " << Capacity(arc) << " flow = " << Flow(arc);
00091 } else {
00092
00093
00094 const FlowQuantity flow = residual_arc_capacity_[Opposite(arc)];
00095 const FlowQuantity flow_excess = flow - new_capacity;
00096 VLOG(2) << "Flow value " << flow << " exceeds new capacity "
00097 << new_capacity << " by " << flow_excess;
00098 SetCapacitySaturate(arc, new_capacity);
00099 const NodeIndex head = Head(arc);
00100 node_excess_.Set(head, node_excess_[head] + flow_excess);
00101 DCHECK_LE(0, residual_arc_capacity_[arc]);
00102 DCHECK_LE(0, residual_arc_capacity_[Opposite(arc)]);
00103 VLOG(2) << DebugString("After SetArcCapacity:", arc);
00104 }
00105 }
00106
00107 bool MaxFlow::CheckResult() const {
00108 bool ok = true;
00109 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00110 const NodeIndex node = node_it.Index();
00111 if (node != source_ && node != sink_) {
00112 if (node_excess_[node] != 0) {
00113 LOG(DFATAL) << "node_excess_[" << node << "] = " << node_excess_[node]
00114 << " != 0";
00115 ok = false;
00116 }
00117 }
00118 }
00119 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00120 const ArcIndex arc = arc_it.Index();
00121 const ArcIndex opposite = Opposite(arc);
00122 const FlowQuantity direct_capacity = residual_arc_capacity_[arc];
00123 const FlowQuantity opposite_capacity = residual_arc_capacity_[opposite];
00124 if (direct_capacity < 0) {
00125 LOG(DFATAL) << "residual_arc_capacity_[" << arc << "] = "
00126 << direct_capacity << " < 0";
00127 ok = false;
00128 }
00129 if (opposite_capacity < 0) {
00130 LOG(DFATAL) << "residual_arc_capacity_[" << opposite << "] = "
00131 << opposite_capacity << " < 0";
00132 ok = false;
00133 }
00134
00135 if (direct_capacity + opposite_capacity < 0) {
00136 LOG(DFATAL) << "initial capacity [" << arc << "] = "
00137 << direct_capacity + opposite_capacity << " < 0";
00138 ok = false;
00139 }
00140 }
00141 return ok;
00142 }
00143
00144 bool MaxFlow::CheckRelabelPrecondition(NodeIndex node) const {
00145 DCHECK(IsActive(node));
00146 for (StarGraph::IncidentArcIterator arc_it(*graph_, node);
00147 arc_it.Ok();
00148 arc_it.Next()) {
00149 const ArcIndex arc = arc_it.Index();
00150 DCHECK(!IsAdmissible(arc));
00151 }
00152 return true;
00153 }
00154
00155 string MaxFlow::DebugString(const string& context, ArcIndex arc) const {
00156 const NodeIndex tail = Tail(arc);
00157 const NodeIndex head = Head(arc);
00158 return StringPrintf("%s Arc %d, from %d to %d, "
00159 "Capacity = %lld, Residual capacity = %lld, "
00160 "Flow = residual capacity for reverse arc = %lld, "
00161 "Height(tail) = %lld, Height(head) = %lld, "
00162 "Excess(tail) = %lld, Excess(head) = %lld",
00163 context.c_str(), arc, tail, head, Capacity(arc),
00164 residual_arc_capacity_[arc], Flow(arc),
00165 node_potential_[tail], node_potential_[head],
00166 node_excess_[tail], node_excess_[head]);
00167 }
00168
00169 bool MaxFlow::Solve() {
00170 status_ = NOT_SOLVED;
00171 if (FLAGS_max_flow_check_input && !CheckInputConsistency()) {
00172 status_ = BAD_INPUT;
00173 return false;
00174 }
00175 InitializePreflow();
00176 ResetFirstAdmissibleArcs();
00177 Refine();
00178 if (FLAGS_max_flow_check_result && !CheckResult()) {
00179 status_ = BAD_RESULT;
00180 return false;
00181 }
00182 total_flow_ = 0;
00183 for (StarGraph::OutgoingArcIterator arc_it(*graph_, source_);
00184 arc_it.Ok();
00185 arc_it.Next()) {
00186 const ArcIndex arc = arc_it.Index();
00187 total_flow_ += Flow(arc);
00188 }
00189 status_ = OPTIMAL;
00190 return true;
00191 }
00192
00193 void MaxFlow::ResetFirstAdmissibleArcs() {
00194 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00195 const NodeIndex node = node_it.Index();
00196 first_admissible_arc_.Set(node, GetFirstIncidentArc(node));
00197 }
00198 }
00199
00200 void MaxFlow::InitializePreflow() {
00201
00202
00203
00204
00205 node_potential_.SetAll(0);
00206 node_excess_.SetAll(0);
00207 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00208 const ArcIndex arc = arc_it.Index();
00209 SetCapacityResetFlow(arc, Capacity(arc));
00210 }
00211
00212 node_potential_.Set(source_, graph_->num_nodes());
00213 for (StarGraph::OutgoingArcIterator arc_it(*graph_, source_);
00214 arc_it.Ok();
00215 arc_it.Next()) {
00216 const ArcIndex arc = arc_it.Index();
00217 const FlowQuantity arc_capacity = Capacity(arc);
00218
00219
00220
00221 SetCapacitySaturate(arc, arc_capacity);
00222 node_excess_.Set(Head(arc), arc_capacity);
00223 VLOG(2) << DebugString("InitializePreflow:", arc);
00224 }
00225 }
00226
00227 void MaxFlow::PushFlow(FlowQuantity flow, ArcIndex arc) {
00228 DCHECK_GT(residual_arc_capacity_[arc], 0);
00229 DCHECK_GT(node_excess_[Tail(arc)], 0);
00230 VLOG(2) << "PushFlow: pushing " << flow << " on arc " << arc
00231 << " from node " << Tail(arc) << " to node " << Head(arc);
00232 PushFlowUnsafe(arc, flow);
00233
00234 const NodeIndex tail = Tail(arc);
00235 node_excess_.Set(tail, node_excess_[tail] - flow);
00236 const NodeIndex head = Head(arc);
00237 node_excess_.Set(head, node_excess_[head] + flow);
00238 VLOG(3) << DebugString("PushFlow: ", arc);
00239 }
00240
00241 void MaxFlow::InitializeActiveNodeContainer() {
00242 DCHECK(IsEmptyActiveNodeContainer());
00243 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00244 const NodeIndex node = node_it.Index();
00245 if (IsActive(node)) {
00246 PushActiveNode(node);
00247 VLOG(2) << "InitializeActiveNodeStack: node " << node << " added.";
00248 }
00249 }
00250 }
00251
00252 void MaxFlow::Refine() {
00253 InitializeActiveNodeContainer();
00254 while (!IsEmptyActiveNodeContainer()) {
00255 const NodeIndex node = GetAndRemoveFirstActiveNode();
00256 if (IsActive(node)) {
00257 VLOG(2) << "Refine: calling Discharge for node " << node;
00258 Discharge(node);
00259 }
00260 }
00261 }
00262
00263 void MaxFlow::Discharge(NodeIndex node) {
00264 DCHECK(IsActive(node));
00265 VLOG(2) << "Discharging node " << node << ", excess = " << node_excess_[node];
00266 while (IsActive(node)) {
00267 for (StarGraph::IncidentArcIterator arc_it(*graph_, node,
00268 first_admissible_arc_[node]);
00269 arc_it.Ok();
00270 arc_it.Next()) {
00271 const ArcIndex arc = arc_it.Index();
00272 VLOG(3) << DebugString("Discharge: considering", arc);
00273 if (IsAdmissible(arc)) {
00274 if (node_excess_[node] != 0) {
00275 VLOG(2) << "Discharge: calling PushFlow.";
00276 const NodeIndex head = Head(arc);
00277 const bool head_active_before_push = IsActive(head);
00278 const FlowQuantity delta = std::min(node_excess_[node],
00279 residual_arc_capacity_[arc]);
00280 PushFlow(delta, arc);
00281 if (IsActive(head) && !head_active_before_push) {
00282 PushActiveNode(Head(arc));
00283 }
00284 }
00285 if (node_excess_[node] == 0) {
00286 first_admissible_arc_.Set(node, arc);
00287 return;
00288 }
00289 }
00290 }
00291 Relabel(node);
00292 }
00293 }
00294
00295 void MaxFlow::Relabel(NodeIndex node) {
00296 DCHECK(CheckRelabelPrecondition(node));
00297 CostValue min_height = node_potential_[node];
00298 for (StarGraph::IncidentArcIterator arc_it(*graph_, node);
00299 arc_it.Ok();
00300 arc_it.Next()) {
00301 const ArcIndex arc = arc_it.Index();
00302 DCHECK_EQ(Tail(arc), node);
00303 if (residual_arc_capacity_[arc] > 0) {
00304
00305 min_height = std::min(min_height, node_potential_[Head(arc)]);
00306 }
00307 }
00308 VLOG(2) << "Relabel: height(" << node << ") relabeled from "
00309 << node_potential_[node] << " to " << min_height + 1;
00310 node_potential_.Set(node, min_height + 1);
00311 first_admissible_arc_.Set(node, GetFirstIncidentArc(node));
00312 }
00313
00314 }