[Lemon-commits] Alpar Juttner: Merge #323

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


details:   http://lemon.cs.elte.hu/hg/lemon/rev/de69a1609410
changeset: 930:de69a1609410
user:      Alpar Juttner <alpar [at] cs.elte.hu>
date:      Wed Mar 03 16:01:25 2010 +0000
description:
	Merge #323

diffstat:

 lemon/suurballe.h      |  461 ++++++++++++++++++++++++++++++++++++++------------
 test/suurballe_test.cc |   12 +-
 2 files changed, 360 insertions(+), 113 deletions(-)

diffs (truncated from 695 to 300 lines):

diff --git a/lemon/suurballe.h b/lemon/suurballe.h
--- a/lemon/suurballe.h
+++ b/lemon/suurballe.h
@@ -29,10 +29,54 @@
 #include <lemon/bin_heap.h>
 #include <lemon/path.h>
 #include <lemon/list_graph.h>
+#include <lemon/dijkstra.h>
 #include <lemon/maps.h>
 
 namespace lemon {
 
+  /// \brief Default traits class of Suurballe algorithm.
+  ///
+  /// Default traits class of Suurballe algorithm.
+  /// \tparam GR The digraph type the algorithm runs on.
+  /// \tparam LEN The type of the length map.
+  /// The default value is <tt>GR::ArcMap<int></tt>.
+#ifdef DOXYGEN
+  template <typename GR, typename LEN>
+#else
+  template < typename GR,
+             typename LEN = typename GR::template ArcMap<int> >
+#endif
+  struct SuurballeDefaultTraits
+  {
+    /// The type of the digraph.
+    typedef GR Digraph;
+    /// The type of the length map.
+    typedef LEN LengthMap;
+    /// The type of the lengths.
+    typedef typename LEN::Value Length;
+    /// The type of the flow map.
+    typedef typename GR::template ArcMap<int> FlowMap;
+    /// The type of the potential map.
+    typedef typename GR::template NodeMap<Length> PotentialMap;
+
+    /// \brief The path type
+    ///
+    /// The type used for storing the found arc-disjoint paths.
+    /// It must conform to the \ref lemon::concepts::Path "Path" concept
+    /// and it must have an \c addBack() function.
+    typedef lemon::Path<Digraph> Path;
+    
+    /// The cross reference type used for the heap.
+    typedef typename GR::template NodeMap<int> HeapCrossRef;
+
+    /// \brief The heap type used for internal Dijkstra computations.
+    ///
+    /// The type of the heap used for internal Dijkstra computations.
+    /// It must conform to the \ref lemon::concepts::Heap "Heap" concept
+    /// and its priority type must be \c Length.
+    typedef BinHeap<Length, HeapCrossRef> Heap;
+  };
+
   /// \addtogroup shortest_path
   /// @{
 
@@ -46,7 +90,7 @@
   /// Note that this problem is a special case of the \ref min_cost_flow
   /// "minimum cost flow problem". This implementation is actually an
   /// efficient specialized version of the \ref CapacityScaling
-  /// "Successive Shortest Path" algorithm directly for this problem.
+  /// "successive shortest path" algorithm directly for this problem.
   /// Therefore this class provides query functions for flow values and
   /// node potentials (the dual solution) just like the minimum cost flow
   /// algorithms.
@@ -55,15 +99,16 @@
   /// \tparam LEN The type of the length map.
   /// The default value is <tt>GR::ArcMap<int></tt>.
   ///
-  /// \warning Length values should be \e non-negative \e integers.
+  /// \warning Length values should be \e non-negative.
   ///
-  /// \note For finding node-disjoint paths this algorithm can be used
+  /// \note For finding \e node-disjoint paths, this algorithm can be used
   /// along with the \ref SplitNodes adaptor.
 #ifdef DOXYGEN
-  template <typename GR, typename LEN>
+  template <typename GR, typename LEN, typename TR>
 #else
   template < typename GR,
-             typename LEN = typename GR::template ArcMap<int> >
+             typename LEN = typename GR::template ArcMap<int>,
+             typename TR = SuurballeDefaultTraits<GR, LEN> >
 #endif
   class Suurballe
   {
@@ -74,26 +119,26 @@
 
   public:
 
-    /// The type of the digraph the algorithm runs on.
-    typedef GR Digraph;
+    /// The type of the digraph.
+    typedef typename TR::Digraph Digraph;
     /// The type of the length map.
-    typedef LEN LengthMap;
+    typedef typename TR::LengthMap LengthMap;
     /// The type of the lengths.
-    typedef typename LengthMap::Value Length;
-#ifdef DOXYGEN
+    typedef typename TR::Length Length;
+
     /// The type of the flow map.
-    typedef GR::ArcMap<int> FlowMap;
+    typedef typename TR::FlowMap FlowMap;
     /// The type of the potential map.
-    typedef GR::NodeMap<Length> PotentialMap;
-#else
-    /// The type of the flow map.
-    typedef typename Digraph::template ArcMap<int> FlowMap;
-    /// The type of the potential map.
-    typedef typename Digraph::template NodeMap<Length> PotentialMap;
-#endif
+    typedef typename TR::PotentialMap PotentialMap;
+    /// The type of the path structures.
+    typedef typename TR::Path Path;
+    /// The cross reference type used for the heap.
+    typedef typename TR::HeapCrossRef HeapCrossRef;
+    /// The heap type used for internal Dijkstra computations.
+    typedef typename TR::Heap Heap;
 
-    /// The type of the path structures.
-    typedef SimplePath<GR> Path;
+    /// The \ref SuurballeDefaultTraits "traits class" of the algorithm.
+    typedef TR Traits;
 
   private:
 
@@ -104,44 +149,38 @@
     // distance of the nodes.
     class ResidualDijkstra
     {
-      typedef typename Digraph::template NodeMap<int> HeapCrossRef;
-      typedef BinHeap<Length, HeapCrossRef> Heap;
-
     private:
 
-      // The digraph the algorithm runs on
       const Digraph &_graph;
-
-      // The main maps
+      const LengthMap &_length;
       const FlowMap &_flow;
-      const LengthMap &_length;
-      PotentialMap &_potential;
-
-      // The distance map
-      PotentialMap _dist;
-      // The pred arc map
+      PotentialMap &_pi;
       PredMap &_pred;
-      // The processed (i.e. permanently labeled) nodes
-      std::vector<Node> _proc_nodes;
-
       Node _s;
       Node _t;
+      
+      PotentialMap _dist;
+      std::vector<Node> _proc_nodes;
 
     public:
 
-      /// Constructor.
-      ResidualDijkstra( const Digraph &graph,
-                        const FlowMap &flow,
-                        const LengthMap &length,
-                        PotentialMap &potential,
-                        PredMap &pred,
-                        Node s, Node t ) :
-        _graph(graph), _flow(flow), _length(length), _potential(potential),
-        _dist(graph), _pred(pred), _s(s), _t(t) {}
+      // Constructor
+      ResidualDijkstra(Suurballe &srb) :
+        _graph(srb._graph), _length(srb._length),
+        _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred), 
+        _s(srb._s), _t(srb._t), _dist(_graph) {}
+        
+      // Run the algorithm and return true if a path is found
+      // from the source node to the target node.
+      bool run(int cnt) {
+        return cnt == 0 ? startFirst() : start();
+      }
 
-      /// \brief Run the algorithm. It returns \c true if a path is found
-      /// from the source node to the target node.
-      bool run() {
+    private:
+    
+      // Execute the algorithm for the first time (the flow and potential
+      // functions have to be identically zero).
+      bool startFirst() {
         HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
         Heap heap(heap_cross_ref);
         heap.push(_s, 0);
@@ -151,29 +190,74 @@
         // Process nodes
         while (!heap.empty() && heap.top() != _t) {
           Node u = heap.top(), v;
-          Length d = heap.prio() + _potential[u], nd;
+          Length d = heap.prio(), dn;
           _dist[u] = heap.prio();
+          _proc_nodes.push_back(u);
           heap.pop();
+
+          // Traverse outgoing arcs
+          for (OutArcIt e(_graph, u); e != INVALID; ++e) {
+            v = _graph.target(e);
+            switch(heap.state(v)) {
+              case Heap::PRE_HEAP:
+                heap.push(v, d + _length[e]);
+                _pred[v] = e;
+                break;
+              case Heap::IN_HEAP:
+                dn = d + _length[e];
+                if (dn < heap[v]) {
+                  heap.decrease(v, dn);
+                  _pred[v] = e;
+                }
+                break;
+              case Heap::POST_HEAP:
+                break;
+            }
+          }
+        }
+        if (heap.empty()) return false;
+
+        // Update potentials of processed nodes
+        Length t_dist = heap.prio();
+        for (int i = 0; i < int(_proc_nodes.size()); ++i)
+          _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
+        return true;
+      }
+
+      // Execute the algorithm.
+      bool start() {
+        HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
+        Heap heap(heap_cross_ref);
+        heap.push(_s, 0);
+        _pred[_s] = INVALID;
+        _proc_nodes.clear();
+
+        // Process nodes
+        while (!heap.empty() && heap.top() != _t) {
+          Node u = heap.top(), v;
+          Length d = heap.prio() + _pi[u], dn;
+          _dist[u] = heap.prio();
           _proc_nodes.push_back(u);
+          heap.pop();
 
           // Traverse outgoing arcs
           for (OutArcIt e(_graph, u); e != INVALID; ++e) {
             if (_flow[e] == 0) {
               v = _graph.target(e);
               switch(heap.state(v)) {
-              case Heap::PRE_HEAP:
-                heap.push(v, d + _length[e] - _potential[v]);
-                _pred[v] = e;
-                break;
-              case Heap::IN_HEAP:
-                nd = d + _length[e] - _potential[v];
-                if (nd < heap[v]) {
-                  heap.decrease(v, nd);
+                case Heap::PRE_HEAP:
+                  heap.push(v, d + _length[e] - _pi[v]);
                   _pred[v] = e;
-                }
-                break;
-              case Heap::POST_HEAP:
-                break;
+                  break;
+                case Heap::IN_HEAP:
+                  dn = d + _length[e] - _pi[v];
+                  if (dn < heap[v]) {
+                    heap.decrease(v, dn);
+                    _pred[v] = e;
+                  }
+                  break;
+                case Heap::POST_HEAP:
+                  break;
               }
             }
           }
@@ -183,19 +267,19 @@
             if (_flow[e] == 1) {
               v = _graph.source(e);
               switch(heap.state(v)) {
-              case Heap::PRE_HEAP:
-                heap.push(v, d - _length[e] - _potential[v]);
-                _pred[v] = e;
-                break;
-              case Heap::IN_HEAP:
-                nd = d - _length[e] - _potential[v];
-                if (nd < heap[v]) {
-                  heap.decrease(v, nd);
+                case Heap::PRE_HEAP:
+                  heap.push(v, d - _length[e] - _pi[v]);
                   _pred[v] = e;
-                }



More information about the Lemon-commits mailing list