# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1354744707 -3600
# Node ID daa8c50a03710af7e489417681d265fb6b7b6f7f
# Parent a26b90a17c81e068cb8777e356b4552a80c611d1
Extend flow bound checking in min cost flow classes (#454)
diff --git a/lemon/capacity_scaling.h b/lemon/capacity_scaling.h
a
|
b
|
|
762 | 762 | } |
763 | 763 | } |
764 | 764 | |
| 765 | // Check the residual capacity values |
| 766 | for (int j = 0; j != _res_arc_num; ++j) { |
| 767 | if (_res_cap[j] < 0) return INFEASIBLE; |
| 768 | } |
| 769 | |
765 | 770 | // Handle negative costs |
766 | 771 | for (int i = 0; i != _root; ++i) { |
767 | 772 | last_out = _first_out[i+1] - 1; |
diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
a
|
b
|
|
840 | 840 | } |
841 | 841 | } |
842 | 842 | |
| 843 | // Check the capacity values |
| 844 | for (ArcIt a(_graph); a != INVALID; ++a) { |
| 845 | if (cap[a] < 0) return INFEASIBLE; |
| 846 | } |
| 847 | |
843 | 848 | _sup_node_num = 0; |
844 | 849 | for (NodeIt n(_graph); n != INVALID; ++n) { |
845 | 850 | if (sup[n] > 0) ++_sup_node_num; |
diff --git a/lemon/cycle_canceling.h b/lemon/cycle_canceling.h
a
|
b
|
|
731 | 731 | } |
732 | 732 | } |
733 | 733 | |
| 734 | // Check the capacity values |
| 735 | for (ArcIt a(_graph); a != INVALID; ++a) { |
| 736 | if (cap[a] < 0) return INFEASIBLE; |
| 737 | } |
| 738 | |
734 | 739 | // Find a feasible flow using Circulation |
735 | 740 | Circulation<Digraph, ConstMap<Arc, Value>, ValueArcMap, ValueNodeMap> |
736 | 741 | circ(_graph, low, cap, sup); |
diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h
a
|
b
|
|
1072 | 1072 | } |
1073 | 1073 | } |
1074 | 1074 | |
| 1075 | // Check the capacity values |
| 1076 | for (int i = 0; i != _arc_num; ++i) { |
| 1077 | if (_cap[i] < 0) return false; |
| 1078 | } |
| 1079 | |
1075 | 1080 | // Initialize artifical cost |
1076 | 1081 | Cost ART_COST; |
1077 | 1082 | if (std::numeric_limits<Cost>::is_exact) { |
diff --git a/test/min_cost_flow_test.cc b/test/min_cost_flow_test.cc
a
|
b
|
|
112 | 112 | " cost\n" |
113 | 113 | "1 2 -1\n"; |
114 | 114 | |
| 115 | char test_lb_lgf[] = |
| 116 | "@nodes\n" |
| 117 | "label sup\n" |
| 118 | " 1 10\n" |
| 119 | " 2 0\n" |
| 120 | " 3 0\n" |
| 121 | " 4 -10\n" |
| 122 | "@arcs\n" |
| 123 | " cost cap low1 low2 low3\n" |
| 124 | "1 2 1 10 0 0 0\n" |
| 125 | "1 3 2 10 0 0 0\n" |
| 126 | "2 3 0 4 4 4 5\n" |
| 127 | "2 4 2 10 3 8 2\n" |
| 128 | "3 4 1 10 3 0 2\n"; |
| 129 | |
115 | 130 | |
116 | 131 | // Test data |
117 | 132 | typedef ListDigraph Digraph; |
… |
… |
|
133 | 148 | ConstMap<Arc, int> neg2_l(0), neg2_u(1000); |
134 | 149 | Digraph::NodeMap<int> neg2_s(neg2_gr); |
135 | 150 | |
| 151 | Digraph lb_gr; |
| 152 | Digraph::ArcMap<int> lb_c(lb_gr), lb_u(lb_gr), lb_l1(lb_gr), lb_l2(lb_gr), lb_l3(lb_gr); |
| 153 | Digraph::NodeMap<int> lb_s(lb_gr); |
| 154 | |
136 | 155 | |
137 | 156 | enum SupplyType { |
138 | 157 | EQ, |
… |
… |
|
331 | 350 | const std::string &test_str = "", |
332 | 351 | bool full_neg_cost_support = false ) |
333 | 352 | { |
334 | | MCF mcf1(gr), mcf2(neg1_gr), mcf3(neg2_gr); |
| 353 | MCF mcf1(gr), mcf2(neg1_gr), mcf3(neg2_gr), mcf_lb(lb_gr); |
335 | 354 | |
336 | 355 | // Basic tests |
337 | 356 | mcf1.upperMap(u).costMap(c).supplyMap(s1); |
… |
… |
|
395 | 414 | mcf3.upperMap(neg2_u); |
396 | 415 | checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s, |
397 | 416 | mcf3.OPTIMAL, true, -300, test_str + "-18", GEQ); |
| 417 | |
| 418 | // Tests with various lower bounds |
| 419 | mcf_lb.upperMap(lb_u).costMap(lb_c).supplyMap(lb_s); |
| 420 | mcf_lb.lowerMap(lb_l1); |
| 421 | checkMcf(mcf_lb, mcf_lb.run(param), lb_gr, lb_l1, lb_u, lb_c, lb_s, |
| 422 | mcf_lb.OPTIMAL, true, 26, test_str + "-19"); |
| 423 | mcf_lb.lowerMap(lb_l2); |
| 424 | checkMcf(mcf_lb, mcf_lb.run(param), lb_gr, lb_l2, lb_u, lb_c, lb_s, |
| 425 | mcf_lb.INFEASIBLE, false, 0, test_str + "-20"); |
| 426 | mcf_lb.lowerMap(lb_l3); |
| 427 | checkMcf(mcf_lb, mcf_lb.run(param), lb_gr, lb_l3, lb_u, lb_c, lb_s, |
| 428 | mcf_lb.INFEASIBLE, false, 0, test_str + "-21"); |
398 | 429 | } |
399 | 430 | |
400 | 431 | template < typename MCF, typename Param > |
… |
… |
|
406 | 437 | mcf1.supplyType(mcf1.LEQ); |
407 | 438 | mcf1.upperMap(u).costMap(c).supplyMap(s6); |
408 | 439 | checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s6, |
409 | | mcf1.OPTIMAL, true, 5080, test_str + "-19", LEQ); |
| 440 | mcf1.OPTIMAL, true, 5080, test_str + "-22", LEQ); |
410 | 441 | mcf1.lowerMap(l2); |
411 | 442 | checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s6, |
412 | | mcf1.OPTIMAL, true, 5930, test_str + "-20", LEQ); |
| 443 | mcf1.OPTIMAL, true, 5930, test_str + "-23", LEQ); |
413 | 444 | mcf1.supplyMap(s5); |
414 | 445 | checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s5, |
415 | | mcf1.INFEASIBLE, false, 0, test_str + "-21", LEQ); |
| 446 | mcf1.INFEASIBLE, false, 0, test_str + "-24", LEQ); |
416 | 447 | } |
417 | 448 | |
418 | 449 | |
… |
… |
|
450 | 481 | .nodeMap("sup", neg2_s) |
451 | 482 | .run(); |
452 | 483 | |
| 484 | std::istringstream lb_inp(test_lb_lgf); |
| 485 | DigraphReader<Digraph>(lb_gr, lb_inp) |
| 486 | .arcMap("cost", lb_c) |
| 487 | .arcMap("cap", lb_u) |
| 488 | .arcMap("low1", lb_l1) |
| 489 | .arcMap("low2", lb_l2) |
| 490 | .arcMap("low3", lb_l3) |
| 491 | .nodeMap("sup", lb_s) |
| 492 | .run(); |
| 493 | |
453 | 494 | // Check the interface of NetworkSimplex |
454 | 495 | { |
455 | 496 | typedef concepts::Digraph GR; |