src/include/dijkstra.h
author klao
Sat, 03 Apr 2004 18:21:25 +0000
changeset 282 7f85e99502db
parent 258 94bafec4f56f
child 296 09d6d48815a5
permissions -rw-r--r--
Bit more elaborated map concepts
alpar@255
     1
// -*- C++ -*-
alpar@255
     2
alpar@255
     3
/* 
alpar@255
     4
 *template <Graph, T, Heap=FibHeap, LengthMap=Graph::EdgeMap<T> >
alpar@255
     5
 *
alpar@255
     6
 *Constructor: 
alpar@255
     7
 *
alpar@255
     8
 *Dijkstra(Graph G, LengthMap length)
alpar@255
     9
 *
alpar@255
    10
 *
alpar@255
    11
 *Methods:
alpar@255
    12
 *
alpar@255
    13
 *void run(Node s)
alpar@255
    14
 *
alpar@255
    15
 *T dist(Node v) : After run(s) was run, it returns the distance from s to v. 
alpar@255
    16
 *   Returns T() if v is not reachable from s.
alpar@255
    17
 *
alpar@255
    18
 *Edge pred(Node v) : After run(s) was run, it returns the last 
alpar@255
    19
 *   edge of a shortest s-v path. It is INVALID for s and for 
alpar@255
    20
 *   the nodes not reachable from s.
alpar@255
    21
 *
alpar@255
    22
 *bool reached(Node v) : After run(s) was run, it is true iff v is 
alpar@255
    23
 *   reachable from s
alpar@255
    24
 *
alpar@255
    25
 */
alpar@255
    26
alpar@255
    27
#ifndef HUGO_DIJKSTRA_H
alpar@255
    28
#define HUGO_DIJKSTRA_H
alpar@255
    29
alpar@255
    30
///\file
alpar@255
    31
///\brief Dijkstra algorithm.
alpar@255
    32
alpar@257
    33
#include <fib_heap.h>
klao@258
    34
#include <bin_heap.h>
alpar@257
    35
#include <invalid.h>
alpar@255
    36
alpar@255
    37
