1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/test/preflow_test.cc Thu Nov 05 15:50:01 2009 +0100
1.3 @@ -0,0 +1,250 @@
1.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
1.5 + *
1.6 + * This file is a part of LEMON, a generic C++ optimization library.
1.7 + *
1.8 + * Copyright (C) 2003-2009
1.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 + *
1.12 + * Permission to use, modify and distribute this software is granted
1.13 + * provided that this copyright notice appears in all copies. For
1.14 + * precise terms see the accompanying LICENSE file.
1.15 + *
1.16 + * This software is provided "AS IS" with no warranty of any kind,
1.17 + * express or implied, and with no claim as to its suitability for any
1.18 + * purpose.
1.19 + *
1.20 + */
1.21 +
1.22 +#include <iostream>
1.23 +
1.24 +#include "test_tools.h"
1.25 +#include <lemon/smart_graph.h>
1.26 +#include <lemon/preflow.h>
1.27 +#include <lemon/concepts/digraph.h>
1.28 +#include <lemon/concepts/maps.h>
1.29 +#include <lemon/lgf_reader.h>
1.30 +#include <lemon/elevator.h>
1.31 +
1.32 +using namespace lemon;
1.33 +
1.34 +char test_lgf[] =
1.35 + "@nodes\n"
1.36 + "label\n"
1.37 + "0\n"
1.38 + "1\n"
1.39 + "2\n"
1.40 + "3\n"
1.41 + "4\n"
1.42 + "5\n"
1.43 + "6\n"
1.44 + "7\n"
1.45 + "8\n"
1.46 + "9\n"
1.47 + "@arcs\n"
1.48 + " label capacity\n"
1.49 + "0 1 0 20\n"
1.50 + "0 2 1 0\n"
1.51 + "1 1 2 3\n"
1.52 + "1 2 3 8\n"
1.53 + "1 3 4 8\n"
1.54 + "2 5 5 5\n"
1.55 + "3 2 6 5\n"
1.56 + "3 5 7 5\n"
1.57 + "3 6 8 5\n"
1.58 + "4 3 9 3\n"
1.59 + "5 7 10 3\n"
1.60 + "5 6 11 10\n"
1.61 + "5 8 12 10\n"
1.62 + "6 8 13 8\n"
1.63 + "8 9 14 20\n"
1.64 + "8 1 15 5\n"
1.65 + "9 5 16 5\n"
1.66 + "@attributes\n"
1.67 + "source 1\n"
1.68 + "target 8\n";
1.69 +
1.70 +void checkPreflowCompile()
1.71 +{
1.72 + typedef int VType;
1.73 + typedef concepts::Digraph Digraph;
1.74 +
1.75 + typedef Digraph::Node Node;
1.76 + typedef Digraph::Arc Arc;
1.77 + typedef concepts::ReadMap<Arc,VType> CapMap;
1.78 + typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
1.79 + typedef concepts::WriteMap<Node,bool> CutMap;
1.80 +
1.81 + typedef Elevator<Digraph, Digraph::Node> Elev;
1.82 + typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
1.83 +
1.84 + Digraph g;
1.85 + Node n;
1.86 + Arc e;
1.87 + CapMap cap;
1.88 + FlowMap flow;
1.89 + CutMap cut;
1.90 + VType v;
1.91 + bool b;
1.92 +
1.93 + typedef Preflow<Digraph, CapMap>
1.94 + ::SetFlowMap<FlowMap>
1.95 + ::SetElevator<Elev>
1.96 + ::SetStandardElevator<LinkedElev>
1.97 + ::Create PreflowType;
1.98 + PreflowType preflow_test(g, cap, n, n);
1.99 + const PreflowType& const_preflow_test = preflow_test;
1.100 +
1.101 + const PreflowType::Elevator& elev = const_preflow_test.elevator();
1.102 + preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
1.103 + PreflowType::Tolerance tol = const_preflow_test.tolerance();
1.104 + preflow_test.tolerance(tol);
1.105 +
1.106 + preflow_test
1.107 + .capacityMap(cap)
1.108 + .flowMap(flow)
1.109 + .source(n)
1.110 + .target(n);
1.111 +
1.112 + preflow_test.init();
1.113 + preflow_test.init(cap);
1.114 + preflow_test.startFirstPhase();
1.115 + preflow_test.startSecondPhase();
1.116 + preflow_test.run();
1.117 + preflow_test.runMinCut();
1.118 +
1.119 + v = const_preflow_test.flowValue();
1.120 + v = const_preflow_test.flow(e);
1.121 + const FlowMap& fm = const_preflow_test.flowMap();
1.122 + b = const_preflow_test.minCut(n);
1.123 + const_preflow_test.minCutMap(cut);
1.124 +
1.125 + ignore_unused_variable_warning(fm);
1.126 +}
1.127 +
1.128 +int cutValue (const SmartDigraph& g,
1.129 + const SmartDigraph::NodeMap<bool>& cut,
1.130 + const SmartDigraph::ArcMap<int>& cap) {
1.131 +
1.132 + int c=0;
1.133 + for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
1.134 + if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
1.135 + }
1.136 + return c;
1.137 +}
1.138 +
1.139 +bool checkFlow(const SmartDigraph& g,
1.140 + const SmartDigraph::ArcMap<int>& flow,
1.141 + const SmartDigraph::ArcMap<int>& cap,
1.142 + SmartDigraph::Node s, SmartDigraph::Node t) {
1.143 +
1.144 + for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
1.145 + if (flow[e] < 0 || flow[e] > cap[e]) return false;
1.146 + }
1.147 +
1.148 + for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
1.149 + if (n == s || n == t) continue;
1.150 + int sum = 0;
1.151 + for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
1.152 + sum += flow[e];
1.153 + }
1.154 + for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
1.155 + sum -= flow[e];
1.156 + }
1.157 + if (sum != 0) return false;
1.158 + }
1.159 + return true;
1.160 +}
1.161 +
1.162 +int main() {
1.163 +
1.164 + typedef SmartDigraph Digraph;
1.165 +
1.166 + typedef Digraph::Node Node;
1.167 + typedef Digraph::NodeIt NodeIt;
1.168 + typedef Digraph::ArcIt ArcIt;
1.169 + typedef Digraph::ArcMap<int> CapMap;
1.170 + typedef Digraph::ArcMap<int> FlowMap;
1.171 + typedef Digraph::NodeMap<bool> CutMap;
1.172 +
1.173 + typedef Preflow<Digraph, CapMap> PType;
1.174 +
1.175 + Digraph g;
1.176 + Node s, t;
1.177 + CapMap cap(g);
1.178 + std::istringstream input(test_lgf);
1.179 + DigraphReader<Digraph>(g,input).
1.180 + arcMap("capacity", cap).
1.181 + node("source",s).
1.182 + node("target",t).
1.183 + run();
1.184 +
1.185 + PType preflow_test(g, cap, s, t);
1.186 + preflow_test.run();
1.187 +
1.188 + check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
1.189 + "The flow is not feasible.");
1.190 +
1.191 + CutMap min_cut(g);
1.192 + preflow_test.minCutMap(min_cut);
1.193 + int min_cut_value=cutValue(g,min_cut,cap);
1.194 +
1.195 + check(preflow_test.flowValue() == min_cut_value,
1.196 + "The max flow value is not equal to the three min cut values.");
1.197 +
1.198 + FlowMap flow(g);
1.199 + for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
1.200 +
1.201 + int flow_value=preflow_test.flowValue();
1.202 +
1.203 + for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
1.204 + preflow_test.init(flow);
1.205 + preflow_test.startFirstPhase();
1.206 +
1.207 + CutMap min_cut1(g);
1.208 + preflow_test.minCutMap(min_cut1);
1.209 + min_cut_value=cutValue(g,min_cut1,cap);
1.210 +
1.211 + check(preflow_test.flowValue() == min_cut_value &&
1.212 + min_cut_value == 2*flow_value,
1.213 + "The max flow value or the min cut value is wrong.");
1.214 +
1.215 + preflow_test.startSecondPhase();
1.216 +
1.217 + check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
1.218 + "The flow is not feasible.");
1.219 +
1.220 + CutMap min_cut2(g);
1.221 + preflow_test.minCutMap(min_cut2);
1.222 + min_cut_value=cutValue(g,min_cut2,cap);
1.223 +
1.224 + check(preflow_test.flowValue() == min_cut_value &&
1.225 + min_cut_value == 2*flow_value,
1.226 + "The max flow value or the three min cut values were not doubled");
1.227 +
1.228 +
1.229 + preflow_test.flowMap(flow);
1.230 +
1.231 + NodeIt tmp1(g,s);
1.232 + ++tmp1;
1.233 + if ( tmp1 != INVALID ) s=tmp1;
1.234 +
1.235 + NodeIt tmp2(g,t);
1.236 + ++tmp2;
1.237 + if ( tmp2 != INVALID ) t=tmp2;
1.238 +
1.239 + preflow_test.source(s);
1.240 + preflow_test.target(t);
1.241 +
1.242 + preflow_test.run();
1.243 +
1.244 + CutMap min_cut3(g);
1.245 + preflow_test.minCutMap(min_cut3);
1.246 + min_cut_value=cutValue(g,min_cut3,cap);
1.247 +
1.248 +
1.249 + check(preflow_test.flowValue() == min_cut_value,
1.250 + "The max flow value or the three min cut values are incorrect.");
1.251 +
1.252 + return 0;
1.253 +}