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 cost-scaling push-relabel algorithm for 00015 // the min-cost flow problem. 00016 // 00017 // In the following, we consider a graph G = (V,E) where V denotes the set 00018 // of nodes (vertices) in the graph, E denotes the set of arcs (edges). 00019 // n = |V| denotes the number of nodes in the graph, and m = |E| denotes the 00020 // number of arcs in the graph. 00021 // 00022 // With each arc (v,w) is associated a nonnegative capacity u(v,w) 00023 // (where 'u' stands for "upper bound") and a unit cost c(v,w). With 00024 // each node v is associated a quantity named supply(v), which 00025 // represents a supply of fluid (if >0) or a demand (if <0). 00026 // Furthermore, no fluid is created in the graph so 00027 // sum on v in V supply(v) = 0 00028 // 00029 // A flow is a function from E to R such that: 00030 // a) f(v,w) <= u(v,w) for all (v,w) in E (capacity constraint). 00031 // b) f(v,w) = -f(w,v) for all (v,w) in E (flow antisymmetry constraint). 00032 // c) sum on v f(v,w) + supply(w) = 0 (flow conservation). 00033 // 00034 // The cost of a flow is sum on (v,w) in E ( f(v,w) * c(v,w) ) [Note: 00035 // It can be confusing to beginners that the cost is actually double 00036 // the amount that it might seem at first because of flow 00037 // antisymmetry.] 00038 // 00039 // The problem to solve is to find a flow of minimum cost such that all the 00040 // fluid flows from the supply nodes to the demand nodes. 00041 // 00042 // The principles behind this algorithm are the following: 00043 // 1/ handle pseudo-flows instead of flows and refine pseudo-flows until an 00044 // epsilon-optimal minimum-cost flow is obtained, 00045 // 2/ deal with epsilon-optimal pseudo-flows. 00046 // 00047 // 1/ A pseudo-flow is like a flow, except that a node's outflow minus 00048 // its inflow can be different from its supply. If it is the case at a 00049 // given node v, it is said that there is an excess (or deficit) at 00050 // node v. A deficit is denoted by a negative excess and inflow = 00051 // outflow + excess. 00052 // (Look at graph/max_flow.h to see that the definition 00053 // of preflow is more restrictive than the one for pseudo-flow in that a preflow 00054 // only allows non-negative excesses, i.e. no deficit.) 00055 // More formally, a pseudo-flow is a function f such that: 00056 // a) f(v,w) <= u(v,w) for all (v,w) in E (capacity constraint). 00057 // b) f(v,w) = -f(w,v) for all (v,w) in E (flow antisymmetry constraint). 00058 // 00059 // For each v in E, we also define the excess at node v, the algebraic sum of 00060 // all the incoming preflows at this node, added together with the supply at v. 00061 // excess(v) = sum on u f(u,v) + supply(v) 00062 // 00063 // The goal of the algorithm is to obtain excess(v) = 0 for all v in V, while 00064 // consuming capacity on some arcs, at the lowest possible cost. 00065 // 00066 // 2/ Internally to the algorithm and its analysis (but invisibly to 00067 // the client), each node has an associated "price" (or potential), in 00068 // addition to its excess. It is formally a function from E to R (the 00069 // set of real numbers.). For a given price function p, the reduced 00070 // cost of an arc (v,w) is: 00071 // c_p(v,w) = c(v,w) + p(v) - p(w) 00072 // (c(v,w) is the cost of arc (v,w).) For those familiar with linear 00073 // programming, the price function can be viewed as a set of dual 00074 // variables. 00075 // 00076 // For a constant epsilon >= 0, a pseudo-flow f is said to be epsilon-optimal 00077 // with respect to a price function p if for every residual arc (v,w) in E, 00078 // c_p(v,w) >= -epsilon. 00079 // 00080 // A flow f is optimal if and only if there exists a price function p such that 00081 // no arc is admissible with respect to f and p. 00082 // 00083 // If the arc costs are integers, and epsilon < 1/n, any epsilon-optimal flow 00084 // is optimal. The integer cost case is handled by multiplying all the arc costs 00085 // and the initial value of epsilon by (n+1). When epsilon reaches 1, and 00086 // the solution is epsilon-optimal, it means: for all residual arc (v,w) in E, 00087 // (n+1) * c_p(v,w) >= -1, thus c_p(v,w) >= -1/(n+1) >= 1/n, and the 00088 // solution is optimal. 00089 // 00090 // A node v is said to be *active* if excess(v) > 0. 00091 // In this case the following operations can be applied to it: 00092 // - if there are *admissible* incident arcs, i.e. arcs which are not saturated, 00093 // and whose reduced costs are negative, a PushFlow operation can 00094 // be applied. It consists in sending as much flow as both the excess at the 00095 // node and the capacity of the arc permit. 00096 // - if there are no admissible arcs, the active node considered is relabeled, 00097 // This is implemented in Discharge, which itself calls PushFlow and Relabel. 00098 // 00099 // Discharge itself is called by Refine. Refine first saturates all the 00100 // admissible arcs, then builds a stack of active nodes. It then applies 00101 // Discharge for each active node, possibly adding new ones in the process, 00102 // until no nodes are active. In that case an epsilon-optimal flow is obtained. 00103 // 00104 // Optimize iteratively calls Refine, while epsilon > 1, and divides epsilon by 00105 // alpha (set by default to 5) before each iteration. 00106 // 00107 // The algorithm starts with epsilon = C, where C is the maximum absolute value 00108 // of the arc costs. In the integer case which we are dealing with, since all 00109 // costs are multiplied by (n+1), the initial value of epsilon is (n+1)*C. 00110 // The algorithm terminates when epsilon = 1, and Refine() has been called. 00111 // In this case, a minimum-cost flow is obtained. 00112 // 00113 // The complexity of the algorithm is O(n^2*m*log(n*C)) where C is the value of 00114 // the largest arc cost in the graph. 00115 // 00116 // IMPORTANT: 00117 // The algorithm is not able to detect the infeasibility of a problem (when 00118 // there is a bottleneck in the network that forbids to send all the supplies.) 00119 // Worse, it could in some cases loop forever. This is why feasibility checking 00120 // is enabled by default (FLAGS_min_cost_flow_check_feasibility=true.) 00121 // Feasibility checking is implemented using a max-flow, which has a much lower 00122 // complexity. The impact on performance is negligible, while the risk of being 00123 // caught in an endless loop is removed. Note that using the feasibility checker 00124 // roughly doubles the memory consumption. 00125 // 00126 // The starting reference for this class of algorithms is: 00127 // A.V. Goldberg and R.E. Tarjan, "Finding Minimum-Cost Circulations by 00128 // Successive Approximation." Mathematics of Operations Research, Vol. 15, 00129 // 1990:430-466. 00130 // http://portal.acm.org/citation.cfm?id=92225 00131 // 00132 // Implementation issues are tackled in: 00133 // A.V. Goldberg, "An Efficient Implementation of a Scaling Minimum-Cost Flow 00134 // Algorithm," Journal of Algorithms, (1997) 22:1-29 00135 // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.31.258 00136 // 00137 // A.V. Goldberg and M. Kharitonov, "On Implementing Scaling Push-Relabel 00138 // Algorithms for the Minimum-Cost Flow Problem", Network flows and matching: 00139 // First DIMACS implementation challenge, DIMACS Series in Discrete Mathematics 00140 // and Theoretical Computer Science, (1993) 12:157-198. 00141 // ftp://dimacs.rutgers.edu/pub/netflow/...mincost/scalmin.ps 00142 // and in: 00143 // U. Bunnagel, B. Korte, and J. Vygen. “Efficient implementation of the 00144 // Goldberg-Tarjan minimum-cost flow algorithm.” Optimization Methods and 00145 // Software (1998) vol. 10, no. 2:157-174. 00146 // http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.84.9897 00147 // 00148 // We have tried as much as possible in this implementation to keep the 00149 // notations and namings of the papers cited above, except for 'demand' or 00150 // 'balance' which have been replaced by 'supply', with the according sign 00151 // changes to better accomodate with the API of the rest of our tools. A demand 00152 // is denoted by a negative supply. 00153 // 00154 // TODO(user): See whether the following can bring any improvements on real-life 00155 // problems. 00156 // R.K. Ahuja, A.V. Goldberg, J.B. Orlin, and R.E. Tarjan, "Finding minimum-cost 00157 // flows by double scaling," Mathematical Programming, (1992) 53:243-266. 00158 // http://www.springerlink.com/index/gu7404218u6kt166.pdf 00159 // 00160 // An interesting general reference on network flows is: 00161 // R. K. Ahuja, T. L. Magnanti, J. B. Orlin, "Network Flows: Theory, Algorithms, 00162 // and Applications," Prentice Hall, 1993, ISBN: 978-0136175490, 00163 // http://www.amazon.com/dp/013617549X 00164 // 00165 // Keywords: Push-relabel, min-cost flow, network, graph, Goldberg, Tarjan, 00166 // Dinic, Dinitz. 00167 00168 00169 #ifndef OR_TOOLS_GRAPH_MIN_COST_FLOW_H_ 00170 #define OR_TOOLS_GRAPH_MIN_COST_FLOW_H_ 00171 00172 #include <algorithm> 00173 #include <stack> 00174 #include <string> 00175 00176 #include "base/integral_types.h" 00177 #include "base/logging.h" 00178 #include "base/macros.h" 00179 #include "graph/ebert_graph.h" 00180 00181 using std::string; 00182 00183 namespace operations_research { 00184 00185 class MinCostFlow { 00186 public: 00187 // Different statuses for a given problem. 00188 typedef enum { 00189 NOT_SOLVED, 00190 OPTIMAL, 00191 FEASIBLE, 00192 INFEASIBLE, 00193 UNBALANCED, 00194 BAD_RESULT, 00195 BAD_COST_RANGE 00196 } Status; 00197 00198 explicit MinCostFlow(const StarGraph* graph); 00199 00200 // Returns the graph associated to the current object. 00201 const StarGraph* graph() const { return graph_; } 00202 00203 // Returns the status of last call to Solve(). NOT_SOLVED is returned Solve() 00204 // has never been called or if the problem has been modified in such a way 00205 // that the previous solution becomes invalid. 00206 Status status() const { return status_; } 00207 00208 // Sets the supply corresponding to node. A demand is modeled as a negative 00209 // supply. 00210 void SetNodeSupply(NodeIndex node, FlowQuantity supply) { 00211 DCHECK(graph_->IsNodeValid(node)); 00212 node_excess_.Set(node, supply); 00213 initial_node_excess_.Set(node, supply); 00214 status_ = NOT_SOLVED; 00215 feasibility_checked_ = false; 00216 } 00217 00218 // Sets the unit cost for arc. 00219 void SetArcUnitCost(ArcIndex arc, CostValue unit_cost) { 00220 DCHECK(graph_->CheckArcValidity(arc)); 00221 scaled_arc_unit_cost_.Set(arc, unit_cost); 00222 scaled_arc_unit_cost_.Set(Opposite(arc), -scaled_arc_unit_cost_[arc]); 00223 status_ = NOT_SOLVED; 00224 feasibility_checked_ = false; 00225 } 00226 00227 // Sets the capacity for arc. 00228 void SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity); 00229 00230 // Sets the flow for arc. Note that new_flow must be smaller than the 00231 // capacity of arc. 00232 void SetArcFlow(ArcIndex arc, FlowQuantity new_flow) { 00233 DCHECK(graph_->CheckArcValidity(arc)); 00234 const FlowQuantity capacity = Capacity(arc); 00235 DCHECK_GE(capacity, new_flow); 00236 residual_arc_capacity_.Set(Opposite(arc), new_flow); 00237 residual_arc_capacity_.Set(arc, capacity - new_flow); 00238 status_ = NOT_SOLVED; 00239 feasibility_checked_ = false; 00240 } 00241 00242 // Runs true is a min-cost flow could be found. 00243 bool Solve(); 00244 00245 // Checks for feasibility, i.e. that all the supplies and demands can be 00246 // matched without exceeding bottlenecks in the network. 00247 // If infeasible_supply_node (resp. infeasible_demand_node) are not NULL, 00248 // they are populated with the indices of the nodes where the initial supplies 00249 // (resp. demands) are too large. Feasible values for the supplies and 00250 // demands are accessible through FeasibleSupply. 00251 // Note that CheckFeasibility is called by Solve() when the flag 00252 // min_cost_flow_check_feasibility is set to true (which is the default.) 00253 bool CheckFeasibility(std::vector<NodeIndex>* const infeasible_supply_node, 00254 std::vector<NodeIndex>* const infeasible_demand_node); 00255 00256 // Makes the min-cost flow problem solvable by truncating supplies and 00257 // demands to a level acceptable by the network. There may be several ways to 00258 // do it. In our case, the levels are computed from the result of the max-flow 00259 // algorithm run in CheckFeasibility(). 00260 // MakeFeasible returns false if CheckFeasibility() was not called before. 00261 bool MakeFeasible(); 00262 00263 // Returns the cost of the minimum-cost flow found by the algorithm. 00264 CostValue GetOptimalCost() const { return total_flow_cost_; } 00265 00266 // Returns the flow on arc using the equations given in the comment on 00267 // residual_arc_capacity_. 00268 FlowQuantity Flow(ArcIndex arc) const { 00269 DCHECK(graph_->CheckArcValidity(arc)); 00270 if (IsDirect(arc)) { 00271 return residual_arc_capacity_[Opposite(arc)]; 00272 } else { 00273 return -residual_arc_capacity_[arc]; 00274 } 00275 } 00276 00277 // Returns the capacity of arc using the equations given in the comment on 00278 // residual_arc_capacity_. 00279 FlowQuantity Capacity(ArcIndex arc) const { 00280 DCHECK(graph_->CheckArcValidity(arc)); 00281 if (IsDirect(arc)) { 00282 return residual_arc_capacity_[arc] 00283 + residual_arc_capacity_[Opposite(arc)]; 00284 } else { 00285 return 0; 00286 } 00287 } 00288 00289 // Returns the unscaled cost for arc. 00290 FlowQuantity Cost(ArcIndex arc) const { 00291 DCHECK(graph_->CheckArcValidity(arc)); 00292 DCHECK_EQ(1ULL, cost_scaling_factor_); 00293 return scaled_arc_unit_cost_[arc]; 00294 } 00295 00296 // Returns the supply at node. Demands are modelled as negative supplies. 00297 FlowQuantity Supply(NodeIndex node) const { 00298 DCHECK(graph_->IsNodeValid(node)); 00299 return node_excess_[node]; 00300 } 00301 00302 // Returns the initial supply at node, given as data. 00303 FlowQuantity InitialSupply(NodeIndex node) const { 00304 return initial_node_excess_[node]; 00305 } 00306 00307 // Returns the largest supply (if > 0) or largest demand in absolute value 00308 // (if < 0) admissible at node. If the problem is not feasible, some of these 00309 // values will be smaller (in absolute value) than than the initial supplies 00310 // and demand given as input. 00311 FlowQuantity FeasibleSupply(NodeIndex node) const { 00312 return feasible_node_excess_[node]; 00313 } 00314 00315 private: 00316 // Returns true if arc is admissible i.e. if its residual capacity is stricly 00317 // positive, and its reduced cost stricly negative, i.e. pushing more flow 00318 // into it will result in a reduction of the total cost. 00319 bool IsAdmissible(ArcIndex arc) const { 00320 return residual_arc_capacity_[arc] > 0 && ReducedCost(arc) < 0; 00321 } 00322 00323 // Returns true if node is active, i.e. if its supply is positive. 00324 bool IsActive(NodeIndex node) const { 00325 return node_excess_[node] > 0; 00326 } 00327 00328 // Returns the reduced cost for an arc. 00329 CostValue ReducedCost(ArcIndex arc) const { 00330 DCHECK(graph_->IsNodeValid(Tail(arc))); 00331 DCHECK(graph_->IsNodeValid(Head(arc))); 00332 DCHECK_LE(node_potential_[Tail(arc)], 0); 00333 DCHECK_LE(node_potential_[Head(arc)], 0); 00334 return scaled_arc_unit_cost_[arc] 00335 + node_potential_[Tail(arc)] 00336 - node_potential_[Head(arc)]; 00337 } 00338 00339 // Returns the first incident arc of node. 00340 ArcIndex GetFirstIncidentArc(NodeIndex node) const { 00341 StarGraph::IncidentArcIterator arc_it(*graph_, node); 00342 return arc_it.Index(); 00343 } 00344 00345 // Checks the consistency of the input, i.e. whether the sum of the supplies 00346 // for all nodes is equal to zero. To be used in a DCHECK. 00347 bool CheckInputConsistency() const; 00348 00349 // Checks whether the result is valid, i.e. whether for each arc, 00350 // residual_arc_capacity_[arc] == 0 || ReducedCost(arc) >= -epsilon_ . 00351 // (A solution is epsilon-optimal if ReducedCost(arc) >= -epsilon.) 00352 // To be used in a DCHECK. 00353 bool CheckResult() const; 00354 00355 // Checks that the cost range fits in the range of int64's. 00356 // To be used in a DCHECK. 00357 bool CheckCostRange() const; 00358 00359 // Checks the relabel precondition, i.e. that none of the arc incident to 00360 // node is admissible. To be used in a DCHECK. 00361 bool CheckRelabelPrecondition(NodeIndex node) const; 00362 00363 // Returns context concatenated with information about arc 00364 // in a human-friendly way. 00365 string DebugString(const string& context, ArcIndex arc) const; 00366 00367 // Resets the first_admissible_arc_ array to the first incident arc of each 00368 // node. 00369 void ResetFirstAdmissibleArcs(); 00370 00371 // Scales the costs, by multiplying them by (graph_->num_nodes() + 1). 00372 void ScaleCosts(); 00373 00374 // Unscales the costs, by dividing them by (graph_->num_nodes() + 1). 00375 void UnscaleCosts(); 00376 00377 // Optimizes the cost by dividing epsilon_ by alpha_ and calling Refine(). 00378 void Optimize(); 00379 00380 // Saturates the admissible arcs, i.e. push as much flow as possible. 00381 void SaturateAdmissibleArcs(); 00382 00383 // Pushes flow on arc, i.e. consumes flow on residual_arc_capacity_[arc], 00384 // and consumes -flow on residual_arc_capacity_[Opposite(arc)]. Updates 00385 // node_excess_ at the tail and head of arc accordingly. 00386 void PushFlow(FlowQuantity flow, ArcIndex arc); 00387 00388 // Initializes the stack active_nodes_. 00389 void InitializeActiveNodeStack(); 00390 00391 // Performs an epsilon-optimization step by saturating admissible arcs 00392 // and discharging the active nodes. 00393 void Refine(); 00394 00395 // Discharges an active node node by saturating its admissible adjacent arcs, 00396 // if any, and by relabelling it when it becomes inactive. 00397 void Discharge(NodeIndex node); 00398 00399 // Relabels node, i.e. increases the its node_potential_ of node. 00400 // The preconditions are that node active, and no arc incident to node is 00401 // admissible. 00402 void Relabel(NodeIndex node); 00403 00404 // Performs a set-relabel operation. 00405 void GlobalRelabel(); 00406 00407 // Handy member functions to make the code more compact. 00408 NodeIndex Head(ArcIndex arc) const { return graph_->Head(arc); } 00409 00410 NodeIndex Tail(ArcIndex arc) const { return graph_->Tail(arc); } 00411 00412 ArcIndex Opposite(ArcIndex arc) const { return graph_->Opposite(arc); } 00413 00414 bool IsDirect(ArcIndex arc) const { return graph_->IsDirect(arc); } 00415 00416 // Pointer to the graph passed as argument. 00417 const StarGraph* graph_; 00418 00419 // A packed array representing the supply (if > 0) or the demand (if < 0) 00420 // for each node in graph_. 00421 QuantityArray node_excess_; 00422 00423 // A packed array representing the potential (or price function) for 00424 // each node in graph_. 00425 CostArray node_potential_; 00426 00427 // A packed array representing the residual_capacity for each arc in graph_. 00428 // Residual capacities enable one to represent the capacity and flow for all 00429 // arcs in the graph in the following manner. 00430 // For all arc, residual_arc_capacity_[arc] = capacity[arc] - flow[arc] 00431 // Moreover, for reverse arcs, capacity[arc] = 0 by definition. 00432 // Also flow[Opposite(arc)] = -flow[arc] by definition. 00433 // Therefore: 00434 // - for a direct arc: 00435 // flow[arc] = 0 - flow[Opposite(arc)] 00436 // = capacity[Opposite(arc)] - flow[Opposite(arc)] 00437 // = residual_arc_capacity_[Opposite(arc)] 00438 // - for a reverse arc: 00439 // flow[arc] = -residual_arc_capacity_[arc] 00440 // Using these facts enables one to only maintain residual_arc_capacity_, 00441 // instead of both capacity and flow, for each direct and indirect arc. This 00442 // reduces the amount of memory for this information by a factor 2. 00443 // Note that the sum of the largest capacity of an arc in the graph and of 00444 // the total flow in the graph not exceed the largest integer representable 00445 // in 64 bits or there would be errors. CheckInputConsistency() verifies 00446 // this. 00447 QuantityArray residual_arc_capacity_; 00448 00449 // A packed array representing the first admissible arc for each node 00450 // in graph_. 00451 ArcIndexArray first_admissible_arc_; 00452 00453 // A stack used for managing active nodes in the algorithm. 00454 // Note that the papers cited above recommend the use of a queue, but 00455 // benchmarking so far has not proved it is better. 00456 std::stack<NodeIndex> active_nodes_; 00457 00458 // epsilon_ is the tolerance for optimality. 00459 CostValue epsilon_; 00460 00461 // alpha_ is the factor by which epsilon_ is divided at each iteration of 00462 // Refine(). 00463 const int64 alpha_; 00464 00465 // cost_scaling_factor_ is the scaling factor for cost. 00466 CostValue cost_scaling_factor_; 00467 00468 // A packed array representing the scaled unit cost for each arc in graph_. 00469 QuantityArray scaled_arc_unit_cost_; 00470 00471 // The total cost of the flow. 00472 CostValue total_flow_cost_; 00473 00474 // The status of the problem. 00475 Status status_; 00476 00477 // A packed array containing the initial excesses (i.e. the supplies) for each 00478 // node. This is used to create the max-flow-based feasibility checker. 00479 QuantityArray initial_node_excess_; 00480 00481 // A packed array containing the best acceptable excesses for each of the 00482 // nodes. These excesses are imposed by the result of the max-flow-based 00483 // feasibility checker for the nodes with an initial supply != 0. For the 00484 // other nodes, the excess is simply 0. 00485 QuantityArray feasible_node_excess_; 00486 00487 // A Boolean which is true when feasibility has been checked. 00488 bool feasibility_checked_; 00489 00490 DISALLOW_COPY_AND_ASSIGN(MinCostFlow); 00491 }; 00492 } // namespace operations_research 00493 #endif // OR_TOOLS_GRAPH_MIN_COST_FLOW_H_