Generated on: Thu Mar 29 07:46:58 PDT 2012 for custom file set | ||
|
||
00001 // Copyright 2010-2012 Google 00002 // Licensed under the Apache License, Version 2.0 (the "License"); 00003 // you may not use this file except in compliance with the License. 00004 // You may obtain a copy of the License at 00005 // 00006 // http://www.apache.org/licenses/LICENSE-2.0 00007 // 00008 // Unless required by applicable law or agreed to in writing, software 00009 // distributed under the License is distributed on an "AS IS" BASIS, 00010 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00011 // See the License for the specific language governing permissions and 00012 // limitations under the License. 00013 00014 // An implementation of a push-relabel algorithm for the max flow problem. 00015 // 00016 // In the following, we consider a graph G = (V,E,s,t) where V denotes the set 00017 // of nodes (vertices) in the graph, E denotes the set of arcs (edges). s and t 00018 // denote distinguished nodes in G called source and target. n = |V| denotes the 00019 // number of nodes in the graph, and m = |E| denotes the number of arcs in the 00020 // graph. 00021 // 00022 // Each arc (v,w) is associated a capacity c(v,w). 00023 // A flow is a function from E to R such that: 00024 // a) f(v,w) <= c(v,w) for all (v,w) in E (capacity constraint.) 00025 // b) f(v,w) = -f(w,v) for all (v,w) in E (flow antisymmetry constraint.) 00026 // c) sum on v f(v,w) = 0 (flow conservation.) 00027 // 00028 // The goal of this algorithm is to find the maximum flow from s to t, i.e. 00029 // for example to maximize sum v f(s,v). 00030 // 00031 // The starting reference for this class of algorithms is: 00032 // A.V. Goldberg and R.E. Tarjan. A new approach to the maximum flow problem. 00033 // ACM Symposium on Theory of Computing, pp. 136-146. 00034 // http://portal.acm.org/citation.cfm?id=12144 00035 // 00036 // The basic idea of the algorithm is to handle preflows instead of flows, 00037 // and to refine preflows until a maximum flow is obtained. 00038 // A preflow is like a flow, except that the inflow can be larger than the 00039 // outflow. If it is the case at a given node v, it is said that there is an 00040 // excess at node v, and inflow = outflow + excess. 00041 // More formally, a preflow is a function f such that: 00042 // 1) f(v,w) <= c(v,w) for all (v,w) in E (capacity constraint). c(v,w) is a 00043 // value representing the maximum capacity for arc (v,w). 00044 // 2) f(v,w) = -f(w,v) for all (v,w) in E (flow antisymmetry constraint) 00045 // 3) excess(v) = sum on u f(u,v) >= 0 is the excess at node v, the 00046 // algebraic sum of all the incoming preflows at this node. 00047 // 00048 // Each node has an associated "height", in addition to its excess. The 00049 // height of the source is defined to be equal to n, and cannot change. The 00050 // height of the target is defined to be zero, and cannot change either. The 00051 // height of all the other nodes is initialized at zero and is updated during 00052 // the algorithm (see below). For those who want to know the details, the height 00053 // of a node, corresponds to a reduced cost, and this enables one to prove that 00054 // the algorithm actually computes the max flow. Note that the height of a node 00055 // can be initialized to the distance to the target node in terms of number of 00056 // nodes. This has not been tried in this implementation. 00057 // 00058 // A node v is said to be *active* if excess(v) > 0. 00059 // In this case the following operations can be applied to it: 00060 // - if there are *admissible* incident arcs, i.e. arcs which are not saturated, 00061 // and whose tail's height is lower than the height of the active node 00062 // considered, a PushFlow operation can be applied. It consists in sending as 00063 // much flow as both the excess at the node and the capacity of the arc 00064 // permit. 00065 // - if there are no admissible arcs, the active node considered is relabeled, 00066 // i.e. its height is increased to 1 + the minimum height of its neighboring 00067 // nodes on admissible arcs. 00068 // This is implemented in Optimize, which itself calls PushFlow and Relabel. 00069 // 00070 // Before running Optimize, it is necessary to initialize the algorithm with a 00071 // preflow. This is done in InitializePreflow, which saturates all the arcs 00072 // leaving the source node, and sets the excess at the heads of those arcs 00073 // accordingly. 00074 // 00075 // The algorithm terminates when there are no remaining active nodes, i.e. all 00076 // the excesses at all nodes are equal to zero. In this case, a maximum flow is 00077 // obtained. 00078 // 00079 // TODO(user): implement the following active node choice rule. 00080 // 00081 // The complexity of this algorithm depends amongst other things on the choice 00082 // of the next active node. It has been shown, for example in: 00083 // L. Tuncel, "On the Complexity of Preflow-Push Algorithms for Maximum-Flow 00084 // Problems", Algorithmica 11(4): 353-359 (1994). 00085 // and 00086 // J. Cheriyan and K. Mehlhorn, "An analysis of the highest-level selection rule 00087 // in the preflow-push max-flow algorithm", Information processing letters, 00088 // 69(5):239-242 (1999). 00089 // http://www.math.uwaterloo.ca/~jcheriya/PS_files/me3.0.ps 00090 // 00091 // that choosing the active node with the highest level yields a complexity of 00092 // O(n^2 * sqrt(m)). 00093 // 00094 // This has been validated experimentally in: 00095 // R.K. Ahuja, M. Kodialam, A.K. Mishra, and J.B. Orlin, "Computational 00096 // Investigations of Maximum Flow Algorithms", EJOR 97:509-542(1997). 00097 // http://jorlin.scripts.mit.edu/docs/publications/ 00098 // 58-comput%20investigations%20of.pdf 00099 // 00100 // TODO(user): an alternative would be to evaluate: 00101 // A.V. Goldberg, "The Partial Augment-Relabel Algorithm for the Maximum Flow 00102 // Problem.” In Proceedings of Algorithms ESA, LNCS 5193:466-477, Springer 2008. 00103 // www.springerlink.com/index/5535k2j1mt646338.pdf 00104 // 00105 // An interesting general reference on network flows is: 00106 // R. K. Ahuja, T. L. Magnanti, J. B. Orlin, "Network Flows: Theory, Algorithms, 00107 // and Applications," Prentice Hall, 1993, ISBN: 978-0136175490, 00108 // http://www.amazon.com/dp/013617549X 00109 // 00110 // Keywords: Push-relabel, max-flow, network, graph, Goldberg, Tarjan, Dinic, 00111 // Dinitz. 00112 00113 #ifndef OR_TOOLS_GRAPH_MAX_FLOW_H_ 00114 #define OR_TOOLS_GRAPH_MAX_FLOW_H_ 00115 00116 #include <algorithm> 00117 #include <stack> 00118 #include <string> 00119 00120 #include "base/integral_types.h" 00121 #include "base/logging.h" 00122 #include "base/macros.h" 00123 #include "graph/ebert_graph.h" 00124 00125 using std::string; 00126 00127 namespace operations_research { 00128 00129 class MaxFlow { 00130 public: 00131 // Different statuses for a given problem. 00132 typedef enum { 00133 NOT_SOLVED, // The problem was not solved, or its data were edited. 00134 OPTIMAL, // Solve() was called and found an optimal solution. 00135 FEASIBLE, // There is a feasible flow. 00136 INFEASIBLE, // There is no feasible flow. 00137 BAD_INPUT, // The input is inconsistent. 00138 BAD_RESULT // There was an error. 00139 } Status; 00140 00141 MaxFlow(const StarGraph* graph, NodeIndex source, NodeIndex target); 00142 00143 virtual ~MaxFlow() {} 00144 00145 // Returns the graph associated to the current object. 00146 const StarGraph* graph() const { return graph_; } 00147 00148 // Returns the status of last call to Solve(). NOT_SOLVED is returned Solve() 00149 // has never been called or if the problem has been modified in such a way 00150 // that the previous solution becomes invalid. 00151 Status status() const { return status_; } 00152 00153 // Returns the index of the node corresponding to the source of the network. 00154 NodeIndex GetSourceNodeIndex() const { return source_; } 00155 00156 // Returns the index of the node corresponding to the sink of the network. 00157 NodeIndex GetSinkNodeIndex() const { return sink_; } 00158 00159 // Sets the capacity for arc to new_capacity. 00160 void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity); 00161 00162 // Sets the flow for arc. 00163 void SetArcFlow(ArcIndex arc, FlowQuantity new_flow) { 00164 DCHECK(graph_->CheckArcValidity(arc)); 00165 const FlowQuantity capacity = Capacity(arc); 00166 DCHECK_GE(capacity, new_flow); 00167 residual_arc_capacity_.Set(Opposite(arc), -new_flow); 00168 residual_arc_capacity_.Set(arc, capacity - new_flow); 00169 status_ = NOT_SOLVED; 00170 } 00171 00172 // Returns true if a maximum flow was solved. 00173 bool Solve(); 00174 00175 // Returns the total flow found by the algorithm. 00176 FlowQuantity GetOptimalFlow() const { return total_flow_; } 00177 00178 // Returns the flow on arc using the equations given in the comment on 00179 // residual_arc_capacity_. 00180 FlowQuantity Flow(ArcIndex arc) const { 00181 DCHECK(graph_->CheckArcValidity(arc)); 00182 if (IsDirect(arc)) { 00183 return residual_arc_capacity_[Opposite(arc)]; 00184 } else { 00185 return -residual_arc_capacity_[arc]; 00186 } 00187 } 00188 00189 // Returns the capacity of arc using the equations given in the comment on 00190 // residual_arc_capacity_. 00191 FlowQuantity Capacity(ArcIndex arc) const { 00192 DCHECK(graph_->CheckArcValidity(arc)); 00193 if (IsDirect(arc)) { 00194 return residual_arc_capacity_[arc] 00195 + residual_arc_capacity_[Opposite(arc)]; 00196 } else { 00197 return 0; 00198 } 00199 } 00200 00201 protected: 00202 // Returns true if arc is admissible. 00203 bool IsAdmissible(ArcIndex arc) const { 00204 return residual_arc_capacity_[arc] > 0 00205 && node_potential_[Tail(arc)] == node_potential_[Head(arc)] + 1; 00206 } 00207 00208 // Returns true if node is active, i.e. if its supply is positive and it 00209 // is neither the source or the target of the graph. 00210 bool IsActive(NodeIndex node) const { 00211 return (node != source_) && (node != sink_) && (node_excess_[node] > 0); 00212 } 00213 00214 // Returns the first incident arc of node. 00215 ArcIndex GetFirstIncidentArc(NodeIndex node) const { 00216 StarGraph::IncidentArcIterator arc_it(*graph_, node); 00217 return arc_it.Index(); 00218 } 00219 00220 // Reduces the residual capacity on arc by flow. 00221 // Increase the residual capacity on opposite arc by flow. 00222 // Does not update the excesses at the tail and head of arc. 00223 // No check is performed either. 00224 void PushFlowUnsafe(ArcIndex arc, FlowQuantity flow) { 00225 residual_arc_capacity_.Set(arc, residual_arc_capacity_[arc] - flow); 00226 const ArcIndex opposite = Opposite(arc); 00227 residual_arc_capacity_.Set(opposite, 00228 residual_arc_capacity_[opposite] + flow); 00229 } 00230 00231 // Sets the capacity of arc to 'capacity' and clears the flow on arc. 00232 void SetCapacityResetFlow(ArcIndex arc, FlowQuantity capacity) { 00233 residual_arc_capacity_.Set(arc, capacity); 00234 residual_arc_capacity_.Set(Opposite(arc), 0); 00235 } 00236 00237 // Sets the capacity of arc to 'capacity' and saturates the flow on arc. 00238 void SetCapacitySaturate(ArcIndex arc, FlowQuantity capacity) { 00239 residual_arc_capacity_.Set(arc, 0); 00240 residual_arc_capacity_.Set(Opposite(arc), capacity); 00241 } 00242 00243 // Checks the consistency of the input, i.e. that capacities on the arcs are 00244 // non-negative (>=0.) 00245 bool CheckInputConsistency() const; 00246 00247 // Checks whether the result is valid, i.e. that node excesses are all equal 00248 // to zero (we have a flow) and that residual capacities are all non-negative 00249 // (>=0.) 00250 bool CheckResult() const; 00251 00252 // Returns true if a precondition for Relabel is met, i.e. the outgoing arcs 00253 // of node are all either saturated or the heights of their heads are greater 00254 // or equal to the height of node. 00255 bool CheckRelabelPrecondition(NodeIndex node) const; 00256 00257 // Returns context concatenated with information about arc 00258 // in a human-friendly way. 00259 string DebugString(const string& context, ArcIndex arc) const; 00260 00261 // Initializes the container active_nodes_. 00262 virtual void InitializeActiveNodeContainer(); 00263 00264 // Get the first element from the active node container 00265 virtual NodeIndex GetAndRemoveFirstActiveNode() { 00266 const NodeIndex node = active_nodes_.top(); 00267 active_nodes_.pop(); 00268 return node; 00269 } 00270 00271 // Push element to the active node container 00272 virtual void PushActiveNode(const NodeIndex& node) { 00273 active_nodes_.push(node); 00274 } 00275 00276 // Check the emptiness of the container 00277 virtual bool IsEmptyActiveNodeContainer() { 00278 return active_nodes_.empty(); 00279 } 00280 00281 // Performs optimization step. 00282 void Refine(); 00283 00284 // Discharges an active node node by saturating its admissible adjacent arcs, 00285 // if any, and by relabelling it when it becomes inactive. 00286 virtual void Discharge(NodeIndex node); 00287 00288 // Resets the first_admissible_arc_ array to the first incident arc of each 00289 // node. 00290 void ResetFirstAdmissibleArcs(); 00291 00292 // Initializes the preflow to a state that enables to run Optimize. 00293 void InitializePreflow(); 00294 00295 // Pushes flow on arc, i.e. consumes flow on residual_arc_capacity_[arc], 00296 // and consumes -flow on residual_arc_capacity_[Opposite(arc)]. Updates 00297 // node_excess_ at the tail and head of arc accordingly. 00298 void PushFlow(FlowQuantity flow, ArcIndex arc); 00299 00300 // Relabels a node, i.e. increases its height by the minimum necessary amount. 00301 void Relabel(NodeIndex node); 00302 00303 // Handy member functions to make the code more compact. 00304 NodeIndex Head(ArcIndex arc) const { return graph_->Head(arc); } 00305 00306 NodeIndex Tail(ArcIndex arc) const { return graph_->Tail(arc); } 00307 00308 ArcIndex Opposite(ArcIndex arc) const { return graph_->Opposite(arc); } 00309 00310 bool IsDirect(ArcIndex arc) const { return graph_->IsDirect(arc); } 00311 00312 // A pointer to the graph passed as argument. 00313 const StarGraph* graph_; 00314 00315 // A packed array representing the excess for each node in graph_. 00316 QuantityArray node_excess_; 00317 00318 // A packed array representing the height function for each node in graph_. 00319 CostArray node_potential_; 00320 00321 // A packed array representing the residual_capacity for each arc in graph_. 00322 // Residual capacities enable one to represent the capacity and flow for all 00323 // arcs in the graph in the following manner. 00324 // For all arc, residual_arc_capacity_[arc] = capacity[arc] - flow[arc] 00325 // Moreover, for reverse arcs, capacity[arc] = 0 by definition, 00326 // Also flow[Opposite(arc)] = -flow[arc] by definition. 00327 // Therefore: 00328 // - for a direct arc: 00329 // flow[arc] = 0 - flow[Opposite(arc)] 00330 // = capacity[Opposite(arc)] - flow[Opposite(arc)] 00331 // = residual_arc_capacity_[Opposite(arc)] 00332 // - for a reverse arc: 00333 // flow[arc] = -residual_arc_capacity_[arc] 00334 // Using these facts enables one to only maintain residual_arc_capacity_, 00335 // instead of both capacity and flow, for each direct and indirect arc. This 00336 // reduces the amount of memory for this information by a factor 2.s reduces 00337 // the amount of memory for this information by a factor 2. 00338 QuantityArray residual_arc_capacity_; 00339 00340 // A packed array representing the first admissible arc for each node 00341 // in graph_. 00342 ArcIndexArray first_admissible_arc_; 00343 00344 // A stack used for managing active nodes in the algorithm. 00345 // Note that the papers cited above recommend the use of a queue, but 00346 // benchmarking so far has not proved it is better. 00347 std::stack<NodeIndex> active_nodes_; 00348 00349 // The index of the source node in graph_. 00350 NodeIndex source_; 00351 00352 // The index of the sink node in graph_. 00353 NodeIndex sink_; 00354 00355 // The total flow. 00356 FlowQuantity total_flow_; 00357 00358 // The status of the problem. 00359 Status status_; 00360 00361 DISALLOW_COPY_AND_ASSIGN(MaxFlow); 00362 }; 00363 } // namespace operations_research 00364 #endif // OR_TOOLS_GRAPH_MAX_FLOW_H_