test/max_flow_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 22 Mar 2018 18:56:26 +0100
changeset 1168 259e3a90ad97
parent 1167 e018899c2926
child 1169 8db773f19586
permissions -rw-r--r--
Improve max flow test method: set expected flow value (#608)
     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-2013
     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/edmonds_karp.h>
    25 #include <lemon/concepts/digraph.h>
    26 #include <lemon/concepts/maps.h>
    27 #include <lemon/lgf_reader.h>
    28 #include <lemon/elevator.h>
    29 #include <lemon/tolerance.h>
    30 
    31 using namespace lemon;
    32 
    33 char test_lgf[] =
    34   "@nodes\n"
    35   "label\n"
    36   "0\n"
    37   "1\n"
    38   "2\n"
    39   "3\n"
    40   "4\n"
    41   "5\n"
    42   "6\n"
    43   "7\n"
    44   "8\n"
    45   "9\n"
    46   "@arcs\n"
    47   "    label capacity\n"
    48   "0 1 0     20\n"
    49   "0 2 1     0\n"
    50   "1 1 2     3\n"
    51   "1 2 3     8\n"
    52   "1 3 4     8\n"
    53   "2 5 5     5\n"
    54   "3 2 6     5\n"
    55   "3 5 7     5\n"
    56   "3 6 8     5\n"
    57   "4 3 9     3\n"
    58   "5 7 10    3\n"
    59   "5 6 11    10\n"
    60   "5 8 12    10\n"
    61   "6 8 13    8\n"
    62   "8 9 14    20\n"
    63   "8 1 15    5\n"
    64   "9 5 16    5\n"
    65   "@attributes\n"
    66   "source 1\n"
    67   "target 8\n";
    68 
    69 // Checks the general interface of a max flow algorithm
    70 template <typename GR, typename CAP>
    71 struct MaxFlowClassConcept
    72 {
    73 
    74   template <typename MF>
    75   struct Constraints {
    76 
    77     typedef typename GR::Node Node;
    78     typedef typename GR::Arc Arc;
    79     typedef typename CAP::Value Value;
    80     typedef concepts::ReadWriteMap<Arc, Value> FlowMap;
    81     typedef concepts::WriteMap<Node, bool> CutMap;
    82 
    83     GR g;
    84     Node n;
    85     Arc e;
    86     CAP cap;
    87     FlowMap flow;
    88     CutMap cut;
    89     Value v;
    90     bool b;
    91 
    92     void constraints() {
    93       checkConcept<concepts::Digraph, GR>();
    94 
    95       const Constraints& me = *this;
    96 
    97       typedef typename MF
    98           ::template SetFlowMap<FlowMap>
    99           ::Create MaxFlowType;
   100       typedef typename MF::Create MaxFlowType2;
   101       MaxFlowType max_flow(me.g, me.cap, me.n, me.n);
   102       const MaxFlowType& const_max_flow = max_flow;
   103 
   104       max_flow
   105           .capacityMap(cap)
   106           .flowMap(flow)
   107           .source(n)
   108           .target(n);
   109 
   110       typename MaxFlowType::Tolerance tol = const_max_flow.tolerance();
   111       max_flow.tolerance(tol);
   112 
   113       max_flow.init();
   114       max_flow.init(cap);
   115       max_flow.run();
   116 
   117       v = const_max_flow.flowValue();
   118       v = const_max_flow.flow(e);
   119       const FlowMap& fm = const_max_flow.flowMap();
   120 
   121       b = const_max_flow.minCut(n);
   122       const_max_flow.minCutMap(cut);
   123 
   124       ::lemon::ignore_unused_variable_warning(fm);
   125     }
   126 
   127   };
   128 
   129 };
   130 
   131 // Checks the specific parts of Preflow's interface
   132 void checkPreflowCompile()
   133 {
   134   typedef int Value;
   135   typedef concepts::Digraph Digraph;
   136   typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
   137   typedef Elevator<Digraph, Digraph::Node> Elev;
   138   typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
   139 
   140   Digraph g;
   141   Digraph::Node n;
   142   CapMap cap;
   143 
   144   typedef Preflow<Digraph, CapMap>
   145       ::SetElevator<Elev>
   146       ::SetStandardElevator<LinkedElev>
   147       ::Create PreflowType;
   148   PreflowType preflow_test(g, cap, n, n);
   149   const PreflowType& const_preflow_test = preflow_test;
   150 
   151   const PreflowType::Elevator& elev = const_preflow_test.elevator();
   152   preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
   153 
   154   bool b = preflow_test.init(cap);
   155   preflow_test.startFirstPhase();
   156   preflow_test.startSecondPhase();
   157   preflow_test.runMinCut();
   158 
   159   ::lemon::ignore_unused_variable_warning(b);
   160 }
   161 
   162 // Checks the specific parts of EdmondsKarp's interface
   163 void checkEdmondsKarpCompile()
   164 {
   165   typedef int Value;
   166   typedef concepts::Digraph Digraph;
   167   typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
   168 
   169   Digraph g;
   170   Digraph::Node n;
   171   CapMap cap;
   172 
   173   EdmondsKarp<Digraph, CapMap> ek_test(g, cap, n, n);
   174 
   175   ek_test.init(cap);
   176   bool b = ek_test.checkedInit(cap);
   177   b = ek_test.augment();
   178   ek_test.start();
   179 
   180   ::lemon::ignore_unused_variable_warning(b);
   181 }
   182 
   183 
   184 template <typename T>
   185 T cutValue(const SmartDigraph& g,
   186            const SmartDigraph::NodeMap<bool>& cut,
   187            const SmartDigraph::ArcMap<T>& cap) {
   188 
   189   T c = 0;
   190   for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
   191     if (cut[g.source(e)] && !cut[g.target(e)]) c += cap[e];
   192   }
   193   return c;
   194 }
   195 
   196 template <typename T>
   197 bool checkFlow(const SmartDigraph& g,
   198                const SmartDigraph::ArcMap<T>& flow,
   199                const SmartDigraph::ArcMap<T>& cap,
   200                SmartDigraph::Node s, SmartDigraph::Node t,
   201                const Tolerance<T>& tol) {
   202 
   203   for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
   204     if (tol.negative(flow[e]) || tol.less(cap[e], flow[e])) return false;
   205   }
   206 
   207   for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
   208     if (n == s || n == t) continue;
   209     T sum = 0;
   210     for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
   211       sum += flow[e];
   212     }
   213     for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
   214       sum -= flow[e];
   215     }
   216     if (tol.nonZero(sum)) return false;
   217   }
   218   return true;
   219 }
   220 
   221 void checkInitPreflow()
   222 {
   223   DIGRAPH_TYPEDEFS(SmartDigraph);
   224 
   225   SmartDigraph g;
   226   SmartDigraph::ArcMap<int> cap(g), iflow(g);
   227   Node s = g.addNode(); Node t = g.addNode();
   228   Node n1 = g.addNode(); Node n2 = g.addNode();
   229   Arc a;
   230   a = g.addArc(s, n1); cap[a] = 20; iflow[a] = 20;
   231   a = g.addArc(n1, n2); cap[a] = 10; iflow[a] = 0;
   232   a = g.addArc(n2, t); cap[a] = 20; iflow[a] = 0;
   233 
   234   Preflow<SmartDigraph> pre(g, cap, s, t);
   235   pre.init(iflow);
   236   pre.startFirstPhase();
   237 
   238   check(pre.flowValue() == 10, "Incorrect max flow value.");
   239   check(pre.minCut(s), "Wrong min cut (Node s).");
   240   check(pre.minCut(n1), "Wrong min cut (Node n1).");
   241   check(!pre.minCut(n2), "Wrong min cut (Node n2).");
   242   check(!pre.minCut(t), "Wrong min cut (Node t).");
   243 }
   244 
   245 template <typename MF, typename SF>
   246 void checkMaxFlowAlg(const char *input_lgf,  typename MF::Value expected) {
   247   typedef SmartDigraph Digraph;
   248   DIGRAPH_TYPEDEFS(Digraph);
   249 
   250   typedef typename MF::Value Value;
   251   typedef Digraph::ArcMap<Value> CapMap;
   252   typedef CapMap FlowMap;
   253   typedef BoolNodeMap CutMap;
   254 
   255   Tolerance<Value> tol;
   256 
   257   Digraph g;
   258   Node s, t;
   259   CapMap cap(g);
   260   std::istringstream input(input_lgf);
   261   DigraphReader<Digraph>(g,input)
   262       .arcMap("capacity", cap)
   263       .node("source",s)
   264       .node("target",t)
   265       .run();
   266 
   267   MF max_flow(g, cap, s, t);
   268   max_flow.run();
   269 
   270   check(!tol.different(expected, max_flow.flowValue()),
   271         "Incorrect max flow value.");
   272   check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
   273         "The flow is not feasible.");
   274 
   275   CutMap min_cut(g);
   276   max_flow.minCutMap(min_cut);
   277   Value min_cut_value = cutValue(g, min_cut, cap);
   278 
   279   check(!tol.different(expected, min_cut_value),
   280         "Incorrect min cut value.");
   281 
   282   FlowMap flow(g);
   283   for (ArcIt e(g); e != INVALID; ++e) flow[e] = max_flow.flowMap()[e];
   284   for (ArcIt e(g); e != INVALID; ++e) cap[e] = 2 * cap[e];
   285   max_flow.init(flow);
   286 
   287   SF::startFirstPhase(max_flow);       // start first phase of the algorithm
   288 
   289   CutMap min_cut1(g);
   290   max_flow.minCutMap(min_cut1);
   291   min_cut_value = cutValue(g, min_cut1, cap);
   292 
   293   check(!tol.different(2 * expected, max_flow.flowValue()),
   294         "Incorrect max flow value.");
   295   check(!tol.different(2 * expected, min_cut_value),
   296         "Incorrect min cut value.");
   297 
   298   SF::startSecondPhase(max_flow);       // start second phase of the algorithm
   299 
   300   check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
   301         "The flow is not feasible.");
   302 
   303   CutMap min_cut2(g);
   304   max_flow.minCutMap(min_cut2);
   305   min_cut_value = cutValue(g, min_cut2, cap);
   306 
   307   check(!tol.different(2 * expected, max_flow.flowValue()),
   308         "Incorrect max flow value.");
   309   check(!tol.different(2 * expected, min_cut_value),
   310         "Incorrect min cut value.");
   311 
   312   max_flow.flowMap(flow);
   313 
   314   NodeIt tmp1(g, s);
   315   ++tmp1;
   316   if (tmp1 != INVALID) s = tmp1;
   317 
   318   NodeIt tmp2(g, t);
   319   ++tmp2;
   320   if (tmp2 != INVALID) t = tmp2;
   321 
   322   max_flow.source(s);
   323   max_flow.target(t);
   324 
   325   max_flow.run();
   326 
   327   CutMap min_cut3(g);
   328   max_flow.minCutMap(min_cut3);
   329   min_cut_value = cutValue(g, min_cut3, cap);
   330 
   331   check(!tol.different(max_flow.flowValue(), min_cut_value),
   332         "The max flow value or the min cut value is wrong.");
   333 }
   334 
   335 // Struct for calling start functions of a general max flow algorithm
   336 template <typename MF>
   337 struct GeneralStartFunctions {
   338 
   339   static void startFirstPhase(MF& mf) {
   340     mf.start();
   341   }
   342 
   343   static void startSecondPhase(MF& mf) {
   344     ::lemon::ignore_unused_variable_warning(mf);
   345   }
   346 
   347 };
   348 
   349 // Struct for calling start functions of Preflow
   350 template <typename MF>
   351 struct PreflowStartFunctions {
   352 
   353   static void startFirstPhase(MF& mf) {
   354     mf.startFirstPhase();
   355   }
   356 
   357   static void startSecondPhase(MF& mf) {
   358     mf.startSecondPhase();
   359   }
   360 
   361 };
   362 
   363 int main() {
   364 
   365   typedef concepts::Digraph GR;
   366   typedef concepts::ReadMap<GR::Arc, int> CM1;
   367   typedef concepts::ReadMap<GR::Arc, double> CM2;
   368 
   369   // Check the interface of Preflow
   370   checkConcept< MaxFlowClassConcept<GR, CM1>,
   371                 Preflow<GR, CM1> >();
   372   checkConcept< MaxFlowClassConcept<GR, CM2>,
   373                 Preflow<GR, CM2> >();
   374 
   375   // Check the interface of EdmondsKarp
   376   checkConcept< MaxFlowClassConcept<GR, CM1>,
   377                 EdmondsKarp<GR, CM1> >();
   378   checkConcept< MaxFlowClassConcept<GR, CM2>,
   379                 EdmondsKarp<GR, CM2> >();
   380 
   381   // Check Preflow
   382   typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<int> > PType1;
   383   typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<float> > PType2;
   384   typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<double> > PType3;
   385   checkMaxFlowAlg<PType1, PreflowStartFunctions<PType1> >(test_lgf, 13);
   386   checkMaxFlowAlg<PType2, PreflowStartFunctions<PType2> >(test_lgf, 13);
   387   checkMaxFlowAlg<PType3, PreflowStartFunctions<PType3> >(test_lgf, 13);
   388 
   389   checkInitPreflow();
   390 
   391   // Check EdmondsKarp
   392   typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<int> > EKType1;
   393   typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<float> > EKType2;
   394   typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<double> > EKType3;
   395   checkMaxFlowAlg<EKType1, GeneralStartFunctions<EKType1> >(test_lgf, 13);
   396   checkMaxFlowAlg<EKType2, GeneralStartFunctions<EKType2> >(test_lgf, 13);
   397   checkMaxFlowAlg<EKType3, GeneralStartFunctions<EKType3> >(test_lgf, 13);
   398 
   399   return 0;
   400 }