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
... ...
@@ -8,48 +8,49 @@
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
#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)
44 45
  /// from a given source node to a given target node in a digraph.
45 46
  ///
46 47
  /// Note that this problem is a special case of the \ref min_cost_flow
47 48
  /// "minimum cost flow problem". This implementation is actually an
48 49
  /// efficient specialized version of the \ref CapacityScaling
49 50
  /// "successive shortest path" algorithm directly for this problem.
50 51
  /// Therefore this class provides query functions for flow values and
51 52
  /// node potentials (the dual solution) just like the minimum cost flow
52 53
  /// algorithms.
53 54
  ///
54 55
  /// \tparam GR The digraph type the algorithm runs on.
55 56
  /// \tparam LEN The type of the length map.
... ...
@@ -76,58 +77,58 @@
76 77

	
77 78
    /// The type of the digraph the algorithm runs on.
78 79
    typedef GR Digraph;
79 80
    /// The type of the length map.
80 81
    typedef LEN LengthMap;
81 82
    /// The type of the lengths.
82 83
    typedef typename LengthMap::Value Length;
83 84
#ifdef DOXYGEN
84 85
    /// The type of the flow map.
85 86
    typedef GR::ArcMap<int> FlowMap;
86 87
    /// The type of the potential map.
87 88
    typedef GR::NodeMap<Length> PotentialMap;
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;
122 123

	
123 124
    public:
124 125

	
125 126
      // Constructor
126 127
      ResidualDijkstra(Suurballe &srb) :
127 128
        _graph(srb._graph), _length(srb._length),
128 129
        _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred), 
129 130
        _s(srb._s), _t(srb._t), _dist(_graph) {}
130 131
        
131 132
      // Run the algorithm and return true if a path is found
132 133
      // from the source node to the target node.
133 134
      bool run(int cnt) {
... ...
@@ -257,185 +258,270 @@
257 258

	
258 259
    // The digraph the algorithm runs on
259 260
    const Digraph &_graph;
260 261
    // The length map
261 262
    const LengthMap &_length;
262 263

	
263 264
    // Arc map of the current flow
264 265
    FlowMap *_flow;
265 266
    bool _local_flow;
266 267
    // Node map of the current potentials
267 268
    PotentialMap *_potential;
268 269
    bool _local_potential;
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
    ///
312 321
    /// \return <tt>(*this)</tt>
313 322
    Suurballe& flowMap(FlowMap &map) {
314 323
      if (_local_flow) {
315 324
        delete _flow;
316 325
        _local_flow = false;
317 326
      }
318 327
      _flow = &map;
319 328
      return *this;
320 329
    }
321 330

	
322 331
    /// \brief Set the potential map.
323 332
    ///
324 333
    /// This function sets the potential map.
325 334
    /// If it is not used before calling \ref run() or \ref init(),
326 335
    /// an instance will be allocated automatically. The destructor
327 336
    /// deallocates this automatically allocated map, of course.
328 337
    ///
329 338
    /// The node potentials provide the dual solution of the underlying
330 339
    /// \ref min_cost_flow "minimum cost flow problem".
331 340
    ///
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);
430 516
          } else {
431 517
            (*_flow)[e] = 0;
432 518
            u = _graph.target(e);
433 519
          }
434 520
        }
435 521
      }
436 522
      return _path_num;
437 523
    }
438 524

	
439 525
    /// \brief Compute the paths from the flow.
440 526
    ///
441 527
    /// This function computes arc-disjoint paths from the found minimum
Ignore white space 48 line context
... ...
@@ -80,48 +80,51 @@
80 80
  typedef Digraph::Node Node;
81 81
  typedef Digraph::Arc Arc;
82 82
  typedef concepts::ReadMap<Arc, VType> LengthMap;
83 83
  
84 84
  typedef Suurballe<Digraph, LengthMap> SuurballeType;
85 85

	
86 86
  Digraph g;
87 87
  Node n;
88 88
  Arc e;
89 89
  LengthMap len;
90 90
  SuurballeType::FlowMap flow(g);
91 91
  SuurballeType::PotentialMap pi(g);
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 =
116 119
    const_suurb_test.potentialMap();
117 120
  k = const_suurb_test.pathNum();
118 121
  Path<Digraph> p = const_suurb_test.path(k);
119 122
  
120 123
  ignore_unused_variable_warning(fm);
121 124
  ignore_unused_variable_warning(pm);
122 125
}
123 126

	
124 127
// Check the feasibility of the flow
125 128
template <typename Digraph, typename FlowMap>
126 129
bool checkFlow( const Digraph& gr, const FlowMap& flow,
127 130
                typename Digraph::Node s, typename Digraph::Node t,
0 comments (0 inline)