COIN-OR::LEMON - Graph Library

source: lemon-main/test/max_flow_test.cc @ 1168:259e3a90ad97

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

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

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