annotate DEPENDENCIES/generic/include/boost/graph/strong_components.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 //
Chris@16 2 //=======================================================================
Chris@16 3 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
Chris@16 4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
Chris@16 5 //
Chris@16 6 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 7 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 8 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //=======================================================================
Chris@16 10 //
Chris@16 11
Chris@16 12 #ifndef BOOST_GRAPH_STRONG_COMPONENTS_HPP
Chris@16 13 #define BOOST_GRAPH_STRONG_COMPONENTS_HPP
Chris@16 14
Chris@16 15 #include <stack>
Chris@16 16 #include <boost/config.hpp>
Chris@16 17 #include <boost/graph/depth_first_search.hpp>
Chris@16 18 #include <boost/type_traits/conversion_traits.hpp>
Chris@16 19 #include <boost/static_assert.hpp>
Chris@16 20 #include <boost/graph/overloading.hpp>
Chris@16 21 #include <boost/concept/assert.hpp>
Chris@16 22
Chris@16 23 namespace boost {
Chris@16 24
Chris@16 25 //==========================================================================
Chris@16 26 // This is Tarjan's algorithm for strongly connected components
Chris@16 27 // from his paper "Depth first search and linear graph algorithms".
Chris@16 28 // It calculates the components in a single application of DFS.
Chris@16 29 // We implement the algorithm as a dfs-visitor.
Chris@16 30
Chris@16 31 namespace detail {
Chris@16 32
Chris@16 33 template <typename ComponentMap, typename RootMap, typename DiscoverTime,
Chris@16 34 typename Stack>
Chris@16 35 class tarjan_scc_visitor : public dfs_visitor<>
Chris@16 36 {
Chris@16 37 typedef typename property_traits<ComponentMap>::value_type comp_type;
Chris@16 38 typedef typename property_traits<DiscoverTime>::value_type time_type;
Chris@16 39 public:
Chris@16 40 tarjan_scc_visitor(ComponentMap comp_map, RootMap r, DiscoverTime d,
Chris@16 41 comp_type& c_, Stack& s_)
Chris@16 42 : c(c_), comp(comp_map), root(r), discover_time(d),
Chris@16 43 dfs_time(time_type()), s(s_) { }
Chris@16 44
Chris@16 45 template <typename Graph>
Chris@16 46 void discover_vertex(typename graph_traits<Graph>::vertex_descriptor v,
Chris@16 47 const Graph&) {
Chris@16 48 put(root, v, v);
Chris@16 49 put(comp, v, (std::numeric_limits<comp_type>::max)());
Chris@16 50 put(discover_time, v, dfs_time++);
Chris@16 51 s.push(v);
Chris@16 52 }
Chris@16 53 template <typename Graph>
Chris@16 54 void finish_vertex(typename graph_traits<Graph>::vertex_descriptor v,
Chris@16 55 const Graph& g) {
Chris@16 56 typename graph_traits<Graph>::vertex_descriptor w;
Chris@16 57 typename graph_traits<Graph>::out_edge_iterator ei, ei_end;
Chris@16 58 for (boost::tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
Chris@16 59 w = target(*ei, g);
Chris@16 60 if (get(comp, w) == (std::numeric_limits<comp_type>::max)())
Chris@16 61 put(root, v, this->min_discover_time(get(root,v), get(root,w)));
Chris@16 62 }
Chris@16 63 if (get(root, v) == v) {
Chris@16 64 do {
Chris@16 65 w = s.top(); s.pop();
Chris@16 66 put(comp, w, c);
Chris@16 67 } while (w != v);
Chris@16 68 ++c;
Chris@16 69 }
Chris@16 70 }
Chris@16 71 private:
Chris@16 72 template <typename Vertex>
Chris@16 73 Vertex min_discover_time(Vertex u, Vertex v) {
Chris@16 74 return get(discover_time, u) < get(discover_time,v) ? u : v;
Chris@16 75 }
Chris@16 76
Chris@16 77 comp_type& c;
Chris@16 78 ComponentMap comp;
Chris@16 79 RootMap root;
Chris@16 80 DiscoverTime discover_time;
Chris@16 81 time_type dfs_time;
Chris@16 82 Stack& s;
Chris@16 83 };
Chris@16 84
Chris@16 85 template <class Graph, class ComponentMap, class RootMap,
Chris@16 86 class DiscoverTime, class P, class T, class R>
Chris@16 87 typename property_traits<ComponentMap>::value_type
Chris@16 88 strong_components_impl
Chris@16 89 (const Graph& g, // Input
Chris@16 90 ComponentMap comp, // Output
Chris@16 91 // Internal record keeping
Chris@16 92 RootMap root,
Chris@16 93 DiscoverTime discover_time,
Chris@16 94 const bgl_named_params<P, T, R>& params)
Chris@16 95 {
Chris@16 96 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 97 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ComponentMap, Vertex> ));
Chris@16 98 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<RootMap, Vertex> ));
Chris@16 99 typedef typename property_traits<RootMap>::value_type RootV;
Chris@16 100 BOOST_CONCEPT_ASSERT(( ConvertibleConcept<RootV, Vertex> ));
Chris@16 101 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<DiscoverTime, Vertex> ));
Chris@16 102
Chris@16 103 typename property_traits<ComponentMap>::value_type total = 0;
Chris@16 104
Chris@16 105 std::stack<Vertex> s;
Chris@16 106 detail::tarjan_scc_visitor<ComponentMap, RootMap, DiscoverTime,
Chris@16 107 std::stack<Vertex> >
Chris@16 108 vis(comp, root, discover_time, total, s);
Chris@16 109 depth_first_search(g, params.visitor(vis));
Chris@16 110 return total;
Chris@16 111 }
Chris@16 112
Chris@16 113 //-------------------------------------------------------------------------
Chris@16 114 // The dispatch functions handle the defaults for the rank and discover
Chris@16 115 // time property maps.
Chris@16 116 // dispatch with class specialization to avoid VC++ bug
Chris@16 117
Chris@16 118 template <class DiscoverTimeMap>
Chris@16 119 struct strong_comp_dispatch2 {
Chris@16 120 template <class Graph, class ComponentMap, class RootMap, class P, class T, class R>
Chris@16 121 inline static typename property_traits<ComponentMap>::value_type
Chris@16 122 apply(const Graph& g,
Chris@16 123 ComponentMap comp,
Chris@16 124 RootMap r_map,
Chris@16 125 const bgl_named_params<P, T, R>& params,
Chris@16 126 DiscoverTimeMap time_map)
Chris@16 127 {
Chris@16 128 return strong_components_impl(g, comp, r_map, time_map, params);
Chris@16 129 }
Chris@16 130 };
Chris@16 131
Chris@16 132
Chris@16 133 template <>
Chris@16 134 struct strong_comp_dispatch2<param_not_found> {
Chris@16 135 template <class Graph, class ComponentMap, class RootMap,
Chris@16 136 class P, class T, class R>
Chris@16 137 inline static typename property_traits<ComponentMap>::value_type
Chris@16 138 apply(const Graph& g,
Chris@16 139 ComponentMap comp,
Chris@16 140 RootMap r_map,
Chris@16 141 const bgl_named_params<P, T, R>& params,
Chris@16 142 param_not_found)
Chris@16 143 {
Chris@16 144 typedef typename graph_traits<Graph>::vertices_size_type size_type;
Chris@16 145 size_type n = num_vertices(g) > 0 ? num_vertices(g) : 1;
Chris@16 146 std::vector<size_type> time_vec(n);
Chris@16 147 return strong_components_impl
Chris@16 148 (g, comp, r_map,
Chris@16 149 make_iterator_property_map(time_vec.begin(), choose_const_pmap
Chris@16 150 (get_param(params, vertex_index),
Chris@16 151 g, vertex_index), time_vec[0]),
Chris@16 152 params);
Chris@16 153 }
Chris@16 154 };
Chris@16 155
Chris@16 156 template <class Graph, class ComponentMap, class RootMap,
Chris@16 157 class P, class T, class R, class DiscoverTimeMap>
Chris@16 158 inline typename property_traits<ComponentMap>::value_type
Chris@16 159 scc_helper2(const Graph& g,
Chris@16 160 ComponentMap comp,
Chris@16 161 RootMap r_map,
Chris@16 162 const bgl_named_params<P, T, R>& params,
Chris@16 163 DiscoverTimeMap time_map)
Chris@16 164 {
Chris@16 165 return strong_comp_dispatch2<DiscoverTimeMap>::apply(g, comp, r_map, params, time_map);
Chris@16 166 }
Chris@16 167
Chris@16 168 template <class RootMap>
Chris@16 169 struct strong_comp_dispatch1 {
Chris@16 170
Chris@16 171 template <class Graph, class ComponentMap, class P, class T, class R>
Chris@16 172 inline static typename property_traits<ComponentMap>::value_type
Chris@16 173 apply(const Graph& g,
Chris@16 174 ComponentMap comp,
Chris@16 175 const bgl_named_params<P, T, R>& params,
Chris@16 176 RootMap r_map)
Chris@16 177 {
Chris@16 178 return scc_helper2(g, comp, r_map, params, get_param(params, vertex_discover_time));
Chris@16 179 }
Chris@16 180 };
Chris@16 181 template <>
Chris@16 182 struct strong_comp_dispatch1<param_not_found> {
Chris@16 183
Chris@16 184 template <class Graph, class ComponentMap,
Chris@16 185 class P, class T, class R>
Chris@16 186 inline static typename property_traits<ComponentMap>::value_type
Chris@16 187 apply(const Graph& g,
Chris@16 188 ComponentMap comp,
Chris@16 189 const bgl_named_params<P, T, R>& params,
Chris@16 190 param_not_found)
Chris@16 191 {
Chris@16 192 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 193 typename std::vector<Vertex>::size_type
Chris@16 194 n = num_vertices(g) > 0 ? num_vertices(g) : 1;
Chris@16 195 std::vector<Vertex> root_vec(n);
Chris@16 196 return scc_helper2
Chris@16 197 (g, comp,
Chris@16 198 make_iterator_property_map(root_vec.begin(), choose_const_pmap
Chris@16 199 (get_param(params, vertex_index),
Chris@16 200 g, vertex_index), root_vec[0]),
Chris@16 201 params,
Chris@16 202 get_param(params, vertex_discover_time));
Chris@16 203 }
Chris@16 204 };
Chris@16 205
Chris@16 206 template <class Graph, class ComponentMap, class RootMap,
Chris@16 207 class P, class T, class R>
Chris@16 208 inline typename property_traits<ComponentMap>::value_type
Chris@16 209 scc_helper1(const Graph& g,
Chris@16 210 ComponentMap comp,
Chris@16 211 const bgl_named_params<P, T, R>& params,
Chris@16 212 RootMap r_map)
Chris@16 213 {
Chris@16 214 return detail::strong_comp_dispatch1<RootMap>::apply(g, comp, params,
Chris@16 215 r_map);
Chris@16 216 }
Chris@16 217
Chris@16 218 } // namespace detail
Chris@16 219
Chris@16 220 template <class Graph, class ComponentMap,
Chris@16 221 class P, class T, class R>
Chris@16 222 inline typename property_traits<ComponentMap>::value_type
Chris@16 223 strong_components(const Graph& g, ComponentMap comp,
Chris@16 224 const bgl_named_params<P, T, R>& params
Chris@16 225 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag))
Chris@16 226 {
Chris@16 227 typedef typename graph_traits<Graph>::directed_category DirCat;
Chris@16 228 BOOST_STATIC_ASSERT((is_convertible<DirCat*, directed_tag*>::value == true));
Chris@16 229 return detail::scc_helper1(g, comp, params,
Chris@16 230 get_param(params, vertex_root_t()));
Chris@16 231 }
Chris@16 232
Chris@16 233 template <class Graph, class ComponentMap>
Chris@16 234 inline typename property_traits<ComponentMap>::value_type
Chris@16 235 strong_components(const Graph& g, ComponentMap comp
Chris@16 236 BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag))
Chris@16 237 {
Chris@16 238 typedef typename graph_traits<Graph>::directed_category DirCat;
Chris@16 239 BOOST_STATIC_ASSERT((is_convertible<DirCat*, directed_tag*>::value == true));
Chris@16 240 bgl_named_params<int, int> params(0);
Chris@16 241 return strong_components(g, comp, params);
Chris@16 242 }
Chris@16 243
Chris@16 244 template <typename Graph, typename ComponentMap, typename ComponentLists>
Chris@16 245 void build_component_lists
Chris@16 246 (const Graph& g,
Chris@16 247 typename graph_traits<Graph>::vertices_size_type num_scc,
Chris@16 248 ComponentMap component_number,
Chris@16 249 ComponentLists& components)
Chris@16 250 {
Chris@16 251 components.resize(num_scc);
Chris@16 252 typename graph_traits<Graph>::vertex_iterator vi, vi_end;
Chris@16 253 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
Chris@16 254 components[component_number[*vi]].push_back(*vi);
Chris@16 255 }
Chris@16 256
Chris@16 257
Chris@16 258 } // namespace boost
Chris@16 259
Chris@16 260 #include <queue>
Chris@16 261 #include <vector>
Chris@16 262 #include <boost/graph/transpose_graph.hpp>
Chris@16 263 #include <boost/pending/indirect_cmp.hpp>
Chris@16 264 #include <boost/graph/connected_components.hpp> // for components_recorder
Chris@16 265
Chris@16 266 namespace boost {
Chris@16 267
Chris@16 268 //==========================================================================
Chris@16 269 // This is the version of strongly connected components from
Chris@16 270 // "Intro. to Algorithms" by Cormen, Leiserson, Rivest, which was
Chris@16 271 // adapted from "Data Structure and Algorithms" by Aho, Hopcroft,
Chris@16 272 // and Ullman, who credit the algorithm to S.R. Kosaraju and M. Sharir.
Chris@16 273 // The algorithm is based on computing DFS forests the graph
Chris@16 274 // and its transpose.
Chris@16 275
Chris@16 276 // This algorithm is slower than Tarjan's by a constant factor, uses
Chris@16 277 // more memory, and puts more requirements on the graph type.
Chris@16 278
Chris@16 279 template <class Graph, class DFSVisitor, class ComponentsMap,
Chris@16 280 class DiscoverTime, class FinishTime,
Chris@16 281 class ColorMap>
Chris@16 282 typename property_traits<ComponentsMap>::value_type
Chris@16 283 kosaraju_strong_components(Graph& G, ComponentsMap c,
Chris@16 284 FinishTime finish_time, ColorMap color)
Chris@16 285 {
Chris@16 286 BOOST_CONCEPT_ASSERT(( MutableGraphConcept<Graph> ));
Chris@16 287 // ...
Chris@16 288
Chris@16 289 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
Chris@16 290 typedef typename property_traits<ColorMap>::value_type ColorValue;
Chris@16 291 typedef color_traits<ColorValue> Color;
Chris@16 292 typename property_traits<FinishTime>::value_type time = 0;
Chris@16 293 depth_first_search
Chris@16 294 (G, make_dfs_visitor(stamp_times(finish_time, time, on_finish_vertex())),
Chris@16 295 color);
Chris@16 296
Chris@16 297 Graph G_T(num_vertices(G));
Chris@16 298 transpose_graph(G, G_T);
Chris@16 299
Chris@16 300 typedef typename property_traits<ComponentsMap>::value_type count_type;
Chris@16 301
Chris@16 302 count_type c_count(0);
Chris@16 303 detail::components_recorder<ComponentsMap>
Chris@16 304 vis(c, c_count);
Chris@16 305
Chris@16 306 // initialize G_T
Chris@16 307 typename graph_traits<Graph>::vertex_iterator ui, ui_end;
Chris@16 308 for (boost::tie(ui, ui_end) = vertices(G_T); ui != ui_end; ++ui)
Chris@16 309 put(color, *ui, Color::white());
Chris@16 310
Chris@16 311 typedef typename property_traits<FinishTime>::value_type D;
Chris@16 312 typedef indirect_cmp< FinishTime, std::less<D> > Compare;
Chris@16 313
Chris@16 314 Compare fl(finish_time);
Chris@16 315 std::priority_queue<Vertex, std::vector<Vertex>, Compare > Q(fl);
Chris@16 316
Chris@16 317 typename graph_traits<Graph>::vertex_iterator i, j, iend, jend;
Chris@16 318 boost::tie(i, iend) = vertices(G_T);
Chris@16 319 boost::tie(j, jend) = vertices(G);
Chris@16 320 for ( ; i != iend; ++i, ++j) {
Chris@16 321 put(finish_time, *i, get(finish_time, *j));
Chris@16 322 Q.push(*i);
Chris@16 323 }
Chris@16 324
Chris@16 325 while ( !Q.empty() ) {
Chris@16 326 Vertex u = Q.top();
Chris@16 327 Q.pop();
Chris@16 328 if (get(color, u) == Color::white()) {
Chris@16 329 depth_first_visit(G_T, u, vis, color);
Chris@16 330 ++c_count;
Chris@16 331 }
Chris@16 332 }
Chris@16 333 return c_count;
Chris@16 334 }
Chris@16 335
Chris@16 336 } // namespace boost
Chris@16 337
Chris@16 338 #ifdef BOOST_GRAPH_USE_MPI
Chris@16 339 # include <boost/graph/distributed/strong_components.hpp>
Chris@16 340 #endif
Chris@16 341
Chris@16 342 #endif // BOOST_GRAPH_STRONG_COMPONENTS_HPP