alpar@255: // -*- C++ -*- alpar@255: #ifndef HUGO_DIJKSTRA_H alpar@255: #define HUGO_DIJKSTRA_H alpar@255: klao@491: ///\ingroup galgs alpar@255: ///\file alpar@255: ///\brief Dijkstra algorithm. alpar@255: klao@258: #include alpar@257: #include alpar@255: alpar@255: namespace hugo { jacint@385: alpar@430: /// \addtogroup galgs alpar@430: /// @{ alpar@430: alpar@255: ///%Dijkstra algorithm class. alpar@255: alpar@255: ///This class provides an efficient implementation of %Dijkstra algorithm. alpar@255: ///The edge lengths are passed to the algorithm using a alpar@255: ///\ref ReadMapSkeleton "readable map", alpar@255: ///so it is easy to change it to any kind of length. alpar@255: /// alpar@255: ///The type of the length is determined by the \c ValueType of the length map. alpar@255: /// alpar@255: ///It is also possible to change the underlying priority heap. alpar@255: /// jacint@385: ///\param Graph The graph type the algorithm runs on. jacint@385: ///\param LengthMap This read-only jacint@385: ///EdgeMap jacint@385: ///determines the jacint@385: ///lengths of the edges. It is read once for each edge, so the map jacint@385: ///may involve in relatively time consuming process to compute the edge jacint@385: ///length if it is necessary. The default map type is jacint@385: ///\ref GraphSkeleton::EdgeMap "Graph::EdgeMap" jacint@385: ///\param Heap The heap type used by the %Dijkstra jacint@385: ///algorithm. The default jacint@385: ///is using \ref BinHeap "binary heap". alpar@456: /// alpar@456: ///\author Jacint Szabo alpar@255: #ifdef DOXYGEN alpar@255: template alpar@255: #else alpar@255: template , alpar@532: template class Heap = BinHeap > alpar@255: #endif alpar@255: class Dijkstra{ alpar@255: public: alpar@255: typedef typename Graph::Node Node; alpar@255: typedef typename Graph::NodeIt NodeIt; alpar@255: typedef typename Graph::Edge Edge; alpar@255: typedef typename Graph::OutEdgeIt OutEdgeIt; alpar@255: alpar@255: typedef typename LengthMap::ValueType ValueType; marci@433: typedef typename Graph::template NodeMap PredMap; marci@433: typedef typename Graph::template NodeMap PredNodeMap; marci@433: typedef typename Graph::template NodeMap DistMap; alpar@255: alpar@255: private: alpar@255: const Graph& G; alpar@255: const LengthMap& length; alpar@255: PredMap predecessor; alpar@255: PredNodeMap pred_node; alpar@255: DistMap distance; alpar@255: alpar@255: public : alpar@255: marci@459: Dijkstra(const Graph& _G, const LengthMap& _length) : alpar@255: G(_G), length(_length), predecessor(_G), pred_node(_G), distance(_G) { } alpar@255: alpar@255: void run(Node s); alpar@255: jacint@385: ///The distance of a node from the root. alpar@255: jacint@385: ///Returns the distance of a node from the root. alpar@255: ///\pre \ref run() must be called before using this function. jacint@385: ///\warning If node \c v in unreachable from the root the return value alpar@255: ///of this funcion is undefined. alpar@255: ValueType dist(Node v) const { return distance[v]; } jacint@373: jacint@385: ///Returns the previous edge of the shortest path tree. alpar@255: jacint@385: ///For a node \c v it returns the previous edge of the shortest path tree, jacint@385: ///i.e. it returns the last edge from a shortest path from the root to \c jacint@385: ///v. It is INVALID if \c v is unreachable from the root or if \c v=s. The jacint@385: ///shortest path tree used here is equal to the shortest path tree used in jacint@385: ///\ref predNode(Node v). \pre \ref run() must be called before using jacint@385: ///this function. alpar@255: Edge pred(Node v) const { return predecessor[v]; } jacint@373: jacint@385: ///Returns the previous node of the shortest path tree. alpar@255: jacint@385: ///For a node \c v it returns the previous node of the shortest path tree, jacint@385: ///i.e. it returns the last but one node from a shortest path from the jacint@385: ///root to \c /v. It is INVALID if \c v is unreachable from the root or if jacint@385: ///\c v=s. The shortest path tree used here is equal to the shortest path jacint@385: ///tree used in \ref pred(Node v). \pre \ref run() must be called before jacint@385: ///using this function. alpar@255: Node predNode(Node v) const { return pred_node[v]; } alpar@255: alpar@255: ///Returns a reference to the NodeMap of distances. alpar@255: jacint@385: ///Returns a reference to the NodeMap of distances. \pre \ref run() must jacint@385: ///be called before using this function. alpar@255: const DistMap &distMap() const { return distance;} jacint@385: alpar@255: ///Returns a reference to the shortest path tree map. alpar@255: alpar@255: ///Returns a reference to the NodeMap of the edges of the alpar@255: ///shortest path tree. alpar@255: ///\pre \ref run() must be called before using this function. alpar@255: const PredMap &predMap() const { return predecessor;} jacint@385: jacint@385: ///Returns a reference to the map of nodes of shortest paths. alpar@255: alpar@255: ///Returns a reference to the NodeMap of the last but one nodes of the jacint@385: ///shortest path tree. alpar@255: ///\pre \ref run() must be called before using this function. alpar@255: const PredNodeMap &predNodeMap() const { return pred_node;} alpar@255: jacint@385: ///Checks if a node is reachable from the root. alpar@255: jacint@385: ///Returns \c true if \c v is reachable from the root. jacint@385: ///\warning the root node is reported to be unreached! alpar@255: ///\todo Is this what we want? alpar@255: ///\pre \ref run() must be called before using this function. jacint@385: /// alpar@255: bool reached(Node v) { return G.valid(predecessor[v]); } alpar@255: alpar@255: }; alpar@255: alpar@255: alpar@255: // ********************************************************************** alpar@255: // IMPLEMENTATIONS alpar@255: // ********************************************************************** alpar@255: jacint@385: ///Runs %Dijkstra algorithm from node the root. alpar@255: jacint@385: ///This method runs the %Dijkstra algorithm from a root node \c s jacint@385: ///in order to jacint@385: ///compute the jacint@385: ///shortest path to each node. The algorithm computes jacint@385: ///- The shortest path tree. jacint@385: ///- The distance of each node from the root. alpar@255: template class Heap > alpar@255: void Dijkstra::run(Node s) { alpar@255: alpar@255: NodeIt u; alpar@255: for ( G.first(u) ; G.valid(u) ; G.next(u) ) { alpar@255: predecessor.set(u,INVALID); alpar@255: pred_node.set(u,INVALID); alpar@255: } alpar@255: marci@433: typename Graph::template NodeMap heap_map(G,-1); alpar@255: alpar@532: typedef Heap, alpar@532: std::less > alpar@532: HeapType; alpar@532: alpar@532: HeapType heap(heap_map); jacint@385: alpar@255: heap.push(s,0); alpar@255: jacint@385: while ( !heap.empty() ) { alpar@255: jacint@385: Node v=heap.top(); jacint@385: ValueType oldvalue=heap[v]; jacint@385: heap.pop(); jacint@385: distance.set(v, oldvalue); jacint@385: jacint@385: { //FIXME this bracket is for e to be local jacint@385: OutEdgeIt e; jacint@385: for(G.first(e, v); jacint@385: G.valid(e); G.next(e)) { marci@421: Node w=G.bNode(e); alpar@255: alpar@255: switch(heap.state(w)) { alpar@532: case HeapType::PRE_HEAP: alpar@255: heap.push(w,oldvalue+length[e]); alpar@255: predecessor.set(w,e); alpar@255: pred_node.set(w,v); alpar@255: break; alpar@532: case HeapType::IN_HEAP: alpar@255: if ( oldvalue+length[e] < heap[w] ) { alpar@255: heap.decrease(w, oldvalue+length[e]); alpar@255: predecessor.set(w,e); alpar@255: pred_node.set(w,v); alpar@255: } alpar@255: break; alpar@532: case HeapType::POST_HEAP: alpar@255: break; alpar@255: } alpar@255: } jacint@385: } //FIXME tis bracket jacint@385: } alpar@255: } alpar@430: alpar@430: /// @} alpar@255: alpar@255: } //END OF NAMESPACE HUGO alpar@255: alpar@255: #endif alpar@255: alpar@255: