sl@0: // sl@0: //======================================================================= sl@0: // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. sl@0: // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: //======================================================================= sl@0: // sl@0: #ifndef BOOST_GRAPH_UTILITY_HPP sl@0: #define BOOST_GRAPH_UTILITY_HPP sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #if !defined BOOST_NO_SLIST sl@0: # ifdef BOOST_SLIST_HEADER sl@0: # include BOOST_SLIST_HEADER sl@0: # else sl@0: # include sl@0: # endif sl@0: #endif sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: // iota moved to detail/algorithm.hpp sl@0: #include sl@0: sl@0: namespace boost { sl@0: sl@0: // Provide an undirected graph interface alternative to the sl@0: // the source() and target() edge functions. sl@0: template sl@0: inline sl@0: std::pair::vertex_descriptor, sl@0: typename graph_traits::vertex_descriptor> sl@0: incident(typename graph_traits::edge_descriptor e, sl@0: UndirectedGraph& g) sl@0: { sl@0: return std::make_pair(source(e,g), target(e,g)); sl@0: } sl@0: sl@0: // Provide an undirected graph interface alternative sl@0: // to the out_edges() function. sl@0: template sl@0: inline sl@0: std::pair::out_edge_iterator, sl@0: typename graph_traits::out_edge_iterator> sl@0: incident_edges(typename graph_traits::vertex_descriptor u, sl@0: Graph& g) sl@0: { sl@0: return out_edges(u, g); sl@0: } sl@0: sl@0: template sl@0: inline typename graph_traits::vertex_descriptor sl@0: opposite(typename graph_traits::edge_descriptor e, sl@0: typename graph_traits::vertex_descriptor v, sl@0: const Graph& g) sl@0: { sl@0: typedef typename graph_traits::vertex_descriptor vertex_descriptor; sl@0: if (v == source(e, g)) sl@0: return target(e, g); sl@0: else if (v == target(e, g)) sl@0: return source(e, g); sl@0: else sl@0: return vertex_descriptor(); sl@0: } sl@0: sl@0: //=========================================================================== sl@0: // Some handy predicates sl@0: sl@0: template sl@0: struct incident_from_predicate { sl@0: incident_from_predicate(Vertex u, const Graph& g) sl@0: : m_u(u), m_g(g) { } sl@0: template sl@0: bool operator()(const Edge& e) const { sl@0: return source(e, m_g) == m_u; sl@0: } sl@0: Vertex m_u; sl@0: const Graph& m_g; sl@0: }; sl@0: template sl@0: inline incident_from_predicate sl@0: incident_from(Vertex u, const Graph& g) { sl@0: return incident_from_predicate(u, g); sl@0: } sl@0: sl@0: template sl@0: struct incident_to_predicate { sl@0: incident_to_predicate(Vertex u, const Graph& g) sl@0: : m_u(u), m_g(g) { } sl@0: template sl@0: bool operator()(const Edge& e) const { sl@0: return target(e, m_g) == m_u; sl@0: } sl@0: Vertex m_u; sl@0: const Graph& m_g; sl@0: }; sl@0: template sl@0: inline incident_to_predicate sl@0: incident_to(Vertex u, const Graph& g) { sl@0: return incident_to_predicate(u, g); sl@0: } sl@0: sl@0: template sl@0: struct incident_on_predicate { sl@0: incident_on_predicate(Vertex u, const Graph& g) sl@0: : m_u(u), m_g(g) { } sl@0: template sl@0: bool operator()(const Edge& e) const { sl@0: return source(e, m_g) == m_u || target(e, m_g) == m_u; sl@0: } sl@0: Vertex m_u; sl@0: const Graph& m_g; sl@0: }; sl@0: template sl@0: inline incident_on_predicate sl@0: incident_on(Vertex u, const Graph& g) { sl@0: return incident_on_predicate(u, g); sl@0: } sl@0: sl@0: template sl@0: struct connects_predicate { sl@0: connects_predicate(Vertex u, Vertex v, const Graph& g) sl@0: : m_u(u), m_v(v), m_g(g) { } sl@0: template sl@0: bool operator()(const Edge& e) const { sl@0: if (is_directed(m_g)) sl@0: return source(e, m_g) == m_u && target(e, m_g) == m_v; sl@0: else sl@0: return (source(e, m_g) == m_u && target(e, m_g) == m_v) sl@0: || (source(e, m_g) == m_v && target(e, m_g) == m_u); sl@0: } sl@0: Vertex m_u, m_v; sl@0: const Graph& m_g; sl@0: }; sl@0: template sl@0: inline connects_predicate sl@0: connects(Vertex u, Vertex v, const Graph& g) { sl@0: return connects_predicate(u, v, g); sl@0: } sl@0: sl@0: sl@0: // Need to convert all of these printing functions to take an ostream object sl@0: // -JGS sl@0: sl@0: template sl@0: void print_in_edges(const IncidenceGraph& G, Name name) sl@0: { sl@0: typename graph_traits::vertex_iterator ui,ui_end; sl@0: for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) { sl@0: std::cout << get(name,*ui) << " <-- "; sl@0: typename graph_traits sl@0: ::in_edge_iterator ei, ei_end; sl@0: for(tie(ei,ei_end) = in_edges(*ui,G); ei != ei_end; ++ei) sl@0: std::cout << get(name,source(*ei,G)) << " "; sl@0: std::cout << std::endl; sl@0: } sl@0: } sl@0: sl@0: template sl@0: void print_graph_dispatch(const IncidenceGraph& G, Name name, directed_tag) sl@0: { sl@0: typename graph_traits::vertex_iterator ui,ui_end; sl@0: for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) { sl@0: std::cout << get(name,*ui) << " --> "; sl@0: typename graph_traits sl@0: ::out_edge_iterator ei, ei_end; sl@0: for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei) sl@0: std::cout << get(name,target(*ei,G)) << " "; sl@0: std::cout << std::endl; sl@0: } sl@0: } sl@0: template sl@0: void print_graph_dispatch(const IncidenceGraph& G, Name name, undirected_tag) sl@0: { sl@0: typename graph_traits::vertex_iterator ui,ui_end; sl@0: for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) { sl@0: std::cout << get(name,*ui) << " <--> "; sl@0: typename graph_traits sl@0: ::out_edge_iterator ei, ei_end; sl@0: for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei) sl@0: std::cout << get(name,target(*ei,G)) << " "; sl@0: std::cout << std::endl; sl@0: } sl@0: } sl@0: template sl@0: void print_graph(const IncidenceGraph& G, Name name) sl@0: { sl@0: typedef typename graph_traits sl@0: ::directed_category Cat; sl@0: print_graph_dispatch(G, name, Cat()); sl@0: } sl@0: template sl@0: void print_graph(const IncidenceGraph& G) { sl@0: print_graph(G, get(vertex_index, G)); sl@0: } sl@0: sl@0: template sl@0: void print_edges(const EdgeListGraph& G, Name name) sl@0: { sl@0: typename graph_traits::edge_iterator ei, ei_end; sl@0: for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) sl@0: std::cout << "(" << get(name, source(*ei, G)) sl@0: << "," << get(name, target(*ei, G)) << ") "; sl@0: std::cout << std::endl; sl@0: } sl@0: sl@0: template sl@0: void print_edges2(const EdgeListGraph& G, VertexName vname, EdgeName ename) sl@0: { sl@0: typename graph_traits::edge_iterator ei, ei_end; sl@0: for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) sl@0: std::cout << get(ename, *ei) << "(" << get(vname, source(*ei, G)) sl@0: << "," << get(vname, target(*ei, G)) << ") "; sl@0: std::cout << std::endl; sl@0: } sl@0: sl@0: template sl@0: void print_vertices(const VertexListGraph& G, Name name) sl@0: { sl@0: typename graph_traits::vertex_iterator vi,vi_end; sl@0: for (tie(vi,vi_end) = vertices(G); vi != vi_end; ++vi) sl@0: std::cout << get(name,*vi) << " "; sl@0: std::cout << std::endl; sl@0: } sl@0: sl@0: template sl@0: bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag) sl@0: { sl@0: typedef typename graph_traits::edge_descriptor sl@0: edge_descriptor; sl@0: typename graph_traits::adjacency_iterator vi, viend, sl@0: adj_found; sl@0: tie(vi, viend) = adjacent_vertices(a, g); sl@0: adj_found = std::find(vi, viend, b); sl@0: if (adj_found == viend) sl@0: return false; sl@0: sl@0: typename graph_traits::out_edge_iterator oi, oiend, sl@0: out_found; sl@0: tie(oi, oiend) = out_edges(a, g); sl@0: out_found = std::find_if(oi, oiend, incident_to(b, g)); sl@0: if (out_found == oiend) sl@0: return false; sl@0: sl@0: typename graph_traits::in_edge_iterator ii, iiend, sl@0: in_found; sl@0: tie(ii, iiend) = in_edges(b, g); sl@0: in_found = std::find_if(ii, iiend, incident_from(a, g)); sl@0: if (in_found == iiend) sl@0: return false; sl@0: sl@0: return true; sl@0: } sl@0: template sl@0: bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag) sl@0: { sl@0: typedef typename graph_traits::edge_descriptor sl@0: edge_descriptor; sl@0: typename graph_traits::adjacency_iterator vi, viend, found; sl@0: tie(vi, viend) = adjacent_vertices(a, g); sl@0: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) sl@0: // Getting internal compiler error with std::find() sl@0: found = viend; sl@0: for (; vi != viend; ++vi) sl@0: if (*vi == b) { sl@0: found = vi; sl@0: break; sl@0: } sl@0: #else sl@0: found = std::find(vi, viend, b); sl@0: #endif sl@0: if ( found == viend ) sl@0: return false; sl@0: sl@0: typename graph_traits::out_edge_iterator oi, oiend, sl@0: out_found; sl@0: tie(oi, oiend) = out_edges(a, g); sl@0: sl@0: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) sl@0: // Getting internal compiler error with std::find() sl@0: out_found = oiend; sl@0: for (; oi != oiend; ++oi) sl@0: if (target(*oi, g) == b) { sl@0: out_found = oi; sl@0: break; sl@0: } sl@0: #else sl@0: out_found = std::find_if(oi, oiend, incident_to(b, g)); sl@0: #endif sl@0: if (out_found == oiend) sl@0: return false; sl@0: return true; sl@0: } sl@0: template sl@0: bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, undirected_tag) sl@0: { sl@0: return is_adj_dispatch(g, a, b, directed_tag()); sl@0: } sl@0: sl@0: template sl@0: bool is_adjacent(Graph& g, Vertex a, Vertex b) { sl@0: typedef typename graph_traits::directed_category Cat; sl@0: return is_adj_dispatch(g, a, b, Cat()); sl@0: } sl@0: sl@0: template sl@0: bool in_edge_set(Graph& g, Edge e) sl@0: { sl@0: typename Graph::edge_iterator ei, ei_end, found; sl@0: tie(ei, ei_end) = edges(g); sl@0: found = std::find(ei, ei_end, e); sl@0: return found != ei_end; sl@0: } sl@0: sl@0: template sl@0: bool in_vertex_set(Graph& g, Vertex v) sl@0: { sl@0: typename Graph::vertex_iterator vi, vi_end, found; sl@0: tie(vi, vi_end) = vertices(g); sl@0: found = std::find(vi, vi_end, v); sl@0: return found != vi_end; sl@0: } sl@0: sl@0: template sl@0: bool in_edge_set(Graph& g, Vertex u, Vertex v) sl@0: { sl@0: typename Graph::edge_iterator ei, ei_end; sl@0: for (tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) sl@0: if (source(*ei,g) == u && target(*ei,g) == v) sl@0: return true; sl@0: return false; sl@0: } sl@0: sl@0: // is x a descendant of y? sl@0: template sl@0: inline bool is_descendant sl@0: (typename property_traits::value_type x, sl@0: typename property_traits::value_type y, sl@0: ParentMap parent) sl@0: { sl@0: if (get(parent, x) == x) // x is the root of the tree sl@0: return false; sl@0: else if (get(parent, x) == y) sl@0: return true; sl@0: else sl@0: return is_descendant(get(parent, x), y, parent); sl@0: } sl@0: sl@0: // is y reachable from x? sl@0: template sl@0: inline bool is_reachable sl@0: (typename graph_traits::vertex_descriptor x, sl@0: typename graph_traits::vertex_descriptor y, sl@0: const IncidenceGraph& g, sl@0: VertexColorMap color) // should start out white for every vertex sl@0: { sl@0: typedef typename property_traits::value_type ColorValue; sl@0: dfs_visitor<> vis; sl@0: depth_first_visit(g, x, vis, color); sl@0: return get(color, y) != color_traits::white(); sl@0: } sl@0: sl@0: // Is the undirected graph connected? sl@0: // Is the directed graph strongly connected? sl@0: template sl@0: inline bool is_connected(const VertexListGraph& g, VertexColorMap color) sl@0: { sl@0: typedef typename property_traits::value_type ColorValue; sl@0: typedef color_traits Color; sl@0: typename graph_traits::vertex_iterator sl@0: ui, ui_end, vi, vi_end, ci, ci_end; sl@0: for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) sl@0: for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) sl@0: if (*ui != *vi) { sl@0: for (tie(ci, ci_end) = vertices(g); ci != ci_end; ++ci) sl@0: put(color, *ci, Color::white()); sl@0: if (! is_reachable(*ui, *vi, color)) sl@0: return false; sl@0: } sl@0: return true; sl@0: } sl@0: sl@0: template sl@0: bool is_self_loop sl@0: (typename graph_traits::edge_descriptor e, sl@0: const Graph& g) sl@0: { sl@0: return source(e, g) == target(e, g); sl@0: } sl@0: sl@0: sl@0: template sl@0: std::pair sl@0: make_list(const T1& t1, const T2& t2) sl@0: { return std::make_pair(t1, t2); } sl@0: sl@0: template sl@0: std::pair > sl@0: make_list(const T1& t1, const T2& t2, const T3& t3) sl@0: { return std::make_pair(t1, std::make_pair(t2, t3)); } sl@0: sl@0: template sl@0: std::pair > > sl@0: make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4) sl@0: { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, t4))); } sl@0: sl@0: template sl@0: std::pair > > > sl@0: make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) sl@0: { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, std::make_pair(t4, t5)))); } sl@0: sl@0: } /* namespace boost */ sl@0: sl@0: #endif /* BOOST_GRAPH_UTILITY_HPP*/