Ticket #180: 180cas408f7479bbc45.patch
File 180cas408f7479bbc45.patch, 5.0 KB (added by , 10 years ago) 


lemon/capacity_scaling.h
# HG changeset patch # User Peter Kovacs <kpeter@inf.elte.hu> # Date 1252683113 7200 # Node ID 08f7479bbc4500fb408e916af3d5b019c42d1dfc # Parent c9964582a1bd5c5b380a63612cf2cc41195901b3 Handle negative costs in CapacityScaling (#180) This algorithm cannot handle arcs of negative cost and infinite upper bound, thus it returns UNBOUNDED if such an arc exists. diff git a/lemon/capacity_scaling.h b/lemon/capacity_scaling.h
a b 55 55 /// 56 56 /// \warning Both value types must be signed and all input data must 57 57 /// be integer. 58 /// \warning This implementation can handle only nonnegative arc costs. 58 /// \warning This algorithm does not support negative costs for such 59 /// arcs that have infinite upper bound. 59 60 template <typename GR, typename V = int, typename C = V> 60 61 class CapacityScaling 61 62 { … … 79 80 /// bounded), and the algorithm has found optimal flow and node 80 81 /// potentials (primal and dual solutions). 81 82 OPTIMAL, 82 /// The objective function of the problem is unbounded, i.e. 83 /// there is a directed cycle having negative total cost and 84 /// infinite upper bound. 83 /// The digraph contains an arc of negative cost and infinite 84 /// upper bound. It means that the objective function is unbounded 85 /// on that arc, however note that it could actually be bounded 86 /// over the feasible flows, but this algroithm cannot handle 87 /// these cases. 85 88 UNBOUNDED 86 89 }; 87 90 … … 459 462 /// \n \c OPTIMAL if the problem has optimal solution 460 463 /// (i.e. it is feasible and bounded), and the algorithm has found 461 464 /// optimal flow and node potentials (primal and dual solutions), 462 /// \n \c UNBOUNDED if the objective function of the problem is 463 /// unbounded, i.e. there is a directed cycle having negative total 464 /// cost and infinite upper bound. 465 /// \n \c UNBOUNDED if the digraph contains an arc of negative cost 466 /// and infinite upper bound. It means that the objective function 467 /// is unbounded on that arc, however note that it could actually be 468 /// bounded over the feasible flows, but this algroithm cannot handle 469 /// these cases. 465 470 /// 466 471 /// \see ProblemType 467 472 ProblemType run(bool scaling = true) { 468 if (!init(scaling)) return INFEASIBLE; 473 ProblemType pt = init(scaling); 474 if (pt != OPTIMAL) return pt; 469 475 return start(); 470 476 } 471 477 … … 609 615 private: 610 616 611 617 // Initialize the algorithm 612 boolinit(bool scaling) {613 if (_node_num == 0) return false;618 ProblemType init(bool scaling) { 619 if (_node_num == 0) return INFEASIBLE; 614 620 615 621 // Check the sum of supply values 616 622 _sum_supply = 0; 617 623 for (int i = 0; i != _root; ++i) { 618 624 _sum_supply += _supply[i]; 619 625 } 620 if (_sum_supply > 0) return false;626 if (_sum_supply > 0) return INFEASIBLE; 621 627 622 628 // Initialize maps 623 629 for (int i = 0; i != _root; ++i) { … … 648 654 _res_cap[j] = _forward[j] ? _upper[j] : 0; 649 655 } 650 656 } 657 658 // Handle negative costs 659 for (int u = 0; u != _root; ++u) { 660 for (int a = _first_out[u]; a != _first_out[u+1]; ++a) { 661 Value rc = _res_cap[a]; 662 if (_cost[a] < 0 && rc > 0) { 663 if (rc == INF) return UNBOUNDED; 664 _excess[u] = rc; 665 _excess[_target[a]] += rc; 666 _res_cap[a] = 0; 667 _res_cap[_reverse[a]] += rc; 668 } 669 } 670 } 651 671 652 672 // Handle GEQ supply type 653 673 if (_sum_supply < 0) { … … 696 716 _delta = 1; 697 717 } 698 718 699 return true;719 return OPTIMAL; 700 720 } 701 721 702 722 ProblemType start() { 
test/min_cost_flow_test.cc
diff git a/test/min_cost_flow_test.cc b/test/min_cost_flow_test.cc
a b 501 501 mcf.supplyMap(s6); 502 502 checkMcf(mcf, mcf.run(), 503 503 gr, l2, u, c, s6, mcf.INFEASIBLE, false, 0, "#C15", GEQ); 504 505 // Check negative costs 506 CapacityScaling<Digraph> neg_mcf(neg_gr); 507 neg_mcf.lowerMap(neg_l1).costMap(neg_c).supplyMap(neg_s); 508 checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u1, 509 neg_c, neg_s, neg_mcf.UNBOUNDED, false, 0, "#C16"); 510 neg_mcf.upperMap(neg_u2); 511 checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u2, 512 neg_c, neg_s, neg_mcf.OPTIMAL, true, 40000, "#C17"); 513 neg_mcf.reset().lowerMap(neg_l2).costMap(neg_c).supplyMap(neg_s); 514 checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l2, neg_u1, 515 neg_c, neg_s, neg_mcf.UNBOUNDED, false, 0, "#C18"); 516 517 CapacityScaling<Digraph> negs_mcf(negs_gr); 518 negs_mcf.costMap(negs_c).supplyMap(negs_s); 519 checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u, 520 negs_c, negs_s, negs_mcf.UNBOUNDED, false, 0, "#C19", GEQ); 521 negs_mcf.upperMap(negs_u); 522 checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u, 523 negs_c, negs_s, negs_mcf.OPTIMAL, true, 300, "#C20", GEQ); 504 524 } 505 525 506 526 return 0;