| [389] | 1 | /* -*- mode: C++; indent-tabs-mode: nil; -*- | 
|---|
 | 2 |  * | 
|---|
 | 3 |  * This file is a part of LEMON, a generic C++ optimization library. | 
|---|
 | 4 |  * | 
|---|
| [877] | 5 |  * Copyright (C) 2003-2010 | 
|---|
| [389] | 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 |  | 
|---|
| [423] | 19 | #include <iostream> | 
|---|
| [389] | 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> | 
|---|
| [394] | 27 | #include <lemon/elevator.h> | 
|---|
| [389] | 28 |  | 
|---|
 | 29 | using namespace lemon; | 
|---|
 | 30 |  | 
|---|
| [423] | 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 |  | 
|---|
| [394] | 67 | void checkPreflowCompile() | 
|---|
| [389] | 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 |  | 
|---|
| [394] | 78 |   typedef Elevator<Digraph, Digraph::Node> Elev; | 
|---|
 | 79 |   typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev; | 
|---|
 | 80 |  | 
|---|
| [389] | 81 |   Digraph g; | 
|---|
 | 82 |   Node n; | 
|---|
 | 83 |   Arc e; | 
|---|
 | 84 |   CapMap cap; | 
|---|
 | 85 |   FlowMap flow; | 
|---|
 | 86 |   CutMap cut; | 
|---|
| [585] | 87 |   VType v; | 
|---|
 | 88 |   bool b; | 
|---|
| [389] | 89 |  | 
|---|
| [585] | 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; | 
|---|
| [877] | 97 |  | 
|---|
| [689] | 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); | 
|---|
| [389] | 102 |  | 
|---|
| [585] | 103 |   preflow_test | 
|---|
 | 104 |     .capacityMap(cap) | 
|---|
 | 105 |     .flowMap(flow) | 
|---|
 | 106 |     .source(n) | 
|---|
 | 107 |     .target(n); | 
|---|
| [389] | 108 |  | 
|---|
 | 109 |   preflow_test.init(); | 
|---|
| [392] | 110 |   preflow_test.init(cap); | 
|---|
| [389] | 111 |   preflow_test.startFirstPhase(); | 
|---|
 | 112 |   preflow_test.startSecondPhase(); | 
|---|
 | 113 |   preflow_test.run(); | 
|---|
 | 114 |   preflow_test.runMinCut(); | 
|---|
 | 115 |  | 
|---|
| [585] | 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); | 
|---|
| [877] | 121 |  | 
|---|
| [585] | 122 |   ignore_unused_variable_warning(fm); | 
|---|
| [389] | 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); | 
|---|
| [423] | 175 |   std::istringstream input(test_lgf); | 
|---|
 | 176 |   DigraphReader<Digraph>(g,input). | 
|---|
| [389] | 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]; | 
|---|
| [392] | 201 |   preflow_test.init(flow); | 
|---|
| [389] | 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 | } | 
|---|