00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "graph/min_cost_flow.h"
00015
00016 #include <math.h>
00017 #include <algorithm>
00018 #include <limits>
00019
00020 #include "base/commandlineflags.h"
00021 #include "base/stringprintf.h"
00022 #include "base/mathutil.h"
00023 #include "graph/max_flow.h"
00024
00025 DEFINE_int64(min_cost_flow_alpha, 5,
00026 "Divide factor for epsilon at each refine step.");
00027 DEFINE_bool(min_cost_flow_check_feasibility, true,
00028 "Check that the graph has enough capacity to send all supplies "
00029 "and serve all demands. Also check that the sum of supplies "
00030 "is equal to the sum of demands.");
00031 DEFINE_bool(min_cost_flow_check_balance, true,
00032 "Check that the sum of supplies is equal to the sum of demands.");
00033 DEFINE_bool(min_cost_flow_check_costs, true,
00034 "Check that the magnitude of the costs will not exceed the "
00035 "precision of the machine when scaled (multiplied) by the number "
00036 "of nodes");
00037 DEFINE_bool(min_cost_flow_fast_potential_update, true,
00038 "Fast node potential update. Faster when set to true, but does not"
00039 "detect as many infeasibilities as when set to false.");
00040 DEFINE_bool(min_cost_flow_check_result, true,
00041 "Check that the result is valid.");
00042
00043 namespace operations_research {
00044
00045 MinCostFlow::MinCostFlow(const StarGraph* graph)
00046 : graph_(graph),
00047 node_excess_(),
00048 node_potential_(),
00049 residual_arc_capacity_(),
00050 first_admissible_arc_(),
00051 active_nodes_(),
00052 epsilon_(0),
00053 alpha_(FLAGS_min_cost_flow_alpha),
00054 cost_scaling_factor_(1),
00055 scaled_arc_unit_cost_(),
00056 total_flow_cost_(0),
00057 status_(NOT_SOLVED),
00058 initial_node_excess_(),
00059 feasible_node_excess_(),
00060 feasibility_checked_(false) {
00061 const NodeIndex max_num_nodes = graph_->max_num_nodes();
00062 if (max_num_nodes > 0) {
00063 node_excess_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00064 node_excess_.SetAll(0);
00065 node_potential_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00066 node_potential_.SetAll(0);
00067 first_admissible_arc_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00068 first_admissible_arc_.SetAll(StarGraph::kNilArc);
00069 initial_node_excess_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00070 initial_node_excess_.SetAll(0);
00071 feasible_node_excess_.Reserve(StarGraph::kFirstNode, max_num_nodes - 1);
00072 feasible_node_excess_.SetAll(0);
00073 }
00074 const ArcIndex max_num_arcs = graph_->max_num_arcs();
00075 if (max_num_arcs > 0) {
00076 residual_arc_capacity_.Reserve(-max_num_arcs, max_num_arcs - 1);
00077 residual_arc_capacity_.SetAll(0);
00078 scaled_arc_unit_cost_.Reserve(-max_num_arcs, max_num_arcs - 1);
00079 scaled_arc_unit_cost_.SetAll(0);
00080 }
00081 }
00082
00083 void MinCostFlow::SetArcCapacity(ArcIndex arc, FlowQuantity new_capacity) {
00084 DCHECK_LE(0, new_capacity);
00085 DCHECK(graph_->CheckArcValidity(arc));
00086 const FlowQuantity free_capacity = residual_arc_capacity_[arc];
00087 const FlowQuantity capacity_delta = new_capacity - Capacity(arc);
00088 VLOG(3) << "Changing capacity on arc " << arc
00089 << " from " << Capacity(arc) << " to " << new_capacity
00090 << ". Current free capacity = " << free_capacity;
00091 if (capacity_delta == 0) {
00092 return;
00093 }
00094 status_ = NOT_SOLVED;
00095 feasibility_checked_ = false;
00096 const FlowQuantity new_availability = free_capacity + capacity_delta;
00097 if (new_availability >= 0) {
00098
00099
00100
00101
00102
00103 DCHECK((capacity_delta > 0) ||
00104 (capacity_delta < 0 && new_availability >= 0));
00105 residual_arc_capacity_.Set(arc, new_availability);
00106 DCHECK_LE(0, residual_arc_capacity_[arc]);
00107 VLOG(3) << "Now: capacity = " << Capacity(arc) << " flow = " << Flow(arc);
00108 } else {
00109
00110
00111 const FlowQuantity flow = residual_arc_capacity_[Opposite(arc)];
00112 const FlowQuantity flow_excess = flow - new_capacity;
00113 VLOG(3) << "Flow value " << flow << " exceeds new capacity "
00114 << new_capacity << " by " << flow_excess;
00115 residual_arc_capacity_.Set(arc, 0);
00116 residual_arc_capacity_.Set(Opposite(arc), new_capacity);
00117 const NodeIndex tail = Tail(arc);
00118 node_excess_.Set(tail, node_excess_[tail] + flow_excess);
00119 const NodeIndex head = Head(arc);
00120 node_excess_.Set(head, node_excess_[head] - flow_excess);
00121 DCHECK_LE(0, residual_arc_capacity_[arc]);
00122 DCHECK_LE(0, residual_arc_capacity_[Opposite(arc)]);
00123 VLOG(3) << DebugString("After SetArcCapacity:", arc);
00124 }
00125 }
00126
00127 bool MinCostFlow::CheckInputConsistency() const {
00128 FlowQuantity total_supply = 0;
00129 uint64 max_capacity = 0;
00130
00131 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00132 const ArcIndex arc = arc_it.Index();
00133 const uint64 capacity = static_cast<uint64>(residual_arc_capacity_[arc]);
00134 max_capacity = std::max(capacity, max_capacity);
00135 }
00136 uint64 total_flow = 0;
00137 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00138 const NodeIndex node = node_it.Index();
00139 const FlowQuantity excess = node_excess_[node];
00140 total_supply += excess;
00141 if (excess > 0) {
00142 total_flow += excess;
00143 if (std::numeric_limits<FlowQuantity>::max() <
00144 max_capacity + total_flow) {
00145 LOG(DFATAL) << "Input consistency error: max capacity + flow exceed "
00146 << "precision";
00147 }
00148 }
00149 }
00150 if (total_supply != 0) {
00151 LOG(DFATAL) << "Input consistency error: unbalanced problem";
00152 }
00153 return true;
00154 }
00155
00156 bool MinCostFlow::CheckResult() const {
00157 for (StarGraph::NodeIterator it(*graph_); it.Ok(); it.Next()) {
00158 const NodeIndex node = it.Index();
00159 if (node_excess_[node] != 0) {
00160 LOG(DFATAL) << "node_excess_[" << node << "] != 0";
00161 return false;
00162 }
00163 for (StarGraph::IncidentArcIterator
00164 arc_it(*graph_, node); arc_it.Ok(); arc_it.Next()) {
00165 const ArcIndex arc = arc_it.Index();
00166 bool ok = true;
00167 if (residual_arc_capacity_[arc] < 0) {
00168 LOG(DFATAL) << "residual_arc_capacity_[" << arc << "] < 0";
00169 ok = false;
00170 }
00171 if (residual_arc_capacity_[arc] > 0 && ReducedCost(arc) < -epsilon_) {
00172 LOG(DFATAL) << "residual_arc_capacity_[" << arc
00173 << "] > 0 && ReducedCost(" << arc << ") < " << -epsilon_
00174 << ". (epsilon_ = " << epsilon_ << ").";
00175 ok = false;
00176 }
00177 if (!ok) {
00178 LOG(DFATAL) << DebugString("CheckResult ", arc);
00179 }
00180 }
00181 }
00182 return true;
00183 }
00184
00185 bool MinCostFlow::CheckCostRange() const {
00186 CostValue min_cost_magnitude = std::numeric_limits<CostValue>::max();
00187 CostValue max_cost_magnitude = 0;
00188
00189 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00190 const ArcIndex arc = arc_it.Index();
00191 const CostValue cost_magnitude = MathUtil::Abs(scaled_arc_unit_cost_[arc]);
00192 max_cost_magnitude = std::max(max_cost_magnitude, cost_magnitude);
00193 if (cost_magnitude != 0.0) {
00194 min_cost_magnitude = std::min(min_cost_magnitude, cost_magnitude);
00195 }
00196 }
00197 VLOG(3) << "Min cost magnitude = " << min_cost_magnitude
00198 << ", Max cost magnitude = " << max_cost_magnitude;
00199 #if !defined(_MSC_VER)
00200 if (log(std::numeric_limits<CostValue>::max()) <
00201 log(max_cost_magnitude + 1) + log(graph_->num_nodes() + 1)) {
00202 LOG(DFATAL) << "Maximum cost magnitude " << max_cost_magnitude << " is too "
00203 << "high for the number of nodes. Try changing the data.";
00204 return false;
00205 }
00206 #endif
00207 return true;
00208 }
00209
00210 bool MinCostFlow::CheckRelabelPrecondition(NodeIndex node) const {
00211 DCHECK(IsActive(node));
00212 for (StarGraph::IncidentArcIterator arc_it(*graph_, node);
00213 arc_it.Ok();
00214 arc_it.Next()) {
00215 const ArcIndex arc = arc_it.Index();
00216 DCHECK(!IsAdmissible(arc));
00217 }
00218 return true;
00219 }
00220
00221 string MinCostFlow::DebugString(const string& context, ArcIndex arc) const {
00222 const NodeIndex tail = Tail(arc);
00223 const NodeIndex head = Head(arc);
00224
00225
00226
00227 const CostValue reduced_cost = scaled_arc_unit_cost_[arc]
00228 + node_potential_[tail]
00229 - node_potential_[head];
00230 return StringPrintf("%s Arc %d, from %d to %d, "
00231 "Capacity = %lld, Residual capacity = %lld, "
00232 "Flow = residual capacity for reverse arc = %lld, "
00233 "Height(tail) = %lld, Height(head) = %lld, "
00234 "Excess(tail) = %lld, Excess(head) = %lld, "
00235 "Cost = %lld, Reduced cost = %lld, ",
00236 context.c_str(), arc, tail, head, Capacity(arc),
00237 residual_arc_capacity_[arc], Flow(arc),
00238 node_potential_[tail], node_potential_[head],
00239 node_excess_[tail], node_excess_[head],
00240 scaled_arc_unit_cost_[arc], reduced_cost);
00241 }
00242
00243 bool MinCostFlow::CheckFeasibility(
00244 std::vector<NodeIndex>* const infeasible_supply_node,
00245 std::vector<NodeIndex>* const infeasible_demand_node) {
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 feasibility_checked_ = false;
00258 ArcIndex num_extra_arcs = 0;
00259 for (StarGraph::NodeIterator it(*graph_); it.Ok(); it.Next()) {
00260 const NodeIndex node = it.Index();
00261 if (initial_node_excess_[node] != 0) {
00262 ++num_extra_arcs;
00263 }
00264 }
00265 const NodeIndex num_nodes_in_max_flow = graph_->num_nodes() + 2;
00266 const ArcIndex num_arcs_in_max_flow = graph_->num_arcs() + num_extra_arcs;
00267 const NodeIndex source = num_nodes_in_max_flow - 2;
00268 const NodeIndex sink = num_nodes_in_max_flow - 1;
00269 StarGraph checker_graph(num_nodes_in_max_flow, num_arcs_in_max_flow);
00270 MaxFlow checker(&checker_graph, source, sink);
00271
00272 for (StarGraph::ArcIterator it(*graph_); it.Ok(); it.Next()) {
00273 const ArcIndex arc = it.Index();
00274 const ArcIndex new_arc = checker_graph.AddArc(graph_->Tail(arc),
00275 graph_->Head(arc));
00276 DCHECK_EQ(arc, new_arc);
00277 checker.SetArcCapacity(new_arc, Capacity(arc));
00278 }
00279 FlowQuantity total_demand = 0;
00280 FlowQuantity total_supply = 0;
00281
00282 for (StarGraph::NodeIterator it(*graph_); it.Ok(); it.Next()) {
00283 const NodeIndex node = it.Index();
00284 const FlowQuantity supply = initial_node_excess_[node];
00285 if (supply > 0) {
00286 const ArcIndex new_arc = checker_graph.AddArc(source, node);
00287 checker.SetArcCapacity(new_arc, supply);
00288 total_supply += supply;
00289 } else if (supply < 0) {
00290 const ArcIndex new_arc = checker_graph.AddArc(node, sink);
00291 checker.SetArcCapacity(new_arc, -supply);
00292 total_demand -= supply;
00293 }
00294 }
00295 if (total_supply != total_demand) {
00296 LOG(DFATAL) << "total_supply(" << total_supply << ") != total_demand("
00297 << total_demand << ").";
00298 return false;
00299 }
00300 if (!checker.Solve()) {
00301 LOG(DFATAL) << "Max flow could not be computed.";
00302 return false;
00303 }
00304 const FlowQuantity optimal_max_flow = checker.GetOptimalFlow();
00305 feasible_node_excess_.SetAll(0);
00306 for (StarGraph::OutgoingArcIterator it(checker_graph, source);
00307 it.Ok(); it.Next()) {
00308 const ArcIndex arc = it.Index();
00309 const NodeIndex node = checker_graph.Head(arc);
00310 const FlowQuantity flow = checker.Flow(arc);
00311 feasible_node_excess_.Set(node, flow);
00312 if (infeasible_supply_node != NULL) {
00313 infeasible_supply_node->push_back(node);
00314 }
00315 }
00316 for (StarGraph::IncomingArcIterator it(checker_graph, sink);
00317 it.Ok(); it.Next()) {
00318 const ArcIndex arc = checker_graph.DirectArc(it.Index());
00319 const NodeIndex node = checker_graph.Tail(arc);
00320 const FlowQuantity flow = checker.Flow(arc);
00321 feasible_node_excess_.Set(node, -flow);
00322 if (infeasible_demand_node != NULL) {
00323 infeasible_demand_node->push_back(node);
00324 }
00325 }
00326 feasibility_checked_ = true;
00327 return optimal_max_flow == total_supply;
00328 }
00329
00330 bool MinCostFlow::MakeFeasible() {
00331 if (!feasibility_checked_) {
00332 return false;
00333 }
00334 for (StarGraph::NodeIterator it(*graph_); it.Ok(); it.Next()) {
00335 const NodeIndex node = it.Index();
00336 const FlowQuantity excess = feasible_node_excess_[node];
00337 node_excess_.Set(node, excess);
00338 initial_node_excess_.Set(node, excess);
00339 }
00340 return true;
00341 }
00342
00343 bool MinCostFlow::Solve() {
00344 status_ = NOT_SOLVED;
00345 if (FLAGS_min_cost_flow_check_balance && !CheckInputConsistency()) {
00346 status_ = UNBALANCED;
00347 return false;
00348 }
00349 if (FLAGS_min_cost_flow_check_costs && !CheckCostRange()) {
00350 status_ = BAD_COST_RANGE;
00351 return false;
00352 }
00353 if (FLAGS_min_cost_flow_check_feasibility && !CheckFeasibility(NULL, NULL)) {
00354 status_ = INFEASIBLE;
00355 return false;
00356 }
00357 node_potential_.SetAll(0);
00358 ResetFirstAdmissibleArcs();
00359 ScaleCosts();
00360 Optimize();
00361 if (FLAGS_min_cost_flow_check_result && !CheckResult()) {
00362 status_ = BAD_RESULT;
00363 UnscaleCosts();
00364 return false;
00365 }
00366 UnscaleCosts();
00367 if (status_ != OPTIMAL) {
00368 LOG(DFATAL) << "Status != OPTIMAL";
00369 total_flow_cost_ = 0;
00370 return false;
00371 }
00372 total_flow_cost_ = 0;
00373 for (StarGraph::ArcIterator it(*graph_); it.Ok(); it.Next()) {
00374 const ArcIndex arc = it.Index();
00375 const FlowQuantity flow_on_arc = residual_arc_capacity_[Opposite(arc)];
00376 VLOG(3) << "Flow for arc " << arc << " = " << flow_on_arc
00377 << ", scaled cost = " << scaled_arc_unit_cost_[arc];
00378 total_flow_cost_ += scaled_arc_unit_cost_[arc] * flow_on_arc;
00379 }
00380 status_ = OPTIMAL;
00381 return true;
00382 }
00383
00384 void MinCostFlow::ResetFirstAdmissibleArcs() {
00385 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00386 const NodeIndex node = node_it.Index();
00387 first_admissible_arc_.Set(node, GetFirstIncidentArc(node));
00388 }
00389 }
00390
00391 void MinCostFlow::ScaleCosts() {
00392 cost_scaling_factor_ = graph_->num_nodes() + 1;
00393 epsilon_ = 1LL;
00394 VLOG(3) << "Number of arcs in the graph = " << graph_->num_arcs();
00395 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00396 const ArcIndex arc = arc_it.Index();
00397 const CostValue cost = scaled_arc_unit_cost_[arc] * cost_scaling_factor_;
00398 scaled_arc_unit_cost_.Set(arc, cost);
00399 scaled_arc_unit_cost_.Set(Opposite(arc), -cost);
00400 epsilon_ = std::max(epsilon_, MathUtil::Abs(cost));
00401 }
00402 VLOG(3) << "Initial epsilon = " << epsilon_;
00403 VLOG(3) << "Cost scaling factor = " << cost_scaling_factor_;
00404 }
00405
00406 void MinCostFlow::UnscaleCosts() {
00407 for (StarGraph::ArcIterator arc_it(*graph_); arc_it.Ok(); arc_it.Next()) {
00408 const ArcIndex arc = arc_it.Index();
00409 const CostValue cost = scaled_arc_unit_cost_[arc] / cost_scaling_factor_;
00410 scaled_arc_unit_cost_.Set(arc, cost);
00411 scaled_arc_unit_cost_.Set(Opposite(arc), -cost);
00412 }
00413 cost_scaling_factor_ = 1;
00414 }
00415
00416 void MinCostFlow::Optimize() {
00417 const CostValue kEpsilonMin = 1LL;
00418 do {
00419
00420 epsilon_ = std::max(epsilon_ / alpha_, kEpsilonMin);
00421 VLOG(3) << "Epsilon changed to: " << epsilon_;
00422 Refine();
00423 } while (epsilon_ != 1LL && status_ != INFEASIBLE);
00424 if (status_ == NOT_SOLVED) {
00425 status_ = OPTIMAL;
00426 }
00427 }
00428
00429 void MinCostFlow::SaturateAdmissibleArcs() {
00430 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00431 const NodeIndex node = node_it.Index();
00432 for (StarGraph::IncidentArcIterator
00433 arc_it(*graph_, node, first_admissible_arc_[node]);
00434 arc_it.Ok();
00435 arc_it.Next()) {
00436 const ArcIndex arc = arc_it.Index();
00437 if (IsAdmissible(arc)) {
00438 VLOG(3) << DebugString("SaturateAdmissibleArcs: calling PushFlow", arc);
00439 PushFlow(residual_arc_capacity_[arc], arc);
00440 }
00441 }
00442 }
00443 }
00444
00445 void MinCostFlow::PushFlow(FlowQuantity flow, ArcIndex arc) {
00446 DCHECK_GT(residual_arc_capacity_[arc], 0);
00447 VLOG(3) << "PushFlow: pushing " << flow << " on arc " << arc
00448 << " from node " << Tail(arc) << " to node " << Head(arc);
00449
00450 residual_arc_capacity_.Set(arc, residual_arc_capacity_[arc] - flow);
00451
00452 const ArcIndex opposite = Opposite(arc);
00453 residual_arc_capacity_.Set(opposite, residual_arc_capacity_[opposite] + flow);
00454
00455 const NodeIndex tail = Tail(arc);
00456 node_excess_.Set(tail, node_excess_[tail] - flow);
00457 const NodeIndex head = Head(arc);
00458 node_excess_.Set(head, node_excess_[head] + flow);
00459 VLOG(4) << DebugString("PushFlow: ", arc);
00460 }
00461
00462 void MinCostFlow::InitializeActiveNodeStack() {
00463 DCHECK(active_nodes_.empty());
00464 for (StarGraph::NodeIterator node_it(*graph_); node_it.Ok(); node_it.Next()) {
00465 const NodeIndex node = node_it.Index();
00466 if (IsActive(node)) {
00467 active_nodes_.push(node);
00468 VLOG(3) << "InitializeActiveNodeStack: node " << node << " added.";
00469 }
00470 }
00471 }
00472
00473 void MinCostFlow::Refine() {
00474 SaturateAdmissibleArcs();
00475 InitializeActiveNodeStack();
00476 while (!active_nodes_.empty()) {
00477 const NodeIndex node = active_nodes_.top();
00478 active_nodes_.pop();
00479 if (IsActive(node)) {
00480 VLOG(3) << "Refine: calling Discharge for node " << node;
00481 Discharge(node);
00482 if (status_ == INFEASIBLE) {
00483 return;
00484 }
00485 }
00486 }
00487 }
00488
00489 void MinCostFlow::Discharge(NodeIndex node) {
00490 DCHECK(IsActive(node));
00491 VLOG(3) << "Discharging node " << node << ", excess = " << node_excess_[node];
00492 while (IsActive(node)) {
00493 for (StarGraph::IncidentArcIterator arc_it(*graph_, node,
00494 first_admissible_arc_[node]);
00495 arc_it.Ok();
00496 arc_it.Next()) {
00497 const ArcIndex arc = arc_it.Index();
00498 VLOG(4) << DebugString("Discharge: considering", arc);
00499 if (IsAdmissible(arc)) {
00500 if (node_excess_[node] != 0) {
00501 VLOG(3) << "Discharge: calling PushFlow.";
00502 const NodeIndex head = Head(arc);
00503 const bool head_active_before_push = IsActive(head);
00504 const FlowQuantity delta = std::min(node_excess_[node],
00505 residual_arc_capacity_[arc]);
00506 PushFlow(delta, arc);
00507 if (IsActive(head) && !head_active_before_push) {
00508 active_nodes_.push(Head(arc));
00509 }
00510 }
00511 if (node_excess_[node] == 0) {
00512 first_admissible_arc_.Set(node, arc);
00513 return;
00514 }
00515 }
00516 }
00517 Relabel(node);
00518 if (status_ == INFEASIBLE) {
00519 return;
00520 }
00521 }
00522 }
00523
00524 void MinCostFlow::Relabel(NodeIndex node) {
00525 DCHECK(CheckRelabelPrecondition(node));
00526 CostValue new_potential;
00527 if (FLAGS_min_cost_flow_fast_potential_update) {
00528 new_potential = node_potential_[node] - epsilon_;
00529 } else {
00530 new_potential = kint64min;
00531 for (StarGraph::IncidentArcIterator arc_it(*graph_, node);
00532 arc_it.Ok();
00533 arc_it.Next()) {
00534 ArcIndex arc = arc_it.Index();
00535 DCHECK_EQ(Tail(arc), node);
00536 if (residual_arc_capacity_[arc] > 0) {
00537 const NodeIndex head = Head(arc);
00538 new_potential = std::max(new_potential, node_potential_[head]
00539 - scaled_arc_unit_cost_[arc]
00540 - epsilon_);
00541 DCHECK_GE(0, new_potential);
00542 }
00543 }
00544 if (new_potential == kint64min) {
00545
00546
00547 status_ = INFEASIBLE;
00548 return;
00549 }
00550 }
00551 VLOG(3) << "Relabel: node " << node << " from " << node_potential_[node]
00552 << " to " << new_potential;
00553 node_potential_.Set(node, new_potential);
00554 first_admissible_arc_.Set(node, GetFirstIncidentArc(node));
00555 }
00556 }