depth_first_search.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // Copyright (C) 2004-2008 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #ifndef BOOST_GRAPH_DISTRIBUTED_DFS_HPP
  8. #define BOOST_GRAPH_DISTRIBUTED_DFS_HPP
  9. #ifndef BOOST_GRAPH_USE_MPI
  10. #error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
  11. #endif
  12. #include <boost/graph/graph_traits.hpp>
  13. #include <boost/property_map/property_map.hpp>
  14. #include <boost/property_map/parallel/parallel_property_maps.hpp>
  15. #include <boost/graph/overloading.hpp>
  16. #include <boost/graph/properties.hpp>
  17. #include <boost/graph/distributed/concepts.hpp>
  18. #include <boost/static_assert.hpp>
  19. #include <boost/assert.hpp>
  20. #include <boost/graph/parallel/process_group.hpp>
  21. #include <boost/graph/parallel/container_traits.hpp>
  22. namespace boost {
  23. namespace graph { namespace distributed { namespace detail {
  24. template<typename DistributedGraph, typename ColorMap, typename ParentMap,
  25. typename ExploreMap, typename VertexIndexMap, typename DFSVisitor>
  26. class parallel_dfs
  27. {
  28. typedef typename graph_traits<DistributedGraph>::vertex_iterator
  29. vertex_iterator;
  30. typedef typename graph_traits<DistributedGraph>::vertex_descriptor
  31. vertex_descriptor;
  32. typedef typename graph_traits<DistributedGraph>::out_edge_iterator
  33. out_edge_iterator;
  34. typedef typename boost::graph::parallel::process_group_type<DistributedGraph>
  35. ::type process_group_type;
  36. typedef typename process_group_type::process_id_type process_id_type;
  37. /**
  38. * The first vertex in the pair is the local node (i) and the
  39. * second vertex in the pair is the (possibly remote) node (j).
  40. */
  41. typedef boost::parallel::detail::untracked_pair<vertex_descriptor, vertex_descriptor> vertex_pair;
  42. typedef typename property_traits<ColorMap>::value_type color_type;
  43. typedef color_traits<color_type> Color;
  44. // Message types
  45. enum { discover_msg = 10, return_msg = 50, visited_msg = 100 , done_msg = 150};
  46. public:
  47. parallel_dfs(const DistributedGraph& g, ColorMap color,
  48. ParentMap parent, ExploreMap explore,
  49. VertexIndexMap index_map, DFSVisitor vis)
  50. : g(g), color(color), parent(parent), explore(explore),
  51. index_map(index_map), vis(vis), pg(process_group(g)),
  52. owner(get(vertex_owner, g)), next_out_edge(num_vertices(g))
  53. { }
  54. void run(vertex_descriptor s)
  55. {
  56. vertex_iterator vi, vi_end;
  57. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
  58. put(color, *vi, Color::white());
  59. put(parent, *vi, *vi);
  60. put(explore, *vi, *vi);
  61. next_out_edge[get(index_map, *vi)] = out_edges(*vi, g).first;
  62. vis.initialize_vertex(*vi, g);
  63. }
  64. vis.start_vertex(s, g);
  65. if (get(owner, s) == process_id(pg)) {
  66. send_oob(pg, get(owner, s), discover_msg, vertex_pair(s, s));
  67. }
  68. bool done = false;
  69. while (!done) {
  70. std::pair<process_id_type, int> msg = *pg.poll(true);
  71. switch (msg.second) {
  72. case discover_msg:
  73. {
  74. vertex_pair p;
  75. receive_oob(pg, msg.first, msg.second, p);
  76. if (p.first != p.second) {
  77. // delete j from nomessage(j)
  78. if (get(color, p.second) != Color::black())
  79. local_put(color, p.second, Color::gray());
  80. if (recover(p)) break;
  81. }
  82. if (get(color, p.first) == Color::white()) {
  83. put(color, p.first, Color::gray());
  84. put(parent, p.first, p.second);
  85. vis.discover_vertex(p.first, g);
  86. if (shift_center_of_activity(p.first)) break;
  87. out_edge_iterator ei, ei_end;
  88. for (boost::tie(ei,ei_end) = out_edges(p.first, g); ei != ei_end; ++ei)
  89. {
  90. // Notify everyone who may not know that the source
  91. // vertex has been visited. They can then mark the
  92. // corresponding color map entry gray.
  93. if (get(parent, p.first) != target(*ei, g)
  94. && get(explore, p.first) != target(*ei, g)) {
  95. vertex_pair visit(target(*ei, g), p.first);
  96. send_oob(pg, get(owner, target(*ei, g)), visited_msg, visit);
  97. }
  98. }
  99. }
  100. }
  101. break;
  102. case visited_msg:
  103. {
  104. vertex_pair p;
  105. receive_oob(pg, msg.first, msg.second, p);
  106. // delete j from nomessage(j)
  107. if (get(color, p.second) != Color::black())
  108. local_put(color, p.second, Color::gray());
  109. recover(p);
  110. }
  111. break;
  112. case return_msg:
  113. {
  114. vertex_pair p;
  115. receive_oob(pg, msg.first, msg.second, p);
  116. // delete j from nomessage(i)
  117. local_put(color, p.second, Color::black());
  118. shift_center_of_activity(p.first);
  119. }
  120. break;
  121. case done_msg:
  122. {
  123. receive_oob(pg, msg.first, msg.second, done);
  124. // Propagate done message downward in tree
  125. done = true;
  126. process_id_type id = process_id(pg);
  127. process_id_type left = 2*id + 1;
  128. process_id_type right = left + 1;
  129. if (left < num_processes(pg))
  130. send_oob(pg, left, done_msg, done);
  131. if (right < num_processes(pg))
  132. send_oob(pg, right, done_msg, done);
  133. }
  134. break;
  135. default:
  136. BOOST_ASSERT(false);
  137. }
  138. }
  139. }
  140. private:
  141. bool recover(const vertex_pair& p)
  142. {
  143. if (get(explore, p.first) == p.second) {
  144. return shift_center_of_activity(p.first);
  145. }
  146. else
  147. return false;
  148. }
  149. bool shift_center_of_activity(vertex_descriptor i)
  150. {
  151. for (out_edge_iterator ei = next_out_edge[get(index_map, i)],
  152. ei_end = out_edges(i, g).second;
  153. ei != ei_end; ++ei) {
  154. vis.examine_edge(*ei, g);
  155. vertex_descriptor k = target(*ei, g);
  156. color_type target_color = get(color, k);
  157. if (target_color == Color::black()) vis.forward_or_cross_edge(*ei, g);
  158. else if (target_color == Color::gray()) vis.back_edge(*ei, g);
  159. else {
  160. put(explore, i, k);
  161. vis.tree_edge(*ei, g);
  162. vertex_pair p(k, i);
  163. send_oob(pg, get(owner, k), discover_msg, p);
  164. next_out_edge[get(index_map, i)] = ++ei;
  165. return false;
  166. }
  167. }
  168. next_out_edge[get(index_map, i)] = out_edges(i, g).second;
  169. put(explore, i, i);
  170. put(color, i, Color::black());
  171. vis.finish_vertex(i, g);
  172. if (get(parent, i) == i) {
  173. send_oob(pg, 0, done_msg, true);
  174. return true;
  175. }
  176. else {
  177. vertex_pair ret(get(parent, i), i);
  178. send_oob(pg, get(owner, ret.first), return_msg, ret);
  179. }
  180. return false;
  181. }
  182. const DistributedGraph& g;
  183. ColorMap color;
  184. ParentMap parent;
  185. ExploreMap explore;
  186. VertexIndexMap index_map;
  187. DFSVisitor vis;
  188. process_group_type pg;
  189. typename property_map<DistributedGraph, vertex_owner_t>::const_type owner;
  190. std::vector<out_edge_iterator> next_out_edge;
  191. };
  192. } // end namespace detail
  193. template<typename DistributedGraph, typename ColorMap, typename ParentMap,
  194. typename ExploreMap, typename VertexIndexMap, typename DFSVisitor>
  195. void
  196. tsin_depth_first_visit
  197. (const DistributedGraph& g,
  198. typename graph_traits<DistributedGraph>::vertex_descriptor s,
  199. DFSVisitor vis, ColorMap color, ParentMap parent, ExploreMap explore,
  200. VertexIndexMap index_map)
  201. {
  202. typedef typename graph_traits<DistributedGraph>::directed_category
  203. directed_category;
  204. BOOST_STATIC_ASSERT(
  205. (is_convertible<directed_category, undirected_tag>::value));
  206. set_property_map_role(vertex_color, color);
  207. graph::distributed::detail::parallel_dfs
  208. <DistributedGraph, ColorMap, ParentMap, ExploreMap, VertexIndexMap,
  209. DFSVisitor> do_dfs(g, color, parent, explore, index_map, vis);
  210. do_dfs.run(s);
  211. using boost::graph::parallel::process_group;
  212. synchronize(process_group(g));
  213. }
  214. template<typename DistributedGraph, typename DFSVisitor,
  215. typename VertexIndexMap>
  216. void
  217. tsin_depth_first_visit
  218. (const DistributedGraph& g,
  219. typename graph_traits<DistributedGraph>::vertex_descriptor s,
  220. DFSVisitor vis,
  221. VertexIndexMap index_map)
  222. {
  223. typedef typename graph_traits<DistributedGraph>::vertex_descriptor
  224. vertex_descriptor;
  225. std::vector<default_color_type> colors(num_vertices(g));
  226. std::vector<vertex_descriptor> parent(num_vertices(g));
  227. std::vector<vertex_descriptor> explore(num_vertices(g));
  228. tsin_depth_first_visit
  229. (g, s,
  230. vis,
  231. make_iterator_property_map(colors.begin(), index_map),
  232. make_iterator_property_map(parent.begin(), index_map),
  233. make_iterator_property_map(explore.begin(), index_map),
  234. index_map);
  235. }
  236. template<typename DistributedGraph, typename DFSVisitor,
  237. typename VertexIndexMap>
  238. void
  239. tsin_depth_first_visit
  240. (const DistributedGraph& g,
  241. typename graph_traits<DistributedGraph>::vertex_descriptor s,
  242. DFSVisitor vis)
  243. {
  244. tsin_depth_first_visit(g, s, vis, get(vertex_index, g));
  245. }
  246. } // end namespace distributed
  247. using distributed::tsin_depth_first_visit;
  248. } // end namespace graph
  249. template<typename DistributedGraph, typename DFSVisitor>
  250. void
  251. depth_first_visit
  252. (const DistributedGraph& g,
  253. typename graph_traits<DistributedGraph>::vertex_descriptor s,
  254. DFSVisitor vis)
  255. {
  256. graph::tsin_depth_first_visit(g, s, vis, get(vertex_index, g));
  257. }
  258. } // end namespace boost
  259. #endif // BOOST_GRAPH_DISTRIBUTED_DFS_HPP