gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add traits class + named parameters to Suurballe (#323) The following types can be modified using named parameters: - FlowMap - PotentialMap - Path - Heap + HeapCrossRef
0 2 0
default
2 files changed with 146 insertions and 21 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_SUURBALLE_H
20 20
#define LEMON_SUURBALLE_H
21 21

	
22 22
///\ingroup shortest_path
23 23
///\file
24 24
///\brief An algorithm for finding arc-disjoint paths between two
25 25
/// nodes having minimum total length.
26 26

	
27 27
#include <vector>
28 28
#include <limits>
29 29
#include <lemon/bin_heap.h>
30 30
#include <lemon/path.h>
31 31
#include <lemon/list_graph.h>
32 32
#include <lemon/dijkstra.h>
33 33
#include <lemon/maps.h>
34 34

	
35 35
namespace lemon {
36 36

	
37
  /// \brief Default traits class of Suurballe algorithm.
38
  ///
39
  /// Default traits class of Suurballe algorithm.
40
  /// \tparam GR The digraph type the algorithm runs on.
41
  /// \tparam LEN The type of the length map.
42
  /// The default value is <tt>GR::ArcMap<int></tt>.
43
#ifdef DOXYGEN
44
  template <typename GR, typename LEN>
45
#else
46
  template < typename GR,
47
             typename LEN = typename GR::template ArcMap<int> >
48
#endif
49
  struct SuurballeDefaultTraits
50
  {
51
    /// The type of the digraph.
52
    typedef GR Digraph;
53
    /// The type of the length map.
54
    typedef LEN LengthMap;
55
    /// The type of the lengths.
56
    typedef typename LEN::Value Length;
57
    /// The type of the flow map.
58
    typedef typename GR::template ArcMap<int> FlowMap;
59
    /// The type of the potential map.
60
    typedef typename GR::template NodeMap<Length> PotentialMap;
61

	
62
    /// \brief The path type
63
    ///
64
    /// The type used for storing the found arc-disjoint paths.
65
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
66
    /// and it must have an \c addBack() function.
67
    typedef lemon::Path<Digraph> Path;
68
    
69
    /// The cross reference type used for the heap.
70
    typedef typename GR::template NodeMap<int> HeapCrossRef;
71

	
72
    /// \brief The heap type used for internal Dijkstra computations.
73
    ///
74
    /// The type of the heap used for internal Dijkstra computations.
75
    /// It must conform to the \ref lemon::concepts::Heap "Heap" concept
76
    /// and its priority type must be \c Length.
77
    typedef BinHeap<Length, HeapCrossRef> Heap;
78
  };
79

	
37 80
  /// \addtogroup shortest_path
38 81
  /// @{
39 82

	
40 83
  /// \brief Algorithm for finding arc-disjoint paths between two nodes
41 84
  /// having minimum total length.
42 85
  ///
43 86
  /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
44 87
  /// finding arc-disjoint paths having minimum total length (cost)
45 88
  /// from a given source node to a given target node in a digraph.
46 89
  ///
47 90
  /// Note that this problem is a special case of the \ref min_cost_flow
48 91
  /// "minimum cost flow problem". This implementation is actually an
49 92
  /// efficient specialized version of the \ref CapacityScaling
50 93
  /// "successive shortest path" algorithm directly for this problem.
51 94
  /// Therefore this class provides query functions for flow values and
52 95
  /// node potentials (the dual solution) just like the minimum cost flow
53 96
  /// algorithms.
54 97
  ///
55 98
  /// \tparam GR The digraph type the algorithm runs on.
56 99
  /// \tparam LEN The type of the length map.
57 100
  /// The default value is <tt>GR::ArcMap<int></tt>.
58 101
  ///
59 102
  /// \warning Length values should be \e non-negative.
60 103
  ///
61 104
  /// \note For finding \e node-disjoint paths, this algorithm can be used
62 105
  /// along with the \ref SplitNodes adaptor.
63 106
#ifdef DOXYGEN
64
  template <typename GR, typename LEN>
107
  template <typename GR, typename LEN, typename TR>
65 108
#else
66 109
  template < typename GR,
67
             typename LEN = typename GR::template ArcMap<int> >
110
             typename LEN = typename GR::template ArcMap<int>,
111
             typename TR = SuurballeDefaultTraits<GR, LEN> >
68 112
#endif
69 113
  class Suurballe
70 114
  {
71 115
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
72 116

	
73 117
    typedef ConstMap<Arc, int> ConstArcMap;
74 118
    typedef typename GR::template NodeMap<Arc> PredMap;
75 119

	
76 120
  public:
77 121

	
78
    /// The type of the digraph the algorithm runs on.
79
    typedef GR Digraph;
122
    /// The type of the digraph.
123
    typedef typename TR::Digraph Digraph;
80 124
    /// The type of the length map.
81
    typedef LEN LengthMap;
125
    typedef typename TR::LengthMap LengthMap;
82 126
    /// The type of the lengths.
83
    typedef typename LengthMap::Value Length;
84
#ifdef DOXYGEN
127
    typedef typename TR::Length Length;
128

	
85 129
    /// The type of the flow map.
86
    typedef GR::ArcMap<int> FlowMap;
130
    typedef typename TR::FlowMap FlowMap;
87 131
    /// The type of the potential map.
88
    typedef GR::NodeMap<Length> PotentialMap;
89
#else
90
    /// The type of the flow map.
91
    typedef typename Digraph::template ArcMap<int> FlowMap;
92
    /// The type of the potential map.
93
    typedef typename Digraph::template NodeMap<Length> PotentialMap;
94
#endif
132
    typedef typename TR::PotentialMap PotentialMap;
133
    /// The type of the path structures.
134
    typedef typename TR::Path Path;
135
    /// The cross reference type used for the heap.
136
    typedef typename TR::HeapCrossRef HeapCrossRef;
137
    /// The heap type used for internal Dijkstra computations.
138
    typedef typename TR::Heap Heap;
95 139

	
96
    /// The type of the path structures.
97
    typedef SimplePath<GR> Path;
140
    /// The \ref SuurballeDefaultTraits "traits class" of the algorithm.
141
    typedef TR Traits;
98 142

	
99 143
  private:
100 144

	
101
    typedef typename Digraph::template NodeMap<int> HeapCrossRef;
102
    typedef BinHeap<Length, HeapCrossRef> Heap;
103

	
104 145
    // ResidualDijkstra is a special implementation of the
105 146
    // Dijkstra algorithm for finding shortest paths in the
106 147
    // residual network with respect to the reduced arc lengths
107 148
    // and modifying the node potentials according to the
108 149
    // distance of the nodes.
109 150
    class ResidualDijkstra
110 151
    {
111 152
    private:
112 153

	
113 154
      const Digraph &_graph;
114 155
      const LengthMap &_length;
115 156
      const FlowMap &_flow;
116 157
      PotentialMap &_pi;
117 158
      PredMap &_pred;
118 159
      Node _s;
119 160
      Node _t;
120 161
      
121 162
      PotentialMap _dist;
122 163
      std::vector<Node> _proc_nodes;
123 164

	
124 165
    public:
125 166

	
126 167
      // Constructor
127 168
      ResidualDijkstra(Suurballe &srb) :
128 169
        _graph(srb._graph), _length(srb._length),
129 170
        _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred), 
130 171
        _s(srb._s), _t(srb._t), _dist(_graph) {}
131 172
        
132 173
      // Run the algorithm and return true if a path is found
133 174
      // from the source node to the target node.
134 175
      bool run(int cnt) {
135 176
        return cnt == 0 ? startFirst() : start();
136 177
      }
137 178

	
138 179
    private:
139 180
    
140 181
      // Execute the algorithm for the first time (the flow and potential
141 182
      // functions have to be identically zero).
142 183
      bool startFirst() {
143 184
        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
144 185
        Heap heap(heap_cross_ref);
145 186
        heap.push(_s, 0);
146 187
        _pred[_s] = INVALID;
147 188
        _proc_nodes.clear();
148 189

	
149 190
        // Process nodes
150 191
        while (!heap.empty() && heap.top() != _t) {
151 192
          Node u = heap.top(), v;
152 193
          Length d = heap.prio(), dn;
153 194
          _dist[u] = heap.prio();
154 195
          _proc_nodes.push_back(u);
155 196
          heap.pop();
156 197

	
157 198
          // Traverse outgoing arcs
158 199
          for (OutArcIt e(_graph, u); e != INVALID; ++e) {
159 200
            v = _graph.target(e);
160 201
            switch(heap.state(v)) {
161 202
              case Heap::PRE_HEAP:
162 203
                heap.push(v, d + _length[e]);
163 204
                _pred[v] = e;
164 205
                break;
165 206
              case Heap::IN_HEAP:
166 207
                dn = d + _length[e];
167 208
                if (dn < heap[v]) {
168 209
                  heap.decrease(v, dn);
169 210
                  _pred[v] = e;
170 211
                }
171 212
                break;
172 213
              case Heap::POST_HEAP:
173 214
                break;
174 215
            }
175 216
          }
176 217
        }
177 218
        if (heap.empty()) return false;
178 219

	
179 220
        // Update potentials of processed nodes
180 221
        Length t_dist = heap.prio();
181 222
        for (int i = 0; i < int(_proc_nodes.size()); ++i)
182 223
          _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
183 224
        return true;
184 225
      }
185 226

	
186 227
      // Execute the algorithm.
187 228
      bool start() {
188 229
        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
189 230
        Heap heap(heap_cross_ref);
190 231
        heap.push(_s, 0);
191 232
        _pred[_s] = INVALID;
192 233
        _proc_nodes.clear();
193 234

	
194 235
        // Process nodes
195 236
        while (!heap.empty() && heap.top() != _t) {
196 237
          Node u = heap.top(), v;
197 238
          Length d = heap.prio() + _pi[u], dn;
198 239
          _dist[u] = heap.prio();
199 240
          _proc_nodes.push_back(u);
200 241
          heap.pop();
201 242

	
202 243
          // Traverse outgoing arcs
203 244
          for (OutArcIt e(_graph, u); e != INVALID; ++e) {
204 245
            if (_flow[e] == 0) {
205 246
              v = _graph.target(e);
206 247
              switch(heap.state(v)) {
207 248
                case Heap::PRE_HEAP:
208 249
                  heap.push(v, d + _length[e] - _pi[v]);
209 250
                  _pred[v] = e;
210 251
                  break;
211 252
                case Heap::IN_HEAP:
212 253
                  dn = d + _length[e] - _pi[v];
213 254
                  if (dn < heap[v]) {
214 255
                    heap.decrease(v, dn);
215 256
                    _pred[v] = e;
216 257
                  }
217 258
                  break;
218 259
                case Heap::POST_HEAP:
219 260
                  break;
220 261
              }
221 262
            }
222 263
          }
223 264

	
224 265
          // Traverse incoming arcs
225 266
          for (InArcIt e(_graph, u); e != INVALID; ++e) {
226 267
            if (_flow[e] == 1) {
227 268
              v = _graph.source(e);
228 269
              switch(heap.state(v)) {
229 270
                case Heap::PRE_HEAP:
230 271
                  heap.push(v, d - _length[e] - _pi[v]);
231 272
                  _pred[v] = e;
232 273
                  break;
233 274
                case Heap::IN_HEAP:
234 275
                  dn = d - _length[e] - _pi[v];
235 276
                  if (dn < heap[v]) {
236 277
                    heap.decrease(v, dn);
237 278
                    _pred[v] = e;
238 279
                  }
239 280
                  break;
240 281
                case Heap::POST_HEAP:
241 282
                  break;
242 283
              }
243 284
            }
244 285
          }
245 286
        }
246 287
        if (heap.empty()) return false;
247 288

	
248 289
        // Update potentials of processed nodes
249 290
        Length t_dist = heap.prio();
250 291
        for (int i = 0; i < int(_proc_nodes.size()); ++i)
251 292
          _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
252 293
        return true;
253 294
      }
254 295

	
255 296
    }; //class ResidualDijkstra
256 297

	
298
  public:
299

	
300
    /// \name Named Template Parameters
301
    /// @{
302

	
303
    template <typename T>
304
    struct SetFlowMapTraits : public Traits {
305
      typedef T FlowMap;
306
    };
307

	
308
    /// \brief \ref named-templ-param "Named parameter" for setting
309
    /// \c FlowMap type.
310
    ///
311
    /// \ref named-templ-param "Named parameter" for setting
312
    /// \c FlowMap type.
313
    template <typename T>
314
    struct SetFlowMap
315
      : public Suurballe<GR, LEN, SetFlowMapTraits<T> > {
316
      typedef Suurballe<GR, LEN, SetFlowMapTraits<T> > Create;
317
    };
318

	
319
    template <typename T>
320
    struct SetPotentialMapTraits : public Traits {
321
      typedef T PotentialMap;
322
    };
323

	
324
    /// \brief \ref named-templ-param "Named parameter" for setting
325
    /// \c PotentialMap type.
326
    ///
327
    /// \ref named-templ-param "Named parameter" for setting
328
    /// \c PotentialMap type.
329
    template <typename T>
330
    struct SetPotentialMap
331
      : public Suurballe<GR, LEN, SetPotentialMapTraits<T> > {
332
      typedef Suurballe<GR, LEN, SetPotentialMapTraits<T> > Create;
333
    };
334

	
335
    template <typename T>
336
    struct SetPathTraits : public Traits {
337
      typedef T Path;
338
    };
339

	
340
    /// \brief \ref named-templ-param "Named parameter" for setting
341
    /// \c %Path type.
342
    ///
343
    /// \ref named-templ-param "Named parameter" for setting \c %Path type.
344
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
345
    /// and it must have an \c addBack() function.
346
    template <typename T>
347
    struct SetPath
348
      : public Suurballe<GR, LEN, SetPathTraits<T> > {
349
      typedef Suurballe<GR, LEN, SetPathTraits<T> > Create;
350
    };
351
    
352
    template <typename H, typename CR>
353
    struct SetHeapTraits : public Traits {
354
      typedef H Heap;
355
      typedef CR HeapCrossRef;
356
    };
357

	
358
    /// \brief \ref named-templ-param "Named parameter" for setting
359
    /// \c Heap and \c HeapCrossRef types.
360
    ///
361
    /// \ref named-templ-param "Named parameter" for setting \c Heap
362
    /// and \c HeapCrossRef types with automatic allocation. 
363
    /// They will be used for internal Dijkstra computations.
364
    /// The heap type must conform to the \ref lemon::concepts::Heap "Heap"
365
    /// concept and its priority type must be \c Length.
366
    template <typename H,
367
              typename CR = typename Digraph::template NodeMap<int> >
368
    struct SetHeap
369
      : public Suurballe<GR, LEN, SetHeapTraits<H, CR> > {
370
      typedef Suurballe<GR, LEN, SetHeapTraits<H, CR> > Create;
371
    };
372

	
373
    /// @}
374

	
257 375
  private:
258 376

	
259 377
    // The digraph the algorithm runs on
260 378
    const Digraph &_graph;
261 379
    // The length map
262 380
    const LengthMap &_length;
263 381

	
264 382
    // Arc map of the current flow
265 383
    FlowMap *_flow;
266 384
    bool _local_flow;
267 385
    // Node map of the current potentials
268 386
    PotentialMap *_potential;
269 387
    bool _local_potential;
270 388

	
271 389
    // The source node
272 390
    Node _s;
273 391
    // The target node
274 392
    Node _t;
275 393

	
276 394
    // Container to store the found paths
277 395
    std::vector<Path> _paths;
278 396
    int _path_num;
279 397

	
280 398
    // The pred arc map
281 399
    PredMap _pred;
282 400
    
283 401
    // Data for full init
284 402
    PotentialMap *_init_dist;
285 403
    PredMap *_init_pred;
286 404
    bool _full_init;
287 405

	
288 406
  public:
289 407

	
290 408
    /// \brief Constructor.
291 409
    ///
292 410
    /// Constructor.
293 411
    ///
294 412
    /// \param graph The digraph the algorithm runs on.
295 413
    /// \param length The length (cost) values of the arcs.
296 414
    Suurballe( const Digraph &graph,
297 415
               const LengthMap &length ) :
298 416
      _graph(graph), _length(length), _flow(0), _local_flow(false),
299 417
      _potential(0), _local_potential(false), _pred(graph),
300 418
      _init_dist(0), _init_pred(0)
301 419
    {}
302 420

	
303 421
    /// Destructor.
304 422
    ~Suurballe() {
305 423
      if (_local_flow) delete _flow;
306 424
      if (_local_potential) delete _potential;
307 425
      delete _init_dist;
308 426
      delete _init_pred;
309 427
    }
310 428

	
311 429
    /// \brief Set the flow map.
312 430
    ///
313 431
    /// This function sets the flow map.
314 432
    /// If it is not used before calling \ref run() or \ref init(),
315 433
    /// an instance will be allocated automatically. The destructor
316 434
    /// deallocates this automatically allocated map, of course.
317 435
    ///
318 436
    /// The found flow contains only 0 and 1 values, since it is the
319 437
    /// union of the found arc-disjoint paths.
320 438
    ///
321 439
    /// \return <tt>(*this)</tt>
322 440
    Suurballe& flowMap(FlowMap &map) {
323 441
      if (_local_flow) {
324 442
        delete _flow;
325 443
        _local_flow = false;
326 444
      }
327 445
      _flow = &map;
328 446
      return *this;
329 447
    }
330 448

	
331 449
    /// \brief Set the potential map.
332 450
    ///
333 451
    /// This function sets the potential map.
334 452
    /// If it is not used before calling \ref run() or \ref init(),
335 453
    /// an instance will be allocated automatically. The destructor
336 454
    /// deallocates this automatically allocated map, of course.
337 455
    ///
338 456
    /// The node potentials provide the dual solution of the underlying
339 457
    /// \ref min_cost_flow "minimum cost flow problem".
340 458
    ///
341 459
    /// \return <tt>(*this)</tt>
342 460
    Suurballe& potentialMap(PotentialMap &map) {
343 461
      if (_local_potential) {
344 462
        delete _potential;
345 463
        _local_potential = false;
346 464
      }
347 465
      _potential = &map;
348 466
      return *this;
349 467
    }
350 468

	
351 469
    /// \name Execution Control
352 470
    /// The simplest way to execute the algorithm is to call the run()
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <iostream>
20 20

	
21 21
#include <lemon/list_graph.h>
22 22
#include <lemon/lgf_reader.h>
23 23
#include <lemon/path.h>
24 24
#include <lemon/suurballe.h>
25 25
#include <lemon/concepts/digraph.h>
26
#include <lemon/concepts/heap.h>
26 27

	
27 28
#include "test_tools.h"
28 29

	
29 30
using namespace lemon;
30 31

	
31 32
char test_lgf[] =
32 33
  "@nodes\n"
33 34
  "label\n"
34 35
  "1\n"
35 36
  "2\n"
36 37
  "3\n"
37 38
  "4\n"
38 39
  "5\n"
39 40
  "6\n"
40 41
  "7\n"
41 42
  "8\n"
42 43
  "9\n"
43 44
  "10\n"
44 45
  "11\n"
45 46
  "12\n"
46 47
  "@arcs\n"
47 48
  "      length\n"
48 49
  " 1  2  70\n"
49 50
  " 1  3 150\n"
50 51
  " 1  4  80\n"
51 52
  " 2  8  80\n"
52 53
  " 3  5 140\n"
53 54
  " 4  6  60\n"
54 55
  " 4  7  80\n"
55 56
  " 4  8 110\n"
56 57
  " 5  7  60\n"
57 58
  " 5 11 120\n"
58 59
  " 6  3   0\n"
59 60
  " 6  9 140\n"
60 61
  " 6 10  90\n"
61 62
  " 7  1  30\n"
62 63
  " 8 12  60\n"
63 64
  " 9 12  50\n"
64 65
  "10 12  70\n"
65 66
  "10  2 100\n"
66 67
  "10  7  60\n"
67 68
  "11 10  20\n"
68 69
  "12 11  30\n"
69 70
  "@attributes\n"
70 71
  "source  1\n"
71 72
  "target 12\n"
72 73
  "@end\n";
73 74

	
74 75
// Check the interface of Suurballe
75 76
void checkSuurballeCompile()
76 77
{
77 78
  typedef int VType;
78 79
  typedef concepts::Digraph Digraph;
79 80

	
80 81
  typedef Digraph::Node Node;
81 82
  typedef Digraph::Arc Arc;
82 83
  typedef concepts::ReadMap<Arc, VType> LengthMap;
83 84
  
84
  typedef Suurballe<Digraph, LengthMap> SuurballeType;
85
  typedef Suurballe<Digraph, LengthMap> ST;
86
  typedef Suurballe<Digraph, LengthMap>
87
    ::SetFlowMap<ST::FlowMap>
88
    ::SetPotentialMap<ST::PotentialMap>
89
    ::SetPath<SimplePath<Digraph> >
90
    ::SetHeap<concepts::Heap<VType, Digraph::NodeMap<int> > >
91
    ::Create SuurballeType;
85 92

	
86 93
  Digraph g;
87 94
  Node n;
88 95
  Arc e;
89 96
  LengthMap len;
90 97
  SuurballeType::FlowMap flow(g);
91 98
  SuurballeType::PotentialMap pi(g);
92 99

	
93 100
  SuurballeType suurb_test(g, len);
94 101
  const SuurballeType& const_suurb_test = suurb_test;
95 102

	
96 103
  suurb_test
97 104
    .flowMap(flow)
98 105
    .potentialMap(pi);
99 106

	
100 107
  int k;
101 108
  k = suurb_test.run(n, n);
102 109
  k = suurb_test.run(n, n, k);
103 110
  suurb_test.init(n);
104 111
  suurb_test.fullInit(n);
105 112
  suurb_test.start(n);
106 113
  suurb_test.start(n, k);
107 114
  k = suurb_test.findFlow(n);
108 115
  k = suurb_test.findFlow(n, k);
109 116
  suurb_test.findPaths();
110 117
  
111 118
  int f;
112 119
  VType c;
113 120
  c = const_suurb_test.totalLength();
114 121
  f = const_suurb_test.flow(e);
115 122
  const SuurballeType::FlowMap& fm =
116 123
    const_suurb_test.flowMap();
117 124
  c = const_suurb_test.potential(n);
118 125
  const SuurballeType::PotentialMap& pm =
119 126
    const_suurb_test.potentialMap();
120 127
  k = const_suurb_test.pathNum();
121 128
  Path<Digraph> p = const_suurb_test.path(k);
122 129
  
123 130
  ignore_unused_variable_warning(fm);
124 131
  ignore_unused_variable_warning(pm);
125 132
}
126 133

	
127 134
// Check the feasibility of the flow
128 135
template <typename Digraph, typename FlowMap>
129 136
bool checkFlow( const Digraph& gr, const FlowMap& flow,
130 137
                typename Digraph::Node s, typename Digraph::Node t,
131 138
                int value )
132 139
{
133 140
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
134 141
  for (ArcIt e(gr); e != INVALID; ++e)
135 142
    if (!(flow[e] == 0 || flow[e] == 1)) return false;
136 143

	
137 144
  for (NodeIt n(gr); n != INVALID; ++n) {
138 145
    int sum = 0;
139 146
    for (OutArcIt e(gr, n); e != INVALID; ++e)
140 147
      sum += flow[e];
141 148
    for (InArcIt e(gr, n); e != INVALID; ++e)
142 149
      sum -= flow[e];
143 150
    if (n == s && sum != value) return false;
144 151
    if (n == t && sum != -value) return false;
145 152
    if (n != s && n != t && sum != 0) return false;
146 153
  }
147 154

	
148 155
  return true;
149 156
}
150 157

	
151 158
// Check the optimalitiy of the flow
152 159
template < typename Digraph, typename CostMap,
153 160
           typename FlowMap, typename PotentialMap >
154 161
bool checkOptimality( const Digraph& gr, const CostMap& cost,
155 162
                      const FlowMap& flow, const PotentialMap& pi )
156 163
{
157 164
  // Check the "Complementary Slackness" optimality condition
158 165
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
159 166
  bool opt = true;
160 167
  for (ArcIt e(gr); e != INVALID; ++e) {
161 168
    typename CostMap::Value red_cost =
162 169
      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
163 170
    opt = (flow[e] == 0 && red_cost >= 0) ||
164 171
          (flow[e] == 1 && red_cost <= 0);
165 172
    if (!opt) break;
166 173
  }
167 174
  return opt;
168 175
}
169 176

	
170 177
// Check a path
171 178
template <typename Digraph, typename Path>
172 179
bool checkPath( const Digraph& gr, const Path& path,
173 180
                typename Digraph::Node s, typename Digraph::Node t)
174 181
{
175 182
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
176 183
  Node n = s;
177 184
  for (int i = 0; i < path.length(); ++i) {
178 185
    if (gr.source(path.nth(i)) != n) return false;
179 186
    n = gr.target(path.nth(i));
180 187
  }
0 comments (0 inline)