gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Def->Set change in lemon/circulation.h
0 1 0
default
1 file changed with 12 insertions and 12 deletions:
↑ Collapse diff ↑
Ignore white space 768 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-2008
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_CIRCULATION_H
20 20
#define LEMON_CIRCULATION_H
21 21

	
22 22
#include <iostream>
23 23
#include <queue>
24 24
#include <lemon/tolerance.h>
25 25
#include <lemon/elevator.h>
26 26

	
27 27
///\ingroup max_flow
28 28
///\file
29 29
///\brief Push-prelabel algorithm for finding a feasible circulation.
30 30
///
31 31
namespace lemon {
32 32

	
33 33
  /// \brief Default traits class of Circulation class.
34 34
  ///
35 35
  /// Default traits class of Circulation class.
36 36
  /// \param _Graph Digraph type.
37 37
  /// \param _CapacityMap Type of capacity map.
38 38
  template <typename _Graph, typename _LCapMap,
39 39
            typename _UCapMap, typename _DeltaMap>
40 40
  struct CirculationDefaultTraits {
41 41

	
42 42
    /// \brief The digraph type the algorithm runs on.
43 43
    typedef _Graph Digraph;
44 44

	
45 45
    /// \brief The type of the map that stores the circulation lower
46 46
    /// bound.
47 47
    ///
48 48
    /// The type of the map that stores the circulation lower bound.
49 49
    /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
50 50
    typedef _LCapMap LCapMap;
51 51

	
52 52
    /// \brief The type of the map that stores the circulation upper
53 53
    /// bound.
54 54
    ///
55 55
    /// The type of the map that stores the circulation upper bound.
56 56
    /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
57 57
    typedef _UCapMap UCapMap;
58 58

	
59 59
    /// \brief The type of the map that stores the upper bound of
60 60
    /// node excess.
61 61
    ///
62 62
    /// The type of the map that stores the lower bound of node
63 63
    /// excess. It must meet the \ref concepts::ReadMap "ReadMap"
64 64
    /// concept.
65 65
    typedef _DeltaMap DeltaMap;
66 66

	
67 67
    /// \brief The type of the length of the arcs.
68 68
    typedef typename DeltaMap::Value Value;
69 69

	
70 70
    /// \brief The map type that stores the flow values.
71 71
    ///
72 72
    /// The map type that stores the flow values.
73 73
    /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
74 74
    typedef typename Digraph::template ArcMap<Value> FlowMap;
75 75

	
76 76
    /// \brief Instantiates a FlowMap.
77 77
    ///
78 78
    /// This function instantiates a \ref FlowMap.
79 79
    /// \param digraph The digraph, to which we would like to define
80 80
    /// the flow map.
81 81
    static FlowMap* createFlowMap(const Digraph& digraph) {
82 82
      return new FlowMap(digraph);
83 83
    }
84 84

	
85 85
    /// \brief The eleavator type used by Circulation algorithm.
86 86
    ///
87 87
    /// The elevator type used by Circulation algorithm.
88 88
    ///
89 89
    /// \sa Elevator
90 90
    /// \sa LinkedElevator
91 91
    typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
92 92

	
93 93
    /// \brief Instantiates an Elevator.
94 94
    ///
95 95
    /// This function instantiates a \ref Elevator.
96 96
    /// \param digraph The digraph, to which we would like to define
97 97
    /// the elevator.
98 98
    /// \param max_level The maximum level of the elevator.
99 99
    static Elevator* createElevator(const Digraph& digraph, int max_level) {
100 100
      return new Elevator(digraph, max_level);
101 101
    }
102 102

	
103 103
    /// \brief The tolerance used by the algorithm
104 104
    ///
105 105
    /// The tolerance used by the algorithm to handle inexact computation.
106 106
    typedef lemon::Tolerance<Value> Tolerance;
107 107

	
108 108
  };
109 109

	
110 110
  ///Push-relabel algorithm for the Network Circulation Problem.
111 111

	
112 112
  /**
113 113
     \ingroup max_flow
114 114
     This class implements a push-relabel algorithm
115 115
     or the Network Circulation Problem.
116 116
     The exact formulation of this problem is the following.
117 117
     \f[\sum_{e\in\rho(v)}x(e)-\sum_{e\in\delta(v)}x(e)\leq
118 118
     -delta(v)\quad \forall v\in V \f]
119 119
     \f[ lo(e)\leq x(e) \leq up(e) \quad \forall e\in E \f]
120 120
  */
121 121
  template<class _Graph,
122 122
           class _LCapMap=typename _Graph::template ArcMap<int>,
123 123
           class _UCapMap=_LCapMap,
124 124
           class _DeltaMap=typename _Graph::template NodeMap<
125 125
             typename _UCapMap::Value>,
126 126
           class _Traits=CirculationDefaultTraits<_Graph, _LCapMap,
127 127
                                                  _UCapMap, _DeltaMap> >
128 128
  class Circulation {
129 129

	
130 130
    typedef _Traits Traits;
131 131
    typedef typename Traits::Digraph Digraph;
132 132
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
133 133

	
134 134
    typedef typename Traits::Value Value;
135 135

	
136 136
    typedef typename Traits::LCapMap LCapMap;
137 137
    typedef typename Traits::UCapMap UCapMap;
138 138
    typedef typename Traits::DeltaMap DeltaMap;
139 139
    typedef typename Traits::FlowMap FlowMap;
140 140
    typedef typename Traits::Elevator Elevator;
141 141
    typedef typename Traits::Tolerance Tolerance;
142 142

	
143 143
    typedef typename Digraph::template NodeMap<Value> ExcessMap;
144 144

	
145 145
    const Digraph &_g;
146 146
    int _node_num;
147 147

	
148 148
    const LCapMap *_lo;
149 149
    const UCapMap *_up;
150 150
    const DeltaMap *_delta;
151 151

	
152 152
    FlowMap *_flow;
153 153
    bool _local_flow;
154 154

	
155 155
    Elevator* _level;
156 156
    bool _local_level;
157 157

	
158 158
    ExcessMap* _excess;
159 159

	
160 160
    Tolerance _tol;
161 161
    int _el;
162 162

	
163 163
  public:
164 164

	
165 165
    typedef Circulation Create;
166 166

	
167 167
    ///\name Named template parameters
168 168

	
169 169
    ///@{
170 170

	
171 171
    template <typename _FlowMap>
172
    struct DefFlowMapTraits : public Traits {
172
    struct SetFlowMapTraits : public Traits {
173 173
      typedef _FlowMap FlowMap;
174 174
      static FlowMap *createFlowMap(const Digraph&) {
175 175
        LEMON_ASSERT(false, "FlowMap is not initialized");
176 176
        return 0; // ignore warnings
177 177
      }
178 178
    };
179 179

	
180 180
    /// \brief \ref named-templ-param "Named parameter" for setting
181 181
    /// FlowMap type
182 182
    ///
183 183
    /// \ref named-templ-param "Named parameter" for setting FlowMap
184 184
    /// type
185 185
    template <typename _FlowMap>
186
    struct DefFlowMap
186
    struct SetFlowMap
187 187
      : public Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
188
                           DefFlowMapTraits<_FlowMap> > {
188
                           SetFlowMapTraits<_FlowMap> > {
189 189
      typedef Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
190
                          DefFlowMapTraits<_FlowMap> > Create;
190
                          SetFlowMapTraits<_FlowMap> > Create;
191 191
    };
192 192

	
193 193
    template <typename _Elevator>
194
    struct DefElevatorTraits : public Traits {
194
    struct SetElevatorTraits : public Traits {
195 195
      typedef _Elevator Elevator;
196 196
      static Elevator *createElevator(const Digraph&, int) {
197 197
        LEMON_ASSERT(false, "Elevator is not initialized");
198 198
        return 0; // ignore warnings
199 199
      }
200 200
    };
201 201

	
202 202
    /// \brief \ref named-templ-param "Named parameter" for setting
203 203
    /// Elevator type
204 204
    ///
205 205
    /// \ref named-templ-param "Named parameter" for setting Elevator
206 206
    /// type
207 207
    template <typename _Elevator>
208
    struct DefElevator
208
    struct SetElevator
209 209
      : public Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
210
                           DefElevatorTraits<_Elevator> > {
210
                           SetElevatorTraits<_Elevator> > {
211 211
      typedef Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
212
                          DefElevatorTraits<_Elevator> > Create;
212
                          SetElevatorTraits<_Elevator> > Create;
213 213
    };
214 214

	
215 215
    template <typename _Elevator>
216
    struct DefStandardElevatorTraits : public Traits {
216
    struct SetStandardElevatorTraits : public Traits {
217 217
      typedef _Elevator Elevator;
218 218
      static Elevator *createElevator(const Digraph& digraph, int max_level) {
219 219
        return new Elevator(digraph, max_level);
220 220
      }
221 221
    };
222 222

	
223 223
    /// \brief \ref named-templ-param "Named parameter" for setting
224 224
    /// Elevator type
225 225
    ///
226 226
    /// \ref named-templ-param "Named parameter" for setting Elevator
227 227
    /// type. The Elevator should be standard constructor interface, ie.
228 228
    /// the digraph and the maximum level should be passed to it.
229 229
    template <typename _Elevator>
230
    struct DefStandardElevator
230
    struct SetStandardElevator
231 231
      : public Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
232
                       DefStandardElevatorTraits<_Elevator> > {
232
                       SetStandardElevatorTraits<_Elevator> > {
233 233
      typedef Circulation<Digraph, LCapMap, UCapMap, DeltaMap,
234
                      DefStandardElevatorTraits<_Elevator> > Create;
234
                      SetStandardElevatorTraits<_Elevator> > Create;
235 235
    };
236 236

	
237 237
    /// @}
238 238

	
239 239
  protected:
240 240

	
241 241
    Circulation() {}
242 242

	
243 243
  public:
244 244

	
245 245
    /// The constructor of the class.
246 246

	
247 247
    /// The constructor of the class.
248 248
    /// \param g The digraph the algorithm runs on.
249 249
    /// \param lo The lower bound capacity of the arcs.
250 250
    /// \param up The upper bound capacity of the arcs.
251 251
    /// \param delta The lower bound on node excess.
252 252
    Circulation(const Digraph &g,const LCapMap &lo,
253 253
                const UCapMap &up,const DeltaMap &delta)
254 254
      : _g(g), _node_num(),
255 255
        _lo(&lo),_up(&up),_delta(&delta),_flow(0),_local_flow(false),
256 256
        _level(0), _local_level(false), _excess(0), _el() {}
257 257

	
258 258
    /// Destrcutor.
259 259
    ~Circulation() {
260 260
      destroyStructures();
261 261
    }
262 262

	
263 263
  private:
264 264

	
265 265
    void createStructures() {
266 266
      _node_num = _el = countNodes(_g);
267 267

	
268 268
      if (!_flow) {
269 269
        _flow = Traits::createFlowMap(_g);
270 270
        _local_flow = true;
271 271
      }
272 272
      if (!_level) {
273 273
        _level = Traits::createElevator(_g, _node_num);
274 274
        _local_level = true;
275 275
      }
276 276
      if (!_excess) {
277 277
        _excess = new ExcessMap(_g);
278 278
      }
279 279
    }
280 280

	
281 281
    void destroyStructures() {
282 282
      if (_local_flow) {
283 283
        delete _flow;
284 284
      }
285 285
      if (_local_level) {
286 286
        delete _level;
287 287
      }
288 288
      if (_excess) {
289 289
        delete _excess;
290 290
      }
291 291
    }
292 292

	
293 293
  public:
294 294

	
295 295
    /// Sets the lower bound capacity map.
296 296

	
297 297
    /// Sets the lower bound capacity map.
298 298
    /// \return \c (*this)
299 299
    Circulation& lowerCapMap(const LCapMap& map) {
300 300
      _lo = &map;
301 301
      return *this;
302 302
    }
303 303

	
304 304
    /// Sets the upper bound capacity map.
305 305

	
306 306
    /// Sets the upper bound capacity map.
307 307
    /// \return \c (*this)
308 308
    Circulation& upperCapMap(const LCapMap& map) {
309 309
      _up = &map;
310 310
      return *this;
311 311
    }
312 312

	
313 313
    /// Sets the lower bound map on excess.
314 314

	
315 315
    /// Sets the lower bound map on excess.
316 316
    /// \return \c (*this)
317 317
    Circulation& deltaMap(const DeltaMap& map) {
318 318
      _delta = &map;
319 319
      return *this;
320 320
    }
321 321

	
322 322
    /// Sets the flow map.
323 323

	
324 324
    /// Sets the flow map.
325 325
    /// \return \c (*this)
326 326
    Circulation& flowMap(FlowMap& map) {
327 327
      if (_local_flow) {
328 328
        delete _flow;
329 329
        _local_flow = false;
330 330
      }
331 331
      _flow = &map;
332 332
      return *this;
333 333
    }
334 334

	
335 335
    /// Returns the flow map.
336 336

	
337 337
    /// \return The flow map.
338 338
    ///
339 339
    const FlowMap& flowMap() {
340 340
      return *_flow;
341 341
    }
342 342

	
343 343
    /// Sets the elevator.
344 344

	
345 345
    /// Sets the elevator.
346 346
    /// \return \c (*this)
347 347
    Circulation& elevator(Elevator& elevator) {
348 348
      if (_local_level) {
349 349
        delete _level;
350 350
        _local_level = false;
351 351
      }
352 352
      _level = &elevator;
353 353
      return *this;
354 354
    }
355 355

	
356 356
    /// Returns the elevator.
357 357

	
358 358
    /// \return The elevator.
359 359
    ///
360 360
    const Elevator& elevator() {
361 361
      return *_level;
362 362
    }
363 363

	
364 364
    /// Sets the tolerance used by algorithm.
365 365

	
366 366
    /// Sets the tolerance used by algorithm.
367 367
    ///
368 368
    Circulation& tolerance(const Tolerance& tolerance) const {
369 369
      _tol = tolerance;
370 370
      return *this;
371 371
    }
372 372

	
373 373
    /// Returns the tolerance used by algorithm.
374 374

	
375 375
    /// Returns the tolerance used by algorithm.
376 376
    ///
377 377
    const Tolerance& tolerance() const {
378 378
      return tolerance;
379 379
    }
380 380

	
381 381
    /// \name Execution control
382 382
    /// The simplest way to execute the algorithm is to use one of the
383 383
    /// member functions called \c run().
384 384
    /// \n
385 385
    /// If you need more control on initial solution or execution then
386 386
    /// you have to call one \ref init() function and then the start()
387 387
    /// function.
388 388

	
389 389
    ///@{
390 390

	
391 391
    /// Initializes the internal data structures.
392 392

	
393 393
    /// Initializes the internal data structures. This function sets
394 394
    /// all flow values to the lower bound.
395 395
    /// \return This function returns false if the initialization
396 396
    /// process found a barrier.
397 397
    void init()
398 398
    {
399 399
      createStructures();
400 400

	
401 401
      for(NodeIt n(_g);n!=INVALID;++n) {
402 402
        _excess->set(n, (*_delta)[n]);
403 403
      }
404 404

	
405 405
      for (ArcIt e(_g);e!=INVALID;++e) {
406 406
        _flow->set(e, (*_lo)[e]);
407 407
        _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_flow)[e]);
408 408
        _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_flow)[e]);
409 409
      }
410 410

	
411 411
      // global relabeling tested, but in general case it provides
412 412
      // worse performance for random digraphs
413 413
      _level->initStart();
414 414
      for(NodeIt n(_g);n!=INVALID;++n)
415 415
        _level->initAddItem(n);
416 416
      _level->initFinish();
417 417
      for(NodeIt n(_g);n!=INVALID;++n)
418 418
        if(_tol.positive((*_excess)[n]))
419 419
          _level->activate(n);
420 420
    }
421 421

	
422 422
    /// Initializes the internal data structures.
423 423

	
424 424
    /// Initializes the internal data structures. This functions uses
425 425
    /// greedy approach to construct the initial solution.
426 426
    void greedyInit()
427 427
    {
428 428
      createStructures();
429 429

	
430 430
      for(NodeIt n(_g);n!=INVALID;++n) {
431 431
        _excess->set(n, (*_delta)[n]);
432 432
      }
433 433

	
434 434
      for (ArcIt e(_g);e!=INVALID;++e) {
435 435
        if (!_tol.positive((*_excess)[_g.target(e)] + (*_up)[e])) {
436 436
          _flow->set(e, (*_up)[e]);
437 437
          _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_up)[e]);
438 438
          _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_up)[e]);
439 439
        } else if (_tol.positive((*_excess)[_g.target(e)] + (*_lo)[e])) {
440 440
          _flow->set(e, (*_lo)[e]);
441 441
          _excess->set(_g.target(e), (*_excess)[_g.target(e)] + (*_lo)[e]);
442 442
          _excess->set(_g.source(e), (*_excess)[_g.source(e)] - (*_lo)[e]);
443 443
        } else {
444 444
          Value fc = -(*_excess)[_g.target(e)];
445 445
          _flow->set(e, fc);
446 446
          _excess->set(_g.target(e), 0);
447 447
          _excess->set(_g.source(e), (*_excess)[_g.source(e)] - fc);
448 448
        }
449 449
      }
450 450

	
451 451
      _level->initStart();
452 452
      for(NodeIt n(_g);n!=INVALID;++n)
453 453
        _level->initAddItem(n);
454 454
      _level->initFinish();
455 455
      for(NodeIt n(_g);n!=INVALID;++n)
456 456
        if(_tol.positive((*_excess)[n]))
457 457
          _level->activate(n);
458 458
    }
