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