00001
00007 #ifndef VVELIB_ALGORITHMS_GRAPH_H
00008 #define VVELIB_ALGORITHMS_GRAPH_H
00009
00010 #include <config.h>
00011 #include <graph/vvgraph.h>
00012 #include <set>
00013 #include <util/unorderedset.h>
00014 #include <utility>
00015
00016 namespace algorithms
00017 {
00018
00020
00021 namespace shortest_path
00022 {
00023 template <typename VertexContent>
00024 struct DistanceStructure
00025 {
00026 DistanceStructure(const graph::Vertex<VertexContent>& tgt, double d, const graph::Vertex<VertexContent>& src)
00027 : distance(d)
00028 , source(src)
00029 , target(tgt)
00030 { }
00031 double distance;
00032 graph::Vertex<VertexContent> source, target;
00033 };
00034
00035 template <typename VertexContent>
00036 DistanceStructure<VertexContent> make_distance(const graph::Vertex<VertexContent>& tgt, double distance, const graph::Vertex<VertexContent>& src)
00037 {
00038 return DistanceStructure<VertexContent>(tgt, distance, src);
00039 }
00040
00041 struct no_sp_tag {};
00042
00043 template <typename VertexContent, typename Model, typename tag_t>
00044 double distance( const graph::Vertex<VertexContent>& tgt, const Model& m, const tag_t& t)
00045 {
00046 return m.graphDistance(tgt, t);
00047 }
00048
00049 template <typename VertexContent, typename Model>
00050 double distance( const graph::Vertex<VertexContent>& tgt, const Model& m, const no_sp_tag&)
00051 {
00052 return m.graphDistance(tgt);
00053 }
00054
00055 template <typename VertexContent, typename Model, typename tag_t>
00056 double distance( const graph::Vertex<VertexContent>& src, const graph::Vertex<VertexContent>& tgt, const Model& m, const tag_t& t)
00057 {
00058 if(src == tgt)
00059 return 0;
00060 return m.graphDistance(src, tgt, t);
00061 }
00062
00063 template <typename VertexContent, typename Model>
00064 double distance( const graph::Vertex<VertexContent>& src, const graph::Vertex<VertexContent>& tgt, const Model& m, const no_sp_tag&)
00065 {
00066 if(src == tgt)
00067 return 0;
00068 return m.graphDistance(src, tgt);
00069 }
00070
00071 template <typename VertexContent, typename Model, typename tag_t>
00072 void setDistance( const graph::Vertex<VertexContent>& src, const graph::Vertex<VertexContent>& tgt, double dist, Model& m, const tag_t& t)
00073 {
00074 m.setGraphDistance(src, tgt, dist, t);
00075 }
00076
00077 template <typename VertexContent, typename Model>
00078 void setDistance( const graph::Vertex<VertexContent>& src, const graph::Vertex<VertexContent>& tgt, double dist, Model& m, const no_sp_tag&)
00079 {
00080 m.setGraphDistance(src, tgt, dist);
00081 }
00082
00083 template <typename VertexContent, typename Model, typename tag_t>
00084 double edgeWeight( const Vertex<VertexContent>& src, const Vertex<VertexContent>& tgt, const Model& m, const tag_t& t)
00085 {
00086 return m.edgeWeight(src, tgt, t);
00087 }
00088
00089 template <typename VertexContent, typename Model>
00090 double edgeWeight( const Vertex<VertexContent>& src, const Vertex<VertexContent>& tgt, const Model& m, const no_sp_tag&)
00091 {
00092 return m.edgeWeight(src, tgt);
00093 }
00094
00095 template <typename VertexContent>
00096 struct CompareWeightedVertexes
00097 {
00098 typedef graph::Vertex<VertexContent> vertex;
00099 typedef std::pair<vertex,double> value_type;
00100 bool operator()(const value_type& v1, const value_type& v2) const
00101 {
00102 if(v1.second == v2.second)
00103 return v1.first < v2.first;
00104 return v1.second < v2.second;
00105 }
00106 };
00107
00108 template <typename VertexContent>
00109 struct CompareDistances
00110 {
00111 typedef DistanceStructure<VertexContent> value_type;
00112 bool operator()(const value_type& v1, const value_type& v2) const
00113 {
00114 double d1 = v1.distance;
00115 double d2 = v2.distance;
00116 if(d1 == d2)
00117 return v1.target < v2.target;
00118 return d1 < d2;
00119 }
00120 };
00121
00122 }
00123
00125
00153 template <typename VertexContent, typename EdgeContent, bool compact, typename Model, typename tag_t>
00154 void shortest_paths_FloydWarshall( const graph::VVGraph<VertexContent,EdgeContent,compact>& m, Model& model, const tag_t& t )
00155 {
00156 typedef graph::VVGraph<VertexContent,EdgeContent,compact> vvgraph;
00157 typedef typename vvgraph::vertex_t vertex;
00158
00159 forall(const vertex& v1, m)
00160 {
00161 forall(const vertex& v2, m)
00162 {
00163 if(v1 != v2)
00164 {
00165 shortest_path::setDistance(v1, v2, m.edge(v1, v2)?shortest_path::edgeWeight(v1,v2,model,t):HUGE_VAL,model,t);
00166 shortest_path::setDistance(v2, v1, m.edge(v2, v1)?shortest_path::edgeWeight(v2,v1,model,t):HUGE_VAL,model,t);
00167 }
00168 }
00169 }
00170
00171 forall(const vertex& k, m)
00172 {
00173 forall(const vertex& i, m)
00174 {
00175 forall(const vertex& j, m)
00176 {
00177 if( i != j )
00178 {
00179 double dist = shortest_path::distance(i,k,model,t) + shortest_path::distance(k,j,model,t);
00180 if(dist < shortest_path::distance(i,j,model,t))
00181 {
00182 shortest_path::setDistance(i,j,dist,model,t);
00183 }
00184 }
00185 }
00186 }
00187 }
00188 }
00189
00196 template <typename VVGraph, typename Model>
00197 void shortest_paths_FloydWarshall( const VVGraph& m, const Model& model)
00198 {
00199 shortest_paths_FloydWarshall(m, model, shortest_path::no_sp_tag());
00200 }
00201
00215 template <typename VertexContent, typename EdgeContent, bool compact, typename Model, typename tag_t>
00216 void shortest_paths_Dijkstra( const Vertex<VertexContent>& src, const graph::VVGraph<VertexContent,EdgeContent,compact>& m, Model& model, const tag_t& t)
00217 {
00218 typedef graph::VVGraph<VertexContent,EdgeContent,compact> vvgraph;
00219 typedef typename vvgraph::vertex_t vertex;
00220 std::set<std::pair<vertex,double>,shortest_path::CompareWeightedVertexes<VertexContent> > active_vertexes;
00221 active_vertexes.insert(std::make_pair(src,0));
00222 forall(const vertex& v, m)
00223 {
00224 if(v != src)
00225 {
00226 shortest_path::setDistance(src, v, HUGE_VAL, model, t);
00227 }
00228 }
00229 while(!active_vertexes.empty())
00230 {
00231 std::pair<vertex,double> av = *active_vertexes.begin();
00232 active_vertexes.erase(active_vertexes.begin());
00233 double dist = av.second;
00234 forall(const vertex& v, m.neighbors(av.first))
00235 {
00236 double w = shortest_path::edgeWeight(av.first,v,model,t);
00237 double d1 = dist+w;
00238 if(d1 < shortest_path::distance(src,v,model,t))
00239 {
00240 shortest_path::setDistance(src,v,d1,model,t);
00241 active_vertexes.insert(std::make_pair(v,d1));
00242 }
00243 }
00244 }
00245 }
00246
00247 template <typename VertexContent, typename EdgeContent, bool compact, typename Model>
00248 void shortest_paths_Dijkstra( const Vertex<VertexContent>& src, const graph::VVGraph<VertexContent,EdgeContent,compact>& m, const Model& model)
00249 {
00250 shortest_paths_Dijkstra(src, m, model, shortest_path::no_sp_tag());
00251 }
00252
00256 template <typename VertexContent, typename EdgeContent, bool compact, typename Model, typename tag_t>
00257 void shortest_paths_Dijkstra( const std::unordered_set<Vertex<VertexContent> >& srcs, const graph::VVGraph<VertexContent,EdgeContent,compact>& m, Model& model, const tag_t& t)
00258 {
00259 typedef graph::VVGraph<VertexContent,EdgeContent,compact> vvgraph;
00260 typedef typename vvgraph::vertex_t vertex;
00261 std::set<shortest_path::DistanceStructure<VertexContent>,shortest_path::CompareDistances<VertexContent> > active_vertexes;
00262 forall(const vertex& v, srcs)
00263 {
00264 active_vertexes.insert(shortest_path::make_distance(v,0,v));
00265 }
00266 while(!active_vertexes.empty())
00267 {
00268 shortest_path::DistanceStructure<VertexContent> av = *active_vertexes.begin();
00269 active_vertexes.erase(active_vertexes.begin());
00270 double dist = av.distance;
00271 forall(const vertex& v, m.neighbors(av.target))
00272 {
00273 double w = shortest_path::edgeWeight(av.target,v,model,t);
00274 double d1 = dist+w;
00275 if(d1 < shortest_path::distance(v,model,t))
00276 {
00277 shortest_path::setDistance(av.source,v,d1,model,t);
00278 active_vertexes.insert(shortest_path::make_distance(v,d1,av.source));
00279 }
00280 }
00281 }
00282 }
00283
00284
00285 };
00286
00287 #endif // VVELIB_ALGORITHMS_GRAPH_H