459 459

	
460 460
    ///Starts the algorithm
461 461

	
462 462
    ///This function starts the algorithm.
463 463
    ///\return This function returns true if it found a feasible circulation.
464 464
    ///
465 465
    ///\sa barrier()
466 466
    bool start()
467 467
    {
468 468

	
469 469
      Node act;
470 470
      Node bact=INVALID;
471 471
      Node last_activated=INVALID;
472 472
      while((act=_level->highestActive())!=INVALID) {
473 473
        int actlevel=(*_level)[act];
474 474
        int mlevel=_node_num;
475 475
        Value exc=(*_excess)[act];
476 476

	
477 477
        for(OutArcIt e(_g,act);e!=INVALID; ++e) {
478 478
          Node v = _g.target(e);
479 479
          Value fc=(*_up)[e]-(*_flow)[e];
480 480
          if(!_tol.positive(fc)) continue;
481 481
          if((*_level)[v]<actlevel) {
482 482
            if(!_tol.less(fc, exc)) {
483 483
              _flow->set(e, (*_flow)[e] + exc);
484 484
              _excess->set(v, (*_excess)[v] + exc);
485 485
              if(!_level->active(v) && _tol.positive((*_excess)[v]))
486 486
                _level->activate(v);
487 487
              _excess->set(act,0);
488 488
              _level->deactivate(act);
489 489
              goto next_l;
490 490
            }
491 491
            else {
492 492
              _flow->set(e, (*_up)[e]);
493 493
              _excess->set(v, (*_excess)[v] + fc);
494 494
              if(!_level->active(v) && _tol.positive((*_excess)[v]))
495 495
                _level->activate(v);
496 496
              exc-=fc;
497 497
            }
498 498
          }
499 499
          else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
500 500
        }
501 501
        for(InArcIt e(_g,act);e!=INVALID; ++e) {
502 502
          Node v = _g.source(e);
503 503
          Value fc=(*_flow)[e]-(*_lo)[e];
504 504
          if(!_tol.positive(fc)) continue;
505 505
          if((*_level)[v]<actlevel) {
506 506
            if(!_tol.less(fc, exc)) {
507 507
              _flow->set(e, (*_flow)[e] - exc);
508 508
              _excess->set(v, (*_excess)[v] + exc);
509 509
              if(!_level->active(v) && _tol.positive((*_excess)[v]))
510 510
                _level->activate(v);
511 511
              _excess->set(act,0);
512 512
              _level->deactivate(act);
513 513
              goto next_l;
514 514
            }
515 515
            else {
516 516
              _flow->set(e, (*_lo)[e]);
517 517
              _excess->set(v, (*_excess)[v] + fc);
518 518
              if(!_level->active(v) && _tol.positive((*_excess)[v]))
519 519
                _level->activate(v);
520 520
              exc-=fc;
521 521
            }
522 522
          }
523 523
          else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
524 524
        }
525 525

	
526 526
        _excess->set(act, exc);
527 527
        if(!_tol.positive(exc)) _level->deactivate(act);
528 528
        else if(mlevel==_node_num) {
529 529
          _level->liftHighestActiveToTop();
530 530
          _el = _node_num;
531 531
          return false;
532 532
        }
533 533
        else {
534 534
          _level->liftHighestActive(mlevel+1);
535 535
          if(_level->onLevel(actlevel)==0) {
536 536
            _el = actlevel;
537 537
            return false;
538 538
          }
539 539
        }
540 540
      next_l:
541 541
        ;
542 542
      }
543 543
      return true;
544 544
    }
