[Lemon-commits] [lemon_svn] alpar: r1527 - hugo/trunk/src/work/alpar

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:46:02 CET 2006


Author: alpar
Date: Sun Feb  6 15:44:41 2005
New Revision: 1527

Modified:
   hugo/trunk/src/work/alpar/dijkstra.h

Log:
Several important changes:
- Named parameters for setting ReachedMap
- run() is separated into initialization and processing phase
- It is possible to run Dijkstra from multiple sources
- It is possible to stop the execution when a destination is reached.

Modified: hugo/trunk/src/work/alpar/dijkstra.h
==============================================================================
--- hugo/trunk/src/work/alpar/dijkstra.h	(original)
+++ hugo/trunk/src/work/alpar/dijkstra.h	Sun Feb  6 15:44:41 2005
@@ -158,7 +158,7 @@
   ///a Dijkstra traits class.
   ///
   ///\author Jacint Szabo and Alpar Juttner
-  ///\todo We need a typedef-names should be standardized. (-:
+  ///\todo A compare object would be nice.
 
 #ifdef DOXYGEN
   template <typename GR,
@@ -237,11 +237,11 @@
     ///The source node of the last execution.
     Node source;
 
-    ///Initializes the maps.
+    ///Creates the maps if necessary.
     
     ///\todo Error if \c G or are \c NULL. What about \c length?
     ///\todo Better memory allocation (instead of new).
-    void init_maps() 
+    void create_maps() 
     {
       if(!_pred) {
 	local_pred = true;
@@ -263,11 +263,13 @@
     
   public :
  
+    ///\name Named template parameters
+
+    ///@{
+
     template <class T>
     struct DefPredMapTraits : public Traits {
       typedef T PredMap;
-      ///\todo An exception should be thrown.
-      ///
       static PredMap *createPredMap(const Graph &G) 
       {
 	throw UninitializedParameter();
@@ -285,8 +287,6 @@
     template <class T>
     struct DefPredNodeMapTraits : public Traits {
       typedef T PredNodeMap;
-      ///\todo An exception should be thrown.
-      ///
       static PredNodeMap *createPredNodeMap(const Graph &G) 
       {
 	throw UninitializedParameter();
@@ -304,8 +304,6 @@
     template <class T>
     struct DefDistMapTraits : public Traits {
       typedef T DistMap;
-      ///\todo An exception should be thrown.
-      ///
       static DistMap *createDistMap(const Graph &G) 
       {
 	throw UninitializedParameter();
@@ -320,6 +318,50 @@
 					LengthMap,
 					DefDistMapTraits<T> > { };
     
+    template <class T>
+    struct DefReachedMapTraits : public Traits {
+      typedef T ReachedMap;
+      static ReachedMap *createReachedMap(const Graph &G) 
+      {
+	throw UninitializedParameter();
+      }
+    };
+    ///\ref named-templ-param "Named parameter" for setting ReachedMap type
+
+    ///\ref named-templ-param "Named parameter" for setting ReachedMap type
+    ///
+    template <class T>
+    class DefReachedMap : public Dijkstra< Graph,
+					LengthMap,
+					DefReachedMapTraits<T> > { };
+    
+    struct DefGraphReachedMapTraits : public Traits {
+      typedef typename Graph::NodeMap<bool> ReachedMap;
+      static ReachedMap *createReachedMap(const Graph &G) 
+      {
+	return new ReachedMap(G);
+      }
+    };
+    ///\brief \ref named-templ-param "Named parameter"
+    ///for setting the ReachedMap type to be Graph::NodeMap<bool>.
+    ///
+    ///\ref named-templ-param "Named parameter"
+    ///for setting the ReachedMap type to be Graph::NodeMap<bool>.
+    ///If you don't set it explicitely, it will be automatically allocated.
+    template <class T>
+    class DefReachedMapToBeDefaultMap :
+      public Dijkstra< Graph,
+		       LengthMap,
+		       DefGraphReachedMapTraits> { };
+    
+    ///@}
+
+
+  private:
+    typename Graph::template NodeMap<int> _heap_map;
+    Heap _heap;
+  public:      
+    
     ///Constructor.
     
     ///\param _G the graph the algorithm will run on.
@@ -329,7 +371,8 @@
       _pred(NULL), local_pred(false),
       pred_node(NULL), local_pred_node(false),
       distance(NULL), local_distance(false),
-      _reached(NULL), local_reached(false)
+      _reached(NULL), local_reached(false),
+      _heap_map(*G,-1),_heap(_heap_map)
     { }
     
     ///Destructor.
@@ -401,65 +444,147 @@
       distance = &m;
       return *this;
     }
-    
-  ///Runs %Dijkstra algorithm from node \c s.
 
-  ///This method runs the %Dijkstra algorithm from a root node \c s
-  ///in order to
-  ///compute the
-  ///shortest path to each node. The algorithm computes
-  ///- The shortest path tree.
-  ///- The distance of each node from the root.
-  ///\todo heap_map's type could also be in the traits class.
-    void run(Node s) {
-      
-      init_maps();
-      
-      source = s;
+    ///\name Excetution control
+    ///The simplest way to execute the algorithm is to use
+    ///\ref run().
+    ///\n
+    ///It you need more control on the execution,
+    ///first you must call \ref init(), then you can add several source nodes
+    ///with \ref addSource(). Finally \ref start() will perform the actual path
+    ///computation.
+
+    ///@{
+
+    ///Initializes the internal data structures.
+
+    ///Initializes the internal data structures.
+    ///
+    ///\todo _heap_map's type could also be in the traits class.
+    void init()
+    {
+      create_maps();
       
       for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
 	_pred->set(u,INVALID);
 	pred_node->set(u,INVALID);
 	///\todo *_reached is not set to false.
+	_heap_map.set(u,Heap::PRE_HEAP);
       }
+    }
+    
+    ///Adds a new source node.
+
+    ///Adds a new source node the the priority heap.
+    ///It checks if the node has already been added to the heap.
+    ///
+    ///The optional second parameter is the initial distance of the node.
+    ///
+    ///\todo Do we really want to check it?
+    void addSource(Node s,Value dst=0)
+    {
+      source = s;
+      if(_heap.state(s) != Heap::IN_HEAP) _heap.push(s,dst);
+    }
+    
+    void processNode()
+    {
+      Node v=_heap.top(); 
+      _reached->set(v,true);
+      Value oldvalue=_heap[v];
+      _heap.pop();
+      distance->set(v, oldvalue);
       
-      typename Graph::template NodeMap<int> heap_map(*G,-1);
-      
-      Heap heap(heap_map);
-      
-      heap.push(s,0); 
-      
-      while ( !heap.empty() ) {
-	
-	Node v=heap.top(); 
-	_reached->set(v,true);
-	Value oldvalue=heap[v];
-	heap.pop();
-	distance->set(v, oldvalue);
-	
-	
-	for(OutEdgeIt e(*G,v); e!=INVALID; ++e) {
-	  Node w=G->target(e); 
-	  switch(heap.state(w)) {
-	  case Heap::PRE_HEAP:
-	    heap.push(w,oldvalue+(*length)[e]); 
+      for(OutEdgeIt e(*G,v); e!=INVALID; ++e) {
+	Node w=G->target(e); 
+	switch(_heap.state(w)) {
+	case Heap::PRE_HEAP:
+	  _heap.push(w,oldvalue+(*length)[e]); 
+	  _pred->set(w,e);
+	  pred_node->set(w,v);
+	  break;
+	case Heap::IN_HEAP:
+	  if ( oldvalue+(*length)[e] < _heap[w] ) {
+	    _heap.decrease(w, oldvalue+(*length)[e]); 
 	    _pred->set(w,e);
 	    pred_node->set(w,v);
-	    break;
-	  case Heap::IN_HEAP:
-	    if ( oldvalue+(*length)[e] < heap[w] ) {
-	      heap.decrease(w, oldvalue+(*length)[e]); 
-	      _pred->set(w,e);
-	      pred_node->set(w,v);
-	    }
-	    break;
-	  case Heap::POST_HEAP:
-	    break;
 	  }
+	  break;
+	case Heap::POST_HEAP:
+	  break;
 	}
       }
     }
+
+    ///Starts the execution of the algorithm.
+
+    ///Starts the execution of the algorithm.
+    ///
+    ///\pre init() must be called before and at least one node should be added
+    ///with addSource().
+    ///
+    ///This method runs the %Dijkstra algorithm from the root node(s)
+    ///in order to
+    ///compute the
+    ///shortest path to each node. The algorithm computes
+    ///- The shortest path tree.
+    ///- The distance of each node from the root(s).
+    ///
+    void start()
+    {
+      while ( !_heap.empty() ) processNode();
+    }
+    
+    ///Starts the execution of the algorithm until \c dest is reached.
+
+    ///Starts the execution of the algorithm until \c dest is reached.
+    ///
+    ///\pre init() must be called before and at least one node should be added
+    ///with addSource().
+    ///
+    ///This method runs the %Dijkstra algorithm from the root node(s)
+    ///in order to
+    ///compute the
+    ///shortest path to \c dest. The algorithm computes
+    ///- The shortest path to \c  dest.
+    ///- The distance of \c dest from the root(s).
+    ///
+    void start(Node dest)
+    {
+      while ( !_heap.empty() && _heap.top()!=dest) processNode();
+    }
     
+    ///Runs %Dijkstra algorithm from node \c s.
+    
+    ///This method runs the %Dijkstra algorithm from a root node \c s
+    ///in order to
+    ///compute the
+    ///shortest path to each node. The algorithm computes
+    ///- The shortest path tree.
+    ///- The distance of each node from the root.
+    ///
+    ///\note d.run(s) is just a shortcut of the following code.
+    ///\code
+    ///  d.init();
+    ///  d.addSource(s);
+    ///  d.start();
+    ///\endcode
+    void run(Node s) {
+      init();
+      addSource(s);
+      start();
+    }
+    
+    ///@}
+
+    ///\name Query Functions
+    ///The result of the %Dijkstra algorithm can be obtained using these
+    ///functions.\n
+    ///Before the use of these functions,
+    ///either run() or start() must be called.
+    
+    ///@{
+
     ///The distance of a node from the root.
 
     ///Returns the distance of a node from the root.
@@ -513,11 +638,13 @@
     ///Checks if a node is reachable from the root.
 
     ///Returns \c true if \c v is reachable from the root.
-    ///\note The root node is reported to be reached!
+    ///\warning If the algorithm is started from multiple nodes,
+    ///this function may give false result for the source nodes.
     ///\pre \ref run() must be called before using this function.
     ///
     bool reached(Node v) { return v==source || (*_pred)[v]!=INVALID; }
     
+    ///@}
   };
 
   /// Default traits used by \ref DijkstraWizard



More information about the Lemon-commits mailing list