File indexing completed on 2025-01-18 09:37:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
0012 #define BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP
0013
0014
0015
0016
0017
0018
0019 #include <boost/config.hpp>
0020 #include <boost/ref.hpp>
0021 #include <vector>
0022 #include <boost/pending/queue.hpp>
0023 #include <boost/graph/graph_traits.hpp>
0024 #include <boost/graph/graph_concepts.hpp>
0025 #include <boost/graph/visitors.hpp>
0026 #include <boost/graph/named_function_params.hpp>
0027 #include <boost/concept/assert.hpp>
0028
0029 namespace boost
0030 {
0031
0032 template < class Visitor, class Graph > struct NeighborBFSVisitorConcept
0033 {
0034 void constraints()
0035 {
0036 BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >));
0037 vis.initialize_vertex(u, g);
0038 vis.discover_vertex(u, g);
0039 vis.examine_vertex(u, g);
0040 vis.examine_out_edge(e, g);
0041 vis.examine_in_edge(e, g);
0042 vis.tree_out_edge(e, g);
0043 vis.tree_in_edge(e, g);
0044 vis.non_tree_out_edge(e, g);
0045 vis.non_tree_in_edge(e, g);
0046 vis.gray_target(e, g);
0047 vis.black_target(e, g);
0048 vis.gray_source(e, g);
0049 vis.black_source(e, g);
0050 vis.finish_vertex(u, g);
0051 }
0052 Visitor vis;
0053 Graph g;
0054 typename graph_traits< Graph >::vertex_descriptor u;
0055 typename graph_traits< Graph >::edge_descriptor e;
0056 };
0057
0058 template < class Visitors = null_visitor > class neighbor_bfs_visitor
0059 {
0060 public:
0061 neighbor_bfs_visitor(Visitors vis = Visitors()) : m_vis(vis) {}
0062
0063 template < class Vertex, class Graph >
0064 void initialize_vertex(Vertex u, Graph& g)
0065 {
0066 invoke_visitors(m_vis, u, g, on_initialize_vertex());
0067 }
0068 template < class Vertex, class Graph >
0069 void discover_vertex(Vertex u, Graph& g)
0070 {
0071 invoke_visitors(m_vis, u, g, on_discover_vertex());
0072 }
0073 template < class Vertex, class Graph >
0074 void examine_vertex(Vertex u, Graph& g)
0075 {
0076 invoke_visitors(m_vis, u, g, on_examine_vertex());
0077 }
0078 template < class Edge, class Graph > void examine_out_edge(Edge e, Graph& g)
0079 {
0080 invoke_visitors(m_vis, e, g, on_examine_edge());
0081 }
0082 template < class Edge, class Graph > void tree_out_edge(Edge e, Graph& g)
0083 {
0084 invoke_visitors(m_vis, e, g, on_tree_edge());
0085 }
0086 template < class Edge, class Graph >
0087 void non_tree_out_edge(Edge e, Graph& g)
0088 {
0089 invoke_visitors(m_vis, e, g, on_non_tree_edge());
0090 }
0091 template < class Edge, class Graph > void gray_target(Edge e, Graph& g)
0092 {
0093 invoke_visitors(m_vis, e, g, on_gray_target());
0094 }
0095 template < class Edge, class Graph > void black_target(Edge e, Graph& g)
0096 {
0097 invoke_visitors(m_vis, e, g, on_black_target());
0098 }
0099 template < class Edge, class Graph > void examine_in_edge(Edge e, Graph& g)
0100 {
0101 invoke_visitors(m_vis, e, g, on_examine_edge());
0102 }
0103 template < class Edge, class Graph > void tree_in_edge(Edge e, Graph& g)
0104 {
0105 invoke_visitors(m_vis, e, g, on_tree_edge());
0106 }
0107 template < class Edge, class Graph > void non_tree_in_edge(Edge e, Graph& g)
0108 {
0109 invoke_visitors(m_vis, e, g, on_non_tree_edge());
0110 }
0111 template < class Edge, class Graph > void gray_source(Edge e, Graph& g)
0112 {
0113 invoke_visitors(m_vis, e, g, on_gray_target());
0114 }
0115 template < class Edge, class Graph > void black_source(Edge e, Graph& g)
0116 {
0117 invoke_visitors(m_vis, e, g, on_black_target());
0118 }
0119 template < class Vertex, class Graph >
0120 void finish_vertex(Vertex u, Graph& g)
0121 {
0122 invoke_visitors(m_vis, u, g, on_finish_vertex());
0123 }
0124
0125 protected:
0126 Visitors m_vis;
0127 };
0128
0129 template < class Visitors >
0130 neighbor_bfs_visitor< Visitors > make_neighbor_bfs_visitor(Visitors vis)
0131 {
0132 return neighbor_bfs_visitor< Visitors >(vis);
0133 }
0134
0135 namespace detail
0136 {
0137
0138 template < class BidirectionalGraph, class Buffer, class BFSVisitor,
0139 class ColorMap >
0140 void neighbor_bfs_impl(const BidirectionalGraph& g,
0141 typename graph_traits< BidirectionalGraph >::vertex_descriptor s,
0142 Buffer& Q, BFSVisitor vis, ColorMap color)
0143
0144 {
0145 BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< BidirectionalGraph >));
0146 typedef graph_traits< BidirectionalGraph > GTraits;
0147 typedef typename GTraits::vertex_descriptor Vertex;
0148 typedef typename GTraits::edge_descriptor Edge;
0149 BOOST_CONCEPT_ASSERT(
0150 (NeighborBFSVisitorConcept< BFSVisitor, BidirectionalGraph >));
0151 BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< ColorMap, Vertex >));
0152 typedef typename property_traits< ColorMap >::value_type ColorValue;
0153 typedef color_traits< ColorValue > Color;
0154
0155 put(color, s, Color::gray());
0156 vis.discover_vertex(s, g);
0157 Q.push(s);
0158 while (!Q.empty())
0159 {
0160 Vertex u = Q.top();
0161 Q.pop();
0162 vis.examine_vertex(u, g);
0163
0164 typename GTraits::out_edge_iterator ei, ei_end;
0165 for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei)
0166 {
0167 Edge e = *ei;
0168 vis.examine_out_edge(e, g);
0169 Vertex v = target(e, g);
0170 ColorValue v_color = get(color, v);
0171 if (v_color == Color::white())
0172 {
0173 vis.tree_out_edge(e, g);
0174 put(color, v, Color::gray());
0175 vis.discover_vertex(v, g);
0176 Q.push(v);
0177 }
0178 else
0179 {
0180 vis.non_tree_out_edge(e, g);
0181 if (v_color == Color::gray())
0182 vis.gray_target(e, g);
0183 else
0184 vis.black_target(e, g);
0185 }
0186 }
0187
0188 typename GTraits::in_edge_iterator in_ei, in_ei_end;
0189 for (boost::tie(in_ei, in_ei_end) = in_edges(u, g);
0190 in_ei != in_ei_end; ++in_ei)
0191 {
0192 Edge e = *in_ei;
0193 vis.examine_in_edge(e, g);
0194 Vertex v = source(e, g);
0195 ColorValue v_color = get(color, v);
0196 if (v_color == Color::white())
0197 {
0198 vis.tree_in_edge(e, g);
0199 put(color, v, Color::gray());
0200 vis.discover_vertex(v, g);
0201 Q.push(v);
0202 }
0203 else
0204 {
0205 vis.non_tree_in_edge(e, g);
0206 if (v_color == Color::gray())
0207 vis.gray_source(e, g);
0208 else
0209 vis.black_source(e, g);
0210 }
0211 }
0212
0213 put(color, u, Color::black());
0214 vis.finish_vertex(u, g);
0215 }
0216 }
0217
0218 template < class VertexListGraph, class ColorMap, class BFSVisitor, class P,
0219 class T, class R >
0220 void neighbor_bfs_helper(VertexListGraph& g,
0221 typename graph_traits< VertexListGraph >::vertex_descriptor s,
0222 ColorMap color, BFSVisitor vis,
0223 const bgl_named_params< P, T, R >& params)
0224 {
0225 typedef graph_traits< VertexListGraph > Traits;
0226
0227 typedef typename Traits::vertex_descriptor Vertex;
0228 typedef boost::queue< Vertex > queue_t;
0229 queue_t Q;
0230
0231 typedef typename property_traits< ColorMap >::value_type ColorValue;
0232 typedef color_traits< ColorValue > Color;
0233 typename boost::graph_traits< VertexListGraph >::vertex_iterator i,
0234 i_end;
0235 for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i)
0236 {
0237 put(color, *i, Color::white());
0238 vis.initialize_vertex(*i, g);
0239 }
0240 neighbor_bfs_impl(g, s,
0241 choose_param(get_param(params, buffer_param_t()), boost::ref(Q))
0242 .get(),
0243 vis, color);
0244 }
0245
0246
0247
0248
0249
0250
0251 template < class ColorMap > struct neighbor_bfs_dispatch
0252 {
0253 template < class VertexListGraph, class P, class T, class R >
0254 static void apply(VertexListGraph& g,
0255 typename graph_traits< VertexListGraph >::vertex_descriptor s,
0256 const bgl_named_params< P, T, R >& params, ColorMap color)
0257 {
0258 neighbor_bfs_helper(g, s, color,
0259 choose_param(get_param(params, graph_visitor),
0260 make_neighbor_bfs_visitor(null_visitor())),
0261 params);
0262 }
0263 };
0264
0265 template <> struct neighbor_bfs_dispatch< param_not_found >
0266 {
0267 template < class VertexListGraph, class P, class T, class R >
0268 static void apply(VertexListGraph& g,
0269 typename graph_traits< VertexListGraph >::vertex_descriptor s,
0270 const bgl_named_params< P, T, R >& params, param_not_found)
0271 {
0272 std::vector< default_color_type > color_vec(num_vertices(g));
0273 null_visitor null_vis;
0274
0275 neighbor_bfs_helper(g, s,
0276 make_iterator_property_map(color_vec.begin(),
0277 choose_const_pmap(
0278 get_param(params, vertex_index), g, vertex_index),
0279 color_vec[0]),
0280 choose_param(get_param(params, graph_visitor),
0281 make_neighbor_bfs_visitor(null_vis)),
0282 params);
0283 }
0284 };
0285
0286 }
0287
0288
0289 template < class VertexListGraph, class P, class T, class R >
0290 void neighbor_breadth_first_search(const VertexListGraph& g,
0291 typename graph_traits< VertexListGraph >::vertex_descriptor s,
0292 const bgl_named_params< P, T, R >& params)
0293 {
0294
0295
0296
0297
0298 VertexListGraph& ng = const_cast< VertexListGraph& >(g);
0299 typedef typename get_param_type< vertex_color_t,
0300 bgl_named_params< P, T, R > >::type C;
0301 detail::neighbor_bfs_dispatch< C >::apply(
0302 ng, s, params, get_param(params, vertex_color));
0303 }
0304
0305
0306
0307 template < class IncidenceGraph, class P, class T, class R >
0308 void neighbor_breadth_first_visit(IncidenceGraph& g,
0309 typename graph_traits< IncidenceGraph >::vertex_descriptor s,
0310 const bgl_named_params< P, T, R >& params)
0311 {
0312 typedef graph_traits< IncidenceGraph > Traits;
0313
0314 typedef boost::queue< typename Traits::vertex_descriptor > queue_t;
0315 queue_t Q;
0316
0317 detail::neighbor_bfs_impl(g, s,
0318 choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(),
0319 choose_param(get_param(params, graph_visitor),
0320 make_neighbor_bfs_visitor(null_visitor())),
0321 choose_pmap(get_param(params, vertex_color), g, vertex_color));
0322 }
0323
0324 }
0325
0326 #endif