545 545

	
546 546
    /// Runs the circulation algorithm.
547 547

	
548 548
    /// Runs the circulation algorithm.
549 549
    /// \note fc.run() is just a shortcut of the following code.
550 550
    /// \code
551 551
    ///   fc.greedyInit();
552 552
    ///   return fc.start();
553 553
    /// \endcode
554 554
    bool run() {
555 555
      greedyInit();
556 556
      return start();
557 557
    }
558 558

	
559 559
    /// @}
560 560

	
561 561
    /// \name Query Functions
562 562
    /// The result of the %Circulation algorithm can be obtained using
563 563
    /// these functions.
564 564
    /// \n
565 565
    /// Before the use of these functions,
566 566
    /// either run() or start() must be called.
567 567

	
568 568
    ///@{
569 569

	
570 570
    /**
571 571
       \brief Returns a barrier
572 572
       
573 573
       Barrier is a set \e B of nodes for which
574 574
       \f[ \sum_{v\in B}-delta(v)<
575 575
       \sum_{e\in\rho(B)}lo(e)-\sum_{e\in\delta(B)}up(e) \f]
576 576
       holds. The existence of a set with this property prooves that a feasible
577 577
       flow cannot exists.
578 578
       \sa checkBarrier()
579 579
       \sa run()
580 580
    */
