gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Modify the interface of Suurballe (#266, #181) - Move the parameters s and t from the constructor to the run() function. It makes the interface capable for multiple run(s,t,k) calls (possible improvement in the future) and it is more similar to Dijkstra. - Simliarly init() and findFlow(k) were replaced by init(s) and findFlow(t,k). The separation of parameters s and t is for the future plans of supporting multiple targets with one source node. For more information see #181. - LEMON_ASSERT for the Length type (check if it is integer). - Doc improvements. - Rearrange query functions. - Extend test file.
0 3 0
default
3 files changed with 222 insertions and 149 deletions:
↑ Collapse diff ↑
Ignore white space 12 line context
... ...
@@ -22,12 +22,13 @@
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
#include <limits>
28 29
#include <lemon/bin_heap.h>
29 30
#include <lemon/path.h>
30 31
#include <lemon/list_graph.h>
31 32
#include <lemon/maps.h>
32 33

	
33 34
namespace lemon {
... ...
@@ -39,28 +40,32 @@
39 40
  /// having minimum total length.
40 41
  ///
41 42
  /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
42 43
  /// finding arc-disjoint paths having minimum total length (cost)
43 44
  /// from a given source node to a given target node in a digraph.
44 45
  ///
45
  /// In fact, this implementation is the specialization of the
46
  /// \ref CapacityScaling "successive shortest path" algorithm.
46
  /// Note that this problem is a special case of the \ref min_cost_flow
47
  /// "minimum cost flow problem". This implementation is actually an
48
  /// efficient specialized version of the \ref CapacityScaling
49
  /// "Successive Shortest Path" algorithm directly for this problem.
50
  /// Therefore this class provides query functions for flow values and
51
  /// node potentials (the dual solution) just like the minimum cost flow
52
  /// algorithms.
47 53
  ///
48 54
  /// \tparam GR The digraph type the algorithm runs on.
49
  /// The default value is \c ListDigraph.
50
  /// \tparam LEN The type of the length (cost) map.
51
  /// The default value is <tt>Digraph::ArcMap<int></tt>.
55
  /// \tparam LEN The type of the length map.
56
  /// The default value is <tt>GR::ArcMap<int></tt>.
52 57
  ///
53 58
  /// \warning Length values should be \e non-negative \e integers.
54 59
  ///
55 60
  /// \note For finding node-disjoint paths this algorithm can be used
56
  /// with \ref SplitNodes.
61
  /// along with the \ref SplitNodes adaptor.
57 62
#ifdef DOXYGEN
58 63
  template <typename GR, typename LEN>
59 64
#else
60
  template < typename GR = ListDigraph,
65
  template < typename GR,
61 66
             typename LEN = typename GR::template ArcMap<int> >
62 67
#endif
63 68
  class Suurballe
64 69
  {
65 70
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
66 71

	
... ...
@@ -72,29 +77,34 @@
72 77
    /// The type of the digraph the algorithm runs on.
73 78
    typedef GR Digraph;
74 79
    /// The type of the length map.
75 80
    typedef LEN LengthMap;
76 81
    /// The type of the lengths.
77 82
    typedef typename LengthMap::Value Length;
83
#ifdef DOXYGEN
84
    /// The type of the flow map.
85
    typedef GR::ArcMap<int> FlowMap;
86
    /// The type of the potential map.
87
    typedef GR::NodeMap<Length> PotentialMap;
88
#else
78 89
    /// The type of the flow map.
79 90
    typedef typename Digraph::template ArcMap<int> FlowMap;
80 91
    /// The type of the potential map.
81 92
    typedef typename Digraph::template NodeMap<Length> PotentialMap;
93
#endif
94

	
82 95
    /// The type of the path structures.
83
    typedef SimplePath<Digraph> Path;
96
    typedef SimplePath<GR> Path;
84 97

	
85 98
  private:
86 99

	
87
    /// \brief Special implementation of the Dijkstra algorithm
88
    /// for finding shortest paths in the residual network.
89
    ///
90
    /// \ref ResidualDijkstra is a special implementation of the
91
    /// \ref Dijkstra algorithm for finding shortest paths in the
92
    /// residual network of the digraph with respect to the reduced arc
93
    /// lengths and modifying the node potentials according to the
94
    /// distance of the nodes.
100
    // ResidualDijkstra is a special implementation of the
101
    // Dijkstra algorithm for finding shortest paths in the
102
    // residual network with respect to the reduced arc lengths
103
    // and modifying the node potentials according to the
104
    // distance of the nodes.
95 105
    class ResidualDijkstra
96 106
    {
97 107
      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
98 108
      typedef BinHeap<Length, HeapCrossRef> Heap;
99 109

	
100 110
    private:
... ...
@@ -117,20 +127,20 @@
117 127
      Node _s;
118 128
      Node _t;
119 129

	
120 130
    public:
121 131

	
122 132
      /// Constructor.
123
      ResidualDijkstra( const Digraph &digraph,
133
      ResidualDijkstra( const Digraph &graph,
124 134
                        const FlowMap &flow,
125 135
                        const LengthMap &length,
126 136
                        PotentialMap &potential,
127 137
                        PredMap &pred,
128 138
                        Node s, Node t ) :
129
        _graph(digraph), _flow(flow), _length(length), _potential(potential),
130
        _dist(digraph), _pred(pred), _s(s), _t(t) {}
139
        _graph(graph), _flow(flow), _length(length), _potential(potential),
140
        _dist(graph), _pred(pred), _s(s), _t(t) {}
131 141

	
132 142
      /// \brief Run the algorithm. It returns \c true if a path is found
133 143
      /// from the source node to the target node.
134 144
      bool run() {
135 145
        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
136 146
        Heap heap(heap_cross_ref);
... ...
@@ -233,36 +243,39 @@
233 243
  public:
234 244

	
235 245
    /// \brief Constructor.
236 246
    ///
237 247
    /// Constructor.
238 248
    ///
239
    /// \param digraph The digraph the algorithm runs on.
249
    /// \param graph The digraph the algorithm runs on.
240 250
    /// \param length The length (cost) values of the arcs.
241
    /// \param s The source node.
242
    /// \param t The target node.
243
    Suurballe( const Digraph &digraph,
244
               const LengthMap &length,
245
               Node s, Node t ) :
246
      _graph(digraph), _length(length), _flow(0), _local_flow(false),
247
      _potential(0), _local_potential(false), _source(s), _target(t),
248
      _pred(digraph) {}
251
    Suurballe( const Digraph &graph,
252
               const LengthMap &length ) :
253
      _graph(graph), _length(length), _flow(0), _local_flow(false),
254
      _potential(0), _local_potential(false), _pred(graph)
255
    {
256
      LEMON_ASSERT(std::numeric_limits<Length>::is_integer,
257
        "The length type of Suurballe must be integer");
258
    }
249 259

	
250 260
    /// Destructor.
251 261
    ~Suurballe() {
252 262
      if (_local_flow) delete _flow;
253 263
      if (_local_potential) delete _potential;
254 264
      delete _dijkstra;
255 265
    }
256 266

	
257 267
    /// \brief Set the flow map.
258 268
    ///
259 269
    /// This function sets the flow map.
270
    /// If it is not used before calling \ref run() or \ref init(),
271
    /// an instance will be allocated automatically. The destructor
272
    /// deallocates this automatically allocated map, of course.
260 273
    ///
261
    /// The found flow contains only 0 and 1 values. It is the union of
262
    /// the found arc-disjoint paths.
274
    /// The found flow contains only 0 and 1 values, since it is the
275
    /// union of the found arc-disjoint paths.
263 276
    ///
264 277
    /// \return <tt>(*this)</tt>
265 278
    Suurballe& flowMap(FlowMap &map) {
266 279
      if (_local_flow) {
267 280
        delete _flow;
268 281
        _local_flow = false;
... ...
@@ -271,15 +284,18 @@
271 284
      return *this;
272 285
    }
273 286

	
274 287
    /// \brief Set the potential map.
275 288
    ///
276 289
    /// This function sets the potential map.
290
    /// If it is not used before calling \ref run() or \ref init(),
291
    /// an instance will be allocated automatically. The destructor
292
    /// deallocates this automatically allocated map, of course.
277 293
    ///
278
    /// The potentials provide the dual solution of the underlying
279
    /// minimum cost flow problem.
294
    /// The node potentials provide the dual solution of the underlying
295
    /// \ref min_cost_flow "minimum cost flow problem".
280 296
    ///
281 297
    /// \return <tt>(*this)</tt>
282 298
    Suurballe& potentialMap(PotentialMap &map) {
283 299
      if (_local_potential) {
284 300
        delete _potential;
285 301
        _local_potential = false;
... ...
@@ -298,66 +314,75 @@
298 314
    /// @{
299 315

	
300 316
    /// \brief Run the algorithm.
301 317
    ///
302 318
    /// This function runs the algorithm.
303 319
    ///
320
    /// \param s The source node.
321
    /// \param t The target node.
304 322
    /// \param k The number of paths to be found.
305 323
    ///
306 324
    /// \return \c k if there are at least \c k arc-disjoint paths from
307 325
    /// \c s to \c t in the digraph. Otherwise it returns the number of
308 326
    /// arc-disjoint paths found.
309 327
    ///
310
    /// \note Apart from the return value, <tt>s.run(k)</tt> is just a
311
    /// shortcut of the following code.
328
    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
329
    /// just a shortcut of the following code.
312 330
    /// \code
313
    ///   s.init();
314
    ///   s.findFlow(k);
331
    ///   s.init(s);
332
    ///   s.findFlow(t, k);
315 333
    ///   s.findPaths();
316 334
    /// \endcode
317
    int run(int k = 2) {
318
      init();
319
      findFlow(k);
335
    int run(const Node& s, const Node& t, int k = 2) {
336
      init(s);
337
      findFlow(t, k);
320 338
      findPaths();
321 339
      return _path_num;
322 340
    }
323 341

	
324 342
    /// \brief Initialize the algorithm.
325 343
    ///
326 344
    /// This function initializes the algorithm.
327
    void init() {
345
    ///
346
    /// \param s The source node.
347
    void init(const Node& s) {
348
      _source = s;
349

	
328 350
      // Initialize maps
329 351
      if (!_flow) {
330 352
        _flow = new FlowMap(_graph);
331 353
        _local_flow = true;
332 354
      }
333 355
      if (!_potential) {
334 356
        _potential = new PotentialMap(_graph);
335 357
        _local_potential = true;
336 358
      }
337 359
      for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
338 360
      for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
339

	
340
      _dijkstra = new ResidualDijkstra( _graph, *_flow, _length,
341
                                        *_potential, _pred,
342
                                        _source, _target );
343 361
    }
344 362

	
345
    /// \brief Execute the successive shortest path algorithm to find
346
    /// an optimal flow.
363
    /// \brief Execute the algorithm to find an optimal flow.
347 364
    ///
348 365
    /// This function executes the successive shortest path algorithm to
349
    /// find a minimum cost flow, which is the union of \c k or less
366
    /// find a minimum cost flow, which is the union of \c k (or less)
350 367
    /// arc-disjoint paths.
351 368
    ///
369
    /// \param t The target node.
370
    /// \param k The number of paths to be found.
371
    ///
352 372
    /// \return \c k if there are at least \c k arc-disjoint paths from
353
    /// \c s to \c t in the digraph. Otherwise it returns the number of
354
    /// arc-disjoint paths found.
373
    /// the source node to the given node \c t in the digraph.
374
    /// Otherwise it returns the number of arc-disjoint paths found.
355 375
    ///
356 376
    /// \pre \ref init() must be called before using this function.
357
    int findFlow(int k = 2) {
377
    int findFlow(const Node& t, int k = 2) {
378
      _target = t;
379
      _dijkstra =
380
        new ResidualDijkstra( _graph, *_flow, _length, *_potential, _pred,
381
                              _source, _target );
382

	
358 383
      // Find shortest paths
359 384
      _path_num = 0;
360 385
      while (_path_num < k) {
361 386
        // Run Dijkstra
362 387
        if (!_dijkstra->run()) break;
363 388
        ++_path_num;
... ...
@@ -377,19 +402,18 @@
377 402
      }
378 403
      return _path_num;
379 404
    }
380 405

	
381 406
    /// \brief Compute the paths from the flow.
382 407
    ///
383
    /// This function computes the paths from the flow.
408
    /// This function computes the paths from the found minimum cost flow,
409
    /// which is the union of some arc-disjoint paths.
384 410
    ///
385 411
    /// \pre \ref init() and \ref findFlow() must be called before using
386 412
    /// this function.
387 413
    void findPaths() {
388
      // Create the residual flow map (the union of the paths not found
389
      // so far)
390 414
      FlowMap res_flow(_graph);
391 415
      for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
392 416

	
393 417
      paths.clear();
394 418
      paths.resize(_path_num);
395 419
      for (int i = 0; i < _path_num; ++i) {
... ...
@@ -410,71 +434,74 @@
410 434
    /// The results of the algorithm can be obtained using these
411 435
    /// functions.
412 436
    /// \n The algorithm should be executed before using them.
413 437

	
414 438
    /// @{
415 439

	
416
    /// \brief Return a const reference to the arc map storing the
440
    /// \brief Return the total length of the found paths.
441
    ///
442
    /// This function returns the total length of the found paths, i.e.
443
    /// the total cost of the found flow.
444
    /// The complexity of the function is O(e).
445
    ///
446
    /// \pre \ref run() or \ref findFlow() must be called before using
447
    /// this function.
448
    Length totalLength() const {
449
      Length c = 0;
450
      for (ArcIt e(_graph); e != INVALID; ++e)
451
        c += (*_flow)[e] * _length[e];
452
      return c;
453
    }
454

	
455
    /// \brief Return the flow value on the given arc.
456
    ///
457
    /// This function returns the flow value on the given arc.
458
    /// It is \c 1 if the arc is involved in one of the found arc-disjoint
459
    /// paths, otherwise it is \c 0.
460
    ///
461
    /// \pre \ref run() or \ref findFlow() must be called before using
462
    /// this function.
463
    int flow(const Arc& arc) const {
464
      return (*_flow)[arc];
465
    }
466

	
467
    /// \brief Return a const reference to an arc map storing the
417 468
    /// found flow.
418 469
    ///
419
    /// This function returns a const reference to the arc map storing
470
    /// This function returns a const reference to an arc map storing
420 471
    /// the flow that is the union of the found arc-disjoint paths.
421 472
    ///
422 473
    /// \pre \ref run() or \ref findFlow() must be called before using
423 474
    /// this function.
424 475
    const FlowMap& flowMap() const {
425 476
      return *_flow;
426 477
    }
427 478

	
428
    /// \brief Return a const reference to the node map storing the
429
    /// found potentials (the dual solution).
430
    ///
431
    /// This function returns a const reference to the node map storing
432
    /// the found potentials that provide the dual solution of the
433
    /// underlying minimum cost flow problem.
434
    ///
435
    /// \pre \ref run() or \ref findFlow() must be called before using
436
    /// this function.
437
    const PotentialMap& potentialMap() const {
438
      return *_potential;
439
    }
440

	
441
    /// \brief Return the flow on the given arc.
442
    ///
443
    /// This function returns the flow on the given arc.
444
    /// It is \c 1 if the arc is involved in one of the found paths,
445
    /// otherwise it is \c 0.
446
    ///
447
    /// \pre \ref run() or \ref findFlow() must be called before using
448
    /// this function.
449
    int flow(const Arc& arc) const {
450
      return (*_flow)[arc];
451
    }
452

	
453 479
    /// \brief Return the potential of the given node.
454 480
    ///
455 481
    /// This function returns the potential of the given node.
482
    /// The node potentials provide the dual solution of the
483
    /// underlying \ref min_cost_flow "minimum cost flow problem".
456 484
    ///
457 485
    /// \pre \ref run() or \ref findFlow() must be called before using
458 486
    /// this function.
459 487
    Length potential(const Node& node) const {
460 488
      return (*_potential)[node];
461 489
    }
462 490

	
463
    /// \brief Return the total length (cost) of the found paths (flow).
491
    /// \brief Return a const reference to a node map storing the
492
    /// found potentials (the dual solution).
464 493
    ///
465
    /// This function returns the total length (cost) of the found paths
466
    /// (flow). The complexity of the function is O(e).
494
    /// This function returns a const reference to a node map storing
495
    /// the found potentials that provide the dual solution of the
496
    /// underlying \ref min_cost_flow "minimum cost flow problem".
467 497
    ///
468 498
    /// \pre \ref run() or \ref findFlow() must be called before using
469 499
    /// this function.
470
    Length totalLength() const {
471
      Length c = 0;
472
      for (ArcIt e(_graph); e != INVALID; ++e)
473
        c += (*_flow)[e] * _length[e];
474
      return c;
500
    const PotentialMap& potentialMap() const {
501
      return *_potential;
475 502
    }
476 503

	
477 504
    /// \brief Return the number of the found paths.
478 505
    ///
479 506
    /// This function returns the number of the found paths.
480 507
    ///
... ...
@@ -485,13 +512,13 @@
485 512
    }
486 513

	
487 514
    /// \brief Return a const reference to the specified path.
488 515
    ///
489 516
    /// This function returns a const reference to the specified path.
490 517
    ///
491
    /// \param i The function returns the \c i-th path.
518
    /// \param i The function returns the <tt>i</tt>-th path.
492 519
    /// \c i must be between \c 0 and <tt>%pathNum()-1</tt>.
493 520
    ///
494 521
    /// \pre \ref run() or \ref findPaths() must be called before using
495 522
    /// this function.
496 523
    Path path(int i) const {
497 524
      return paths[i];
Ignore white space 6 line context
... ...
@@ -19,60 +19,111 @@
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
#include <lemon/concepts/digraph.h>
25 26

	
26 27
#include "test_tools.h"
27 28

	
28 29
using namespace lemon;
29 30

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

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

	
80
  typedef Digraph::Node Node;
81
  typedef Digraph::Arc Arc;
82
  typedef concepts::ReadMap<Arc, VType> LengthMap;
83
  
84
  typedef Suurballe<Digraph, LengthMap> SuurballeType;
85

	
86
  Digraph g;
87
  Node n;
88
  Arc e;
89
  LengthMap len;
90
  SuurballeType::FlowMap flow(g);
91
  SuurballeType::PotentialMap pi(g);
92

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

	
96
  suurb_test
97
    .flowMap(flow)
98
    .potentialMap(pi);
99

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

	
73 124
// Check the feasibility of the flow
74 125
template <typename Digraph, typename FlowMap>
75 126
bool checkFlow( const Digraph& gr, const FlowMap& flow,
76 127
                typename Digraph::Node s, typename Digraph::Node t,
77 128
                int value )
78 129
{
... ...
@@ -115,13 +166,12 @@
115 166

	
116 167
// Check a path
117 168
template <typename Digraph, typename Path>
118 169
bool checkPath( const Digraph& gr, const Path& path,
119 170
                typename Digraph::Node s, typename Digraph::Node t)
120 171
{
121
  // Check the "Complementary Slackness" optimality condition
122 172
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
123 173
  Node n = s;
124 174
  for (int i = 0; i < path.length(); ++i) {
125 175
    if (gr.source(path.nth(i)) != n) return false;
126 176
    n = gr.target(path.nth(i));
127 177
  }
... ...
@@ -133,62 +183,59 @@
133 183
{
134 184
  DIGRAPH_TYPEDEFS(ListDigraph);
135 185

	
136 186
  // Read the test digraph
137 187
  ListDigraph digraph;
138 188
  ListDigraph::ArcMap<int> length(digraph);
139
  Node source, target;
189
  Node s, t;
140 190

	
141 191
  std::istringstream input(test_lgf);
142 192
  DigraphReader<ListDigraph>(digraph, input).
143
    arcMap("cost", length).
144
    node("source", source).
145
    node("target", target).
193
    arcMap("length", length).
194
    node("source", s).
195
    node("target", t).
146 196
    run();
147 197

	
148 198
  // Find 2 paths
149 199
  {
150
    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
151
    check(suurballe.run(2) == 2, "Wrong number of paths");
152
    check(checkFlow(digraph, suurballe.flowMap(), source, target, 2),
200
    Suurballe<ListDigraph> suurballe(digraph, length);
201
    check(suurballe.run(s, t) == 2, "Wrong number of paths");
202
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
153 203
          "The flow is not feasible");
154 204
    check(suurballe.totalLength() == 510, "The flow is not optimal");
155 205
    check(checkOptimality(digraph, length, suurballe.flowMap(),
156 206
                          suurballe.potentialMap()),
157 207
          "Wrong potentials");
158 208
    for (int i = 0; i < suurballe.pathNum(); ++i)
159
      check(checkPath(digraph, suurballe.path(i), source, target),
160
            "Wrong path");
209
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
161 210
  }
162 211

	
163 212
  // Find 3 paths
164 213
  {
165
    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
166
    check(suurballe.run(3) == 3, "Wrong number of paths");
167
    check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
214
    Suurballe<ListDigraph> suurballe(digraph, length);
215
    check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
216
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
168 217
          "The flow is not feasible");
169 218
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
170 219
    check(checkOptimality(digraph, length, suurballe.flowMap(),
171 220
                          suurballe.potentialMap()),
172 221
          "Wrong potentials");
173 222
    for (int i = 0; i < suurballe.pathNum(); ++i)
174
      check(checkPath(digraph, suurballe.path(i), source, target),
175
            "Wrong path");
223
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
176 224
  }
177 225

	
178 226
  // Find 5 paths (only 3 can be found)
179 227
  {
180
    Suurballe<ListDigraph> suurballe(digraph, length, source, target);
181
    check(suurballe.run(5) == 3, "Wrong number of paths");
182
    check(checkFlow(digraph, suurballe.flowMap(), source, target, 3),
228
    Suurballe<ListDigraph> suurballe(digraph, length);
229
    check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
230
    check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
183 231
          "The flow is not feasible");
184 232
    check(suurballe.totalLength() == 1040, "The flow is not optimal");
185 233
    check(checkOptimality(digraph, length, suurballe.flowMap(),
186 234
                          suurballe.potentialMap()),
187 235
          "Wrong potentials");
188 236
    for (int i = 0; i < suurballe.pathNum(); ++i)
189
      check(checkPath(digraph, suurballe.path(i), source, target),
190
            "Wrong path");
237
      check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
191 238
  }
192 239

	
193 240
  return 0;
194 241
}
Ignore white space 6 line context
... ...
@@ -477,14 +477,14 @@
477 477
      ei!=arcs.rend();++ei)
478 478
    {
479 479
      Node a=g.u(*ei);
480 480
      Node b=g.v(*ei);
481 481
      g.erase(*ei);
482 482
      ConstMap<Arc,int> cegy(1);
483
      Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy,a,b);
484
      int k=sur.run(2);
483
      Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
484
      int k=sur.run(a,b,2);
485 485
      if(k<2 || sur.totalLength()>d)
486 486
        g.addEdge(a,b);
487 487
      else cnt++;
488 488
//       else std::cout << "Remove arc " << g.id(a) << "-" << g.id(b) << '\n';
489 489
    }
490 490
}
... ...
@@ -508,15 +508,14 @@
508 508
      Line li(pi->a,pi->b);
509 509
      EdgeIt e(g);
510 510
      for(;e!=INVALID && !cross(e,li);++e) ;
511 511
      Edge ne;
512 512
      if(e==INVALID) {
513 513
        ConstMap<Arc,int> cegy(1);
514
        Suurballe<ListGraph,ConstMap<Arc,int> >
515
          sur(g,cegy,pi->a,pi->b);
516
        int k=sur.run(2);
514
        Suurballe<ListGraph,ConstMap<Arc,int> > sur(g,cegy);
515
        int k=sur.run(pi->a,pi->b,2);
517 516
        if(k<2 || sur.totalLength()>d)
518 517
          {
519 518
            ne=g.addEdge(pi->a,pi->b);
520 519
            arcs.push_back(ne);
521 520
            cnt++;
522 521
          }
0 comments (0 inline)