annotate DEPENDENCIES/generic/include/boost/graph/depth_first_search.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 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
Chris@16 3 // Copyright 2003 Bruce Barr
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 // Nonrecursive implementation of depth_first_visit_impl submitted by
Chris@16 12 // Bruce Barr, schmoost <at> yahoo.com, May/June 2003.
Chris@16 13 #ifndef BOOST_GRAPH_RECURSIVE_DFS_HPP
Chris@16 14 #define BOOST_GRAPH_RECURSIVE_DFS_HPP
Chris@16 15
Chris@16 16 #include <boost/config.hpp>
Chris@16 17 #include <boost/graph/graph_traits.hpp>
Chris@16 18 #include <boost/graph/graph_concepts.hpp>
Chris@16 19 #include <boost/graph/properties.hpp>
Chris@16 20 #include <boost/graph/visitors.hpp>
Chris@16 21 #include <boost/graph/named_function_params.hpp>
Chris@16 22 #include <boost/ref.hpp>
Chris@16 23 #include <boost/implicit_cast.hpp>
Chris@16 24 #include <boost/optional.hpp>
Chris@16 25 #include <boost/parameter.hpp>
Chris@16 26 #include <boost/concept/assert.hpp>
Chris@16 27 #include <boost/tti/has_member_function.hpp>
Chris@16 28
Chris@16 29 #include <vector>
Chris@16 30 #include <utility>
Chris@16 31
Chris@16 32 namespace boost {
Chris@16 33
Chris@16 34 template <class Visitor, class Graph>
Chris@16 35 class DFSVisitorConcept {
Chris@16 36 public:
Chris@16 37 void constraints() {
Chris@16 38 BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept<Visitor> ));
Chris@16 39 vis.initialize_vertex(u, g);
Chris@16 40 vis.start_vertex(u, g);
Chris@16 41 vis.discover_vertex(u, g);
Chris@16 42 vis.examine_edge(e, g);
Chris@16 43 vis.tree_edge(e, g);
Chris@16 44 vis.back_edge(e, g);
Chris@16 45 vis.forward_or_cross_edge(e, g);
Chris@16 46 // vis.finish_edge(e, g); // Optional for user
Chris@16 47 vis.finish_vertex(u, g);
Chris@16 48 }
Chris@16 49 private:
Chris@16 50 Visitor vis;
Chris@16 51 Graph g;
Chris@16 52 typename graph_traits<Graph>::vertex_descriptor u;
Chris@16 53 typename graph_traits<Graph>::edge_descriptor e;
Chris@16 54 };
Chris@16 55
Chris@16 56 namespace detail {
Chris@16 57
Chris@16 58 struct nontruth2 {
Chris@16 59 template<class T, class T2>
Chris@16 60 bool operator()(const T&, const T2&) const { return false; }
Chris@16 61 };
Chris@16 62
Chris@16 63 BOOST_TTI_HAS_MEMBER_FUNCTION(finish_edge)
Chris@16 64
Chris@16 65 template <bool IsCallable> struct do_call_finish_edge {
Chris@16 66 template <typename E, typename G, typename Vis>
Chris@16 67 static void call_finish_edge(Vis& vis, const E& e, const G& g) {
Chris@16 68 vis.finish_edge(e, g);
Chris@16 69 }
Chris@16 70 };
Chris@16 71
Chris@16 72 template <> struct do_call_finish_edge<false> {
Chris@16 73 template <typename E, typename G, typename Vis>
Chris@16 74 static void call_finish_edge(Vis&, const E&, const G&) {}
Chris@16 75 };
Chris@16 76
Chris@16 77 template <typename E, typename G, typename Vis>
Chris@16 78 void call_finish_edge(Vis& vis, const E& e, const G& g) { // Only call if method exists
Chris@16 79 do_call_finish_edge<has_member_function_finish_edge<Vis, void>::value>::call_finish_edge(vis, e, g);
Chris@16 80 }
Chris@16 81
Chris@16 82
Chris@16 83 // Define BOOST_RECURSIVE_DFS to use older, recursive version.
Chris@16 84 // It is retained for a while in order to perform performance
Chris@16 85 // comparison.
Chris@16 86 #ifndef BOOST_RECURSIVE_DFS
Chris@16 87
Chris@16 88 // If the vertex u and the iterators ei and ei_end are thought of as the
Chris@16 89 // context of the algorithm, each push and pop from the stack could
Chris@16 90 // be thought of as a context shift.
Chris@16 91 // Each pass through "while (ei != ei_end)" may refer to the out-edges of
Chris@16 92 // an entirely different vertex, because the context of the algorithm
Chris@16 93 // shifts every time a white adjacent vertex is discovered.
Chris@16 94 // The corresponding context shift back from the adjacent vertex occurs
Chris@16 95 // after all of its out-edges have been examined.
Chris@16 96 //
Chris@16 97 // See http://lists.boost.org/MailArchives/boost/msg48752.php for FAQ.
Chris@16 98
Chris@16 99 template <class IncidenceGraph, class DFSVisitor, class ColorMap,
Chris@16 100 class TerminatorFunc>
Chris@16 101 void depth_first_visit_impl
Chris@16 102 (const IncidenceGraph& g,
Chris@16 103 typename graph_traits<IncidenceGraph>::vertex_descriptor u,
Chris@16 104 DFSVisitor& vis,
Chris@16 105 ColorMap color, TerminatorFunc func = TerminatorFunc())
Chris@16 106 {
Chris@16 107 BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<IncidenceGraph> ));
Chris@16 108 BOOST_CONCEPT_ASSERT(( DFSVisitorConcept<DFSVisitor, IncidenceGraph> ));
Chris@16 109 typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
Chris@16 110 typedef typename graph_traits<IncidenceGraph>::edge_descriptor Edge;
Chris@16 111 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ColorMap, Vertex> ));
Chris@16 112 typedef typename property_traits<ColorMap>::value_type ColorValue;
Chris@16 113 BOOST_CONCEPT_ASSERT(( ColorValueConcept<ColorValue> ));
Chris@16 114 typedef color_traits<ColorValue> Color;
Chris@16 115 typedef typename graph_traits<IncidenceGraph>::out_edge_iterator Iter;
Chris@16 116 typedef std::pair<Vertex, std::pair<boost::optional<Edge>, std::pair<Iter, Iter> > > VertexInfo;
Chris@16 117
Chris@16 118 boost::optional<Edge> src_e;
Chris@16 119 Iter ei, ei_end;
Chris@16 120 std::vector<VertexInfo> stack;
Chris@16 121
Chris@16 122 // Possible optimization for vector
Chris@16 123 //stack.reserve(num_vertices(g));
Chris@16 124
Chris@16 125 put(color, u, Color::gray());
Chris@16 126 vis.discover_vertex(u, g);
Chris@16 127 boost::tie(ei, ei_end) = out_edges(u, g);
Chris@16 128 if (func(u, g)) {
Chris@16 129 // If this vertex terminates the search, we push empty range
Chris@16 130 stack.push_back(std::make_pair(u, std::make_pair(boost::optional<Edge>(), std::make_pair(ei_end, ei_end))));
Chris@16 131 } else {
Chris@16 132 stack.push_back(std::make_pair(u, std::make_pair(boost::optional<Edge>(), std::make_pair(ei, ei_end))));
Chris@16 133 }
Chris@16 134 while (!stack.empty()) {
Chris@16 135 VertexInfo& back = stack.back();
Chris@16 136 u = back.first;
Chris@16 137 src_e = back.second.first;
Chris@16 138 boost::tie(ei, ei_end) = back.second.second;
Chris@16 139 stack.pop_back();
Chris@16 140 while (ei != ei_end) {
Chris@16 141 Vertex v = target(*ei, g);
Chris@16 142 vis.examine_edge(*ei, g);
Chris@16 143 ColorValue v_color = get(color, v);
Chris@16 144 if (v_color == Color::white()) {
Chris@16 145 vis.tree_edge(*ei, g);
Chris@16 146 src_e = *ei;
Chris@16 147 stack.push_back(std::make_pair(u, std::make_pair(src_e, std::make_pair(++ei, ei_end))));
Chris@16 148 u = v;
Chris@16 149 put(color, u, Color::gray());
Chris@16 150 vis.discover_vertex(u, g);
Chris@16 151 boost::tie(ei, ei_end) = out_edges(u, g);
Chris@16 152 if (func(u, g)) {
Chris@16 153 ei = ei_end;
Chris@16 154 }
Chris@16 155 } else {
Chris@16 156 if (v_color == Color::gray()) {
Chris@16 157 vis.back_edge(*ei, g);
Chris@16 158 } else {
Chris@16 159 vis.forward_or_cross_edge(*ei, g);
Chris@16 160 }
Chris@16 161 call_finish_edge(vis, *ei, g);
Chris@16 162 ++ei;
Chris@16 163 }
Chris@16 164 }
Chris@16 165 put(color, u, Color::black());
Chris@16 166 vis.finish_vertex(u, g);
Chris@16 167 if (src_e) call_finish_edge(vis, src_e.get(), g);
Chris@16 168 }
Chris@16 169 }
Chris@16 170
Chris@16 171 #else // BOOST_RECURSIVE_DFS is defined
Chris@16 172
Chris@16 173 template <class IncidenceGraph, class DFSVisitor, class ColorMap,
Chris@16 174 class TerminatorFunc>
Chris@16 175 void depth_first_visit_impl
Chris@16 176 (const IncidenceGraph& g,
Chris@16 177 typename graph_traits<IncidenceGraph>::vertex_descriptor u,
Chris@16 178 DFSVisitor& vis, // pass-by-reference here, important!
Chris@16 179 ColorMap color, TerminatorFunc func)
Chris@16 180 {
Chris@16 181 BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<IncidenceGraph> ));
Chris@16 182 BOOST_CONCEPT_ASSERT(( DFSVisitorConcept<DFSVisitor, IncidenceGraph> ));
Chris@16 183 typedef typename graph_traits<IncidenceGraph>::vertex_descriptor Vertex;
Chris@16 184 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ColorMap, Vertex> ));
Chris@16 185 typedef typename property_traits<ColorMap>::value_type ColorValue;
Chris@16 186 BOOST_CONCEPT_ASSERT(( ColorValueConcept<ColorValue> ));
Chris@16 187 typedef color_traits<ColorValue> Color;
Chris@16 188 typename graph_traits<IncidenceGraph>::out_edge_iterator ei, ei_end;
Chris@16 189
Chris@16 190 put(color, u, Color::gray()); vis.discover_vertex(u, g);
Chris@16 191
Chris@16 192 if (!func(u, g))
Chris@16 193 for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
Chris@16 194 Vertex v = target(*ei, g); vis.examine_edge(*ei, g);
Chris@16 195 ColorValue v_color = get(color, v);
Chris@16 196 if (v_color == Color::white()) { vis.tree_edge(*ei, g);
Chris@16 197 depth_first_visit_impl(g, v, vis, color, func);
Chris@16 198 } else if (v_color == Color::gray()) vis.back_edge(*ei, g);
Chris@16 199 else vis.forward_or_cross_edge(*ei, g);
Chris@16 200 call_finish_edge(vis, *ei, g);
Chris@16 201 }
Chris@16 202 put(color, u, Color::black()); vis.finish_vertex(u, g);
Chris@16 203 }
Chris@16 204
Chris@16 205 #endif
Chris@16 206
Chris@16 207 } // namespace detail
Chris@16 208
Chris@16 209 template <class VertexListGraph, class DFSVisitor, class ColorMap>
Chris@16 210 void
Chris@16 211 depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color,
Chris@16 212 typename graph_traits<VertexListGraph>::vertex_descriptor start_vertex)
Chris@16 213 {
Chris@16 214 typedef typename graph_traits<VertexListGraph>::vertex_descriptor Vertex;
Chris@16 215 BOOST_CONCEPT_ASSERT(( DFSVisitorConcept<DFSVisitor, VertexListGraph> ));
Chris@16 216 typedef typename property_traits<ColorMap>::value_type ColorValue;
Chris@16 217 typedef color_traits<ColorValue> Color;
Chris@16 218
Chris@16 219 typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
Chris@16 220 for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
Chris@16 221 Vertex u = implicit_cast<Vertex>(*ui);
Chris@16 222 put(color, u, Color::white()); vis.initialize_vertex(u, g);
Chris@16 223 }
Chris@16 224
Chris@16 225 if (start_vertex != detail::get_default_starting_vertex(g)){ vis.start_vertex(start_vertex, g);
Chris@16 226 detail::depth_first_visit_impl(g, start_vertex, vis, color,
Chris@16 227 detail::nontruth2());
Chris@16 228 }
Chris@16 229
Chris@16 230 for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
Chris@16 231 Vertex u = implicit_cast<Vertex>(*ui);
Chris@16 232 ColorValue u_color = get(color, u);
Chris@16 233 if (u_color == Color::white()) { vis.start_vertex(u, g);
Chris@16 234 detail::depth_first_visit_impl(g, u, vis, color, detail::nontruth2());
Chris@16 235 }
Chris@16 236 }
Chris@16 237 }
Chris@16 238
Chris@16 239 template <class VertexListGraph, class DFSVisitor, class ColorMap>
Chris@16 240 void
Chris@16 241 depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color)
Chris@16 242 {
Chris@16 243 typedef typename boost::graph_traits<VertexListGraph>::vertex_iterator vi;
Chris@16 244 std::pair<vi, vi> verts = vertices(g);
Chris@16 245 if (verts.first == verts.second)
Chris@16 246 return;
Chris@16 247
Chris@16 248 depth_first_search(g, vis, color, detail::get_default_starting_vertex(g));
Chris@16 249 }
Chris@16 250
Chris@16 251 template <class Visitors = null_visitor>
Chris@16 252 class dfs_visitor {
Chris@16 253 public:
Chris@16 254 dfs_visitor() { }
Chris@16 255 dfs_visitor(Visitors vis) : m_vis(vis) { }
Chris@16 256
Chris@16 257 template <class Vertex, class Graph>
Chris@16 258 void initialize_vertex(Vertex u, const Graph& g) {
Chris@16 259 invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex());
Chris@16 260 }
Chris@16 261 template <class Vertex, class Graph>
Chris@16 262 void start_vertex(Vertex u, const Graph& g) {
Chris@16 263 invoke_visitors(m_vis, u, g, ::boost::on_start_vertex());
Chris@16 264 }
Chris@16 265 template <class Vertex, class Graph>
Chris@16 266 void discover_vertex(Vertex u, const Graph& g) {
Chris@16 267 invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex());
Chris@16 268 }
Chris@16 269 template <class Edge, class Graph>
Chris@16 270 void examine_edge(Edge u, const Graph& g) {
Chris@16 271 invoke_visitors(m_vis, u, g, ::boost::on_examine_edge());
Chris@16 272 }
Chris@16 273 template <class Edge, class Graph>
Chris@16 274 void tree_edge(Edge u, const Graph& g) {
Chris@16 275 invoke_visitors(m_vis, u, g, ::boost::on_tree_edge());
Chris@16 276 }
Chris@16 277 template <class Edge, class Graph>
Chris@16 278 void back_edge(Edge u, const Graph& g) {
Chris@16 279 invoke_visitors(m_vis, u, g, ::boost::on_back_edge());
Chris@16 280 }
Chris@16 281 template <class Edge, class Graph>
Chris@16 282 void forward_or_cross_edge(Edge u, const Graph& g) {
Chris@16 283 invoke_visitors(m_vis, u, g, ::boost::on_forward_or_cross_edge());
Chris@16 284 }
Chris@16 285 template <class Edge, class Graph>
Chris@16 286 void finish_edge(Edge u, const Graph& g) {
Chris@16 287 invoke_visitors(m_vis, u, g, ::boost::on_finish_edge());
Chris@16 288 }
Chris@16 289 template <class Vertex, class Graph>
Chris@16 290 void finish_vertex(Vertex u, const Graph& g) {
Chris@16 291 invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex());
Chris@16 292 }
Chris@16 293
Chris@16 294 BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,dfs)
Chris@16 295 BOOST_GRAPH_EVENT_STUB(on_start_vertex,dfs)
Chris@16 296 BOOST_GRAPH_EVENT_STUB(on_discover_vertex,dfs)
Chris@16 297 BOOST_GRAPH_EVENT_STUB(on_examine_edge,dfs)
Chris@16 298 BOOST_GRAPH_EVENT_STUB(on_tree_edge,dfs)
Chris@16 299 BOOST_GRAPH_EVENT_STUB(on_back_edge,dfs)
Chris@16 300 BOOST_GRAPH_EVENT_STUB(on_forward_or_cross_edge,dfs)
Chris@16 301 BOOST_GRAPH_EVENT_STUB(on_finish_edge,dfs)
Chris@16 302 BOOST_GRAPH_EVENT_STUB(on_finish_vertex,dfs)
Chris@16 303
Chris@16 304 protected:
Chris@16 305 Visitors m_vis;
Chris@16 306 };
Chris@16 307 template <class Visitors>
Chris@16 308 dfs_visitor<Visitors>
Chris@16 309 make_dfs_visitor(Visitors vis) {
Chris@16 310 return dfs_visitor<Visitors>(vis);
Chris@16 311 }
Chris@16 312 typedef dfs_visitor<> default_dfs_visitor;
Chris@16 313
Chris@16 314 // Boost.Parameter named parameter variant
Chris@16 315 namespace graph {
Chris@16 316 namespace detail {
Chris@16 317 template <typename Graph>
Chris@16 318 struct depth_first_search_impl {
Chris@16 319 typedef void result_type;
Chris@16 320 template <typename ArgPack>
Chris@16 321 void operator()(const Graph& g, const ArgPack& arg_pack) const {
Chris@16 322 using namespace boost::graph::keywords;
Chris@16 323 boost::depth_first_search(g,
Chris@16 324 arg_pack[_visitor | make_dfs_visitor(null_visitor())],
Chris@16 325 boost::detail::make_color_map_from_arg_pack(g, arg_pack),
Chris@16 326 arg_pack[_root_vertex || boost::detail::get_default_starting_vertex_t<Graph>(g)]);
Chris@16 327 }
Chris@16 328 };
Chris@16 329 }
Chris@16 330 BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(depth_first_search, 1, 4)
Chris@16 331 }
Chris@16 332
Chris@16 333 BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(depth_first_search, 1)
Chris@16 334
Chris@16 335 template <class IncidenceGraph, class DFSVisitor, class ColorMap>
Chris@16 336 void depth_first_visit
Chris@16 337 (const IncidenceGraph& g,
Chris@16 338 typename graph_traits<IncidenceGraph>::vertex_descriptor u,
Chris@16 339 DFSVisitor vis, ColorMap color)
Chris@16 340 {
Chris@16 341 vis.start_vertex(u, g);
Chris@16 342 detail::depth_first_visit_impl(g, u, vis, color, detail::nontruth2());
Chris@16 343 }
Chris@16 344
Chris@16 345 template <class IncidenceGraph, class DFSVisitor, class ColorMap,
Chris@16 346 class TerminatorFunc>
Chris@16 347 void depth_first_visit
Chris@16 348 (const IncidenceGraph& g,
Chris@16 349 typename graph_traits<IncidenceGraph>::vertex_descriptor u,
Chris@16 350 DFSVisitor vis, ColorMap color, TerminatorFunc func = TerminatorFunc())
Chris@16 351 {
Chris@16 352 vis.start_vertex(u, g);
Chris@16 353 detail::depth_first_visit_impl(g, u, vis, color, func);
Chris@16 354 }
Chris@16 355 } // namespace boost
Chris@16 356
Chris@16 357 #ifdef BOOST_GRAPH_USE_MPI
Chris@16 358 # include <boost/graph/distributed/depth_first_search.hpp>
Chris@16 359 #endif
Chris@16 360
Chris@16 361 #endif