namespace hugo {
alpar@255
    38
  
alpar@255
    39
  //Alpar: Changed the order of the parameters
alpar@255
    40
  
alpar@255
    41
  ///%Dijkstra algorithm class.
alpar@255
    42
alpar@255
    43
  ///This class provides an efficient implementation of %Dijkstra algorithm.
alpar@255
    44
  ///The edge lengths are passed to the algorithm using a
alpar@255
    45
  ///\ref ReadMapSkeleton "readable map",
alpar@255
    46
  ///so it is easy to change it to any kind of length.
alpar@255
    47
  ///
alpar@255
    48
  ///The type of the length is determined by the \c ValueType of the length map.
alpar@255
    49
  ///
alpar@255
    50
  ///It is also possible to change the underlying priority heap.
alpar@255
    51
  ///
alpar@255
    52
  ///\param Graph The graph type the algorithm runs on.
alpar@255
    53
  ///\param LengthMap This read-only
alpar@255
    54
  ///EdgeMap
alpar@255
    55
  ///determines the
alpar@255
    56
  ///lengths of the edges. It is read once for each edge, so the map
alpar@255
    57
  ///may involve in relatively time consuming process to compute the edge
alpar@255
    58
  ///length if it is necessary. The default map type is
alpar@255
    59
  ///\ref GraphSkeleton::EdgeMap "Graph::EdgeMap<int>"
alpar@255
    60
  ///\param Heap The heap type used by the %Dijkstra
alpar@255
    61
  ///algorithm. The default
alpar@255
    62
  ///is using \ref BinHeap "binary heap".
alpar@255
    63
  
alpar@255
    64
#ifdef DOXYGEN
alpar@255
    65
  template <typename Graph,
alpar@255
    66
	    typename LengthMap,
alpar@255
    67
	    typename Heap>
alpar@255
    68
#else
alpar@255
    69
  template <typename Graph,
alpar@255
    70
	    typename LengthMap=typename Graph::EdgeMap<int>,
alpar@255
    71
	    template <class,class,class> class Heap = BinHeap >
alpar@255
    72
// 	    typename Heap=BinHeap <typename Graph::Node,
alpar@255
    73
// 				   typename LengthMap::ValueType, 
alpar@255
    74
// 				   typename Graph::NodeMap<int> > >
alpar@255
    75
#endif
alpar@255
    76
  class Dijkstra{
alpar@255
    77
  public:
alpar@255
    78
    typedef typename Graph::Node Node;
alpar@255
    79
    typedef typename Graph::NodeIt NodeIt;
alpar@255
    80
    typedef typename Graph::Edge Edge;
alpar@255
    81
    typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@255
    82
    
alpar@255
    83
    typedef typename LengthMap::ValueType ValueType;
alpar@255
    84
    typedef typename Graph::NodeMap<Edge> PredMap;
alpar@255
    85
    typedef typename Graph::NodeMap<Node> PredNodeMap;
alpar@255
    86
    typedef typename Graph::NodeMap<ValueType> DistMap;
alpar@255
    87
alpar@255
    88
  private:
alpar@255
    89
    const Graph& G;
alpar@255
    90
    const LengthMap& length;
alpar@255
    91
    PredMap predecessor;
alpar@255
    92
    //In place of reach:
alpar@255
    93
    PredNodeMap pred_node;
alpar@255
    94
    DistMap distance;
alpar@255
    95
    //I don't like this:
alpar@255
    96
    //     //FIXME:
alpar@255
    97
    //     typename Graph::NodeMap<bool> reach;
alpar@255
    98
    //     //typename Graph::NodeMap<int> reach;
alpar@255
    99
    
alpar@255
   100
  public :
alpar@255
   101
    
alpar@255
   102
    /*
alpar@255
   103
      The distance of the nodes is 0.
alpar@255
   104
    */
alpar@255
   105
    Dijkstra(Graph& _G, LengthMap& _length) :
alpar@255
   106
      G(_G), length(_length), predecessor(_G), pred_node(_G), distance(_G) { }
alpar@255
   107
    
alpar@255
   108
    void run(Node s);
alpar@255
   109
    
alpar@255
   110
    ///The distance of a node from the source.
alpar@255
   111
alpar@255
   112
    ///Returns the distance of a node from the source.
alpar@255
   113
    ///\pre \ref run() must be called before using this function.
alpar@255
   114
    ///\warning If node \c v in unreachable from the source the return value
alpar@255
   115
    ///of this funcion is undefined.
alpar@255
   116
    ValueType dist(Node v) const { return distance[v]; }
alpar@255
   117
    ///Returns the edges of the shortest path tree.
alpar@255
   118
alpar@255
   119
    ///For a node \c v it returns the last edge of the shortest path
alpar@255
   120
    ///from the source to \c v or INVALID if \c v is unreachable
alpar@255
   121
    ///from the source.
alpar@255
   122
    ///\pre \ref run() must be called before using this function.
alpar@255
   123
    Edge pred(Node v) const { return predecessor[v]; }
alpar@255
   124
    ///Returns the nodes of the shortest paths.
alpar@255
   125
alpar@255
   126
    ///For a node \c v it returns the last but one node of the shortest path
alpar@255
   127
    ///from the source to \c v or INVALID if \c v is unreachable
alpar@255
   128
    ///from the source.
alpar@255
   129
    ///\pre \ref run() must be called before using this function.
alpar@255
   130
    Node predNode(Node v) const { return pred_node[v]; }
alpar@255
   131
    
alpar@255
   132
    ///Returns a reference to the NodeMap of distances.
alpar@255
   133
alpar@255
   134
    ///\pre \ref run() must be called before using this function.
alpar@255
   135
    ///
alpar@255
   136
    const DistMap &distMap() const { return distance;}
alpar@255
   137
    ///Returns a reference to the shortest path tree map.
alpar@255
   138
alpar@255
   139
    ///Returns a reference to the NodeMap of the edges of the
alpar@255
   140
    ///shortest path tree.
alpar@255
   141
    ///\pre \ref run() must be called before using this function.
alpar@255
   142
    const PredMap &predMap() const { return predecessor;}
alpar@255
   143
    ///Returns a reference to the map of nodes of  shortest paths.
alpar@255
   144
alpar@255
   145
    ///Returns a reference to the NodeMap of the last but one nodes of the
alpar@255
   146
    ///shortest paths.
alpar@255
   147
    ///\pre \ref run() must be called before using this function.
alpar@255
   148
    const PredNodeMap &predNodeMap() const { return pred_node;}
alpar@255
   149
alpar@255
   150
    //    bool reached(Node v) { return reach[v]; }
alpar@255
   151
alpar@255
   152
    ///Checks if a node is reachable from the source.
alpar@255
   153
alpar@255
   154
    ///Returns \c true if \c v is reachable from the source.
alpar@255
   155
    ///\warning the source node is reported to be unreached!
alpar@255
   156
    ///\todo Is this what we want?
alpar@255
   157
    ///\pre \ref run() must be called before using this function.
alpar@255
   158
    ///
alpar@255
   159
    bool reached(Node v) { return G.valid(predecessor[v]); }
alpar@255
   160
    
alpar@255
   161
  };
alpar@255
   162
  
alpar@255
   163
alpar@255
   164
  // **********************************************************************
alpar@255
   165
  //  IMPLEMENTATIONS
alpar@255
   166
  // **********************************************************************
alpar@255
   167
alpar@255
   168
  ///Runs %Dijkstra algorithm from node the source.
alpar@255
   169
alpar@255
   170
  ///This method runs the %Dijkstra algorithm from a source node \c s
alpar@255
   171
  ///in order to
alpar@255
   172
  ///compute the
alpar@255
   173
  ///shortest path to each node. The algorithm computes
alpar@255
   174
  ///- The shortest path tree.
alpar@255
   175
  ///- The distance of each node from the source.
alpar@255
   176
  template <typename Graph, typename LengthMap,
alpar@255
   177
	    template<class,class,class> class Heap >
alpar@255
   178
  void Dijkstra<Graph,LengthMap,Heap>::run(Node s) {
alpar@255
   179
    
alpar@255
   180
    NodeIt u;
alpar@255
   181
    for ( G.first(u) ; G.valid(u) ; G.next(u) ) {
alpar@255
   182
      predecessor.set(u,INVALID);
alpar@255
   183
      pred_node.set(u,INVALID);
alpar@255
   184
      // If a node is unreacheable, then why should be the dist=0?
alpar@255
   185
      // distance.set(u,0);
alpar@255
   186
      //      reach.set(u,false);
alpar@255
   187
    }
alpar@255
   188
    
alpar@255
   189
    //We don't need it at all.
alpar@255
   190
    //     //FIXME:
alpar@255
   191
    //     typename Graph::NodeMap<bool> scanned(G,false);
alpar@255
   192
    //     //typename Graph::NodeMap<int> scanned(G,false);
alpar@255
   193
    typename Graph::NodeMap<int> heap_map(G,-1);
alpar@255
   194
    
alpar@255
   195
    //Heap heap(heap_map);
alpar@255
   196
    Heap<Node,ValueType,typename Graph::NodeMap<int> > heap(heap_map);
alpar@255
   197
    
alpar@255
   198
    heap.push(s,0); 
alpar@255
   199
    //    reach.set(s, true);
alpar@255
   200
    
alpar@255
   201
      while ( !heap.empty() ) {
alpar@255
   202
	
alpar@255
   203
	Node v=heap.top(); 
alpar@255
   204
	ValueType oldvalue=heap[v];
alpar@255
   205
	heap.pop();
alpar@255
   206
	distance.set(v, oldvalue);
alpar@255
   207
	
athos@276
   208
	for(OutEdgeIt e = G.template first<OutEdgeIt>(v);
athos@276
   209
	    G.valid(e); G.next(e)) {
alpar@255
   210
	  Node w=G.head(e); 
alpar@255
   211
	  
alpar@255
   212
	  switch(heap.state(w)) {
alpar@255
   213
	  case heap.PRE_HEAP:
alpar@255
   214
	    //	    reach.set(w,true);
alpar@255
   215
	    heap.push(w,oldvalue+length[e]); 
alpar@255
   216
	    predecessor.set(w,e);
alpar@255
   217
	    pred_node.set(w,v);
alpar@255
   218
	    break;
alpar@255
   219
	  case heap.IN_HEAP:
alpar@255
   220
	    if ( oldvalue+length[e] < heap[w] ) {
alpar@255
   221
	      heap.decrease(w, oldvalue+length[e]); 
alpar@255
   222
	      predecessor.set(w,e);
alpar@255
   223
	      pred_node.set(w,v);
alpar@255
   224
	    }
alpar@255
   225
	    break;
alpar@255
   226
	  case heap.POST_HEAP:
alpar@255
   227
	    break;
alpar@255
   228
	  }
alpar@255
   229
	}
alpar@255
   230
      }
alpar@255
   231
  }
alpar@255
   232
  
alpar@255
   233
} //END OF NAMESPACE HUGO
alpar@255
   234
alpar@255
   235
#endif
alpar@255
   236
alpar@255
   237