Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r53289 - in trunk: boost/graph libs/graph/test
From: asutton_at_[hidden]
Date: 2009-05-26 18:22:56


Author: asutton
Date: 2009-05-26 18:22:55 EDT (Tue, 26 May 2009)
New Revision: 53289
URL: http://svn.boost.org/trac/boost/changeset/53289

Log:
Augmenting property lookup strategies for subgraphs.

Text files modified:
   trunk/boost/graph/properties.hpp | 1
   trunk/boost/graph/subgraph.hpp | 1316 ++++++++++++++++++++++-----------------
   trunk/libs/graph/test/Jamfile.v2 | 4
   3 files changed, 732 insertions(+), 589 deletions(-)

Modified: trunk/boost/graph/properties.hpp
==============================================================================
--- trunk/boost/graph/properties.hpp (original)
+++ trunk/boost/graph/properties.hpp 2009-05-26 18:22:55 EDT (Tue, 26 May 2009)
@@ -385,6 +385,7 @@
       { };
   }
 
+ // Specialize the property map template to generate bundled property maps.
   template <typename Graph, typename T, typename Bundle>
   struct property_map<Graph, T Bundle::*>
   {

Modified: trunk/boost/graph/subgraph.hpp
==============================================================================
--- trunk/boost/graph/subgraph.hpp (original)
+++ trunk/boost/graph/subgraph.hpp 2009-05-26 18:22:55 EDT (Tue, 26 May 2009)
@@ -27,40 +27,57 @@
 
 namespace boost {
 
- struct subgraph_tag { };
+struct subgraph_tag { };
 
- // Invariants of an induced subgraph:
- // - If vertex u is in subgraph g, then u must be in g.parent().
- // - If edge e is in subgraph g, then e must be in g.parent().
- // - If edge e=(u,v) is in the root graph, then edge e
- // is also in any subgraph that contains both vertex u and v.
-
- // The Graph template parameter must have a vertex_index and edge_index
- // internal property. It is assumed that the vertex indices are assigned
- // automatically by the graph during a call to add_vertex(). It is not
- // assumed that the edge vertices are assigned automatically, they are
- // explicitly assigned here.
- //
- // NOTE: The requirement of internal indexing causes this to fail for many,
- // many graphs (i.e., those of non-vecS storage, and using bundled
- // properties).
- template <typename Graph>
- class subgraph {
+/** @name Property Lookup
+ * The local_property and global_property functions are used to create
+ * structures that determine the lookup strategy for properties in subgraphs.
+ */
+//@{
+template <typename T>
+struct local_subgraph_property {
+ local_subgraph_property(T x) : value(x) { }
+ T value;
+};
+
+template <typename T>
+inline local_subgraph_property<T> local(T x)
+{ return local_subgraph_property<T>(x); }
+
+template <typename T>
+struct global_subgraph_property {
+ global_subgraph_property(T x) : value(x) { }
+ T value;
+};
+
+template <typename T>
+inline global_subgraph_property<T> global(T x)
+{ return global_subgraph_property<T>(x); }
+//@}
+
+// Invariants of an induced subgraph:
+// - If vertex u is in subgraph g, then u must be in g.parent().
+// - If edge e is in subgraph g, then e must be in g.parent().
+// - If edge e=(u,v) is in the root graph, then edge e
+// is also in any subgraph that contains both vertex u and v.
+
+// The Graph template parameter must have a vertex_index and edge_index
+// internal property. It is assumed that the vertex indices are assigned
+// automatically by the graph during a call to add_vertex(). It is not
+// assumed that the edge vertices are assigned automatically, they are
+// explicitly assigned here.
+
+template <typename Graph>
+class subgraph {
     typedef graph_traits<Graph> Traits;
     typedef std::list<subgraph<Graph>*> ChildrenList;
- public:
- // Graph requirements
- typedef typename Traits::vertex_descriptor vertex_descriptor;
- typedef typename Traits::edge_descriptor edge_descriptor;
- typedef typename Traits::directed_category directed_category;
- typedef typename Traits::edge_parallel_category edge_parallel_category;
- typedef typename Traits::traversal_category traversal_category;
-
- static vertex_descriptor null_vertex()
- {
- return Traits::null_vertex();
- }
-
+public:
+// Graph requirements
+typedef typename Traits::vertex_descriptor vertex_descriptor;
+typedef typename Traits::edge_descriptor edge_descriptor;
+typedef typename Traits::directed_category directed_category;
+typedef typename Traits::edge_parallel_category edge_parallel_category;
+typedef typename Traits::traversal_category traversal_category;
 
     // IncidenceGraph requirements
     typedef typename Traits::out_edge_iterator out_edge_iterator;
@@ -87,117 +104,109 @@
     typedef Graph graph_type;
     typedef typename Graph::graph_property_type graph_property_type;
 
- // Constructors
-
     // Create the main graph, the root of the subgraph tree
     subgraph()
- : m_parent(0), m_edge_counter(0)
+ : m_parent(0), m_edge_counter(0)
     { }
+
     subgraph(const graph_property_type& p)
- : m_graph(p), m_parent(0), m_edge_counter(0)
+ : m_graph(p), m_parent(0), m_edge_counter(0)
     { }
- subgraph(vertices_size_type n,
- const graph_property_type& p = graph_property_type())
- : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n)
- {
- typename Graph::vertex_iterator v, v_end;
- vertices_size_type i = 0;
- for (tie(v, v_end) = vertices(m_graph); v != v_end; ++v)
- m_global_vertex[i++] = *v;
+
+ subgraph(vertices_size_type n, const graph_property_type& p = graph_property_type())
+ : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n)
+ {
+ typename Graph::vertex_iterator v, v_end;
+ vertices_size_type i = 0;
+ for(tie(v, v_end) = vertices(m_graph); v != v_end; ++v)
+ m_global_vertex[i++] = *v;
     }
 
     // copy constructor
     subgraph(const subgraph& x)
- : m_graph(x.m_graph), m_parent(x.m_parent),
- m_edge_counter(x.m_edge_counter),
- m_global_vertex(x.m_global_vertex),
- m_global_edge(x.m_global_edge)
- {
- // Do a deep copy
- for (typename ChildrenList::const_iterator i = x.m_children.begin();
- i != x.m_children.end(); ++i)
- m_children.push_back(new subgraph<Graph>( **i ));
+ : m_graph(x.m_graph), m_parent(x.m_parent), m_edge_counter(x.m_edge_counter)
+ , m_global_vertex(x.m_global_vertex), m_global_edge(x.m_global_edge)
+ {
+ // Do a deep copy (recursive).
+ for(typename ChildrenList::const_iterator i = x.m_children.begin();
+ i != x.m_children.end(); ++i)
+ {
+ m_children.push_back(new subgraph<Graph>( **i ));
+ }
     }
 
 
     ~subgraph() {
- for (typename ChildrenList::iterator i = m_children.begin();
- i != m_children.end(); ++i)
- delete *i;
+ for(typename ChildrenList::iterator i = m_children.begin();
+ i != m_children.end(); ++i)
+ {
+ delete *i;
+ }
     }
 
+ // Return a null vertex descriptor for the graph.
+ static vertex_descriptor null_vertex()
+ { return Traits::null_vertex(); }
+
 
     // Create a subgraph
     subgraph<Graph>& create_subgraph() {
- m_children.push_back(new subgraph<Graph>());
- m_children.back()->m_parent = this;
- return *m_children.back();
+ m_children.push_back(new subgraph<Graph>());
+ m_children.back()->m_parent = this;
+ return *m_children.back();
     }
 
     // Create a subgraph with the specified vertex set.
     template <typename VertexIterator>
- subgraph<Graph>& create_subgraph(VertexIterator first,
- VertexIterator last)
- {
- m_children.push_back(new subgraph<Graph>());
- m_children.back()->m_parent = this;
- for (; first != last; ++first)
- add_vertex(*first, *m_children.back());
- return *m_children.back();
+ subgraph<Graph>& create_subgraph(VertexIterator first, VertexIterator last) {
+ m_children.push_back(new subgraph<Graph>());
+ m_children.back()->m_parent = this;
+ for(; first != last; ++first) {
+ add_vertex(*first, *m_children.back());
+ }
+ return *m_children.back();
     }
 
     // local <-> global descriptor conversion functions
     vertex_descriptor local_to_global(vertex_descriptor u_local) const
- {
- return m_global_vertex[u_local];
- }
- vertex_descriptor global_to_local(vertex_descriptor u_global) const
- {
- vertex_descriptor u_local; bool in_subgraph;
- tie(u_local, in_subgraph) = this->find_vertex(u_global);
- assert(in_subgraph == true);
- return u_local;
+ { return m_global_vertex[u_local]; }
+
+ vertex_descriptor global_to_local(vertex_descriptor u_global) const {
+ vertex_descriptor u_local; bool in_subgraph;
+ tie(u_local, in_subgraph) = this->find_vertex(u_global);
+ assert(in_subgraph == true);
+ return u_local;
     }
+
     edge_descriptor local_to_global(edge_descriptor e_local) const
- {
- return m_global_edge[get(get(edge_index, m_graph), e_local)];
- }
+ { return m_global_edge[get(get(edge_index, m_graph), e_local)]; }
+
     edge_descriptor global_to_local(edge_descriptor e_global) const
- {
- return
- (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second;
- }
+ { return (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second; }
 
     // Is vertex u (of the root graph) contained in this subgraph?
     // If so, return the matching local vertex.
     std::pair<vertex_descriptor, bool>
- find_vertex(vertex_descriptor u_global) const
- {
- typename std::map<vertex_descriptor, vertex_descriptor>::const_iterator
- i = m_local_vertex.find(u_global);
- bool valid = i != m_local_vertex.end();
- return std::make_pair((valid ? (*i).second : null_vertex()), valid);
+ find_vertex(vertex_descriptor u_global) const {
+ typename std::map<vertex_descriptor, vertex_descriptor>::const_iterator
+ i = m_local_vertex.find(u_global);
+ bool valid = i != m_local_vertex.end();
+ return std::make_pair((valid ? (*i).second : null_vertex()), valid);
     }
 
     // Return the parent graph.
     subgraph& parent() { return *m_parent; }
     const subgraph& parent() const { return *m_parent; }
 
+ // Return true if this is the root subgraph
     bool is_root() const { return m_parent == 0; }
 
     // Return the root graph of the subgraph tree.
- subgraph& root() {
- if (this->is_root())
- return *this;
- else
- return m_parent->root();
- }
- const subgraph& root() const {
- if (this->is_root())
- return *this;
- else
- return m_parent->root();
- }
+ subgraph& root()
+ { return is_root() ? *this : m_parent->root(); }
+
+ const subgraph& root() const
+ { return is_root() ? *this : m_parent->root(); }
 
     // Return the children subgraphs of this graph/subgraph.
     // Use a list of pointers because the VC++ std::list doesn't like
@@ -216,16 +225,12 @@
>
     const_children_iterator;
 
- std::pair<const_children_iterator, const_children_iterator>
- children() const
- {
+ std::pair<const_children_iterator, const_children_iterator> children() const {
       return std::make_pair(const_children_iterator(m_children.begin()),
                             const_children_iterator(m_children.end()));
     }
 
- std::pair<children_iterator, children_iterator>
- children()
- {
+ std::pair<children_iterator, children_iterator> children() {
       return std::make_pair(children_iterator(m_children.begin()),
                             children_iterator(m_children.end()));
     }
@@ -233,22 +238,41 @@
     std::size_t num_children() const { return m_children.size(); }
 
 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
- // Bundled properties support
- template<typename Descriptor>
+ // Defualt property access delegates the lookup to global properties.
+ template <typename Descriptor>
     typename graph::detail::bundled_result<Graph, Descriptor>::type&
     operator[](Descriptor x)
- {
- if (m_parent == 0) return m_graph[x];
- else return root().m_graph[local_to_global(x)];
- }
+ { return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)]; }
 
- template<typename Descriptor>
+ template <typename Descriptor>
     typename graph::detail::bundled_result<Graph, Descriptor>::type const&
     operator[](Descriptor x) const
- {
- if (m_parent == 0) return m_graph[x];
- else return root().m_graph[local_to_global(x)];
- }
+ { return is_root() ? m_graph[x] : root().m_graph[local_to_global(x)]; }
+
+ // Local property access returns the local property of the given descripor.
+ template <typename Descriptor>
+ typename graph::detail::bundled_result<Graph, Descriptor>::type&
+ operator[](local_subgraph_property<Descriptor> x)
+ { return m_graph[x.value]; }
+
+ template <typename Descriptor>
+ typename graph::detail::bundled_result<Graph, Descriptor>::type const&
+ operator[](local_subgraph_property<Descriptor> x) const
+ { return m_graph[x.value]; }
+
+ // Global property access returns the global property associated with the
+ // given descriptor. This is an alias for the default bundled property
+ // access operations.
+ template <typename Descriptor>
+ typename graph::detail::bundled_result<Graph, Descriptor>::type&
+ operator[](global_subgraph_property<Descriptor> x)
+ { return (*this)[x.value]; }
+
+ template <typename Descriptor>
+ typename graph::detail::bundled_result<Graph, Descriptor>::type const&
+ operator[](global_subgraph_property<Descriptor> x) const
+ { return (*this)[x.value]; }
+
 #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
 
     // private:
@@ -257,46 +281,62 @@
     BOOST_STATIC_ASSERT((!is_same<edge_index_type,
                         boost::detail::error_property_not_found>::value));
 
+private:
+ typedef std::vector<vertex_descriptor> GlobalVertexList;
+ typedef std::vector<edge_descriptor> GlobalEdgeList;
+ typedef std::map<vertex_descriptor, vertex_descriptor> LocalVertexMap;
+ typedef std::map<edge_index_type, edge_descriptor> LocalEdgeMap;
+ // TODO: Should the LocalVertexMap be: map<index_type, descriptor>?
+ // TODO: Can we relax the indexing requirement if both descriptors are
+ // LessThanComparable?
+ // TODO: Should we really be using unorderd_map for improved lookup times?
+
+public: // Probably shouldn't be public....
     Graph m_graph;
     subgraph<Graph>* m_parent;
     edge_index_type m_edge_counter; // for generating unique edge indices
     ChildrenList m_children;
- std::vector<vertex_descriptor> m_global_vertex; // local -> global
- std::map<vertex_descriptor, vertex_descriptor> m_local_vertex; // global -> local
- std::vector<edge_descriptor> m_global_edge; // local -> global
- std::map<edge_index_type, edge_descriptor> m_local_edge; // global -> local
-
- edge_descriptor
- local_add_edge(vertex_descriptor u_local, vertex_descriptor v_local,
- edge_descriptor e_global)
- {
- edge_descriptor e_local;
- bool inserted;
- tie(e_local, inserted) = add_edge(u_local, v_local, m_graph);
- put(edge_index, m_graph, e_local, m_edge_counter++);
- m_global_edge.push_back(e_global);
- m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local;
- return e_local;
+ GlobalVertexList m_global_vertex; // local -> global
+ LocalVertexMap m_local_vertex; // global -> local
+ GlobalEdgeList m_global_edge; // local -> global
+ LocalEdgeMap m_local_edge; // global -> local
+
+ edge_descriptor local_add_edge(vertex_descriptor u_local,
+ vertex_descriptor v_local,
+ edge_descriptor e_global)
+ {
+ edge_descriptor e_local;
+ bool inserted;
+ tie(e_local, inserted) = add_edge(u_local, v_local, m_graph);
+ put(edge_index, m_graph, e_local, m_edge_counter++);
+ m_global_edge.push_back(e_global);
+ m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local;
+ return e_local;
     }
-
- };
+};
 
 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
- template<typename Graph>
- struct vertex_bundle_type<subgraph<Graph> > : vertex_bundle_type<Graph> { };
-
- template<typename Graph>
- struct edge_bundle_type<subgraph<Graph> > : edge_bundle_type<Graph> { };
+// TODO: I don't think these are required since the default metafunction
+// returns Graph::vertex_bundled.
+template <typename Graph>
+struct vertex_bundle_type<subgraph<Graph> >
+ : vertex_bundle_type<Graph>
+{ };
+
+template<typename Graph>
+struct edge_bundle_type<subgraph<Graph> >
+ : edge_bundle_type<Graph>
+{ };
 #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
 
- //===========================================================================
- // Functions special to the Subgraph Class
+//===========================================================================
+// Functions special to the Subgraph Class
 
- template <typename G>
- typename subgraph<G>::vertex_descriptor
- add_vertex(typename subgraph<G>::vertex_descriptor u_global,
- subgraph<G>& g)
- {
+template <typename G>
+typename subgraph<G>::vertex_descriptor
+add_vertex(typename subgraph<G>::vertex_descriptor u_global,
+ subgraph<G>& g)
+{
     assert(!g.is_root());
     typename subgraph<G>::vertex_descriptor u_local, v_global, uu_global;
     typename subgraph<G>::edge_descriptor e_global;
@@ -309,167 +349,163 @@
 
     // remember edge global and local maps
     {
- typename subgraph<G>::out_edge_iterator ei, ei_end;
- for (tie(ei, ei_end) = out_edges(u_global, r);
- ei != ei_end; ++ei) {
- e_global = *ei;
- v_global = target(e_global, r);
- if (g.find_vertex(v_global).second == true)
- g.local_add_edge(u_local, g.global_to_local(v_global), e_global);
- }
+ typename subgraph<G>::out_edge_iterator ei, ei_end;
+ for (tie(ei, ei_end) = out_edges(u_global, r);
+ ei != ei_end; ++ei) {
+ e_global = *ei;
+ v_global = target(e_global, r);
+ if (g.find_vertex(v_global).second == true)
+ g.local_add_edge(u_local, g.global_to_local(v_global), e_global);
+ }
     }
     if (is_directed(g)) { // not necessary for undirected graph
- typename subgraph<G>::vertex_iterator vi, vi_end;
- typename subgraph<G>::out_edge_iterator ei, ei_end;
- for (tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) {
- v_global = *vi;
- if (g.find_vertex(v_global).second)
- for (tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) {
- e_global = *ei;
- uu_global = target(e_global, r);
- if (uu_global == u_global && g.find_vertex(v_global).second)
- g.local_add_edge(g.global_to_local(v_global), u_local, e_global);
- }
- }
+ typename subgraph<G>::vertex_iterator vi, vi_end;
+ typename subgraph<G>::out_edge_iterator ei, ei_end;
+ for(tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) {
+ v_global = *vi;
+ if(g.find_vertex(v_global).second)
+ for(tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) {
+ e_global = *ei;
+ uu_global = target(e_global, r);
+ if(uu_global == u_global && g.find_vertex(v_global).second) {
+ g.local_add_edge(g.global_to_local(v_global), u_local, e_global);
+ }
+ }
+ }
     }
 
     return u_local;
- }
+}
+
+// NOTE: Descriptors are local unless otherwise noted.
 
- //===========================================================================
- // Functions required by the IncidenceGraph concept
+//===========================================================================
+// Functions required by the IncidenceGraph concept
 
- template <typename G>
- std::pair<typename graph_traits<G>::out_edge_iterator,
- typename graph_traits<G>::out_edge_iterator>
- out_edges(typename graph_traits<G>::vertex_descriptor u_local,
- const subgraph<G>& g)
- { return out_edges(u_local, g.m_graph); }
-
- template <typename G>
- typename graph_traits<G>::degree_size_type
- out_degree(typename graph_traits<G>::vertex_descriptor u_local,
- const subgraph<G>& g)
- { return out_degree(u_local, g.m_graph); }
-
- template <typename G>
- typename graph_traits<G>::vertex_descriptor
- source(typename graph_traits<G>::edge_descriptor e_local,
- const subgraph<G>& g)
- { return source(e_local, g.m_graph); }
-
- template <typename G>
- typename graph_traits<G>::vertex_descriptor
- target(typename graph_traits<G>::edge_descriptor e_local,
- const subgraph<G>& g)
- { return target(e_local, g.m_graph); }
-
- //===========================================================================
- // Functions required by the BidirectionalGraph concept
-
- template <typename G>
- std::pair<typename graph_traits<G>::in_edge_iterator,
- typename graph_traits<G>::in_edge_iterator>
- in_edges(typename graph_traits<G>::vertex_descriptor u_local,
- const subgraph<G>& g)
- { return in_edges(u_local, g.m_graph); }
-
- template <typename G>
- typename graph_traits<G>::degree_size_type
- in_degree(typename graph_traits<G>::vertex_descriptor u_local,
- const subgraph<G>& g)
- { return in_degree(u_local, g.m_graph); }
-
- template <typename G>
- typename graph_traits<G>::degree_size_type
- degree(typename graph_traits<G>::vertex_descriptor u_local,
- const subgraph<G>& g)
- { return degree(u_local, g.m_graph); }
-
- //===========================================================================
- // Functions required by the AdjacencyGraph concept
-
- template <typename G>
- std::pair<typename subgraph<G>::adjacency_iterator,
- typename subgraph<G>::adjacency_iterator>
- adjacent_vertices(typename subgraph<G>::vertex_descriptor u_local,
- const subgraph<G>& g)
- { return adjacent_vertices(u_local, g.m_graph); }
-
- //===========================================================================
- // Functions required by the VertexListGraph concept
-
- template <typename G>
- std::pair<typename subgraph<G>::vertex_iterator,
- typename subgraph<G>::vertex_iterator>
- vertices(const subgraph<G>& g)
- { return vertices(g.m_graph); }
-
- template <typename G>
- typename subgraph<G>::vertices_size_type
- num_vertices(const subgraph<G>& g)
- { return num_vertices(g.m_graph); }
-
- //===========================================================================
- // Functions required by the EdgeListGraph concept
-
- template <typename G>
- std::pair<typename subgraph<G>::edge_iterator,
- typename subgraph<G>::edge_iterator>
- edges(const subgraph<G>& g)
- { return edges(g.m_graph); }
-
- template <typename G>
- typename subgraph<G>::edges_size_type
- num_edges(const subgraph<G>& g)
- { return num_edges(g.m_graph); }
-
- //===========================================================================
- // Functions required by the AdjacencyMatrix concept
-
- template <typename G>
- std::pair<typename subgraph<G>::edge_descriptor, bool>
- edge(typename subgraph<G>::vertex_descriptor u_local,
- typename subgraph<G>::vertex_descriptor v_local,
- const subgraph<G>& g)
- {
- return edge(u_local, v_local, g.m_graph);
- }
+template <typename G>
+std::pair<typename graph_traits<G>::out_edge_iterator,
+ typename graph_traits<G>::out_edge_iterator>
+out_edges(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
+{ return out_edges(v, g.m_graph); }
+
+template <typename G>
+typename graph_traits<G>::degree_size_type
+out_degree(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
+{ return out_degree(v, g.m_graph); }
+
+template <typename G>
+typename graph_traits<G>::vertex_descriptor
+source(typename graph_traits<G>::edge_descriptor e, const subgraph<G>& g)
+{ return source(e, g.m_graph); }
+
+template <typename G>
+typename graph_traits<G>::vertex_descriptor
+target(typename graph_traits<G>::edge_descriptor e, const subgraph<G>& g)
+{ return target(e, g.m_graph); }
+
+//===========================================================================
+// Functions required by the BidirectionalGraph concept
+
+template <typename G>
+std::pair<typename graph_traits<G>::in_edge_iterator,
+ typename graph_traits<G>::in_edge_iterator>
+in_edges(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
+{ return in_edges(v, g.m_graph); }
+
+template <typename G>
+typename graph_traits<G>::degree_size_type
+in_degree(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
+{ return in_degree(v, g.m_graph); }
+
+template <typename G>
+typename graph_traits<G>::degree_size_type
+degree(typename graph_traits<G>::vertex_descriptor v, const subgraph<G>& g)
+{ return degree(v, g.m_graph); }
+
+//===========================================================================
+// Functions required by the AdjacencyGraph concept
+
+template <typename G>
+std::pair<typename subgraph<G>::adjacency_iterator,
+ typename subgraph<G>::adjacency_iterator>
+adjacent_vertices(typename subgraph<G>::vertex_descriptor v, const subgraph<G>& g)
+{ return adjacent_vertices(v, g.m_graph); }
+
+//===========================================================================
+// Functions required by the VertexListGraph concept
+
+template <typename G>
+std::pair<typename subgraph<G>::vertex_iterator,
+ typename subgraph<G>::vertex_iterator>
+vertices(const subgraph<G>& g)
+{ return vertices(g.m_graph); }
+
+template <typename G>
+typename subgraph<G>::vertices_size_type
+num_vertices(const subgraph<G>& g)
+{ return num_vertices(g.m_graph); }
+
+//===========================================================================
+// Functions required by the EdgeListGraph concept
+
+template <typename G>
+std::pair<typename subgraph<G>::edge_iterator,
+ typename subgraph<G>::edge_iterator>
+edges(const subgraph<G>& g)
+{ return edges(g.m_graph); }
+
+template <typename G>
+typename subgraph<G>::edges_size_type
+num_edges(const subgraph<G>& g)
+{ return num_edges(g.m_graph); }
+
+//===========================================================================
+// Functions required by the AdjacencyMatrix concept
+
+template <typename G>
+std::pair<typename subgraph<G>::edge_descriptor, bool>
+edge(typename subgraph<G>::vertex_descriptor u,
+ typename subgraph<G>::vertex_descriptor v,
+ const subgraph<G>& g)
+{ return edge(u, v, g.m_graph); }
 
- //===========================================================================
- // Functions required by the MutableGraph concept
+//===========================================================================
+// Functions required by the MutableGraph concept
 
- namespace detail {
+namespace detail {
 
     template <typename Vertex, typename Edge, typename Graph>
- void add_edge_recur_down
- (Vertex u_global, Vertex v_global, Edge e_global, subgraph<Graph>& g);
+ void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
+ subgraph<Graph>& g);
 
     template <typename Vertex, typename Edge, typename Children, typename G>
     void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global,
                            Children& c, subgraph<G>* orig)
     {
- for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
- if ((*i)->find_vertex(u_global).second
- && (*i)->find_vertex(v_global).second)
- add_edge_recur_down(u_global, v_global, e_global, **i, orig);
+ for(typename Children::iterator i = c.begin(); i != c.end(); ++i) {
+ if ((*i)->find_vertex(u_global).second &&
+ (*i)->find_vertex(v_global).second)
+ {
+ add_edge_recur_down(u_global, v_global, e_global, **i, orig);
+ }
+ }
     }
 
     template <typename Vertex, typename Edge, typename Graph>
- void add_edge_recur_down
- (Vertex u_global, Vertex v_global, Edge e_global, subgraph<Graph>& g,
- subgraph<Graph>* orig)
+ void add_edge_recur_down(Vertex u_global, Vertex v_global, Edge e_global,
+ subgraph<Graph>& g, subgraph<Graph>* orig)
     {
- if (&g != orig ) {
- // add local edge only if u_global and v_global are in subgraph g
- Vertex u_local, v_local;
- bool u_in_subgraph, v_in_subgraph;
- tie(u_local, u_in_subgraph) = g.find_vertex(u_global);
- tie(v_local, v_in_subgraph) = g.find_vertex(v_global);
- if (u_in_subgraph && v_in_subgraph)
- g.local_add_edge(u_local, v_local, e_global);
- }
- children_add_edge(u_global, v_global, e_global, g.m_children, orig);
+ if(&g != orig ) {
+ // add local edge only if u_global and v_global are in subgraph g
+ Vertex u_local, v_local;
+ bool u_in_subgraph, v_in_subgraph;
+ tie(u_local, u_in_subgraph) = g.find_vertex(u_global);
+ tie(v_local, v_in_subgraph) = g.find_vertex(v_global);
+ if(u_in_subgraph && v_in_subgraph) {
+ g.local_add_edge(u_local, v_local, e_global);
+ }
+ }
+ children_add_edge(u_global, v_global, e_global, g.m_children, orig);
     }
 
     template <typename Vertex, typename Graph>
@@ -478,58 +514,57 @@
                       const typename Graph::edge_property_type& ep,
                       subgraph<Graph>& g, subgraph<Graph>* orig)
     {
- if (g.is_root()) {
- typename subgraph<Graph>::edge_descriptor e_global;
+ if(g.is_root()) {
+ typename subgraph<Graph>::edge_descriptor e_global;
+ bool inserted;
+ tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph);
+ put(edge_index, g.m_graph, e_global, g.m_edge_counter++);
+ g.m_global_edge.push_back(e_global);
+ children_add_edge(u_global, v_global, e_global, g.m_children, orig);
+ return std::make_pair(e_global, inserted);
+ } else {
+ return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
+ }
+ }
+
+} // namespace detail
+
+// Add an edge to the subgraph g, specified by the local vertex descriptors u
+// and v. In addition, the edge will be added to any (all) other subgraphs that
+// contain vertex descriptors u and v.
+
+template <typename G>
+std::pair<typename subgraph<G>::edge_descriptor, bool>
+add_edge(typename subgraph<G>::vertex_descriptor u,
+ typename subgraph<G>::vertex_descriptor v,
+ const typename G::edge_property_type& ep,
+ subgraph<G>& g)
+{
+ if (g.is_root()) {
+ // u and v are really global
+ return detail::add_edge_recur_up(u, v, ep, g, &g);
+ } else {
+ typename subgraph<G>::edge_descriptor e_local, e_global;
         bool inserted;
- tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph);
- put(edge_index, g.m_graph, e_global, g.m_edge_counter++);
- g.m_global_edge.push_back(e_global);
- children_add_edge(u_global, v_global, e_global, g.m_children, orig);
- return std::make_pair(e_global, inserted);
- } else
- return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig);
- }
-
- } // namespace detail
-
- // Add an edge to the subgraph g, specified by the local vertex
- // descriptors u and v. In addition, the edge will be added to any
- // other subgraphs which contain vertex descriptors u and v.
-
- template <typename G>
- std::pair<typename subgraph<G>::edge_descriptor, bool>
- add_edge(typename subgraph<G>::vertex_descriptor u_local,
- typename subgraph<G>::vertex_descriptor v_local,
- const typename G::edge_property_type& ep,
- subgraph<G>& g)
- {
- if (g.is_root()) // u_local and v_local are really global
- return detail::add_edge_recur_up(u_local, v_local, ep, g, &g);
- else {
- typename subgraph<G>::edge_descriptor e_local, e_global;
- bool inserted;
- tie(e_global, inserted) = detail::add_edge_recur_up
- (g.local_to_global(u_local), g.local_to_global(v_local), ep, g, &g);
- e_local = g.local_add_edge(u_local, v_local, e_global);
- return std::make_pair(e_local, inserted);
- }
- }
-
- template <typename G>
- std::pair<typename subgraph<G>::edge_descriptor, bool>
- add_edge(typename subgraph<G>::vertex_descriptor u,
- typename subgraph<G>::vertex_descriptor v,
- subgraph<G>& g)
- {
- typename G::edge_property_type ep;
- return add_edge(u, v, ep, g);
- }
-
- namespace detail {
+ tie(e_global, inserted) =
+ detail::add_edge_recur_up(g.local_to_global(u),
+ g.local_to_global(v),
+ ep, g, &g);
+ e_local = g.local_add_edge(u, v, e_global);
+ return std::make_pair(e_local, inserted);
+ }
+}
+
+template <typename G>
+std::pair<typename subgraph<G>::edge_descriptor, bool>
+add_edge(typename subgraph<G>::vertex_descriptor u,
+ typename subgraph<G>::vertex_descriptor v,
+ subgraph<G>& g)
+{ return add_edge(u, v, typename G::edge_property_type(), g); }
 
+namespace detail {
     //-------------------------------------------------------------------------
     // implementation of remove_edge(u,v,g)
-
     template <typename Vertex, typename Graph>
     void remove_edge_recur_down(Vertex u_global, Vertex v_global,
                                 subgraph<Graph>& g);
@@ -538,378 +573,481 @@
     void children_remove_edge(Vertex u_global, Vertex v_global,
                               Children& c)
     {
- for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
- if ((*i)->find_vertex(u_global).second
- && (*i)->find_vertex(v_global).second)
- remove_edge_recur_down(u_global, v_global, **i);
+ for(typename Children::iterator i = c.begin(); i != c.end(); ++i) {
+ if((*i)->find_vertex(u_global).second &&
+ (*i)->find_vertex(v_global).second)
+ {
+ remove_edge_recur_down(u_global, v_global, **i);
+ }
+ }
     }
 
     template <typename Vertex, typename Graph>
     void remove_edge_recur_down(Vertex u_global, Vertex v_global,
                                 subgraph<Graph>& g)
     {
- Vertex u_local, v_local;
- u_local = g.m_local_vertex[u_global];
- v_local = g.m_local_vertex[v_global];
- remove_edge(u_local, v_local, g.m_graph);
- children_remove_edge(u_global, v_global, g.m_children);
+ Vertex u_local, v_local;
+ u_local = g.m_local_vertex[u_global];
+ v_local = g.m_local_vertex[v_global];
+ remove_edge(u_local, v_local, g.m_graph);
+ children_remove_edge(u_global, v_global, g.m_children);
     }
 
     template <typename Vertex, typename Graph>
     void remove_edge_recur_up(Vertex u_global, Vertex v_global,
                               subgraph<Graph>& g)
     {
- if (g.is_root()) {
- remove_edge(u_global, v_global, g.m_graph);
- children_remove_edge(u_global, v_global, g.m_children);
- } else
- remove_edge_recur_up(u_global, v_global, *g.m_parent);
+ if(g.is_root()) {
+ remove_edge(u_global, v_global, g.m_graph);
+ children_remove_edge(u_global, v_global, g.m_children);
+ } else {
+ remove_edge_recur_up(u_global, v_global, *g.m_parent);
+ }
     }
 
     //-------------------------------------------------------------------------
     // implementation of remove_edge(e,g)
-
     template <typename Edge, typename Graph>
     void remove_edge_recur_down(Edge e_global, subgraph<Graph>& g);
 
     template <typename Edge, typename Children>
     void children_remove_edge(Edge e_global, Children& c)
     {
- for (typename Children::iterator i = c.begin(); i != c.end(); ++i)
- if ((*i)->find_vertex(source(e_global, **i)).second
- && (*i)->find_vertex(target(e_global, **i)).second)
- remove_edge_recur_down(source(e_global, **i),
- target(e_global, **i), **i);
+ for(typename Children::iterator i = c.begin(); i != c.end(); ++i) {
+ if((*i)->find_vertex(source(e_global, **i)).second &&
+ (*i)->find_vertex(target(e_global, **i)).second)
+ {
+ remove_edge_recur_down(source(e_global, **i),
+ target(e_global, **i),
+ **i);
+ }
+ }
     }
 
     template <typename Edge, typename Graph>
     void remove_edge_recur_down(Edge e_global, subgraph<Graph>& g)
     {
- remove_edge(g.global_to_local(e_global), g.m_graph);
- children_remove_edge(e_global, g.m_children);
+ remove_edge(g.global_to_local(e_global), g.m_graph);
+ children_remove_edge(e_global, g.m_children);
     }
 
     template <typename Edge, typename Graph>
     void remove_edge_recur_up(Edge e_global, subgraph<Graph>& g)
     {
- if (g.is_root()) {
- remove_edge(e_global, g.m_graph);
- children_remove_edge(e_global, g.m_children);
- } else
- remove_edge_recur_up(e_global, *g.m_parent);
+ if (g.is_root()) {
+ remove_edge(e_global, g.m_graph);
+ children_remove_edge(e_global, g.m_children);
+ } else {
+ remove_edge_recur_up(e_global, *g.m_parent);
+ }
+ }
+
+} // namespace detail
+
+template <typename G>
+void
+remove_edge(typename subgraph<G>::vertex_descriptor u,
+ typename subgraph<G>::vertex_descriptor v,
+ subgraph<G>& g)
+{
+ if(g.is_root()) {
+ detail::remove_edge_recur_up(u, v, g);
+ } else {
+ detail::remove_edge_recur_up(g.local_to_global(u),
+ g.local_to_global(v), g);
     }
+}
 
- } // namespace detail
-
- template <typename G>
- void
- remove_edge(typename subgraph<G>::vertex_descriptor u_local,
- typename subgraph<G>::vertex_descriptor v_local,
- subgraph<G>& g)
- {
- if (g.is_root())
- detail::remove_edge_recur_up(u_local, v_local, g);
- else
- detail::remove_edge_recur_up(g.local_to_global(u_local),
- g.local_to_global(v_local), g);
- }
-
- template <typename G>
- void
- remove_edge(typename subgraph<G>::edge_descriptor e_local,
- subgraph<G>& g)
- {
- if (g.is_root())
- detail::remove_edge_recur_up(e_local, g);
- else
- detail::remove_edge_recur_up(g.local_to_global(e_local), g);
- }
-
- template <typename Predicate, typename G>
- void
- remove_edge_if(Predicate p, subgraph<G>& g)
- {
- // This is wrong...
- remove_edge_if(p, g.m_graph);
- }
-
- template <typename G>
- void
- clear_vertex(typename subgraph<G>::vertex_descriptor v_local,
- subgraph<G>& g)
- {
- // this is wrong...
- clear_vertex(v_local, g.m_graph);
- }
+template <typename G>
+void
+remove_edge(typename subgraph<G>::edge_descriptor e, subgraph<G>& g)
+{
+ if(g.is_root()) {
+ detail::remove_edge_recur_up(e, g);
+ } else {
+ detail::remove_edge_recur_up(g.local_to_global(e), g);
+ }
+}
 
- namespace detail {
+// TODO: This is wrong...
+template <typename Predicate, typename G>
+void
+remove_edge_if(Predicate p, subgraph<G>& g)
+{ remove_edge_if(p, g.m_graph); }
+
+// TODO: Ths is wrong
+template <typename G>
+void
+clear_vertex(typename subgraph<G>::vertex_descriptor v, subgraph<G>& g)
+{ clear_vertex(v, g.m_graph); }
 
+namespace detail {
     template <typename G>
     typename subgraph<G>::vertex_descriptor
     add_vertex_recur_up(subgraph<G>& g)
     {
- typename subgraph<G>::vertex_descriptor u_local, u_global;
- if (g.is_root()) {
+ typename subgraph<G>::vertex_descriptor u_local, u_global;
+ if (g.is_root()) {
+ u_global = add_vertex(g.m_graph);
+ g.m_global_vertex.push_back(u_global);
+ } else {
+ u_global = add_vertex_recur_up(*g.m_parent);
+ u_local = add_vertex(g.m_graph);
+ g.m_global_vertex.push_back(u_global);
+ g.m_local_vertex[u_global] = u_local;
+ }
+ return u_global;
+ }
+} // namespace detail
+
+template <typename G>
+typename subgraph<G>::vertex_descriptor
+add_vertex(subgraph<G>& g)
+{
+ typename subgraph<G>::vertex_descriptor u_local, u_global;
+ if(g.is_root()) {
         u_global = add_vertex(g.m_graph);
         g.m_global_vertex.push_back(u_global);
- } else {
- u_global = add_vertex_recur_up(*g.m_parent);
+ u_local = u_global;
+ } else {
+ u_global = detail::add_vertex_recur_up(g.parent());
         u_local = add_vertex(g.m_graph);
         g.m_global_vertex.push_back(u_global);
         g.m_local_vertex[u_global] = u_local;
- }
- return u_global;
- }
-
- } // namespace detail
-
- template <typename G>
- typename subgraph<G>::vertex_descriptor
- add_vertex(subgraph<G>& g)
- {
- typename subgraph<G>::vertex_descriptor u_local, u_global;
- if (g.is_root()) {
- u_global = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- u_local = u_global;
- } else {
- u_global = detail::add_vertex_recur_up(g.parent());
- u_local = add_vertex(g.m_graph);
- g.m_global_vertex.push_back(u_global);
- g.m_local_vertex[u_global] = u_local;
     }
     return u_local;
- }
+}
 
- template <typename G>
- typename subgraph<G>::vertex_descriptor
- add_vertex(typename subgraph<G>::vertex_property_type const& vp,
- subgraph<G>& g)
- {
- // UNDER CONSTRUCTION
- assert(false);
- }
-
- template <typename G>
- void remove_vertex(typename subgraph<G>::vertex_descriptor u,
- subgraph<G>& g)
- {
- // UNDER CONSTRUCTION
- assert(false);
- }
 
- //===========================================================================
- // Functions required by the PropertyGraph concept
-
- template <typename GraphPtr, typename PropertyMap, typename Tag>
- class subgraph_global_property_map
+// TODO: Under Construction
+template <typename G>
+void remove_vertex(typename subgraph<G>::vertex_descriptor u, subgraph<G>& g)
+{ assert(false); }
+
+//===========================================================================
+// Functions required by the PropertyGraph concept
+
+/**
+ * The global property map returns the global properties associated with local
+ * descriptors.
+ */
+template <typename GraphPtr, typename PropertyMap, typename Tag>
+class subgraph_global_property_map
     : public put_get_helper<
         typename property_traits<PropertyMap>::reference,
- subgraph_global_property_map<GraphPtr, PropertyMap, Tag> >
- {
+ subgraph_global_property_map<GraphPtr, PropertyMap, Tag>
+ >
+{
     typedef property_traits<PropertyMap> Traits;
- public:
+public:
     typedef typename Traits::category category;
     typedef typename Traits::value_type value_type;
     typedef typename Traits::key_type key_type;
     typedef typename Traits::reference reference;
 
- subgraph_global_property_map() { }
+ subgraph_global_property_map()
+ { }
 
     subgraph_global_property_map(GraphPtr g)
- : m_g(g) { }
+ : m_g(g)
+ { }
 
- inline reference operator[](key_type e_local) const {
- PropertyMap pmap = get(Tag(), m_g->root().m_graph);
- if (m_g->m_parent == 0)
- return pmap[e_local];
- else
- return pmap[m_g->local_to_global(e_local)];
+ reference operator[](key_type e) const {
+ PropertyMap pmap = get(Tag(), m_g->root().m_graph);
+ return m_g->is_root()
+ ? pmap[e]
+ : pmap[m_g->local_to_global(e)];
     }
+
     GraphPtr m_g;
- };
+};
 
- template <typename GraphPtr, typename PropertyMap, typename Tag>
- class subgraph_local_property_map
+/**
+ * The local property map returns the local property associated with the local
+ * descriptors.
+ */
+template <typename GraphPtr, typename PropertyMap, typename Tag>
+class subgraph_local_property_map
     : public put_get_helper<
         typename property_traits<PropertyMap>::reference,
- subgraph_local_property_map<GraphPtr, PropertyMap, Tag> >
- {
+ subgraph_local_property_map<GraphPtr, PropertyMap, Tag>
+ >
+{
     typedef property_traits<PropertyMap> Traits;
- public:
+public:
     typedef typename Traits::category category;
     typedef typename Traits::value_type value_type;
     typedef typename Traits::key_type key_type;
     typedef typename Traits::reference reference;
 
- subgraph_local_property_map() { }
+ subgraph_local_property_map()
+ { }
 
     subgraph_local_property_map(GraphPtr g)
- : m_g(g) { }
+ : m_g(g)
+ { }
 
- inline reference operator[](key_type e_local) const {
- PropertyMap pmap = get(Tag(), *m_g);
- return pmap[e_local];
+ reference operator[](key_type e) const {
+ PropertyMap pmap = get(Tag(), *m_g);
+ return pmap[e];
     }
- GraphPtr m_g;
- };
 
- namespace detail {
+ GraphPtr m_g;
+};
 
- struct subgraph_any_pmap {
- template <class Tag, class SubGraph, class Property>
- class bind_ {
- typedef typename SubGraph::graph_type Graph;
- typedef SubGraph* SubGraphPtr;
- typedef const SubGraph* const_SubGraphPtr;
- typedef typename property_map<Graph, Tag>::type PMap;
- typedef typename property_map<Graph, Tag>::const_type const_PMap;
- public:
- typedef subgraph_global_property_map<SubGraphPtr, PMap, Tag> type;
- typedef subgraph_global_property_map<const_SubGraphPtr, const_PMap, Tag>
- const_type;
- };
+namespace detail {
+ struct subgraph_global_pmap {
+ template <class Tag, class SubGraph, class Property>
+ class bind_ {
+ typedef typename SubGraph::graph_type Graph;
+ typedef SubGraph* SubGraphPtr;
+ typedef const SubGraph* const_SubGraphPtr;
+ typedef typename property_map<Graph, Tag>::type PMap;
+ typedef typename property_map<Graph, Tag>::const_type const_PMap;
+ public:
+ typedef subgraph_global_property_map<SubGraphPtr, PMap, Tag> type;
+ typedef subgraph_global_property_map<const_SubGraphPtr, const_PMap, Tag>
+ const_type;
+ };
     };
- struct subgraph_id_pmap {
- template <class Tag, class SubGraph, class Property>
- struct bind_ {
- typedef typename SubGraph::graph_type Graph;
- typedef SubGraph* SubGraphPtr;
- typedef const SubGraph* const_SubGraphPtr;
- typedef typename property_map<Graph, Tag>::type PMap;
- typedef typename property_map<Graph, Tag>::const_type const_PMap;
- public:
- typedef subgraph_local_property_map<SubGraphPtr, PMap, Tag> type;
- typedef subgraph_local_property_map<const_SubGraphPtr, const_PMap, Tag>
- const_type;
- };
+
+ struct subgraph_local_pmap {
+ template <class Tag, class SubGraph, class Property>
+ struct bind_ {
+ typedef typename SubGraph::graph_type Graph;
+ typedef SubGraph* SubGraphPtr;
+ typedef const SubGraph* const_SubGraphPtr;
+ typedef typename property_map<Graph, Tag>::type PMap;
+ typedef typename property_map<Graph, Tag>::const_type const_PMap;
+ public:
+ typedef subgraph_local_property_map<SubGraphPtr, PMap, Tag> type;
+ typedef subgraph_local_property_map<const_SubGraphPtr, const_PMap, Tag>
+ const_type;
+ };
     };
+
+ // These metafunctions select the corresponding metafunctions above, and
+ // are used by the choose_pmap metafunction below to specialize the choice
+ // of local/global property map.
     template <class Tag>
     struct subgraph_choose_pmap_helper {
- typedef subgraph_any_pmap type;
+ typedef subgraph_global_pmap type;
     };
     template <>
     struct subgraph_choose_pmap_helper<vertex_index_t> {
- typedef subgraph_id_pmap type;
+ typedef subgraph_local_pmap type;
     };
+
+ // Determine the kind of property. If SameType<Tag, vertex_index_t>, then
+ // the property lookup is always local. Otherwise, the lookup is global.
     template <class Tag, class Graph, class Property>
     struct subgraph_choose_pmap {
- typedef typename subgraph_choose_pmap_helper<Tag>::type Helper;
- typedef typename Helper::template bind_<Tag, Graph, Property> Bind;
- typedef typename Bind::type type;
- typedef typename Bind::const_type const_type;
+ typedef typename subgraph_choose_pmap_helper<Tag>::type Helper;
+ typedef typename Helper::template bind_<Tag, Graph, Property> Bind;
+ typedef typename Bind::type type;
+ typedef typename Bind::const_type const_type;
     };
+
+ // Used by the vertex/edge property selectors to determine the kind(s) of
+ // property maps used by the property_map type generator.
     struct subgraph_property_generator {
- template <class SubGraph, class Property, class Tag>
- struct bind_ {
- typedef subgraph_choose_pmap<Tag, SubGraph, Property> Choice;
- typedef typename Choice::type type;
- typedef typename Choice::const_type const_type;
- };
+ template <class SubGraph, class Property, class Tag>
+ struct bind_ {
+ typedef subgraph_choose_pmap<Tag, SubGraph, Property> Choice;
+ typedef typename Choice::type type;
+ typedef typename Choice::const_type const_type;
+ };
     };
 
   } // namespace detail
 
- template <>
- struct vertex_property_selector<subgraph_tag> {
+template <>
+struct vertex_property_selector<subgraph_tag> {
     typedef detail::subgraph_property_generator type;
- };
+};
 
- template <>
- struct edge_property_selector<subgraph_tag> {
+template <>
+struct edge_property_selector<subgraph_tag> {
     typedef detail::subgraph_property_generator type;
- };
+};
+
+#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
+template<typename Graph, typename Descriptor, typename Bundle, typename T>
+struct subgraph_local_bundle_property_map
+ : put_get_helper<
+ T&,
+ subgraph_local_bundle_property_map<Graph, Descriptor, Bundle, T>
+ >
+{
+ typedef Descriptor key_type;
+ typedef typename remove_const<T>::type value_type;
+ typedef T& reference;
+ typedef lvalue_property_map_tag category;
+
+ subgraph_local_bundle_property_map()
+ { }
 
- template <typename G, typename Property>
- typename property_map< subgraph<G>, Property>::type
- get(Property, subgraph<G>& g)
- {
+ subgraph_local_bundle_property_map(Graph* g, T Bundle::* p)
+ : m_g(g), m_prop(p)
+ { }
+
+ reference operator[](key_type k) const
+ { return (*m_g)[local(k)].*m_prop; }
+
+private:
+ Graph* m_g;
+ T Bundle::* m_prop;
+};
+
+// Specialize the property map template to generate bundled property maps.
+// NOTE: I'm cheating (actually double-dipping) with the local/global subgraph
+// property templates. I'm not using them store descriptors, just specialize
+// the property map template for specific lookups.
+
+template <typename Graph, typename T, typename Bundle>
+struct property_map<subgraph<Graph>, local_subgraph_property<T Bundle::*> >
+{
+private:
+ typedef subgraph<Graph> SubGraph;
+ typedef graph_traits<SubGraph> Traits;
+ typedef typename SubGraph::vertex_bundled VertBundled;
+ typedef typename SubGraph::edge_bundled EdgeBundled;
+
+ // Deduce the descriptor from the template params
+ typedef typename mpl::if_c<
+ detail::is_vertex_bundle<VertBundled, EdgeBundled, Bundle>::value,
+ typename Traits::vertex_descriptor,
+ typename Traits::edge_descriptor
+ >::type Desc;
+
+ // Deduce the bundled property type
+ typedef typename mpl::if_c<
+ detail::is_vertex_bundle<VertBundled, EdgeBundled, Bundle>::value,
+ VertBundled,
+ EdgeBundled
+ >::type Prop;
+public:
+ typedef subgraph_local_bundle_property_map<SubGraph, Desc, Prop, T> type;
+ typedef subgraph_local_bundle_property_map<const SubGraph, Desc, Prop, const T> const_type;
+};
+#endif
+
+template <typename G, typename Property>
+typename property_map<subgraph<G>, Property>::type
+get(Property, subgraph<G>& g) {
     typedef typename property_map< subgraph<G>, Property>::type PMap;
     return PMap(&g);
- }
+}
 
- template <typename G, typename Property>
- typename property_map< subgraph<G>, Property>::const_type
- get(Property, const subgraph<G>& g)
- {
+template <typename G, typename Property>
+typename property_map<subgraph<G>, Property>::const_type
+get(Property, const subgraph<G>& g) {
     typedef typename property_map< subgraph<G>, Property>::const_type PMap;
     return PMap(&g);
- }
+}
 
- template <typename G, typename Property, typename Key>
- typename property_traits<
- typename property_map< subgraph<G>, Property>::const_type
- >::value_type
- get(Property, const subgraph<G>& g, const Key& k)
- {
+template <typename G, typename Property, typename Key>
+typename property_traits<
+ typename property_map<subgraph<G>, Property>::const_type
+>::value_type
+get(Property, const subgraph<G>& g, const Key& k) {
     typedef typename property_map< subgraph<G>, Property>::const_type PMap;
     PMap pmap(&g);
     return pmap[k];
- }
+}
 
 #ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
- template<typename G, typename T, typename Bundle>
- inline typename property_map<subgraph<G>, T Bundle::*>::type
- get(T Bundle::* p, subgraph<G>& g) {
- typedef typename property_map<subgraph<G>, T Bundle::*>::type Map;
- return Map(&g, p);
- }
-
- template<typename G, typename T, typename Bundle>
- inline typename property_map<subgraph<G>, T Bundle::*>::const_type
- get(T Bundle::* p, subgraph<G> const& g) {
- typedef typename property_map<subgraph<G>, T Bundle::*>::const_type Map;
- return Map(&g, p);
- }
-
- template <typename Graph, typename Type, typename Bundle, typename Key>
- inline Type get(Type Bundle::* p, subgraph<Graph> const& g, Key const& k)
- { return get(get(p, g), k); }
-
- template <
- typename Graph, typename Type, typename Bundle, typename Key,
- typename Value>
- inline void put(Type Bundle::* p, Graph& g, Key const& k, Value const& v)
- { put(get(p, g), k, v); }
+template<typename G, typename T, typename Bundle>
+inline typename property_map<subgraph<G>, T Bundle::*>::type
+get(T Bundle::* p, subgraph<G>& g) {
+ typedef typename property_map<subgraph<G>, T Bundle::*>::type Map;
+ return Map(&g, p);
+}
+
+template<typename G, typename T, typename Bundle>
+inline typename property_map<subgraph<G>, T Bundle::*>::const_type
+get(T Bundle::* p, subgraph<G> const& g) {
+ typedef typename property_map<subgraph<G>, T Bundle::*>::const_type Map;
+ return Map(&g, p);
+}
+
+template <typename Graph, typename Type, typename Bundle, typename Key>
+inline Type get(Type Bundle::* p, subgraph<Graph> const& g, Key const& k)
+{ return get(get(p, g), k); }
+
+template <typename Graph, typename Type, typename Bundle, typename Key,
+ typename Value>
+inline void put(Type Bundle::* p, Graph& g, Key const& k, Value const& v)
+{ put(get(p, g), k, v); }
+
+// =========================================================
+// Localized bundled, get
+
+template<typename G, typename T, typename Bundle>
+inline typename property_map<
+ subgraph<G>, local_subgraph_property<T Bundle::*>
+>::type
+get(local_subgraph_property<T Bundle::*> p, subgraph<G>& g) {
+ typedef typename property_map<
+ subgraph<G>, local_subgraph_property<T Bundle::*>
+ >::type Map;
+ return Map(&g, p.value);
+}
+
+template<typename G, typename T, typename Bundle>
+inline typename property_map<
+ subgraph<G>, local_subgraph_property<T Bundle::*>
+>::const_type
+get(local_subgraph_property<T Bundle::*> p, subgraph<G> const& g) {
+ typedef typename property_map<
+ subgraph<G>, local_subgraph_property<T Bundle::*>
+ >::const_type Map;
+ return Map(&g, p.value);
+}
+
+template <typename Graph, typename Type, typename Bundle, typename Key>
+inline Type get(local_subgraph_property<Type Bundle::*> p,
+ subgraph<Graph> const& g,
+ Key const& k)
+{ return get(get(p, g), k); }
+
 #endif
 
- template <typename G, typename Property, typename Key, typename Value>
- void put(Property, subgraph<G>& g, const Key& k, const Value& val) {
+template <typename G, typename Property, typename Key, typename Value>
+void put(Property, subgraph<G>& g, const Key& k, const Value& val) {
     typedef typename property_map< subgraph<G>, Property>::type PMap;
     PMap pmap(&g);
     pmap[k] = val;
- }
+}
 
- template <typename G, typename Tag>
- inline typename graph_property<G, Tag>::type&
- get_property(subgraph<G>& g, Tag tag) {
+template <typename G, typename Tag>
+inline typename graph_property<G, Tag>::type&
+get_property(subgraph<G>& g, Tag tag) {
     return get_property(g.m_graph, tag);
- }
+}
 
- template <typename G, typename Tag>
- inline const typename graph_property<G, Tag>::type&
- get_property(const subgraph<G>& g, Tag tag) {
+template <typename G, typename Tag>
+inline const typename graph_property<G, Tag>::type&
+get_property(const subgraph<G>& g, Tag tag) {
     return get_property(g.m_graph, tag);
- }
+}
 
- //===========================================================================
- // Miscellaneous Functions
+//===========================================================================
+// Miscellaneous Functions
 
- template <typename G>
- typename subgraph<G>::vertex_descriptor
- vertex(typename subgraph<G>::vertices_size_type n, const subgraph<G>& g)
- {
- return vertex(n, g.m_graph);
- }
-
- //===========================================================================
- // Mutability Traits
- // Just pull the mutability traits form the underlying graph. Note that this
- // will probably fail (badly) for labeled graphs.
- template <typename G>
- struct graph_mutability_traits< subgraph<G> > {
- typedef typename graph_mutability_traits<G>::category category;
- };
+template <typename G>
+typename subgraph<G>::vertex_descriptor
+vertex(typename subgraph<G>::vertices_size_type n, const subgraph<G>& g)
+{ return vertex(n, g.m_graph); }
+
+//===========================================================================
+// Mutability Traits
+// Just pull the mutability traits form the underlying graph. Note that this
+// will probably fail (badly) for labeled graphs.
+template <typename G>
+struct graph_mutability_traits< subgraph<G> > {
+ typedef typename graph_mutability_traits<G>::category category;
+};
 
 } // namespace boost
 

Modified: trunk/libs/graph/test/Jamfile.v2
==============================================================================
--- trunk/libs/graph/test/Jamfile.v2 (original)
+++ trunk/libs/graph/test/Jamfile.v2 2009-05-26 18:22:55 EDT (Tue, 26 May 2009)
@@ -70,8 +70,12 @@
 
     [ compile reverse_graph_cc.cpp ]
     [ run sequential_vertex_coloring.cpp ]
+
+ # TODO: Merge these into a single test framework.
     [ run subgraph.cpp ../../test/build//boost_test_exec_monitor ]
     [ run subgraph_bundled.cpp ]
+ [ run subgraph_props.cpp ]
+
     [ run isomorphism.cpp ../../test/build//boost_test_exec_monitor ]
     [ run adjacency_matrix_test.cpp ]
     [ compile vector_graph_cc.cpp ]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk