alpar@222: // -*- C++ -*-
alpar@222: /* 
alpar@222:  *template <Graph, T, Heap=FibHeap, LengthMap=Graph::EdgeMap<T> >
alpar@222:  *
alpar@222:  *Constructor: 
alpar@222:  *
alpar@222:  *Dijkstra(Graph G, LengthMap length)
alpar@222:  *
alpar@222:  *
alpar@222:  *Methods:
alpar@222:  *
alpar@222:  *void run(Node s)
alpar@222:  *
alpar@222:  *T dist(Node v) : After run(s) was run, it returns the distance from s to v. 
alpar@222:  *   Returns T() if v is not reachable from s.
alpar@222:  *
alpar@222:  *Edge pred(Node v) : After run(s) was run, it returns the last 
alpar@222:  *   edge of a shortest s-v path. It is INVALID for s and for 
alpar@222:  *   the nodes not reachable from s.
alpar@222:  *
alpar@222:  *bool reached(Node v) : After run(s) was run, it is true iff v is 
alpar@222:  *   reachable from s
alpar@222:  *
alpar@222:  */
alpar@222: 
alpar@222: #ifndef HUGO_DIJKSTRA_H
alpar@222: #define HUGO_DIJKSTRA_H
alpar@222: 
alpar@222: #include <fib_heap.h>
alpar@228: #include <bin_heap.hh>
alpar@222: #include <invalid.h>
alpar@222: 
alpar@222: namespace hugo {
alpar@222:   
alpar@222:   //Alpar: Changed the order of the parameters
alpar@224:   
alpar@229:   ///%Dijkstra algorithm class.
alpar@224: 
alpar@229:   ///This class provides an efficient implementation of %Dijkstra algorithm.
alpar@224:   ///The edge lengths are passed to the algorithm using a
alpar@224:   ///\ref ReadMapSkeleton "readable map",
alpar@224:   ///so it is easy to change it to any kind of length.
alpar@224:   ///
alpar@224:   ///The type of the length is determined by the \c ValueType of the length map.
alpar@224:   ///
alpar@224:   ///It is also posible to change the underlying priority heap.
alpar@224:   ///
alpar@224:   ///\param Graph The graph type the algorithm runs on.
alpar@224:   ///\param LengthMap This read-only EdgeMap determines the
alpar@224:   ///lengths of the edges. It is read once for each edge, so the map
alpar@224:   ///may involve in relatively time consuming process to compute the edge
alpar@224:   ///length if it is necessary.
alpar@229:   ///\param Heap The heap type used by the %Dijkstra
alpar@224:   ///algorithm. The default
alpar@224:   ///is using \ref BinHeap "binary heap".
alpar@222:   template <typename Graph,
alpar@222: 	    typename LengthMap=typename Graph::EdgeMap<int>,
alpar@228: 	    typename Heap=BinHeap <typename Graph::Node,
alpar@228: 				   typename LengthMap::ValueType, 
alpar@228: 				   typename Graph::NodeMap<int> > >
alpar@222:   class Dijkstra{
alpar@222:   public:
alpar@228:     typedef typename Graph::Node Node;
alpar@228:     typedef typename Graph::NodeIt NodeIt;
alpar@228:     typedef typename Graph::Edge Edge;
alpar@228:     typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@228:     
alpar@222:     typedef typename LengthMap::ValueType ValueType;
alpar@224:     typedef typename Graph::NodeMap<Edge> PredMap;
alpar@224:     typedef typename Graph::NodeMap<Node> PredNodeMap;
alpar@224:     typedef typename Graph::NodeMap<ValueType> DistMap;
alpar@222: 
alpar@222:   private:
alpar@222:     const Graph& G;
alpar@222:     const LengthMap& length;
alpar@222:     PredMap predecessor;
alpar@222:     //In place of reach:
alpar@222:     PredNodeMap pred_node;
alpar@222:     DistMap distance;
alpar@222:     //I don't like this:
alpar@222:     //     //FIXME:
alpar@222:     //     typename Graph::NodeMap<bool> reach;
alpar@222:     //     //typename Graph::NodeMap<int> reach;
alpar@222:     
alpar@222:   public :
alpar@222:     
alpar@222:     /*
alpar@222:       The distance of the nodes is 0.
alpar@222:     */
alpar@222:     Dijkstra(Graph& _G, LengthMap& _length) :
alpar@222:       G(_G), length(_length), predecessor(_G), pred_node(_G), distance(_G) { }
alpar@222:     
alpar@222: 
alpar@222:     void run(Node s);
alpar@222:     
alpar@224:     ///The distance of a node from the source.
alpar@224: 
alpar@224:     ///Returns the distance of a node from the source.
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@229:     ///\warning If node \c v in unreachable from the source the return value
alpar@224:     ///of this funcion is undefined.
alpar@222:     ValueType dist(Node v) const { return distance[v]; }
alpar@224:     ///Returns the edges of the shortest path tree.
alpar@224: 
alpar@224:     ///For a node \c v it returns the last edge of the shortest path
alpar@229:     ///from the source to \c v or INVALID if \c v is unreachable
alpar@229:     ///from the source.
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@222:     Edge pred(Node v) const { return predecessor[v]; }
alpar@224:     ///Returns the nodes of the shortest paths.
alpar@224: 
alpar@224:     ///For a node \c v it returns the last but one node of the shortest path
alpar@229:     ///from the source to \c v or INVALID if \c v is unreachable
alpar@229:     ///from the source.
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@222:     Node predNode(Node v) const { return pred_node[v]; }
alpar@222:     
alpar@224:     ///Returns a reference to the NodeMap of distances.
alpar@224: 
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@224:     ///
alpar@222:     const DistMap &distMap() const { return distance;}
alpar@224:     ///Returns a reference to the shortest path tree map.
alpar@224: 
alpar@224:     ///Returns a reference to the NodeMap of the edges of the
alpar@224:     ///shortest path tree.
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@222:     const PredMap &predMap() const { return predecessor;}
alpar@224:     ///Returns a reference to the map of nodes of  shortest paths.
alpar@224: 
alpar@224:     ///Returns a reference to the NodeMap of the last but one nodes of the
alpar@224:     ///shortest paths.
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@222:     const PredNodeMap &predNodeMap() const { return pred_node;}
alpar@222: 
alpar@222:     //    bool reached(Node v) { return reach[v]; }
alpar@224: 
alpar@229:     ///Chechs if a node is reachable from the source.
alpar@224: 
alpar@229:     ///Returns \c true if \c v is reachable from the source.
alpar@229:     ///\warning the source node is reported to be unreached!
alpar@224:     ///\todo Is this what we want?
alpar@224:     ///\pre \ref run() must be called before using this function.
alpar@222:     ///
alpar@222:     bool reached(Node v) { return G.valid(predecessor[v]); }
alpar@222:     
alpar@222:   };
alpar@222:   
alpar@222: 
alpar@224:   // **********************************************************************
alpar@224:   //  IMPLEMENTATIONS
alpar@224:   // **********************************************************************
alpar@222: 
alpar@229:   ///Runs %Dijkstra algorithm from node the source.
alpar@224: 
alpar@229:   ///This method runs the %Dijkstra algorithm from a source node \c s
alpar@229:   ///in order to
alpar@224:   ///compute the
alpar@224:   ///shortest path to each node. The algorithm computes
alpar@224:   ///- The shortest path tree.
alpar@229:   ///- The distance of each node from the source.
alpar@222:   template <typename Graph, typename LengthMap, typename Heap >
alpar@222:   void Dijkstra<Graph,LengthMap,Heap>::run(Node s) {
alpar@222:     
alpar@222:     NodeIt u;
alpar@222:     for ( G.first(u) ; G.valid(u) ; G.next(u) ) {
alpar@222:       predecessor.set(u,INVALID);
alpar@224:       pred_node.set(u,INVALID);
alpar@222:       // If a node is unreacheable, then why should be the dist=0?
alpar@222:       // distance.set(u,0);
alpar@222:       //      reach.set(u,false);
alpar@222:     }
alpar@222:     
alpar@222:     //We don't need it at all.
alpar@222:     //     //FIXME:
alpar@222:     //     typename Graph::NodeMap<bool> scanned(G,false);
alpar@222:     //     //typename Graph::NodeMap<int> scanned(G,false);
alpar@222:     typename Graph::NodeMap<int> heap_map(G,-1);
alpar@222:     
alpar@222:     Heap heap(heap_map);
alpar@222:     
alpar@222:     heap.push(s,0); 
alpar@222:     //    reach.set(s, true);
alpar@222:     
alpar@222:       while ( !heap.empty() ) {
alpar@222: 	
alpar@222: 	Node v=heap.top(); 
alpar@222: 	ValueType oldvalue=heap[v];
alpar@222: 	heap.pop();
alpar@222: 	distance.set(v, oldvalue);
alpar@222: 	
alpar@222: 	for(OutEdgeIt e(G,v); G.valid(e); G.next(e)) {
alpar@222: 	  Node w=G.head(e); 
alpar@222: 	  
alpar@222: 	  switch(heap.state(w)) {
alpar@222: 	  case Heap::PRE_HEAP:
alpar@222: 	    //	    reach.set(w,true);
alpar@222: 	    heap.push(w,oldvalue+length[e]); 
alpar@222: 	    predecessor.set(w,e);
alpar@222: 	    pred_node.set(w,v);
alpar@222: 	    break;
alpar@222: 	  case Heap::IN_HEAP:
alpar@222: 	    if ( oldvalue+length[e] < heap[w] ) {
alpar@222: 	      heap.decrease(w, oldvalue+length[e]); 
alpar@222: 	      predecessor.set(w,e);
alpar@222: 	      pred_node.set(w,v);
alpar@222: 	    }
alpar@222: 	    break;
alpar@222: 	  case Heap::POST_HEAP:
alpar@222: 	    break;
alpar@222: 	  }
alpar@222: 	}
alpar@222:       }
alpar@222:   }
alpar@222:   
alpar@222: } //END OF NAMESPACE HUGO
alpar@222: 
alpar@222: #endif
alpar@222: 
alpar@222: