neighbor_bfs.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
  12. #define BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
  13. /*
  14. Neighbor Breadth First Search
  15. Like BFS, but traverses in-edges as well as out-edges.
  16. (for directed graphs only. use normal BFS for undirected graphs)
  17. */
  18. #include <boost/config.hpp>
  19. #include <boost/ref.hpp>
  20. #include <vector>
  21. #include <boost/pending/queue.hpp>
  22. #include <boost/graph/graph_traits.hpp>
  23. #include <boost/graph/graph_concepts.hpp>
  24. #include <boost/graph/visitors.hpp>
  25. #include <boost/graph/named_function_params.hpp>
  26. #include <boost/concept/assert.hpp>
  27. namespace boost {
  28. template <class Visitor, class Graph>
  29. struct NeighborBFSVisitorConcept {
  30. void constraints() {
  31. BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept<Visitor> ));
  32. vis.initialize_vertex(u, g);
  33. vis.discover_vertex(u, g);
  34. vis.examine_vertex(u, g);
  35. vis.examine_out_edge(e, g);
  36. vis.examine_in_edge(e, g);
  37. vis.tree_out_edge(e, g);
  38. vis.tree_in_edge(e, g);
  39. vis.non_tree_out_edge(e, g);
  40. vis.non_tree_in_edge(e, g);
  41. vis.gray_target(e, g);
  42. vis.black_target(e, g);
  43. vis.gray_source(e, g);
  44. vis.black_source(e, g);
  45. vis.finish_vertex(u, g);
  46. }
  47. Visitor vis;
  48. Graph g;
  49. typename graph_traits<Graph>::vertex_descriptor u;
  50. typename graph_traits<Graph>::edge_descriptor e;
  51. };
  52. template <class Visitors = null_visitor>
  53. class neighbor_bfs_visitor {
  54. public:
  55. neighbor_bfs_visitor(Visitors vis = Visitors()) : m_vis(vis) { }
  56. template <class Vertex, class Graph>
  57. void initialize_vertex(Vertex u, Graph& g) {
  58. invoke_visitors(m_vis, u, g, on_initialize_vertex());
  59. }
  60. template <class Vertex, class Graph>
  61. void discover_vertex(Vertex u, Graph& g) {
  62. invoke_visitors(m_vis, u, g, on_discover_vertex());
  63. }
  64. template <class Vertex, class Graph>
  65. void examine_vertex(Vertex u, Graph& g) {
  66. invoke_visitors(m_vis, u, g, on_examine_vertex());
  67. }
  68. template <class Edge, class Graph>
  69. void examine_out_edge(Edge e, Graph& g) {
  70. invoke_visitors(m_vis, e, g, on_examine_edge());
  71. }
  72. template <class Edge, class Graph>
  73. void tree_out_edge(Edge e, Graph& g) {
  74. invoke_visitors(m_vis, e, g, on_tree_edge());
  75. }
  76. template <class Edge, class Graph>
  77. void non_tree_out_edge(Edge e, Graph& g) {
  78. invoke_visitors(m_vis, e, g, on_non_tree_edge());
  79. }
  80. template <class Edge, class Graph>
  81. void gray_target(Edge e, Graph& g) {
  82. invoke_visitors(m_vis, e, g, on_gray_target());
  83. }
  84. template <class Edge, class Graph>
  85. void black_target(Edge e, Graph& g) {
  86. invoke_visitors(m_vis, e, g, on_black_target());
  87. }
  88. template <class Edge, class Graph>
  89. void examine_in_edge(Edge e, Graph& g) {
  90. invoke_visitors(m_vis, e, g, on_examine_edge());
  91. }
  92. template <class Edge, class Graph>
  93. void tree_in_edge(Edge e, Graph& g) {
  94. invoke_visitors(m_vis, e, g, on_tree_edge());
  95. }
  96. template <class Edge, class Graph>
  97. void non_tree_in_edge(Edge e, Graph& g) {
  98. invoke_visitors(m_vis, e, g, on_non_tree_edge());
  99. }
  100. template <class Edge, class Graph>
  101. void gray_source(Edge e, Graph& g) {
  102. invoke_visitors(m_vis, e, g, on_gray_target());
  103. }
  104. template <class Edge, class Graph>
  105. void black_source(Edge e, Graph& g) {
  106. invoke_visitors(m_vis, e, g, on_black_target());
  107. }
  108. template <class Vertex, class Graph>
  109. void finish_vertex(Vertex u, Graph& g) {
  110. invoke_visitors(m_vis, u, g, on_finish_vertex());
  111. }
  112. protected:
  113. Visitors m_vis;
  114. };
  115. template <class Visitors>
  116. neighbor_bfs_visitor<Visitors>
  117. make_neighbor_bfs_visitor(Visitors vis) {
  118. return neighbor_bfs_visitor<Visitors>(vis);
  119. }
  120. namespace detail {
  121. template <class BidirectionalGraph, class Buffer, class BFSVisitor,
  122. class ColorMap>
  123. void neighbor_bfs_impl
  124. (const BidirectionalGraph& g,
  125. typename graph_traits<BidirectionalGraph>::vertex_descriptor s,
  126. Buffer& Q, BFSVisitor vis, ColorMap color)
  127. {
  128. BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<BidirectionalGraph> ));
  129. typedef graph_traits<BidirectionalGraph> GTraits;
  130. typedef typename GTraits::vertex_descriptor Vertex;
  131. typedef typename GTraits::edge_descriptor Edge;
  132. BOOST_CONCEPT_ASSERT((
  133. NeighborBFSVisitorConcept<BFSVisitor, BidirectionalGraph> ));
  134. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ColorMap, Vertex> ));
  135. typedef typename property_traits<ColorMap>::value_type ColorValue;
  136. typedef color_traits<ColorValue> Color;
  137. put(color, s, Color::gray());
  138. vis.discover_vertex(s, g);
  139. Q.push(s);
  140. while (! Q.empty()) {
  141. Vertex u = Q.top();
  142. Q.pop(); // pop before push to avoid problem if Q is priority_queue.
  143. vis.examine_vertex(u, g);
  144. typename GTraits::out_edge_iterator ei, ei_end;
  145. for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
  146. Edge e = *ei;
  147. vis.examine_out_edge(e, g);
  148. Vertex v = target(e, g);
  149. ColorValue v_color = get(color, v);
  150. if (v_color == Color::white()) {
  151. vis.tree_out_edge(e, g);
  152. put(color, v, Color::gray());
  153. vis.discover_vertex(v, g);
  154. Q.push(v);
  155. } else {
  156. vis.non_tree_out_edge(e, g);
  157. if (v_color == Color::gray())
  158. vis.gray_target(e, g);
  159. else
  160. vis.black_target(e, g);
  161. }
  162. } // for out-edges
  163. typename GTraits::in_edge_iterator in_ei, in_ei_end;
  164. for (boost::tie(in_ei, in_ei_end) = in_edges(u, g);
  165. in_ei != in_ei_end; ++in_ei) {
  166. Edge e = *in_ei;
  167. vis.examine_in_edge(e, g);
  168. Vertex v = source(e, g);
  169. ColorValue v_color = get(color, v);
  170. if (v_color == Color::white()) {
  171. vis.tree_in_edge(e, g);
  172. put(color, v, Color::gray());
  173. vis.discover_vertex(v, g);
  174. Q.push(v);
  175. } else {
  176. vis.non_tree_in_edge(e, g);
  177. if (v_color == Color::gray())
  178. vis.gray_source(e, g);
  179. else
  180. vis.black_source(e, g);
  181. }
  182. } // for in-edges
  183. put(color, u, Color::black());
  184. vis.finish_vertex(u, g);
  185. } // while
  186. }
  187. template <class VertexListGraph, class ColorMap, class BFSVisitor,
  188. class P, class T, class R>
  189. void neighbor_bfs_helper
  190. (VertexListGraph& g,
  191. typename graph_traits<VertexListGraph>::vertex_descriptor s,
  192. ColorMap color,
  193. BFSVisitor vis,
  194. const bgl_named_params<P, T, R>& params)
  195. {
  196. typedef graph_traits<VertexListGraph> Traits;
  197. // Buffer default
  198. typedef typename Traits::vertex_descriptor Vertex;
  199. typedef boost::queue<Vertex> queue_t;
  200. queue_t Q;
  201. // Initialization
  202. typedef typename property_traits<ColorMap>::value_type ColorValue;
  203. typedef color_traits<ColorValue> Color;
  204. typename boost::graph_traits<VertexListGraph>::vertex_iterator i, i_end;
  205. for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) {
  206. put(color, *i, Color::white());
  207. vis.initialize_vertex(*i, g);
  208. }
  209. neighbor_bfs_impl
  210. (g, s,
  211. choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(),
  212. vis, color);
  213. }
  214. //-------------------------------------------------------------------------
  215. // Choose between default color and color parameters. Using
  216. // function dispatching so that we don't require vertex index if
  217. // the color default is not being used.
  218. template <class ColorMap>
  219. struct neighbor_bfs_dispatch {
  220. template <class VertexListGraph, class P, class T, class R>
  221. static void apply
  222. (VertexListGraph& g,
  223. typename graph_traits<VertexListGraph>::vertex_descriptor s,
  224. const bgl_named_params<P, T, R>& params,
  225. ColorMap color)
  226. {
  227. neighbor_bfs_helper
  228. (g, s, color,
  229. choose_param(get_param(params, graph_visitor),
  230. make_neighbor_bfs_visitor(null_visitor())),
  231. params);
  232. }
  233. };
  234. template <>
  235. struct neighbor_bfs_dispatch<param_not_found> {
  236. template <class VertexListGraph, class P, class T, class R>
  237. static void apply
  238. (VertexListGraph& g,
  239. typename graph_traits<VertexListGraph>::vertex_descriptor s,
  240. const bgl_named_params<P, T, R>& params,
  241. param_not_found)
  242. {
  243. std::vector<default_color_type> color_vec(num_vertices(g));
  244. null_visitor null_vis;
  245. neighbor_bfs_helper
  246. (g, s,
  247. make_iterator_property_map
  248. (color_vec.begin(),
  249. choose_const_pmap(get_param(params, vertex_index),
  250. g, vertex_index), color_vec[0]),
  251. choose_param(get_param(params, graph_visitor),
  252. make_neighbor_bfs_visitor(null_vis)),
  253. params);
  254. }
  255. };
  256. } // namespace detail
  257. // Named Parameter Variant
  258. template <class VertexListGraph, class P, class T, class R>
  259. void neighbor_breadth_first_search
  260. (const VertexListGraph& g,
  261. typename graph_traits<VertexListGraph>::vertex_descriptor s,
  262. const bgl_named_params<P, T, R>& params)
  263. {
  264. // The graph is passed by *const* reference so that graph adaptors
  265. // (temporaries) can be passed into this function. However, the
  266. // graph is not really const since we may write to property maps
  267. // of the graph.
  268. VertexListGraph& ng = const_cast<VertexListGraph&>(g);
  269. typedef typename get_param_type< vertex_color_t, bgl_named_params<P,T,R> >::type C;
  270. detail::neighbor_bfs_dispatch<C>::apply(ng, s, params,
  271. get_param(params, vertex_color));
  272. }
  273. // This version does not initialize colors, user has to.
  274. template <class IncidenceGraph, class P, class T, class R>
  275. void neighbor_breadth_first_visit
  276. (IncidenceGraph& g,
  277. typename graph_traits<IncidenceGraph>::vertex_descriptor s,
  278. const bgl_named_params<P, T, R>& params)
  279. {
  280. typedef graph_traits<IncidenceGraph> Traits;
  281. // Buffer default
  282. typedef boost::queue<typename Traits::vertex_descriptor> queue_t;
  283. queue_t Q;
  284. detail::neighbor_bfs_impl
  285. (g, s,
  286. choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(),
  287. choose_param(get_param(params, graph_visitor),
  288. make_neighbor_bfs_visitor(null_visitor())),
  289. choose_pmap(get_param(params, vertex_color), g, vertex_color)
  290. );
  291. }
  292. } // namespace boost
  293. #endif // BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP