LCOV - code coverage report
Current view: top level - usr/include/boost/graph - depth_first_search.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 86 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14