[Lemon-commits] Peter Kovacs: Add a fullInit() function to Suurb...

Lemon HG hg at lemon.cs.elte.hu
Wed Mar 3 17:14:29 CET 2010


details:   http://lemon.cs.elte.hu/hg/lemon/rev/9a7e4e606f83
changeset: 927:9a7e4e606f83
user:      Peter Kovacs <kpeter [at] inf.elte.hu>
date:      Fri Oct 16 02:32:30 2009 +0200
description:
	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.

diffstat:

 lemon/suurballe.h      |  116 +++++++++++++++++++++++++++++++++-----
 test/suurballe_test.cc |    3 +
 2 files changed, 104 insertions(+), 15 deletions(-)

diffs (212 lines):

diff --git a/lemon/suurballe.h b/lemon/suurballe.h
--- a/lemon/suurballe.h
+++ b/lemon/suurballe.h
@@ -29,6 +29,7 @@
 #include <lemon/bin_heap.h>
 #include <lemon/path.h>
 #include <lemon/list_graph.h>
+#include <lemon/dijkstra.h>
 #include <lemon/maps.h>
 
 namespace lemon {
@@ -97,6 +98,9 @@
 
   private:
 
+    typedef typename Digraph::template NodeMap<int> HeapCrossRef;
+    typedef BinHeap<Length, HeapCrossRef> Heap;
+
     // ResidualDijkstra is a special implementation of the
     // Dijkstra algorithm for finding shortest paths in the
     // residual network with respect to the reduced arc lengths
@@ -104,9 +108,6 @@
     // distance of the nodes.
     class ResidualDijkstra
     {
-      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
-      typedef BinHeap<Length, HeapCrossRef> Heap;
-
     private:
 
       const Digraph &_graph;
@@ -278,6 +279,11 @@
 
     // The pred arc map
     PredMap _pred;
+    
+    // Data for full init
+    PotentialMap *_init_dist;
+    PredMap *_init_pred;
+    bool _full_init;
 
   public:
 
@@ -290,13 +296,16 @@
     Suurballe( const Digraph &graph,
                const LengthMap &length ) :
       _graph(graph), _length(length), _flow(0), _local_flow(false),
-      _potential(0), _local_potential(false), _pred(graph)
+      _potential(0), _local_potential(false), _pred(graph),
+      _init_dist(0), _init_pred(0)
     {}
 
     /// Destructor.
     ~Suurballe() {
       if (_local_flow) delete _flow;
       if (_local_potential) delete _potential;
+      delete _init_dist;
+      delete _init_pred;
     }
 
     /// \brief Set the flow map.
@@ -341,10 +350,13 @@
 
     /// \name Execution Control
     /// The simplest way to execute the algorithm is to call the run()
-    /// function.
-    /// \n
+    /// function.\n
+    /// If you need to execute the algorithm many times using the same
+    /// source node, then you may call fullInit() once and start()
+    /// for each target node.\n
     /// If you only need the flow that is the union of the found
-    /// arc-disjoint paths, you may call init() and findFlow().
+    /// arc-disjoint paths, then you may call findFlow() instead of
+    /// start().
 
     /// @{
 
@@ -364,19 +376,17 @@
     /// just a shortcut of the following code.
     /// \code
     ///   s.init(s);
-    ///   s.findFlow(t, k);
-    ///   s.findPaths();
+    ///   s.start(t, k);
     /// \endcode
     int run(const Node& s, const Node& t, int k = 2) {
       init(s);
-      findFlow(t, k);
-      findPaths();
+      start(t, k);
       return _path_num;
     }
 
     /// \brief Initialize the algorithm.
     ///
-    /// This function initializes the algorithm.
+    /// This function initializes the algorithm with the given source node.
     ///
     /// \param s The source node.
     void init(const Node& s) {
@@ -391,8 +401,63 @@
         _potential = new PotentialMap(_graph);
         _local_potential = true;
       }
-      for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
-      for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
+      _full_init = false;
+    }
+
+    /// \brief Initialize the algorithm and perform Dijkstra.
+    ///
+    /// This function initializes the algorithm and performs a full
+    /// Dijkstra search from the given source node. It makes consecutive
+    /// executions of \ref start() "start(t, k)" faster, since they
+    /// have to perform %Dijkstra only k-1 times.
+    ///
+    /// This initialization is usually worth using instead of \ref init()
+    /// if the algorithm is executed many times using the same source node.
+    ///
+    /// \param s The source node.
+    void fullInit(const Node& s) {
+      // Initialize maps
+      init(s);
+      if (!_init_dist) {
+        _init_dist = new PotentialMap(_graph);
+      }
+      if (!_init_pred) {
+        _init_pred = new PredMap(_graph);
+      }
+
+      // Run a full Dijkstra
+      typename Dijkstra<Digraph, LengthMap>
+        ::template SetStandardHeap<Heap>
+        ::template SetDistMap<PotentialMap>
+        ::template SetPredMap<PredMap>
+        ::Create dijk(_graph, _length);
+      dijk.distMap(*_init_dist).predMap(*_init_pred);
+      dijk.run(s);
+      
+      _full_init = true;
+    }
+
+    /// \brief Execute the algorithm.
+    ///
+    /// This function executes the algorithm.
+    ///
+    /// \param t The target node.
+    /// \param k The number of paths to be found.
+    ///
+    /// \return \c k if there are at least \c k arc-disjoint paths from
+    /// \c s to \c t in the digraph. Otherwise it returns the number of
+    /// arc-disjoint paths found.
+    ///
+    /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
+    /// just a shortcut of the following code.
+    /// \code
+    ///   s.findFlow(t, k);
+    ///   s.findPaths();
+    /// \endcode
+    int start(const Node& t, int k = 2) {
+      findFlow(t, k);
+      findPaths();
+      return _path_num;
     }
 
     /// \brief Execute the algorithm to find an optimal flow.
@@ -412,9 +477,30 @@
     int findFlow(const Node& t, int k = 2) {
       _t = t;
       ResidualDijkstra dijkstra(*this);
+      
+      // Initialization
+      for (ArcIt e(_graph); e != INVALID; ++e) {
+        (*_flow)[e] = 0;
+      }
+      if (_full_init) {
+        for (NodeIt n(_graph); n != INVALID; ++n) {
+          (*_potential)[n] = (*_init_dist)[n];
+        }
+        Node u = _t;
+        Arc e;
+        while ((e = (*_init_pred)[u]) != INVALID) {
+          (*_flow)[e] = 1;
+          u = _graph.source(e);
+        }        
+        _path_num = 1;
+      } else {
+        for (NodeIt n(_graph); n != INVALID; ++n) {
+          (*_potential)[n] = 0;
+        }
+        _path_num = 0;
+      }
 
       // Find shortest paths
-      _path_num = 0;
       while (_path_num < k) {
         // Run Dijkstra
         if (!dijkstra.run(_path_num)) break;
diff --git a/test/suurballe_test.cc b/test/suurballe_test.cc
--- a/test/suurballe_test.cc
+++ b/test/suurballe_test.cc
@@ -101,6 +101,9 @@
   k = suurb_test.run(n, n);
   k = suurb_test.run(n, n, k);
   suurb_test.init(n);
+  suurb_test.fullInit(n);
+  suurb_test.start(n);
+  suurb_test.start(n, k);
   k = suurb_test.findFlow(n);
   k = suurb_test.findFlow(n, k);
   suurb_test.findPaths();



More information about the Lemon-commits mailing list