00001 #ifndef BIDIRECTIONALDIJKSTRA_H
00002 #define BIDIRECTIONALDIJKSTRA_H
00003
00004 #include <Structs/Trees/priorityQueue.h>
00005
00006
00018 template<class GraphType>
00019 class BidirectionalDijkstra
00020 {
00021 public:
00022 typedef typename GraphType::NodeIterator NodeIterator;
00023 typedef typename GraphType::NodeDescriptor NodeDescriptor;
00024 typedef typename GraphType::EdgeIterator EdgeIterator;
00025 typedef typename GraphType::InEdgeIterator InEdgeIterator;
00026 typedef typename GraphType::SizeType SizeType;
00027 typedef unsigned int WeightType;
00028 typedef PriorityQueue< WeightType, NodeIterator, HeapStorage> PriorityQueueType;
00029
00036 BidirectionalDijkstra( GraphType& graph, unsigned int* timestamp):G(graph),m_timestamp(timestamp)
00037 {
00038 }
00039
00040
00048 WeightType runQuery( const typename GraphType::NodeIterator& s, const typename GraphType::NodeIterator& t)
00049 {
00050 NodeIterator u,v,lastNode;
00051 EdgeIterator e,lastEdge;
00052
00053 pqFront.clear();
00054 pqBack.clear();
00055 ++(*m_timestamp);
00056
00057 minDistance = std::numeric_limits<WeightType>::max();
00058
00059 s->dist = 0;
00060 s->timestamp = (*m_timestamp);
00061 s->pred = G.nilNodeDescriptor();
00062
00063 t->distBack = 0;
00064 t->timestamp = (*m_timestamp);
00065 t->succ = G.nilNodeDescriptor();
00066
00067 pqFront.insert( s->dist, s, &(s->pqitem));
00068 pqBack.insert( t->distBack, t, &(t->pqitemBack));
00069
00070 while( ! ( pqFront.empty() && pqBack.empty()))
00071 {
00072 curMin = 0;
00073 if( !pqFront.empty()) curMin += pqFront.minKey();
00074 if( !pqBack.empty()) curMin += pqBack.minKey();
00075 if( curMin > minDistance)
00076 {
00077 break;
00078 }
00079 searchForward();
00080 searchBackward( s);
00081 }
00082
00083 u = viaNode;
00084 t->dist = u->dist;
00085 while( u->succ != G.nilNodeDescriptor())
00086 {
00087 v = G.getNodeIterator(u->succ);
00088 v->pred = G.getNodeDescriptor( u);
00089 e = G.getEdgeIterator( u, v);
00090 t->dist += e->weight;
00091 u = v;
00092 }
00093 return t->dist;
00094 }
00095
00096 private:
00097 GraphType& G;
00098 unsigned int* m_timestamp;
00099 PriorityQueueType pqFront, pqBack;
00100 NodeIterator viaNode;
00101 WeightType curMin, minDistance;
00102
00103 bool isBackwardFound( const NodeIterator& u)
00104 {
00105 return (u->timestamp == (*m_timestamp)) && (u->distBack != std::numeric_limits<WeightType>::max());
00106 }
00107
00108 bool isBackwardSettled( const NodeIterator& u)
00109 {
00110 return isBackwardFound(u) && (!isInBackQueue(u));
00111 }
00112
00113 bool isForwardFound( const NodeIterator& u)
00114 {
00115 return (u->timestamp == (*m_timestamp)) && (u->dist != std::numeric_limits<WeightType>::max());
00116 }
00117
00118 bool isForwardSettled( const NodeIterator& u)
00119 {
00120 return isForwardFound(u) && (!isInFrontQueue(u));
00121 }
00122
00123 bool isInBackQueue( const NodeIterator& u)
00124 {
00125 return pqBack.contains( &(u->pqitemBack));
00126 }
00127
00128 bool isInFrontQueue( const NodeIterator& u)
00129 {
00130 return pqFront.contains( &(u->pqitem));
00131 }
00132
00133 void searchForward()
00134 {
00135 EdgeIterator e,lastEdge;
00136 NodeIterator u,v;
00137 if( !pqFront.empty())
00138 {
00139 u = pqFront.minItem();
00140 pqFront.popMin();
00141 for( e = G.beginEdges(u), lastEdge = G.endEdges(u); e != lastEdge; ++e)
00142 {
00143 v = G.target(e);
00144
00145 if( v->timestamp < (*m_timestamp))
00146 {
00147 v->pred = u->getDescriptor();
00148 v->dist = u->dist + e->weight;
00149 v->timestamp = (*m_timestamp);
00150 v->distBack = std::numeric_limits<WeightType>::max();
00151 pqFront.insert( v->dist, v, &(v->pqitem));
00152 }
00153 else if( v->dist == std::numeric_limits<WeightType>::max())
00154 {
00155 v->pred = u->getDescriptor();
00156 v->dist = u->dist + e->weight;
00157 pqFront.insert( v->dist, v, &(v->pqitem));
00158 }
00159 else if( v->dist > u->dist + e->weight )
00160 {
00161 v->pred = u->getDescriptor();
00162 v->dist = u->dist + e->weight;
00163 pqFront.decrease( v->dist, &(v->pqitem));
00164 }
00165
00166 if( isBackwardFound(v) && ( u->dist + e->weight + v->distBack < minDistance))
00167 {
00168 minDistance = u->dist +e->weight + v->distBack;
00169
00170 viaNode = v;
00171 }
00172 }
00173 }
00174 }
00175
00176 void searchBackward( const typename GraphType::NodeIterator& s)
00177 {
00178 InEdgeIterator k,lastInEdge;
00179 NodeIterator u,v;
00180 if( !pqBack.empty())
00181 {
00182 u = pqBack.minItem();
00183 pqBack.popMin();
00184 for( k = G.beginInEdges(u), lastInEdge = G.endInEdges(u); k != lastInEdge; ++k)
00185 {
00186 v = G.source(k);
00187
00188 if( v->timestamp < (*m_timestamp))
00189 {
00190 v->succ = u->getDescriptor();
00191 v->distBack = u->distBack + k->weight;
00192 v->timestamp = (*m_timestamp);
00193 v->dist = std::numeric_limits<WeightType>::max();
00194 pqBack.insert( v->distBack, v, &(v->pqitemBack));
00195 }
00196 else if( v->distBack == std::numeric_limits<WeightType>::max())
00197 {
00198 v->succ = u->getDescriptor();
00199 v->distBack = u->distBack + k->weight;
00200 pqBack.insert( v->distBack, v, &(v->pqitemBack));
00201 }
00202 else if( v->distBack > u->distBack + k->weight )
00203 {
00204 v->succ = u->getDescriptor();
00205 v->distBack = u->distBack + k->weight;
00206 pqBack.decrease( v->distBack, &(v->pqitemBack));
00207 }
00208 if( isForwardFound(v) && ( v->dist + k->weight + u->distBack < minDistance))
00209 {
00210 minDistance = v->dist +k->weight + u->distBack;
00211
00212 viaNode = v;
00213 }
00214 }
00215 }
00216 }
00217 };
00218
00219 #endif//BIDIRECTIONALDIJKSTRA_H
00220