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