gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add a fullInit() function to Suurballe (#181, #323) to provide faster handling of multiple targets. A start() function is also added, just for the sake of convenience.
0 2 0
default
2 files changed with 104 insertions and 15 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -20,24 +20,25 @@
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
#include <lemon/dijkstra.h>
32 33
#include <lemon/maps.h>
33 34

	
34 35
namespace lemon {
35 36

	
36 37
  /// \addtogroup shortest_path
37 38
  /// @{
38 39

	
39 40
  /// \brief Algorithm for finding arc-disjoint paths between two nodes
40 41
  /// having minimum total length.
41 42
  ///
42 43
  /// \ref lemon::Suurballe "Suurballe" implements an algorithm for
43 44
  /// finding arc-disjoint paths having minimum total length (cost)
... ...
@@ -88,34 +89,34 @@
88 89
#else
89 90
    /// The type of the flow map.
90 91
    typedef typename Digraph::template ArcMap<int> FlowMap;
91 92
    /// The type of the potential map.
92 93
    typedef typename Digraph::template NodeMap<Length> PotentialMap;
93 94
#endif
94 95

	
95 96
    /// The type of the path structures.
96 97
    typedef SimplePath<GR> Path;
97 98

	
98 99
  private:
99 100

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

	
100 104
    // ResidualDijkstra is a special implementation of the
101 105
    // Dijkstra algorithm for finding shortest paths in the
102 106
    // residual network with respect to the reduced arc lengths
103 107
    // and modifying the node potentials according to the
104 108
    // distance of the nodes.
105 109
    class ResidualDijkstra
106 110
    {
107
      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
108
      typedef BinHeap<Length, HeapCrossRef> Heap;
109

	
110 111
    private:
111 112

	
112 113
      const Digraph &_graph;
113 114
      const LengthMap &_length;
114 115
      const FlowMap &_flow;
115 116
      PotentialMap &_pi;
116 117
      PredMap &_pred;
117 118
      Node _s;
118 119
      Node _t;
119 120
      
120 121
      PotentialMap _dist;
121 122
      std::vector<Node> _proc_nodes;
... ...
@@ -269,43 +270,51 @@
269 270

	
270 271
    // The source node
271 272
    Node _s;
272 273
    // The target node
273 274
    Node _t;
274 275

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

	
279 280
    // The pred arc map
280 281
    PredMap _pred;
282
    
283
    // Data for full init
284
    PotentialMap *_init_dist;
285
    PredMap *_init_pred;
286
    bool _full_init;
281 287

	
282 288
  public:
283 289

	
284 290
    /// \brief Constructor.
285 291
    ///
286 292
    /// Constructor.
287 293
    ///
288 294
    /// \param graph The digraph the algorithm runs on.
289 295
    /// \param length The length (cost) values of the arcs.
290 296
    Suurballe( const Digraph &graph,
291 297
               const LengthMap &length ) :
292 298
      _graph(graph), _length(length), _flow(0), _local_flow(false),
293
      _potential(0), _local_potential(false), _pred(graph)
299
      _potential(0), _local_potential(false), _pred(graph),
300
      _init_dist(0), _init_pred(0)
294 301
    {}
295 302

	
296 303
    /// Destructor.
297 304
    ~Suurballe() {
298 305
      if (_local_flow) delete _flow;
299 306
      if (_local_potential) delete _potential;
307
      delete _init_dist;
308
      delete _init_pred;
300 309
    }
301 310

	
302 311
    /// \brief Set the flow map.
303 312
    ///
304 313
    /// This function sets the flow map.
305 314
    /// If it is not used before calling \ref run() or \ref init(),
306 315
    /// an instance will be allocated automatically. The destructor
307 316
    /// deallocates this automatically allocated map, of course.
308 317
    ///
309 318
    /// The found flow contains only 0 and 1 values, since it is the
310 319
    /// union of the found arc-disjoint paths.
311 320
    ///
... ...
@@ -332,98 +341,175 @@
332 341
    /// \return <tt>(*this)</tt>
333 342
    Suurballe& potentialMap(PotentialMap &map) {
334 343
      if (_local_potential) {
335 344
        delete _potential;
336 345
        _local_potential = false;
337 346
      }
338 347
      _potential = &map;
339 348
      return *this;
340 349
    }
341 350

	
342 351
    /// \name Execution Control
343 352
    /// The simplest way to execute the algorithm is to call the run()
344
    /// function.
345
    /// \n
353
    /// function.\n
354
    /// If you need to execute the algorithm many times using the same
355
    /// source node, then you may call fullInit() once and start()
356
    /// for each target node.\n
346 357
    /// If you only need the flow that is the union of the found
347
    /// arc-disjoint paths, you may call init() and findFlow().
358
    /// arc-disjoint paths, then you may call findFlow() instead of
359
    /// start().
348 360

	
349 361
    /// @{
350 362

	
351 363
    /// \brief Run the algorithm.
352 364
    ///
353 365
    /// This function runs the algorithm.
354 366
    ///
355 367
    /// \param s The source node.
356 368
    /// \param t The target node.
357 369
    /// \param k The number of paths to be found.
358 370
    ///
359 371
    /// \return \c k if there are at least \c k arc-disjoint paths from
360 372
    /// \c s to \c t in the digraph. Otherwise it returns the number of
361 373
    /// arc-disjoint paths found.
362 374
    ///
363 375
    /// \note Apart from the return value, <tt>s.run(s, t, k)</tt> is
364 376
    /// just a shortcut of the following code.
365 377
    /// \code
366 378
    ///   s.init(s);
367
    ///   s.findFlow(t, k);
368
    ///   s.findPaths();
379
    ///   s.start(t, k);
369 380
    /// \endcode
370 381
    int run(const Node& s, const Node& t, int k = 2) {
371 382
      init(s);
372
      findFlow(t, k);
373
      findPaths();
383
      start(t, k);
374 384
      return _path_num;
375 385
    }
376 386

	
377 387
    /// \brief Initialize the algorithm.
378 388
    ///
379
    /// This function initializes the algorithm.
389
    /// This function initializes the algorithm with the given source node.
380 390
    ///
381 391
    /// \param s The source node.
382 392
    void init(const Node& s) {
383 393
      _s = s;
384 394

	
385 395
      // Initialize maps
386 396
      if (!_flow) {
387 397
        _flow = new FlowMap(_graph);
388 398
        _local_flow = true;
389 399
      }
390 400
      if (!_potential) {
391 401
        _potential = new PotentialMap(_graph);
392 402
        _local_potential = true;
393 403
      }
394
      for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
395
      for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
404
      _full_init = false;
405
    }
406

	
407
    /// \brief Initialize the algorithm and perform Dijkstra.
408
    ///
409
    /// This function initializes the algorithm and performs a full
410
    /// Dijkstra search from the given source node. It makes consecutive
411
    /// executions of \ref start() "start(t, k)" faster, since they
412
    /// have to perform %Dijkstra only k-1 times.
413
    ///
414
    /// This initialization is usually worth using instead of \ref init()
415
    /// if the algorithm is executed many times using the same source node.
416
    ///
417
    /// \param s The source node.
418
    void fullInit(const Node& s) {
419
      // Initialize maps
420
      init(s);
421
      if (!_init_dist) {
422
        _init_dist = new PotentialMap(_graph);
423
      }
424
      if (!_init_pred) {
425
        _init_pred = new PredMap(_graph);
426
      }
427

	
428
      // Run a full Dijkstra
429
      typename Dijkstra<Digraph, LengthMap>
430
        ::template SetStandardHeap<Heap>
431
        ::template SetDistMap<PotentialMap>
432
        ::template SetPredMap<PredMap>
433
        ::Create dijk(_graph, _length);
434
      dijk.distMap(*_init_dist).predMap(*_init_pred);
435
      dijk.run(s);
436
      
437
      _full_init = true;
438
    }
439

	
440
    /// \brief Execute the algorithm.
441
    ///
442
    /// This function executes the algorithm.
443
    ///
444
    /// \param t The target node.
445
    /// \param k The number of paths to be found.
446
    ///
447
    /// \return \c k if there are at least \c k arc-disjoint paths from
448
    /// \c s to \c t in the digraph. Otherwise it returns the number of
449
    /// arc-disjoint paths found.
450
    ///
451
    /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
452
    /// just a shortcut of the following code.
453
    /// \code
454
    ///   s.findFlow(t, k);
455
    ///   s.findPaths();
456
    /// \endcode
457
    int start(const Node& t, int k = 2) {
458
      findFlow(t, k);
459
      findPaths();
460
      return _path_num;
396 461
    }
397 462

	
398 463
    /// \brief Execute the algorithm to find an optimal flow.
399 464
    ///
400 465
    /// This function executes the successive shortest path algorithm to
401 466
    /// find a minimum cost flow, which is the union of \c k (or less)
402 467
    /// arc-disjoint paths.
403 468
    ///
404 469
    /// \param t The target node.
405 470
    /// \param k The number of paths to be found.
406 471
    ///
407 472
    /// \return \c k if there are at least \c k arc-disjoint paths from
408 473
    /// the source node to the given node \c t in the digraph.
409 474
    /// Otherwise it returns the number of arc-disjoint paths found.
410 475
    ///
411 476
    /// \pre \ref init() must be called before using this function.
412 477
    int findFlow(const Node& t, int k = 2) {
413 478
      _t = t;
414 479
      ResidualDijkstra dijkstra(*this);
480
      
481
      // Initialization
482
      for (ArcIt e(_graph); e != INVALID; ++e) {
483
        (*_flow)[e] = 0;
484
      }
485
      if (_full_init) {
486
        for (NodeIt n(_graph); n != INVALID; ++n) {
487
          (*_potential)[n] = (*_init_dist)[n];
488
        }
489
        Node u = _t;
490
        Arc e;
491
        while ((e = (*_init_pred)[u]) != INVALID) {
492
          (*_flow)[e] = 1;
493
          u = _graph.source(e);
494
        }        
495
        _path_num = 1;
496
      } else {
497
        for (NodeIt n(_graph); n != INVALID; ++n) {
498
          (*_potential)[n] = 0;
499
        }
500
        _path_num = 0;
501
      }
415 502

	
416 503
      // Find shortest paths
417
      _path_num = 0;
418 504
      while (_path_num < k) {
419 505
        // Run Dijkstra
420 506
        if (!dijkstra.run(_path_num)) break;
421 507
        ++_path_num;
422 508

	
423 509
        // Set the flow along the found shortest path
424 510
        Node u = _t;
425 511
        Arc e;
426 512
        while ((e = _pred[u]) != INVALID) {
427 513
          if (u == _graph.target(e)) {
428 514
            (*_flow)[e] = 1;
429 515
            u = _graph.source(e);
Ignore white space 24 line context
... ...
@@ -92,24 +92,27 @@
92 92

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

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

	
100 100
  int k;
101 101
  k = suurb_test.run(n, n);
102 102
  k = suurb_test.run(n, n, k);
103 103
  suurb_test.init(n);
104
  suurb_test.fullInit(n);
105
  suurb_test.start(n);
106
  suurb_test.start(n, k);
104 107
  k = suurb_test.findFlow(n);
105 108
  k = suurb_test.findFlow(n, k);
106 109
  suurb_test.findPaths();
107 110
  
108 111
  int f;
109 112
  VType c;
110 113
  c = const_suurb_test.totalLength();
111 114
  f = const_suurb_test.flow(e);
112 115
  const SuurballeType::FlowMap& fm =
113 116
    const_suurb_test.flowMap();
114 117
  c = const_suurb_test.potential(n);
115 118
  const SuurballeType::PotentialMap& pm =
0 comments (0 inline)