test/min_cost_flow_test.cc
branch1.1
changeset 761 f1398882a928
parent 668 4faca85d40e6
equal deleted inserted replaced
9:01fff1bd3558 10:9283fc22174b
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     4  *
     5  * Copyright (C) 2003-2009
     5  * Copyright (C) 2003-2011
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     8  *
     9  * Permission to use, modify and distribute this software is granted
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    10  * provided that this copyright notice appears in all copies. For
    45   "    8     0    0    0    0    0    3\n"
    45   "    8     0    0    0    0    0    3\n"
    46   "    9     3    0    0    0    0    0\n"
    46   "    9     3    0    0    0    0    0\n"
    47   "   10    -2    0    0    0   -7   -2\n"
    47   "   10    -2    0    0    0   -7   -2\n"
    48   "   11     0    0    0    0  -10    0\n"
    48   "   11     0    0    0    0  -10    0\n"
    49   "   12   -20  -27    0  -30  -30  -20\n"
    49   "   12   -20  -27    0  -30  -30  -20\n"
    50   "\n"                
    50   "\n"
    51   "@arcs\n"
    51   "@arcs\n"
    52   "       cost  cap low1 low2 low3\n"
    52   "       cost  cap low1 low2 low3\n"
    53   " 1  2    70   11    0    8    8\n"
    53   " 1  2    70   11    0    8    8\n"
    54   " 1  3   150    3    0    1    0\n"
    54   " 1  3   150    3    0    1    0\n"
    55   " 1  4    80   15    0    2    2\n"
    55   " 1  4    80   15    0    2    2\n"
    91 
    91 
    92   template <typename MCF>
    92   template <typename MCF>
    93   struct Constraints {
    93   struct Constraints {
    94     void constraints() {
    94     void constraints() {
    95       checkConcept<concepts::Digraph, GR>();
    95       checkConcept<concepts::Digraph, GR>();
    96       
    96 
    97       const Constraints& me = *this;
    97       const Constraints& me = *this;
    98 
    98 
    99       MCF mcf(me.g);
    99       MCF mcf(me.g);
   100       const MCF& const_mcf = mcf;
   100       const MCF& const_mcf = mcf;
   101 
   101 
   120     typedef concepts::ReadMap<Node, Value> NM;
   120     typedef concepts::ReadMap<Node, Value> NM;
   121     typedef concepts::ReadMap<Arc, Value> VAM;
   121     typedef concepts::ReadMap<Arc, Value> VAM;
   122     typedef concepts::ReadMap<Arc, Cost> CAM;
   122     typedef concepts::ReadMap<Arc, Cost> CAM;
   123     typedef concepts::WriteMap<Arc, Value> FlowMap;
   123     typedef concepts::WriteMap<Arc, Value> FlowMap;
   124     typedef concepts::WriteMap<Node, Cost> PotMap;
   124     typedef concepts::WriteMap<Node, Cost> PotMap;
   125   
   125 
   126     GR g;
   126     GR g;
   127     VAM lower;
   127     VAM lower;
   128     VAM upper;
   128     VAM upper;
   129     CAM cost;
   129     CAM cost;
   130     NM sup;
   130     NM sup;
   174 // Check the feasibility of the given potentials (dual soluiton)
   174 // Check the feasibility of the given potentials (dual soluiton)
   175 // using the "Complementary Slackness" optimality condition
   175 // using the "Complementary Slackness" optimality condition
   176 template < typename GR, typename LM, typename UM,
   176 template < typename GR, typename LM, typename UM,
   177            typename CM, typename SM, typename FM, typename PM >
   177            typename CM, typename SM, typename FM, typename PM >
   178 bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
   178 bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
   179                      const CM& cost, const SM& supply, const FM& flow, 
   179                      const CM& cost, const SM& supply, const FM& flow,
   180                      const PM& pi, SupplyType type )
   180                      const PM& pi, SupplyType type )
   181 {
   181 {
   182   TEMPLATE_DIGRAPH_TYPEDEFS(GR);
   182   TEMPLATE_DIGRAPH_TYPEDEFS(GR);
   183 
   183 
   184   bool opt = true;
   184   bool opt = true;
   187       cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
   187       cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
   188     opt = red_cost == 0 ||
   188     opt = red_cost == 0 ||
   189           (red_cost > 0 && flow[e] == lower[e]) ||
   189           (red_cost > 0 && flow[e] == lower[e]) ||
   190           (red_cost < 0 && flow[e] == upper[e]);
   190           (red_cost < 0 && flow[e] == upper[e]);
   191   }
   191   }
   192   
   192 
   193   for (NodeIt n(gr); opt && n != INVALID; ++n) {
   193   for (NodeIt n(gr); opt && n != INVALID; ++n) {
   194     typename SM::Value sum = 0;
   194     typename SM::Value sum = 0;
   195     for (OutArcIt e(gr, n); e != INVALID; ++e)
   195     for (OutArcIt e(gr, n); e != INVALID; ++e)
   196       sum += flow[e];
   196       sum += flow[e];
   197     for (InArcIt e(gr, n); e != INVALID; ++e)
   197     for (InArcIt e(gr, n); e != INVALID; ++e)
   200       opt = (pi[n] <= 0) && (sum == supply[n] || pi[n] == 0);
   200       opt = (pi[n] <= 0) && (sum == supply[n] || pi[n] == 0);
   201     } else {
   201     } else {
   202       opt = (pi[n] >= 0) && (sum == supply[n] || pi[n] == 0);
   202       opt = (pi[n] >= 0) && (sum == supply[n] || pi[n] == 0);
   203     }
   203     }
   204   }
   204   }
   205   
   205 
   206   return opt;
   206   return opt;
   207 }
   207 }
   208 
   208 
   209 // Check whether the dual cost is equal to the primal cost
   209 // Check whether the dual cost is equal to the primal cost
   210 template < typename GR, typename LM, typename UM,
   210 template < typename GR, typename LM, typename UM,
   225       dual_cost += lower[a] * cost[a];
   225       dual_cost += lower[a] * cost[a];
   226       red_supply[gr.source(a)] -= lower[a];
   226       red_supply[gr.source(a)] -= lower[a];
   227       red_supply[gr.target(a)] += lower[a];
   227       red_supply[gr.target(a)] += lower[a];
   228     }
   228     }
   229   }
   229   }
   230   
   230 
   231   for (NodeIt n(gr); n != INVALID; ++n) {
   231   for (NodeIt n(gr); n != INVALID; ++n) {
   232     dual_cost -= red_supply[n] * pi[n];
   232     dual_cost -= red_supply[n] * pi[n];
   233   }
   233   }
   234   for (ArcIt a(gr); a != INVALID; ++a) {
   234   for (ArcIt a(gr); a != INVALID; ++a) {
   235     typename CM::Value red_cost =
   235     typename CM::Value red_cost =
   236       cost[a] + pi[gr.source(a)] - pi[gr.target(a)];
   236       cost[a] + pi[gr.source(a)] - pi[gr.target(a)];
   237     dual_cost -= (upper[a] - lower[a]) * std::max(-red_cost, 0);
   237     dual_cost -= (upper[a] - lower[a]) * std::max(-red_cost, 0);
   238   }
   238   }
   239   
   239 
   240   return dual_cost == total;
   240   return dual_cost == total;
   241 }
   241 }
   242 
   242 
   243 // Run a minimum cost flow algorithm and check the results
   243 // Run a minimum cost flow algorithm and check the results
   244 template < typename MCF, typename GR,
   244 template < typename MCF, typename GR,
   306     .nodeMap("sup5", s5)
   306     .nodeMap("sup5", s5)
   307     .nodeMap("sup6", s6)
   307     .nodeMap("sup6", s6)
   308     .node("source", v)
   308     .node("source", v)
   309     .node("target", w)
   309     .node("target", w)
   310     .run();
   310     .run();
   311   
   311 
   312   // Build test digraphs with negative costs
   312   // Build test digraphs with negative costs
   313   Digraph neg_gr;
   313   Digraph neg_gr;
   314   Node n1 = neg_gr.addNode();
   314   Node n1 = neg_gr.addNode();
   315   Node n2 = neg_gr.addNode();
   315   Node n2 = neg_gr.addNode();
   316   Node n3 = neg_gr.addNode();
   316   Node n3 = neg_gr.addNode();
   317   Node n4 = neg_gr.addNode();
   317   Node n4 = neg_gr.addNode();
   318   Node n5 = neg_gr.addNode();
   318   Node n5 = neg_gr.addNode();
   319   Node n6 = neg_gr.addNode();
   319   Node n6 = neg_gr.addNode();
   320   Node n7 = neg_gr.addNode();
   320   Node n7 = neg_gr.addNode();
   321   
   321 
   322   Arc a1 = neg_gr.addArc(n1, n2);
   322   Arc a1 = neg_gr.addArc(n1, n2);
   323   Arc a2 = neg_gr.addArc(n1, n3);
   323   Arc a2 = neg_gr.addArc(n1, n3);
   324   Arc a3 = neg_gr.addArc(n2, n4);
   324   Arc a3 = neg_gr.addArc(n2, n4);
   325   Arc a4 = neg_gr.addArc(n3, n4);
   325   Arc a4 = neg_gr.addArc(n3, n4);
   326   Arc a5 = neg_gr.addArc(n3, n2);
   326   Arc a5 = neg_gr.addArc(n3, n2);
   327   Arc a6 = neg_gr.addArc(n5, n3);
   327   Arc a6 = neg_gr.addArc(n5, n3);
   328   Arc a7 = neg_gr.addArc(n5, n6);
   328   Arc a7 = neg_gr.addArc(n5, n6);
   329   Arc a8 = neg_gr.addArc(n6, n7);
   329   Arc a8 = neg_gr.addArc(n6, n7);
   330   Arc a9 = neg_gr.addArc(n7, n5);
   330   Arc a9 = neg_gr.addArc(n7, n5);
   331   
   331 
   332   Digraph::ArcMap<int> neg_c(neg_gr), neg_l1(neg_gr, 0), neg_l2(neg_gr, 0);
   332   Digraph::ArcMap<int> neg_c(neg_gr), neg_l1(neg_gr, 0), neg_l2(neg_gr, 0);
   333   ConstMap<Arc, int> neg_u1(std::numeric_limits<int>::max()), neg_u2(5000);
   333   ConstMap<Arc, int> neg_u1(std::numeric_limits<int>::max()), neg_u2(5000);
   334   Digraph::NodeMap<int> neg_s(neg_gr, 0);
   334   Digraph::NodeMap<int> neg_s(neg_gr, 0);
   335   
   335 
   336   neg_l2[a7] =  1000;
   336   neg_l2[a7] =  1000;
   337   neg_l2[a8] = -1000;
   337   neg_l2[a8] = -1000;
   338   
   338 
   339   neg_s[n1] =  100;
   339   neg_s[n1] =  100;
   340   neg_s[n4] = -100;
   340   neg_s[n4] = -100;
   341   
   341 
   342   neg_c[a1] =  100;
   342   neg_c[a1] =  100;
   343   neg_c[a2] =   30;
   343   neg_c[a2] =   30;
   344   neg_c[a3] =   20;
   344   neg_c[a3] =   20;
   345   neg_c[a4] =   80;
   345   neg_c[a4] =   80;
   346   neg_c[a5] =   50;
   346   neg_c[a5] =   50;
   420     checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u2,
   420     checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u2,
   421       neg_c, neg_s, neg_mcf.OPTIMAL, true,  -40000, "#A17");
   421       neg_c, neg_s, neg_mcf.OPTIMAL, true,  -40000, "#A17");
   422     neg_mcf.reset().lowerMap(neg_l2).costMap(neg_c).supplyMap(neg_s);
   422     neg_mcf.reset().lowerMap(neg_l2).costMap(neg_c).supplyMap(neg_s);
   423     checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l2, neg_u1,
   423     checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l2, neg_u1,
   424       neg_c, neg_s, neg_mcf.UNBOUNDED, false,    0, "#A18");
   424       neg_c, neg_s, neg_mcf.UNBOUNDED, false,    0, "#A18");
   425       
   425 
   426     NetworkSimplex<Digraph> negs_mcf(negs_gr);
   426     NetworkSimplex<Digraph> negs_mcf(negs_gr);
   427     negs_mcf.costMap(negs_c).supplyMap(negs_s);
   427     negs_mcf.costMap(negs_c).supplyMap(negs_s);
   428     checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u,
   428     checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u,
   429       negs_c, negs_s, negs_mcf.OPTIMAL, true, -300, "#A19", GEQ);
   429       negs_c, negs_s, negs_mcf.OPTIMAL, true, -300, "#A19", GEQ);
   430   }
   430   }