test/preflow_test.cc
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 891 bb70ad62c95f
parent 440 88ed40ad0d4f
child 689 86c49553fea5
child 923 30d5f950aa5f
permissions -rw-r--r--
Fix critical bug in preflow (#372)

The wrong transition between the bound decrease and highest active
heuristics caused the bug. The last node chosen in bound decrease mode
is used in the first iteration in highest active mode.
     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-2009
     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   preflow_test
    99     .capacityMap(cap)
   100     .flowMap(flow)
   101     .source(n)
   102     .target(n);
   103 
   104   preflow_test.init();
   105   preflow_test.init(cap);
   106   preflow_test.startFirstPhase();
   107   preflow_test.startSecondPhase();
   108   preflow_test.run();
   109   preflow_test.runMinCut();
   110 
   111   v = const_preflow_test.flowValue();
   112   v = const_preflow_test.flow(e);
   113   const FlowMap& fm = const_preflow_test.flowMap();
   114   b = const_preflow_test.minCut(n);
   115   const_preflow_test.minCutMap(cut);
   116   
   117   ignore_unused_variable_warning(fm);
   118 }
   119 
   120 int cutValue (const SmartDigraph& g,
   121               const SmartDigraph::NodeMap<bool>& cut,
   122               const SmartDigraph::ArcMap<int>& cap) {
   123 
   124   int c=0;
   125   for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
   126     if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
   127   }
   128   return c;
   129 }
   130 
   131 bool checkFlow(const SmartDigraph& g,
   132                const SmartDigraph::ArcMap<int>& flow,
   133                const SmartDigraph::ArcMap<int>& cap,
   134                SmartDigraph::Node s, SmartDigraph::Node t) {
   135 
   136   for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
   137     if (flow[e] < 0 || flow[e] > cap[e]) return false;
   138   }
   139 
   140   for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
   141     if (n == s || n == t) continue;
   142     int sum = 0;
   143     for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
   144       sum += flow[e];
   145     }
   146     for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
   147       sum -= flow[e];
   148     }
   149     if (sum != 0) return false;
   150   }
   151   return true;
   152 }
   153 
   154 int main() {
   155 
   156   typedef SmartDigraph Digraph;
   157 
   158   typedef Digraph::Node Node;
   159   typedef Digraph::NodeIt NodeIt;
   160   typedef Digraph::ArcIt ArcIt;
   161   typedef Digraph::ArcMap<int> CapMap;
   162   typedef Digraph::ArcMap<int> FlowMap;
   163   typedef Digraph::NodeMap<bool> CutMap;
   164 
   165   typedef Preflow<Digraph, CapMap> PType;
   166 
   167   Digraph g;
   168   Node s, t;
   169   CapMap cap(g);
   170   std::istringstream input(test_lgf);
   171   DigraphReader<Digraph>(g,input).
   172     arcMap("capacity", cap).
   173     node("source",s).
   174     node("target",t).
   175     run();
   176 
   177   PType preflow_test(g, cap, s, t);
   178   preflow_test.run();
   179 
   180   check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
   181         "The flow is not feasible.");
   182 
   183   CutMap min_cut(g);
   184   preflow_test.minCutMap(min_cut);
   185   int min_cut_value=cutValue(g,min_cut,cap);
   186 
   187   check(preflow_test.flowValue() == min_cut_value,
   188         "The max flow value is not equal to the three min cut values.");
   189 
   190   FlowMap flow(g);
   191   for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
   192 
   193   int flow_value=preflow_test.flowValue();
   194 
   195   for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
   196   preflow_test.init(flow);
   197   preflow_test.startFirstPhase();
   198 
   199   CutMap min_cut1(g);
   200   preflow_test.minCutMap(min_cut1);
   201   min_cut_value=cutValue(g,min_cut1,cap);
   202 
   203   check(preflow_test.flowValue() == min_cut_value &&
   204         min_cut_value == 2*flow_value,
   205         "The max flow value or the min cut value is wrong.");
   206 
   207   preflow_test.startSecondPhase();
   208 
   209   check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
   210         "The flow is not feasible.");
   211 
   212   CutMap min_cut2(g);
   213   preflow_test.minCutMap(min_cut2);
   214   min_cut_value=cutValue(g,min_cut2,cap);
   215 
   216   check(preflow_test.flowValue() == min_cut_value &&
   217         min_cut_value == 2*flow_value,
   218         "The max flow value or the three min cut values were not doubled");
   219 
   220 
   221   preflow_test.flowMap(flow);
   222 
   223   NodeIt tmp1(g,s);
   224   ++tmp1;
   225   if ( tmp1 != INVALID ) s=tmp1;
   226 
   227   NodeIt tmp2(g,t);
   228   ++tmp2;
   229   if ( tmp2 != INVALID ) t=tmp2;
   230 
   231   preflow_test.source(s);
   232   preflow_test.target(t);
   233 
   234   preflow_test.run();
   235 
   236   CutMap min_cut3(g);
   237   preflow_test.minCutMap(min_cut3);
   238   min_cut_value=cutValue(g,min_cut3,cap);
   239 
   240 
   241   check(preflow_test.flowValue() == min_cut_value,
   242         "The max flow value or the three min cut values are incorrect.");
   243 
   244   return 0;
   245 }