581 581
    template<class GT>
582 582
    void barrierMap(GT &bar)
583 583
    {
584 584
      for(NodeIt n(_g);n!=INVALID;++n)
585 585
        bar.set(n, (*_level)[n] >= _el);
586 586
    }
587 587

	
588 588
    ///Returns true if the node is in the barrier
589 589

	
590 590
    ///Returns true if the node is in the barrier
591 591
    ///\sa barrierMap()
592 592
    bool barrier(const Node& node)
593 593
    {
594 594
      return (*_level)[node] >= _el;
595 595
    }
596 596

	
597 597
    /// \brief Returns the flow on the arc.
598 598
    ///
599 599
    /// Sets the \c flowMap to the flow on the arcs. This method can
600 600
    /// be called after the second phase of algorithm.
601 601
    Value flow(const Arc& arc) const {
602 602
      return (*_flow)[arc];
603 603
    }
604 604

	
605 605
    /// @}
606 606

	
607 607
    /// \name Checker Functions
608 608
    /// The feasibility  of the results can be checked using
609 609
    /// these functions.
610 610
    /// \n
611 611
    /// Before the use of these functions,
612 612
    /// either run() or start() must be called.
613 613

	
614 614
    ///@{
615 615

	
616 616
    ///Check if the  \c flow is a feasible circulation
617 617
    bool checkFlow() {
618 618
      for(ArcIt e(_g);e!=INVALID;++e)
0 comments (0 inline)