test/preflow_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 877 141f9c0db4a3
parent 923 30d5f950aa5f
child 1008 d216e1c8b3fa
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2010
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #include <iostream>
    20 
    21 #include "test_tools.h"
    22 #include <lemon/smart_graph.h>
    23 #include <lemon/preflow.h>
    24 #include <lemon/concepts/digraph.h>
    25 #include <lemon/concepts/maps.h>
    26 #include <lemon/lgf_reader.h>
    27 #include <lemon/elevator.h>
    28 
    29 using namespace lemon;
    30 
    31 char test_lgf[] =
    32   "@nodes\n"
    33   "label\n"
    34   "0\n"
    35   "1\n"
    36   "2\n"
    37   "3\n"
    38   "4\n"
    39   "5\n"
    40   "6\n"
    41   "7\n"
    42   "8\n"
    43   "9\n"
    44   "@arcs\n"
    45   "    label capacity\n"
    46   "0 1 0     20\n"
    47   "0 2 1     0\n"
    48   "1 1 2     3\n"
    49   "1 2 3     8\n"
    50   "1 3 4     8\n"
    51   "2 5 5     5\n"
    52   "3 2 6     5\n"
    53   "3 5 7     5\n"
    54   "3 6 8     5\n"
    55   "4 3 9     3\n"
    56   "5 7 10    3\n"
    57   "5 6 11    10\n"
    58   "5 8 12    10\n"
    59   "6 8 13    8\n"
    60   "8 9 14    20\n"
    61   "8 1 15    5\n"
    62   "9 5 16    5\n"
    63   "@attributes\n"
    64   "source 1\n"
    65   "target 8\n";
    66 
    67 void checkPreflowCompile()
    68 {
    69   typedef int VType;
    70   typedef concepts::Digraph Digraph;
    71 
    72   typedef Digraph::Node Node;
    73   typedef Digraph::Arc Arc;
    74   typedef concepts::ReadMap<Arc,VType> CapMap;
    75   typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
    76   typedef concepts::WriteMap<Node,bool> CutMap;
    77 
    78   typedef Elevator<Digraph, Digraph::Node> Elev;
    79   typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
    80 
    81   Digraph g;
    82   Node n;
    83   Arc e;
    84   CapMap cap;
    85   FlowMap flow;
    86   CutMap cut;
    87   VType v;
    88   bool b;
    89 
    90   typedef Preflow<Digraph, CapMap>
    91             ::SetFlowMap<FlowMap>
    92             ::SetElevator<Elev>
    93             ::SetStandardElevator<LinkedElev>
    94             ::Create PreflowType;
    95   PreflowType preflow_test(g, cap, n, n);
    96   const PreflowType& const_preflow_test = preflow_test;
    97 
    98   const PreflowType::Elevator& elev = const_preflow_test.elevator();
    99   preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
   100   PreflowType::Tolerance tol = const_preflow_test.tolerance();
   101   preflow_test.tolerance(tol);
   102 
   103   preflow_test
   104     .capacityMap(cap)
   105     .flowMap(flow)
   106     .source(n)
   107     .target(n);
   108 
   109   preflow_test.init();
   110   preflow_test.init(cap);
   111   preflow_test.startFirstPhase();
   112   preflow_test.startSecondPhase();
   113   preflow_test.run();
   114   preflow_test.runMinCut();
   115 
   116   v = const_preflow_test.flowValue();
   117   v = const_preflow_test.flow(e);
   118   const FlowMap& fm = const_preflow_test.flowMap();
   119   b = const_preflow_test.minCut(n);
   120   const_preflow_test.minCutMap(cut);
   121 
   122   ignore_unused_variable_warning(fm);
   123 }
   124 
   125 int cutValue (const SmartDigraph& g,
   126               const SmartDigraph::NodeMap<bool>& cut,
   127               const SmartDigraph::ArcMap<int>& cap) {
   128 
   129   int c=0;
   130   for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
   131     if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
   132   }
   133   return c;
   134 }
   135 
   136 bool checkFlow(const SmartDigraph& g,
   137                const SmartDigraph::ArcMap<int>& flow,
   138                const SmartDigraph::ArcMap<int>& cap,
   139                SmartDigraph::Node s, SmartDigraph::Node t) {
   140 
   141   for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
   142     if (flow[e] < 0 || flow[e] > cap[e]) return false;
   143   }
   144 
   145   for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
   146     if (n == s || n == t) continue;
   147     int sum = 0;
   148     for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
   149       sum += flow[e];
   150     }
   151     for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
   152       sum -= flow[e];
   153     }
   154     if (sum != 0) return false;
   155   }
   156   return true;
   157 }
   158 
   159 void initFlowTest()
   160 {
   161   DIGRAPH_TYPEDEFS(SmartDigraph);
   162   
   163   SmartDigraph g;
   164   SmartDigraph::ArcMap<int> cap(g),iflow(g);
   165   Node s=g.addNode(); Node t=g.addNode();
   166   Node n1=g.addNode(); Node n2=g.addNode();
   167   Arc a;
   168   a=g.addArc(s,n1); cap[a]=20; iflow[a]=20;
   169   a=g.addArc(n1,n2); cap[a]=10; iflow[a]=0;
   170   a=g.addArc(n2,t); cap[a]=20; iflow[a]=0;
   171 
   172   Preflow<SmartDigraph> pre(g,cap,s,t);
   173   pre.init(iflow);
   174   pre.startFirstPhase();
   175   check(pre.flowValue() == 10, "The incorrect max flow value.");
   176   check(pre.minCut(s), "Wrong min cut (Node s).");
   177   check(pre.minCut(n1), "Wrong min cut (Node n1).");
   178   check(!pre.minCut(n2), "Wrong min cut (Node n2).");
   179   check(!pre.minCut(t), "Wrong min cut (Node t).");
   180 }
   181 
   182 
   183 int main() {
   184 
   185   typedef SmartDigraph Digraph;
   186 
   187   typedef Digraph::Node Node;
   188   typedef Digraph::NodeIt NodeIt;
   189   typedef Digraph::ArcIt ArcIt;
   190   typedef Digraph::ArcMap<int> CapMap;
   191   typedef Digraph::ArcMap<int> FlowMap;
   192   typedef Digraph::NodeMap<bool> CutMap;
   193 
   194   typedef Preflow<Digraph, CapMap> PType;
   195 
   196   Digraph g;
   197   Node s, t;
   198   CapMap cap(g);
   199   std::istringstream input(test_lgf);
   200   DigraphReader<Digraph>(g,input).
   201     arcMap("capacity", cap).
   202     node("source",s).
   203     node("target",t).
   204     run();
   205 
   206   PType preflow_test(g, cap, s, t);
   207   preflow_test.run();
   208 
   209   check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
   210         "The flow is not feasible.");
   211 
   212   CutMap min_cut(g);
   213   preflow_test.minCutMap(min_cut);
   214   int min_cut_value=cutValue(g,min_cut,cap);
   215 
   216   check(preflow_test.flowValue() == min_cut_value,
   217         "The max flow value is not equal to the three min cut values.");
   218 
   219   FlowMap flow(g);
   220   for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
   221 
   222   int flow_value=preflow_test.flowValue();
   223 
   224   for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
   225   preflow_test.init(flow);
   226   preflow_test.startFirstPhase();
   227 
   228   CutMap min_cut1(g);
   229   preflow_test.minCutMap(min_cut1);
   230   min_cut_value=cutValue(g,min_cut1,cap);
   231 
   232   check(preflow_test.flowValue() == min_cut_value &&
   233         min_cut_value == 2*flow_value,
   234         "The max flow value or the min cut value is wrong.");
   235 
   236   preflow_test.startSecondPhase();
   237 
   238   check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
   239         "The flow is not feasible.");
   240 
   241   CutMap min_cut2(g);
   242   preflow_test.minCutMap(min_cut2);
   243   min_cut_value=cutValue(g,min_cut2,cap);
   244 
   245   check(preflow_test.flowValue() == min_cut_value &&
   246         min_cut_value == 2*flow_value,
   247         "The max flow value or the three min cut values were not doubled");
   248 
   249 
   250   preflow_test.flowMap(flow);
   251 
   252   NodeIt tmp1(g,s);
   253   ++tmp1;
   254   if ( tmp1 != INVALID ) s=tmp1;
   255 
   256   NodeIt tmp2(g,t);
   257   ++tmp2;
   258   if ( tmp2 != INVALID ) t=tmp2;
   259 
   260   preflow_test.source(s);
   261   preflow_test.target(t);
   262 
   263   preflow_test.run();
   264 
   265   CutMap min_cut3(g);
   266   preflow_test.minCutMap(min_cut3);
   267   min_cut_value=cutValue(g,min_cut3,cap);
   268 
   269 
   270   check(preflow_test.flowValue() == min_cut_value,
   271         "The max flow value or the three min cut values are incorrect.");
   272 
   273   initFlowTest();
   274   
   275   return 0;
   276 }