/Src/Dependencies/Boost/boost/graph/strong_components.hpp

http://hadesmem.googlecode.com/ · C++ Header · 341 lines · 267 code · 43 blank · 31 comment · 19 complexity · 827a9b8c614f18839885b5d9281cd941 MD5 · raw file

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