williamr@2: //======================================================================= williamr@2: // Copyright 2001 University of Notre Dame. williamr@2: // Authors: Jeremy G. Siek and Lie-Quan Lee williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: //======================================================================= williamr@2: williamr@2: #ifndef BOOST_SUBGRAPH_HPP williamr@2: #define BOOST_SUBGRAPH_HPP williamr@2: williamr@2: // UNDER CONSTRUCTION williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include williamr@2: #include williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: struct subgraph_tag { }; williamr@2: williamr@2: // Invariants of an induced subgraph: williamr@2: // - If vertex u is in subgraph g, then u must be in g.parent(). williamr@2: // - If edge e is in subgraph g, then e must be in g.parent(). williamr@2: // - If edge e=(u,v) is in the root graph, then edge e williamr@2: // is also in any subgraph that contains both vertex u and v. williamr@2: williamr@2: // The Graph template parameter must have a vertex_index williamr@2: // and edge_index internal property. It is assumed that williamr@2: // the vertex indices are assigned automatically by the williamr@2: // graph during a call to add_vertex(). It is not williamr@2: // assumed that the edge vertices are assigned automatically, williamr@2: // they are explicitly assigned here. williamr@2: williamr@2: template williamr@2: class subgraph { williamr@2: typedef graph_traits Traits; williamr@2: typedef std::list*> ChildrenList; williamr@2: public: williamr@2: // Graph requirements williamr@2: typedef typename Traits::vertex_descriptor vertex_descriptor; williamr@2: typedef typename Traits::edge_descriptor edge_descriptor; williamr@2: typedef typename Traits::directed_category directed_category; williamr@2: typedef typename Traits::edge_parallel_category edge_parallel_category; williamr@2: typedef typename Traits::traversal_category traversal_category; williamr@2: williamr@2: static vertex_descriptor null_vertex() williamr@2: { williamr@2: return Traits::null_vertex(); williamr@2: } williamr@2: williamr@2: williamr@2: // IncidenceGraph requirements williamr@2: typedef typename Traits::out_edge_iterator out_edge_iterator; williamr@2: typedef typename Traits::degree_size_type degree_size_type; williamr@2: williamr@2: // AdjacencyGraph requirements williamr@2: typedef typename Traits::adjacency_iterator adjacency_iterator; williamr@2: williamr@2: // VertexListGraph requirements williamr@2: typedef typename Traits::vertex_iterator vertex_iterator; williamr@2: typedef typename Traits::vertices_size_type vertices_size_type; williamr@2: williamr@2: // EdgeListGraph requirements williamr@2: typedef typename Traits::edge_iterator edge_iterator; williamr@2: typedef typename Traits::edges_size_type edges_size_type; williamr@2: williamr@2: typedef typename Traits::in_edge_iterator in_edge_iterator; williamr@2: williamr@2: typedef typename Graph::edge_property_type edge_property_type; williamr@2: typedef typename Graph::vertex_property_type vertex_property_type; williamr@2: typedef subgraph_tag graph_tag; williamr@2: typedef Graph graph_type; williamr@2: typedef typename Graph::graph_property_type graph_property_type; williamr@2: williamr@2: // Constructors williamr@2: williamr@2: // Create the main graph, the root of the subgraph tree williamr@2: subgraph() williamr@2: : m_parent(0), m_edge_counter(0) williamr@2: { } williamr@2: subgraph(const graph_property_type& p) williamr@2: : m_graph(p), m_parent(0), m_edge_counter(0) williamr@2: { } williamr@2: subgraph(vertices_size_type n, williamr@2: const graph_property_type& p = graph_property_type()) williamr@2: : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n) williamr@2: { williamr@2: typename Graph::vertex_iterator v, v_end; williamr@2: vertices_size_type i = 0; williamr@2: for (tie(v, v_end) = vertices(m_graph); v != v_end; ++v) williamr@2: m_global_vertex[i++] = *v; williamr@2: } williamr@2: williamr@2: // copy constructor williamr@2: subgraph(const subgraph& x) williamr@2: : m_graph(x.m_graph), m_parent(x.m_parent), williamr@2: m_edge_counter(x.m_edge_counter), williamr@2: m_global_vertex(x.m_global_vertex), williamr@2: m_global_edge(x.m_global_edge) williamr@2: { williamr@2: // Do a deep copy williamr@2: for (typename ChildrenList::const_iterator i = x.m_children.begin(); williamr@2: i != x.m_children.end(); ++i) williamr@2: m_children.push_back(new subgraph( **i )); williamr@2: } williamr@2: williamr@2: williamr@2: ~subgraph() { williamr@2: for (typename ChildrenList::iterator i = m_children.begin(); williamr@2: i != m_children.end(); ++i) williamr@2: delete *i; williamr@2: } williamr@2: williamr@2: williamr@2: // Create a subgraph williamr@2: subgraph& create_subgraph() { williamr@2: m_children.push_back(new subgraph()); williamr@2: m_children.back()->m_parent = this; williamr@2: return *m_children.back(); williamr@2: } williamr@2: williamr@2: // Create a subgraph with the specified vertex set. williamr@2: template williamr@2: subgraph& create_subgraph(VertexIterator first, williamr@2: VertexIterator last) williamr@2: { williamr@2: m_children.push_back(new subgraph()); williamr@2: m_children.back()->m_parent = this; williamr@2: for (; first != last; ++first) williamr@2: add_vertex(*first, *m_children.back()); williamr@2: return *m_children.back(); williamr@2: } williamr@2: williamr@2: // local <-> global descriptor conversion functions williamr@2: vertex_descriptor local_to_global(vertex_descriptor u_local) const williamr@2: { williamr@2: return m_global_vertex[u_local]; williamr@2: } williamr@2: vertex_descriptor global_to_local(vertex_descriptor u_global) const williamr@2: { williamr@2: vertex_descriptor u_local; bool in_subgraph; williamr@2: tie(u_local, in_subgraph) = this->find_vertex(u_global); williamr@2: assert(in_subgraph == true); williamr@2: return u_local; williamr@2: } williamr@2: edge_descriptor local_to_global(edge_descriptor e_local) const williamr@2: { williamr@2: return m_global_edge[get(get(edge_index, m_graph), e_local)]; williamr@2: } williamr@2: edge_descriptor global_to_local(edge_descriptor e_global) const williamr@2: { williamr@2: return williamr@2: (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second; williamr@2: } williamr@2: williamr@2: // Is vertex u (of the root graph) contained in this subgraph? williamr@2: // If so, return the matching local vertex. williamr@2: std::pair williamr@2: find_vertex(vertex_descriptor u_global) const williamr@2: { williamr@2: typename std::map::const_iterator williamr@2: i = m_local_vertex.find(u_global); williamr@2: bool valid = i != m_local_vertex.end(); williamr@2: return std::make_pair((valid ? (*i).second : null_vertex()), valid); williamr@2: } williamr@2: williamr@2: // Return the parent graph. williamr@2: subgraph& parent() { return *m_parent; } williamr@2: const subgraph& parent() const { return *m_parent; } williamr@2: williamr@2: bool is_root() const { return m_parent == 0; } williamr@2: williamr@2: // Return the root graph of the subgraph tree. williamr@2: subgraph& root() { williamr@2: if (this->is_root()) williamr@2: return *this; williamr@2: else williamr@2: return m_parent->root(); williamr@2: } williamr@2: const subgraph& root() const { williamr@2: if (this->is_root()) williamr@2: return *this; williamr@2: else williamr@2: return m_parent->root(); williamr@2: } williamr@2: williamr@2: // Return the children subgraphs of this graph/subgraph. williamr@2: // Use a list of pointers because the VC++ std::list doesn't like williamr@2: // storing incomplete type. williamr@2: typedef indirect_iterator< williamr@2: typename ChildrenList::const_iterator williamr@2: , subgraph williamr@2: , std::bidirectional_iterator_tag williamr@2: > williamr@2: children_iterator; williamr@2: williamr@2: typedef indirect_iterator< williamr@2: typename ChildrenList::const_iterator williamr@2: , subgraph const williamr@2: , std::bidirectional_iterator_tag williamr@2: > williamr@2: const_children_iterator; williamr@2: williamr@2: std::pair williamr@2: children() const williamr@2: { williamr@2: return std::make_pair(const_children_iterator(m_children.begin()), williamr@2: const_children_iterator(m_children.end())); williamr@2: } williamr@2: williamr@2: std::pair williamr@2: children() williamr@2: { williamr@2: return std::make_pair(children_iterator(m_children.begin()), williamr@2: children_iterator(m_children.end())); williamr@2: } williamr@2: williamr@2: std::size_t num_children() const { return m_children.size(); } williamr@2: williamr@2: #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES williamr@2: // Bundled properties support williamr@2: template williamr@2: typename graph::detail::bundled_result::type& williamr@2: operator[](Descriptor x) williamr@2: { williamr@2: if (m_parent == 0) return m_graph[x]; williamr@2: else return root().m_graph[local_to_global(x)]; williamr@2: } williamr@2: williamr@2: template williamr@2: typename graph::detail::bundled_result::type const& williamr@2: operator[](Descriptor x) const williamr@2: { williamr@2: if (m_parent == 0) return m_graph[x]; williamr@2: else return root().m_graph[local_to_global(x)]; williamr@2: } williamr@2: #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES williamr@2: williamr@2: // private: williamr@2: typedef typename property_map::type EdgeIndexMap; williamr@2: typedef typename property_traits::value_type edge_index_type; williamr@2: BOOST_STATIC_ASSERT((!is_same::value)); williamr@2: williamr@2: Graph m_graph; williamr@2: subgraph* m_parent; williamr@2: edge_index_type m_edge_counter; // for generating unique edge indices williamr@2: ChildrenList m_children; williamr@2: std::vector m_global_vertex; // local -> global williamr@2: std::map m_local_vertex; // global -> local williamr@2: std::vector m_global_edge; // local -> global williamr@2: std::map m_local_edge; // global -> local williamr@2: williamr@2: edge_descriptor williamr@2: local_add_edge(vertex_descriptor u_local, vertex_descriptor v_local, williamr@2: edge_descriptor e_global) williamr@2: { williamr@2: edge_descriptor e_local; williamr@2: bool inserted; williamr@2: tie(e_local, inserted) = add_edge(u_local, v_local, m_graph); williamr@2: put(edge_index, m_graph, e_local, m_edge_counter++); williamr@2: m_global_edge.push_back(e_global); williamr@2: m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local; williamr@2: return e_local; williamr@2: } williamr@2: williamr@2: }; williamr@2: williamr@2: #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES williamr@2: template williamr@2: struct vertex_bundle_type > : vertex_bundle_type { }; williamr@2: williamr@2: template williamr@2: struct edge_bundle_type > : edge_bundle_type { }; williamr@2: #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions special to the Subgraph Class williamr@2: williamr@2: template williamr@2: typename subgraph::vertex_descriptor williamr@2: add_vertex(typename subgraph::vertex_descriptor u_global, williamr@2: subgraph& g) williamr@2: { williamr@2: assert(!g.is_root()); williamr@2: typename subgraph::vertex_descriptor u_local, v_global, uu_global; williamr@2: typename subgraph::edge_descriptor e_global; williamr@2: williamr@2: u_local = add_vertex(g.m_graph); williamr@2: g.m_global_vertex.push_back(u_global); williamr@2: g.m_local_vertex[u_global] = u_local; williamr@2: williamr@2: subgraph& r = g.root(); williamr@2: williamr@2: // remember edge global and local maps williamr@2: { williamr@2: typename subgraph::out_edge_iterator ei, ei_end; williamr@2: for (tie(ei, ei_end) = out_edges(u_global, r); williamr@2: ei != ei_end; ++ei) { williamr@2: e_global = *ei; williamr@2: v_global = target(e_global, r); williamr@2: if (g.find_vertex(v_global).second == true) williamr@2: g.local_add_edge(u_local, g.global_to_local(v_global), e_global); williamr@2: } williamr@2: } williamr@2: if (is_directed(g)) { // not necessary for undirected graph williamr@2: typename subgraph::vertex_iterator vi, vi_end; williamr@2: typename subgraph::out_edge_iterator ei, ei_end; williamr@2: for (tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { williamr@2: v_global = *vi; williamr@2: if (g.find_vertex(v_global).second) williamr@2: for (tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) { williamr@2: e_global = *ei; williamr@2: uu_global = target(e_global, r); williamr@2: if (uu_global == u_global && g.find_vertex(v_global).second) williamr@2: g.local_add_edge(g.global_to_local(v_global), u_local, e_global); williamr@2: } williamr@2: } williamr@2: } williamr@2: williamr@2: return u_local; williamr@2: } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the IncidenceGraph concept williamr@2: williamr@2: template williamr@2: std::pair::out_edge_iterator, williamr@2: typename graph_traits::out_edge_iterator> williamr@2: out_edges(typename graph_traits::vertex_descriptor u_local, williamr@2: const subgraph& g) williamr@2: { return out_edges(u_local, g.m_graph); } williamr@2: williamr@2: template williamr@2: typename graph_traits::degree_size_type williamr@2: out_degree(typename graph_traits::vertex_descriptor u_local, williamr@2: const subgraph& g) williamr@2: { return out_degree(u_local, g.m_graph); } williamr@2: williamr@2: template williamr@2: typename graph_traits::vertex_descriptor williamr@2: source(typename graph_traits::edge_descriptor e_local, williamr@2: const subgraph& g) williamr@2: { return source(e_local, g.m_graph); } williamr@2: williamr@2: template williamr@2: typename graph_traits::vertex_descriptor williamr@2: target(typename graph_traits::edge_descriptor e_local, williamr@2: const subgraph& g) williamr@2: { return target(e_local, g.m_graph); } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the BidirectionalGraph concept williamr@2: williamr@2: template williamr@2: std::pair::in_edge_iterator, williamr@2: typename graph_traits::in_edge_iterator> williamr@2: in_edges(typename graph_traits::vertex_descriptor u_local, williamr@2: const subgraph& g) williamr@2: { return in_edges(u_local, g.m_graph); } williamr@2: williamr@2: template williamr@2: typename graph_traits::degree_size_type williamr@2: in_degree(typename graph_traits::vertex_descriptor u_local, williamr@2: const subgraph& g) williamr@2: { return in_degree(u_local, g.m_graph); } williamr@2: williamr@2: template williamr@2: typename graph_traits::degree_size_type williamr@2: degree(typename graph_traits::vertex_descriptor u_local, williamr@2: const subgraph& g) williamr@2: { return degree(u_local, g.m_graph); } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the AdjacencyGraph concept williamr@2: williamr@2: template williamr@2: std::pair::adjacency_iterator, williamr@2: typename subgraph::adjacency_iterator> williamr@2: adjacent_vertices(typename subgraph::vertex_descriptor u_local, williamr@2: const subgraph& g) williamr@2: { return adjacent_vertices(u_local, g.m_graph); } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the VertexListGraph concept williamr@2: williamr@2: template williamr@2: std::pair::vertex_iterator, williamr@2: typename subgraph::vertex_iterator> williamr@2: vertices(const subgraph& g) williamr@2: { return vertices(g.m_graph); } williamr@2: williamr@2: template williamr@2: typename subgraph::vertices_size_type williamr@2: num_vertices(const subgraph& g) williamr@2: { return num_vertices(g.m_graph); } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the EdgeListGraph concept williamr@2: williamr@2: template williamr@2: std::pair::edge_iterator, williamr@2: typename subgraph::edge_iterator> williamr@2: edges(const subgraph& g) williamr@2: { return edges(g.m_graph); } williamr@2: williamr@2: template williamr@2: typename subgraph::edges_size_type williamr@2: num_edges(const subgraph& g) williamr@2: { return num_edges(g.m_graph); } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the AdjacencyMatrix concept williamr@2: williamr@2: template williamr@2: std::pair::edge_descriptor, bool> williamr@2: edge(typename subgraph::vertex_descriptor u_local, williamr@2: typename subgraph::vertex_descriptor v_local, williamr@2: const subgraph& g) williamr@2: { williamr@2: return edge(u_local, v_local, g.m_graph); williamr@2: } williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the MutableGraph concept williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: template williamr@2: void add_edge_recur_down williamr@2: (Vertex u_global, Vertex v_global, Edge e_global, subgraph& g); williamr@2: williamr@2: template williamr@2: void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global, williamr@2: Children& c, subgraph* orig) williamr@2: { williamr@2: for (typename Children::iterator i = c.begin(); i != c.end(); ++i) williamr@2: if ((*i)->find_vertex(u_global).second williamr@2: && (*i)->find_vertex(v_global).second) williamr@2: add_edge_recur_down(u_global, v_global, e_global, **i, orig); williamr@2: } williamr@2: williamr@2: template williamr@2: void add_edge_recur_down williamr@2: (Vertex u_global, Vertex v_global, Edge e_global, subgraph& g, williamr@2: subgraph* orig) williamr@2: { williamr@2: if (&g != orig ) { williamr@2: // add local edge only if u_global and v_global are in subgraph g williamr@2: Vertex u_local, v_local; williamr@2: bool u_in_subgraph, v_in_subgraph; williamr@2: tie(u_local, u_in_subgraph) = g.find_vertex(u_global); williamr@2: tie(v_local, v_in_subgraph) = g.find_vertex(v_global); williamr@2: if (u_in_subgraph && v_in_subgraph) williamr@2: g.local_add_edge(u_local, v_local, e_global); williamr@2: } williamr@2: children_add_edge(u_global, v_global, e_global, g.m_children, orig); williamr@2: } williamr@2: williamr@2: template williamr@2: std::pair::edge_descriptor, bool> williamr@2: add_edge_recur_up(Vertex u_global, Vertex v_global, williamr@2: const typename Graph::edge_property_type& ep, williamr@2: subgraph& g, subgraph* orig) williamr@2: { williamr@2: if (g.is_root()) { williamr@2: typename subgraph::edge_descriptor e_global; williamr@2: bool inserted; williamr@2: tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph); williamr@2: put(edge_index, g.m_graph, e_global, g.m_edge_counter++); williamr@2: g.m_global_edge.push_back(e_global); williamr@2: children_add_edge(u_global, v_global, e_global, g.m_children, orig); williamr@2: return std::make_pair(e_global, inserted); williamr@2: } else williamr@2: return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig); williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: // Add an edge to the subgraph g, specified by the local vertex williamr@2: // descriptors u and v. In addition, the edge will be added to any williamr@2: // other subgraphs which contain vertex descriptors u and v. williamr@2: williamr@2: template williamr@2: std::pair::edge_descriptor, bool> williamr@2: add_edge(typename subgraph::vertex_descriptor u_local, williamr@2: typename subgraph::vertex_descriptor v_local, williamr@2: const typename G::edge_property_type& ep, williamr@2: subgraph& g) williamr@2: { williamr@2: if (g.is_root()) // u_local and v_local are really global williamr@2: return detail::add_edge_recur_up(u_local, v_local, ep, g, &g); williamr@2: else { williamr@2: typename subgraph::edge_descriptor e_local, e_global; williamr@2: bool inserted; williamr@2: tie(e_global, inserted) = detail::add_edge_recur_up williamr@2: (g.local_to_global(u_local), g.local_to_global(v_local), ep, g, &g); williamr@2: e_local = g.local_add_edge(u_local, v_local, e_global); williamr@2: return std::make_pair(e_local, inserted); williamr@2: } williamr@2: } williamr@2: williamr@2: template williamr@2: std::pair::edge_descriptor, bool> williamr@2: add_edge(typename subgraph::vertex_descriptor u, williamr@2: typename subgraph::vertex_descriptor v, williamr@2: subgraph& g) williamr@2: { williamr@2: typename G::edge_property_type ep; williamr@2: return add_edge(u, v, ep, g); williamr@2: } williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: //------------------------------------------------------------------------- williamr@2: // implementation of remove_edge(u,v,g) williamr@2: williamr@2: template williamr@2: void remove_edge_recur_down(Vertex u_global, Vertex v_global, williamr@2: subgraph& g); williamr@2: williamr@2: template williamr@2: void children_remove_edge(Vertex u_global, Vertex v_global, williamr@2: Children& c) williamr@2: { williamr@2: for (typename Children::iterator i = c.begin(); i != c.end(); ++i) williamr@2: if ((*i)->find_vertex(u_global).second williamr@2: && (*i)->find_vertex(v_global).second) williamr@2: remove_edge_recur_down(u_global, v_global, **i); williamr@2: } williamr@2: williamr@2: template williamr@2: void remove_edge_recur_down(Vertex u_global, Vertex v_global, williamr@2: subgraph& g) williamr@2: { williamr@2: Vertex u_local, v_local; williamr@2: u_local = g.m_local_vertex[u_global]; williamr@2: v_local = g.m_local_vertex[v_global]; williamr@2: remove_edge(u_local, v_local, g.m_graph); williamr@2: children_remove_edge(u_global, v_global, g.m_children); williamr@2: } williamr@2: williamr@2: template williamr@2: void remove_edge_recur_up(Vertex u_global, Vertex v_global, williamr@2: subgraph& g) williamr@2: { williamr@2: if (g.is_root()) { williamr@2: remove_edge(u_global, v_global, g.m_graph); williamr@2: children_remove_edge(u_global, v_global, g.m_children); williamr@2: } else williamr@2: remove_edge_recur_up(u_global, v_global, *g.m_parent); williamr@2: } williamr@2: williamr@2: //------------------------------------------------------------------------- williamr@2: // implementation of remove_edge(e,g) williamr@2: williamr@2: template williamr@2: void remove_edge_recur_down(Edge e_global, subgraph& g); williamr@2: williamr@2: template williamr@2: void children_remove_edge(Edge e_global, Children& c) williamr@2: { williamr@2: for (typename Children::iterator i = c.begin(); i != c.end(); ++i) williamr@2: if ((*i)->find_vertex(source(e_global, **i)).second williamr@2: && (*i)->find_vertex(target(e_global, **i)).second) williamr@2: remove_edge_recur_down(source(e_global, **i), williamr@2: target(e_global, **i), **i); williamr@2: } williamr@2: williamr@2: template williamr@2: void remove_edge_recur_down(Edge e_global, subgraph& g) williamr@2: { williamr@2: remove_edge(g.global_to_local(e_global), g.m_graph); williamr@2: children_remove_edge(e_global, g.m_children); williamr@2: } williamr@2: williamr@2: template williamr@2: void remove_edge_recur_up(Edge e_global, subgraph& g) williamr@2: { williamr@2: if (g.is_root()) { williamr@2: remove_edge(e_global, g.m_graph); williamr@2: children_remove_edge(e_global, g.m_children); williamr@2: } else williamr@2: remove_edge_recur_up(e_global, *g.m_parent); williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: template williamr@2: void williamr@2: remove_edge(typename subgraph::vertex_descriptor u_local, williamr@2: typename subgraph::vertex_descriptor v_local, williamr@2: subgraph& g) williamr@2: { williamr@2: if (g.is_root()) williamr@2: detail::remove_edge_recur_up(u_local, v_local, g); williamr@2: else williamr@2: detail::remove_edge_recur_up(g.local_to_global(u_local), williamr@2: g.local_to_global(v_local), g); williamr@2: } williamr@2: williamr@2: template williamr@2: void williamr@2: remove_edge(typename subgraph::edge_descriptor e_local, williamr@2: subgraph& g) williamr@2: { williamr@2: if (g.is_root()) williamr@2: detail::remove_edge_recur_up(e_local, g); williamr@2: else williamr@2: detail::remove_edge_recur_up(g.local_to_global(e_local), g); williamr@2: } williamr@2: williamr@2: template williamr@2: void williamr@2: remove_edge_if(Predicate p, subgraph& g) williamr@2: { williamr@2: // This is wrong... williamr@2: remove_edge_if(p, g.m_graph); williamr@2: } williamr@2: williamr@2: template williamr@2: void williamr@2: clear_vertex(typename subgraph::vertex_descriptor v_local, williamr@2: subgraph& g) williamr@2: { williamr@2: // this is wrong... williamr@2: clear_vertex(v_local, g.m_graph); williamr@2: } williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: template williamr@2: typename subgraph::vertex_descriptor williamr@2: add_vertex_recur_up(subgraph& g) williamr@2: { williamr@2: typename subgraph::vertex_descriptor u_local, u_global; williamr@2: if (g.is_root()) { williamr@2: u_global = add_vertex(g.m_graph); williamr@2: g.m_global_vertex.push_back(u_global); williamr@2: } else { williamr@2: u_global = add_vertex_recur_up(*g.m_parent); williamr@2: u_local = add_vertex(g.m_graph); williamr@2: g.m_global_vertex.push_back(u_global); williamr@2: g.m_local_vertex[u_global] = u_local; williamr@2: } williamr@2: return u_global; williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: template williamr@2: typename subgraph::vertex_descriptor williamr@2: add_vertex(subgraph& g) williamr@2: { williamr@2: typename subgraph::vertex_descriptor u_local, u_global; williamr@2: if (g.is_root()) { williamr@2: u_global = add_vertex(g.m_graph); williamr@2: g.m_global_vertex.push_back(u_global); williamr@2: u_local = u_global; williamr@2: } else { williamr@2: u_global = detail::add_vertex_recur_up(g.parent()); williamr@2: u_local = add_vertex(g.m_graph); williamr@2: g.m_global_vertex.push_back(u_global); williamr@2: g.m_local_vertex[u_global] = u_local; williamr@2: } williamr@2: return u_local; williamr@2: } williamr@2: williamr@2: template williamr@2: void remove_vertex(typename subgraph::vertex_descriptor u, williamr@2: subgraph& g) williamr@2: { williamr@2: // UNDER CONSTRUCTION williamr@2: assert(false); williamr@2: } williamr@2: williamr@2: williamr@2: //=========================================================================== williamr@2: // Functions required by the PropertyGraph concept williamr@2: williamr@2: template williamr@2: class subgraph_global_property_map williamr@2: : public put_get_helper< williamr@2: typename property_traits::reference, williamr@2: subgraph_global_property_map > williamr@2: { williamr@2: typedef property_traits Traits; williamr@2: public: williamr@2: typedef typename Traits::category category; williamr@2: typedef typename Traits::value_type value_type; williamr@2: typedef typename Traits::key_type key_type; williamr@2: typedef typename Traits::reference reference; williamr@2: williamr@2: subgraph_global_property_map() { } williamr@2: williamr@2: subgraph_global_property_map(GraphPtr g) williamr@2: : m_g(g) { } williamr@2: williamr@2: inline reference operator[](key_type e_local) const { williamr@2: PropertyMap pmap = get(Tag(), m_g->root().m_graph); williamr@2: if (m_g->m_parent == 0) williamr@2: return pmap[e_local]; williamr@2: else williamr@2: return pmap[m_g->local_to_global(e_local)]; williamr@2: } williamr@2: GraphPtr m_g; williamr@2: }; williamr@2: williamr@2: template williamr@2: class subgraph_local_property_map williamr@2: : public put_get_helper< williamr@2: typename property_traits::reference, williamr@2: subgraph_local_property_map > williamr@2: { williamr@2: typedef property_traits Traits; williamr@2: public: williamr@2: typedef typename Traits::category category; williamr@2: typedef typename Traits::value_type value_type; williamr@2: typedef typename Traits::key_type key_type; williamr@2: typedef typename Traits::reference reference; williamr@2: williamr@2: subgraph_local_property_map() { } williamr@2: williamr@2: subgraph_local_property_map(GraphPtr g) williamr@2: : m_g(g) { } williamr@2: williamr@2: inline reference operator[](key_type e_local) const { williamr@2: PropertyMap pmap = get(Tag(), *m_g); williamr@2: return pmap[e_local]; williamr@2: } williamr@2: GraphPtr m_g; williamr@2: }; williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: struct subgraph_any_pmap { williamr@2: template williamr@2: class bind_ { williamr@2: typedef typename SubGraph::graph_type Graph; williamr@2: typedef SubGraph* SubGraphPtr; williamr@2: typedef const SubGraph* const_SubGraphPtr; williamr@2: typedef typename property_map::type PMap; williamr@2: typedef typename property_map::const_type const_PMap; williamr@2: public: williamr@2: typedef subgraph_global_property_map type; williamr@2: typedef subgraph_global_property_map williamr@2: const_type; williamr@2: }; williamr@2: }; williamr@2: struct subgraph_id_pmap { williamr@2: template williamr@2: struct bind_ { williamr@2: typedef typename SubGraph::graph_type Graph; williamr@2: typedef SubGraph* SubGraphPtr; williamr@2: typedef const SubGraph* const_SubGraphPtr; williamr@2: typedef typename property_map::type PMap; williamr@2: typedef typename property_map::const_type const_PMap; williamr@2: public: williamr@2: typedef subgraph_local_property_map type; williamr@2: typedef subgraph_local_property_map williamr@2: const_type; williamr@2: }; williamr@2: }; williamr@2: template williamr@2: struct subgraph_choose_pmap_helper { williamr@2: typedef subgraph_any_pmap type; williamr@2: }; williamr@2: template <> williamr@2: struct subgraph_choose_pmap_helper { williamr@2: typedef subgraph_id_pmap type; williamr@2: }; williamr@2: template williamr@2: struct subgraph_choose_pmap { williamr@2: typedef typename subgraph_choose_pmap_helper::type Helper; williamr@2: typedef typename Helper::template bind_ Bind; williamr@2: typedef typename Bind::type type; williamr@2: typedef typename Bind::const_type const_type; williamr@2: }; williamr@2: struct subgraph_property_generator { williamr@2: template williamr@2: struct bind_ { williamr@2: typedef subgraph_choose_pmap Choice; williamr@2: typedef typename Choice::type type; williamr@2: typedef typename Choice::const_type const_type; williamr@2: }; williamr@2: }; williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: template <> williamr@2: struct vertex_property_selector { williamr@2: typedef detail::subgraph_property_generator type; williamr@2: }; williamr@2: williamr@2: template <> williamr@2: struct edge_property_selector { williamr@2: typedef detail::subgraph_property_generator type; williamr@2: }; williamr@2: williamr@2: template williamr@2: typename property_map< subgraph, Property>::type williamr@2: get(Property, subgraph& g) williamr@2: { williamr@2: typedef typename property_map< subgraph, Property>::type PMap; williamr@2: return PMap(&g); williamr@2: } williamr@2: williamr@2: template williamr@2: typename property_map< subgraph, Property>::const_type williamr@2: get(Property, const subgraph& g) williamr@2: { williamr@2: typedef typename property_map< subgraph, Property>::const_type PMap; williamr@2: return PMap(&g); williamr@2: } williamr@2: williamr@2: template williamr@2: typename property_traits< williamr@2: typename property_map< subgraph, Property>::const_type williamr@2: >::value_type williamr@2: get(Property, const subgraph& g, const Key& k) williamr@2: { williamr@2: typedef typename property_map< subgraph, Property>::const_type PMap; williamr@2: PMap pmap(&g); williamr@2: return pmap[k]; williamr@2: } williamr@2: williamr@2: template williamr@2: void williamr@2: put(Property, subgraph& g, const Key& k, const Value& val) williamr@2: { williamr@2: typedef typename property_map< subgraph, Property>::type PMap; williamr@2: PMap pmap(&g); williamr@2: pmap[k] = val; williamr@2: } williamr@2: williamr@2: template williamr@2: inline williamr@2: typename graph_property::type& williamr@2: get_property(subgraph& g, Tag tag) { williamr@2: return get_property(g.m_graph, tag); williamr@2: } williamr@2: williamr@2: template williamr@2: inline williamr@2: const typename graph_property::type& williamr@2: get_property(const subgraph& g, Tag tag) { williamr@2: return get_property(g.m_graph, tag); williamr@2: } williamr@2: williamr@2: //=========================================================================== williamr@2: // Miscellaneous Functions williamr@2: williamr@2: template williamr@2: typename subgraph::vertex_descriptor williamr@2: vertex(typename subgraph::vertices_size_type n, const subgraph& g) williamr@2: { williamr@2: return vertex(n, g.m_graph); williamr@2: } williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: #endif // BOOST_SUBGRAPH_HPP