test/preflow_test.cc
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 585 65fbcf2f978a
child 877 141f9c0db4a3
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
     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   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 int main() {
   160 
   161   typedef SmartDigraph Digraph;
   162 
   163   typedef Digraph::Node Node;
   164   typedef Digraph::NodeIt NodeIt;
   165   typedef Digraph::ArcIt ArcIt;
   166   typedef Digraph::ArcMap<int> CapMap;
   167   typedef Digraph::ArcMap<int> FlowMap;
   168   typedef Digraph::NodeMap<bool> CutMap;
   169 
   170   typedef Preflow<Digraph, CapMap> PType;
   171 
   172   Digraph g;
   173   Node s, t;
   174   CapMap cap(g);
   175   std::istringstream input(test_lgf);
   176   DigraphReader<Digraph>(g,input).
   177     arcMap("capacity", cap).
   178     node("source",s).
   179     node("target",t).
   180     run();
   181 
   182   PType preflow_test(g, cap, s, t);
   183   preflow_test.run();
   184 
   185   check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
   186         "The flow is not feasible.");
   187 
   188   CutMap min_cut(g);
   189   preflow_test.minCutMap(min_cut);
   190   int min_cut_value=cutValue(g,min_cut,cap);
   191 
   192   check(preflow_test.flowValue() == min_cut_value,
   193         "The max flow value is not equal to the three min cut values.");
   194 
   195   FlowMap flow(g);
   196   for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
   197 
   198   int flow_value=preflow_test.flowValue();
   199 
   200   for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
   201   preflow_test.init(flow);
   202   preflow_test.startFirstPhase();
   203 
   204   CutMap min_cut1(g);
   205   preflow_test.minCutMap(min_cut1);
   206   min_cut_value=cutValue(g,min_cut1,cap);
   207 
   208   check(preflow_test.flowValue() == min_cut_value &&
   209         min_cut_value == 2*flow_value,
   210         "The max flow value or the min cut value is wrong.");
   211 
   212   preflow_test.startSecondPhase();
   213 
   214   check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
   215         "The flow is not feasible.");
   216 
   217   CutMap min_cut2(g);
   218   preflow_test.minCutMap(min_cut2);
   219   min_cut_value=cutValue(g,min_cut2,cap);
   220 
   221   check(preflow_test.flowValue() == min_cut_value &&
   222         min_cut_value == 2*flow_value,
   223         "The max flow value or the three min cut values were not doubled");
   224 
   225 
   226   preflow_test.flowMap(flow);
   227 
   228   NodeIt tmp1(g,s);
   229   ++tmp1;
   230   if ( tmp1 != INVALID ) s=tmp1;
   231 
   232   NodeIt tmp2(g,t);
   233   ++tmp2;
   234   if ( tmp2 != INVALID ) t=tmp2;
   235 
   236   preflow_test.source(s);
   237   preflow_test.target(t);
   238 
   239   preflow_test.run();
   240 
   241   CutMap min_cut3(g);
   242   preflow_test.minCutMap(min_cut3);
   243   min_cut_value=cutValue(g,min_cut3,cap);
   244 
   245 
   246   check(preflow_test.flowValue() == min_cut_value,
   247         "The max flow value or the three min cut values are incorrect.");
   248 
   249   return 0;
   250 }