| // Copyright 2008-2010 Gordon Woodhull |
| // Distributed under the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| |
| #ifndef BOOST_MSM_MPL_GRAPH_DEPTH_FIRST_SEARCH_HPP_INCLUDED |
| #define BOOST_MSM_MPL_GRAPH_DEPTH_FIRST_SEARCH_HPP_INCLUDED |
| |
| #include <boost/msm/mpl_graph/mpl_graph.hpp> |
| |
| #include <boost/mpl/has_key.hpp> |
| #include <boost/mpl/insert.hpp> |
| #include <boost/mpl/pair.hpp> |
| #include <boost/mpl/map.hpp> |
| #include <boost/mpl/has_key.hpp> |
| |
| #include "search_colors.hpp" |
| |
| namespace boost { |
| namespace msm { |
| namespace mpl_graph { |
| |
| // dfs takes a visitor which has all the bgl-like metafunctions encapsulated in an |
| // "operations" member class, and also a state. the operations are expected to return a new state |
| // in addition, the visitor operations are expected to update the colors of vertices |
| // and need to support a new metafunction get_color<Vertex, State> |
| |
| struct dfs_default_visitor_operations { |
| template<typename Vertex, typename Graph, typename State> |
| struct initialize_vertex { |
| typedef State type; |
| }; |
| |
| template<typename Vertex, typename Graph, typename State> |
| struct discover_vertex { |
| typedef State type; |
| }; |
| |
| template<typename Vertex, typename Graph, typename State> |
| struct finish_vertex { |
| typedef State type; |
| }; |
| |
| template<typename Edge, typename Graph, typename State> |
| struct tree_edge { |
| typedef State type; |
| }; |
| |
| template<typename Edge, typename Graph, typename State> |
| struct back_edge { |
| typedef State type; |
| }; |
| |
| template<typename Edge, typename Graph, typename State> |
| struct forward_or_cross_edge { |
| typedef State type; |
| }; |
| }; |
| |
| // requires IncidenceGraph |
| // returns pair<VisitorState, ColorState> |
| template<typename Graph, typename VisitorOps, typename VisitorState, |
| typename Vertex, |
| typename ColorState = create_search_color_map::type > |
| struct depth_first_search { |
| // enter vertex |
| typedef typename VisitorOps::template |
| discover_vertex<Vertex, Graph, VisitorState>::type |
| discovered_state; |
| typedef typename search_color_map_ops::template |
| set_color<Vertex, search_colors::Gray, ColorState>::type |
| discovered_colors; |
| |
| // loop over out edges |
| typedef typename |
| mpl::fold<typename mpl_graph::out_edges<Vertex, Graph>::type, |
| mpl::pair<discovered_state, discovered_colors>, |
| mpl::if_<boost::is_same<search_color_map_ops::get_color<mpl_graph::target<mpl::_2, Graph>, mpl::second<mpl::_1> >, |
| search_colors::White>, |
| // unseen target: recurse |
| depth_first_search<Graph, |
| VisitorOps, typename VisitorOps::template tree_edge<mpl::_2, Graph, mpl::first<mpl::_1> >, |
| mpl_graph::target<mpl::_2, Graph>, |
| mpl::second<mpl::_1> >, |
| // seen: back or forward edge |
| mpl::pair<mpl::if_<boost::is_same<typename search_color_map_ops::template |
| get_color<mpl_graph::target<mpl::_2, Graph>, mpl::second<mpl::_1 > >, |
| search_colors::Gray>, |
| typename VisitorOps::template back_edge<mpl::_2, Graph, mpl::first<mpl::_1> >, |
| typename VisitorOps::template forward_or_cross_edge<mpl::_2, Graph, mpl::first<mpl::_1> > >, // Black |
| mpl::second<mpl::_1> > > |
| >::type after_outedges; |
| |
| // leave vertex, and done! |
| typedef mpl::pair<typename VisitorOps::template finish_vertex<Vertex, Graph, typename mpl::first<after_outedges>::type >::type, |
| typename search_color_map_ops::template set_color<Vertex, search_colors::Black, typename mpl::second<after_outedges>::type>::type> type; |
| }; |
| |
| // requires IncidenceGraph, VertexListGraph |
| template<typename Graph, typename VisitorOps, typename VisitorState, |
| typename FirstVertex = typename mpl::front<typename mpl_graph::vertices<Graph>::type>::type, |
| typename ColorState = create_search_color_map::type> |
| struct depth_first_search_all : // visit first then rest |
| mpl::fold<typename mpl_graph::vertices<Graph>::type, |
| typename depth_first_search<Graph, |
| VisitorOps, VisitorState, |
| FirstVertex, |
| ColorState>::type, |
| mpl::if_<boost::is_same<search_color_map_ops::get_color<mpl::_2, mpl::second<mpl::_1> >, |
| search_colors::White>, // visit any yet unvisited |
| depth_first_search<Graph, |
| VisitorOps, mpl::first<mpl::_1>, |
| mpl::_2, |
| mpl::second<mpl::_1> >, |
| mpl::_1> > |
| {}; |
| |
| } // namespace mpl_graph |
| } // namespace msm |
| } // namespace boost |
| |
| |
| #endif // BOOST_MSM_MPL_GRAPH_DEPTH_FIRST_SEARCH_HPP_INCLUDED |