COIN-OR::LEMON - Graph Library

source: lemon/test/max_flow_test.cc @ 1384:259e3a90ad97

Last change on this file since 1384:259e3a90ad97 was 1384:259e3a90ad97, checked in by Peter Kovacs <kpeter@…>, 6 years ago

Improve max flow test method: set expected flow value (#608)

File size: 10.3 KB
RevLine 
[404]1/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library.
4 *
[1270]5 * Copyright (C) 2003-2013
[404]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
[442]19#include <iostream>
[404]20
21#include "test_tools.h"
22#include <lemon/smart_graph.h>
23#include <lemon/preflow.h>
[1228]24#include <lemon/edmonds_karp.h>
[404]25#include <lemon/concepts/digraph.h>
26#include <lemon/concepts/maps.h>
27#include <lemon/lgf_reader.h>
[409]28#include <lemon/elevator.h>
[1383]29#include <lemon/tolerance.h>
[404]30
31using namespace lemon;
32
[442]33char 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
[1228]69// Checks the general interface of a max flow algorithm
70template <typename GR, typename CAP>
71struct 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
[1262]124      ::lemon::ignore_unused_variable_warning(fm);
[1228]125    }
126
127  };
128
129};
130
131// Checks the specific parts of Preflow's interface
[409]132void checkPreflowCompile()
[404]133{
[1228]134  typedef int Value;
[404]135  typedef concepts::Digraph Digraph;
[1228]136  typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
[409]137  typedef Elevator<Digraph, Digraph::Node> Elev;
138  typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
139
[404]140  Digraph g;
[1228]141  Digraph::Node n;
[404]142  CapMap cap;
143
[632]144  typedef Preflow<Digraph, CapMap>
[1228]145      ::SetElevator<Elev>
146      ::SetStandardElevator<LinkedElev>
147      ::Create PreflowType;
[632]148  PreflowType preflow_test(g, cap, n, n);
149  const PreflowType& const_preflow_test = preflow_test;
[404]150
[736]151  const PreflowType::Elevator& elev = const_preflow_test.elevator();
152  preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
[632]153
[1228]154  bool b = preflow_test.init(cap);
[404]155  preflow_test.startFirstPhase();
156  preflow_test.startSecondPhase();
157  preflow_test.runMinCut();
158
[1262]159  ::lemon::ignore_unused_variable_warning(b);
[404]160}
161
[1228]162// Checks the specific parts of EdmondsKarp's interface
163void 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
[1262]180  ::lemon::ignore_unused_variable_warning(b);
[1228]181}
182
183
184template <typename T>
[1382]185T cutValue(const SmartDigraph& g,
186           const SmartDigraph::NodeMap<bool>& cut,
187           const SmartDigraph::ArcMap<T>& cap) {
[404]188
[1382]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];
[404]192  }
193  return c;
194}
195
[1228]196template <typename T>
[404]197bool checkFlow(const SmartDigraph& g,
[1228]198               const SmartDigraph::ArcMap<T>& flow,
199               const SmartDigraph::ArcMap<T>& cap,
[1383]200               SmartDigraph::Node s, SmartDigraph::Node t,
201               const Tolerance<T>& tol) {
[404]202
203  for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
[1383]204    if (tol.negative(flow[e]) || tol.less(cap[e], flow[e])) return false;
[404]205  }
206
207  for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
208    if (n == s || n == t) continue;
[1228]209    T sum = 0;
[404]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    }
[1383]216    if (tol.nonZero(sum)) return false;
[404]217  }
218  return true;
219}
220
[1382]221void checkInitPreflow()
[1027]222{
223  DIGRAPH_TYPEDEFS(SmartDigraph);
[1270]224
[1027]225  SmartDigraph g;
[1382]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();
[1027]229  Arc a;
[1382]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;
[1027]233
[1382]234  Preflow<SmartDigraph> pre(g, cap, s, t);
[1027]235  pre.init(iflow);
236  pre.startFirstPhase();
[1382]237
238  check(pre.flowValue() == 10, "Incorrect max flow value.");
[1027]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
[1228]245template <typename MF, typename SF>
[1384]246void checkMaxFlowAlg(const char *input_lgf,  typename MF::Value expected) {
[1228]247  typedef SmartDigraph Digraph;
248  DIGRAPH_TYPEDEFS(Digraph);
[1027]249
[1228]250  typedef typename MF::Value Value;
251  typedef Digraph::ArcMap<Value> CapMap;
252  typedef CapMap FlowMap;
253  typedef BoolNodeMap CutMap;
[404]254
[1383]255  Tolerance<Value> tol;
256
[404]257  Digraph g;
258  Node s, t;
259  CapMap cap(g);
[1384]260  std::istringstream input(input_lgf);
[1228]261  DigraphReader<Digraph>(g,input)
262      .arcMap("capacity", cap)
263      .node("source",s)
264      .node("target",t)
265      .run();
[404]266
[1228]267  MF max_flow(g, cap, s, t);
268  max_flow.run();
[404]269
[1384]270  check(!tol.different(expected, max_flow.flowValue()),
271        "Incorrect max flow value.");
[1383]272  check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
[404]273        "The flow is not feasible.");
274
275  CutMap min_cut(g);
[1228]276  max_flow.minCutMap(min_cut);
277  Value min_cut_value = cutValue(g, min_cut, cap);
[404]278
[1384]279  check(!tol.different(expected, min_cut_value),
280        "Incorrect min cut value.");
[404]281
282  FlowMap flow(g);
[1228]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
[404]288
289  CutMap min_cut1(g);
[1228]290  max_flow.minCutMap(min_cut1);
291  min_cut_value = cutValue(g, min_cut1, cap);
[404]292
[1384]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.");
[404]297
[1228]298  SF::startSecondPhase(max_flow);       // start second phase of the algorithm
[404]299
[1383]300  check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
[404]301        "The flow is not feasible.");
302
303  CutMap min_cut2(g);
[1228]304  max_flow.minCutMap(min_cut2);
305  min_cut_value = cutValue(g, min_cut2, cap);
[404]306
[1384]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.");
[404]311
[1228]312  max_flow.flowMap(flow);
[404]313
[1228]314  NodeIt tmp1(g, s);
[404]315  ++tmp1;
[1228]316  if (tmp1 != INVALID) s = tmp1;
[404]317
[1228]318  NodeIt tmp2(g, t);
[404]319  ++tmp2;
[1228]320  if (tmp2 != INVALID) t = tmp2;
[404]321
[1228]322  max_flow.source(s);
323  max_flow.target(t);
[404]324
[1228]325  max_flow.run();
[404]326
327  CutMap min_cut3(g);
[1228]328  max_flow.minCutMap(min_cut3);
[1382]329  min_cut_value = cutValue(g, min_cut3, cap);
[404]330
[1383]331  check(!tol.different(max_flow.flowValue(), min_cut_value),
[1228]332        "The max flow value or the min cut value is wrong.");
333}
[404]334
[1228]335// Struct for calling start functions of a general max flow algorithm
336template <typename MF>
337struct GeneralStartFunctions {
338
339  static void startFirstPhase(MF& mf) {
340    mf.start();
341  }
342
343  static void startSecondPhase(MF& mf) {
[1262]344    ::lemon::ignore_unused_variable_warning(mf);
[1228]345  }
346
347};
348
349// Struct for calling start functions of Preflow
350template <typename MF>
351struct 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
363int 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;
[1384]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);
[1382]388
389  checkInitPreflow();
[1270]390
[1228]391  // Check EdmondsKarp
392  typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<int> > EKType1;
393  typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<float> > EKType2;
[1384]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);
[404]398
399  return 0;
400}
Note: See TracBrowser for help on using the repository browser.