diff --git a/doc/subgraph.html b/doc/subgraph.html index 09d07b30..90c6019c 100644 --- a/doc/subgraph.html +++ b/doc/subgraph.html @@ -76,9 +76,9 @@ built in to the adjacency_list. We will be building the graph and subgraphs in Figure 1, so we will need a total of six vertices.
-typedef adjacency_list_traits Traits;
-typedef subgraph< adjacency_list > > Graph;
+typedef adjacency_list_traits< vecS, vecS, directedS > Traits;
+typedef subgraph< adjacency_list< vecS, vecS, directedS,
+  no_property, property< edge_index_t, int > > > Graph;
 
 const int N = 6;
 Graph G0(N);
diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp
index fd1b0415..257438f5 100644
--- a/include/boost/graph/graph_traits.hpp
+++ b/include/boost/graph/graph_traits.hpp
@@ -217,6 +217,11 @@ namespace boost {
     //?? not the right place ?? Lee
     typedef boost::forward_traversal_tag multi_pass_input_iterator_tag;
 
+    // Forward declare graph_bundle_t property name (from
+    // boost/graph/properties.hpp, which includes this file) for
+    // bundled_result.
+    enum graph_bundle_t {graph_bundle};
+
     template 
     struct graph_property_type {
       typedef typename G::graph_property_type type;
@@ -261,6 +266,14 @@ namespace boost {
             typedef typename bundler::type type;
         };
 
+        template
+        class bundled_result {
+            typedef typename graph_traits::vertex_descriptor Vertex;
+            typedef graph_bundle_type bundler;
+        public:
+            typedef typename bundler::type type;
+        };
+
     } } // namespace graph::detail
 
     namespace graph_detail {
diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp
index 9461dc31..f5869026 100644
--- a/include/boost/graph/isomorphism.hpp
+++ b/include/boost/graph/isomorphism.hpp
@@ -284,18 +284,30 @@ namespace boost {
     typedef size_type result_type;
 
     degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g)
-      : m_in_degree_map(in_degree_map), m_g(g) { }
+      : m_in_degree_map(in_degree_map),
+        m_max_vertex_in_degree(0),
+        m_max_vertex_out_degree(0),
+        m_g(g) {
+      BGL_FORALL_VERTICES_T(v, g, Graph) {
+        m_max_vertex_in_degree =
+          (std::max)(m_max_vertex_in_degree, get(m_in_degree_map, v));
+        m_max_vertex_out_degree =
+          (std::max)(m_max_vertex_out_degree, out_degree(v, g));
+      }
+    }
 
     size_type operator()(vertex_t v) const {
-      return (num_vertices(m_g) + 1) * out_degree(v, m_g)
+      return (m_max_vertex_in_degree + 1) * out_degree(v, m_g)
         + get(m_in_degree_map, v);
     }
     // The largest possible vertex invariant number
     size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { 
-      return num_vertices(m_g) * num_vertices(m_g) + num_vertices(m_g);
+      return (m_max_vertex_in_degree + 2) * m_max_vertex_out_degree + 1;
     }
   private:
     InDegreeMap m_in_degree_map;
+    size_type m_max_vertex_in_degree;
+    size_type m_max_vertex_out_degree;
     const Graph& m_g;
   };
 
diff --git a/include/boost/graph/properties.hpp b/include/boost/graph/properties.hpp
index f4c57ea2..dd7a7357 100644
--- a/include/boost/graph/properties.hpp
+++ b/include/boost/graph/properties.hpp
@@ -126,7 +126,8 @@ namespace boost {
   BOOST_DEF_PROPERTY(graph, visitor);
 
   // These tags are used for property bundles
-  BOOST_DEF_PROPERTY(graph, bundle);
+  // BOOST_DEF_PROPERTY(graph, bundle); -- needed in graph_traits.hpp, so enum is defined there
+  BOOST_INSTALL_PROPERTY(graph, bundle);
   BOOST_DEF_PROPERTY(vertex, bundle);
   BOOST_DEF_PROPERTY(edge, bundle);
 
diff --git a/include/boost/graph/reverse_graph.hpp b/include/boost/graph/reverse_graph.hpp
index 30d303b1..4067f2c2 100644
--- a/include/boost/graph/reverse_graph.hpp
+++ b/include/boost/graph/reverse_graph.hpp
@@ -90,12 +90,6 @@ class reverse_graph {
     typename graph::detail::bundled_result::type const&
     operator[](Descriptor x) const
     { return m_g[x]; }
-
-    typename boost::graph_property_type::type& operator[](graph_bundle_t)
-    { return get_property(*this); }
-
-    typename boost::graph_property_type::type const& operator[](graph_bundle_t) const
-    { return get_property(*this); }
 #endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
 
     static vertex_descriptor null_vertex()
diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp
index 9e091941..2b702a80 100644
--- a/include/boost/graph/subgraph.hpp
+++ b/include/boost/graph/subgraph.hpp
@@ -78,12 +78,12 @@ class subgraph {
     typedef graph_traits Traits;
     typedef std::list*> 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;
+    // 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;
@@ -196,12 +196,22 @@ typedef typename Traits::traversal_category        traversal_category;
     std::pair
     find_vertex(vertex_descriptor u_global) const {
         if (is_root()) return std::make_pair(u_global, true);
-        typename std::map::const_iterator
-            i = m_local_vertex.find(u_global);
+        typename LocalVertexMap::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);
     }
 
+    // Is edge e (of the root graph) contained in this subgraph?
+    // If so, return the matching local edge.
+    std::pair
+    find_edge(edge_descriptor e_global) const {
+        if (is_root()) return std::make_pair(e_global, true);
+        typename LocalEdgeMap::const_iterator i =
+          m_local_edge.find(get(get(edge_index, root().m_graph), e_global));
+        bool valid = i != m_local_edge.end();
+        return std::make_pair((valid ? (*i).second : edge_descriptor()), valid);
+    }
+
     // Return the parent graph.
     subgraph& parent() { return *m_parent; }
     const subgraph& parent() const { return *m_parent; }
@@ -617,38 +627,18 @@ namespace detail {
 
     //-------------------------------------------------------------------------
     // implementation of remove_edge(e,g)
-    template 
-    void remove_edge_recur_down(Edge e_global, subgraph& g);
 
-    template 
+    template 
     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);
+            std::pair::edge_descriptor, bool> found =
+              (*i)->find_edge(e_global);
+            if (!found.second) {
+              continue;
             }
-        }
-    }
-
-    template 
-    void remove_edge_recur_down(Edge e_global, subgraph& g)
-    {
-        remove_edge(g.global_to_local(e_global), g.m_graph);
-        children_remove_edge(e_global, g.m_children);
-    }
-
-    template 
-    void remove_edge_recur_up(Edge e_global, subgraph& 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);
+            children_remove_edge(e_global, (*i)->m_children);
+            remove_edge(found.first, (*i)->m_graph);
         }
     }
 
@@ -672,11 +662,14 @@ template 
 void
 remove_edge(typename subgraph::edge_descriptor e, subgraph& g)
 {
-    if(g.is_root()) {
-        detail::remove_edge_recur_up(e, g);
-    } else {
-        detail::remove_edge_recur_up(g.local_to_global(e), g);
-    }
+    typename subgraph::edge_descriptor e_global = g.local_to_global(e);
+#ifndef NDEBUG
+    std::pair::edge_descriptor, bool> fe = g.find_edge(e_global);
+    assert(fe.second && fe.first == e);
+#endif //NDEBUG
+    subgraph &root = g.root(); // chase to root
+    detail::children_remove_edge(e_global, root.m_children);
+    remove_edge(e_global, root.m_graph); // kick edge from root
 }
 
 // This is slow, but there may not be a good way to do it safely otherwise
@@ -691,7 +684,7 @@ remove_edge_if(Predicate p, subgraph& g) {
       if (p(*ep.first)) {
         any_removed = true;
         remove_edge(*ep.first, g);
-        continue; /* Since iterators may be invalidated */
+        break; /* Since iterators may be invalidated */
       }
     }
     if (!any_removed) break;
diff --git a/include/boost/graph/transitive_reduction.hpp b/include/boost/graph/transitive_reduction.hpp
index 44dfee98..f7cb34b8 100644
--- a/include/boost/graph/transitive_reduction.hpp
+++ b/include/boost/graph/transitive_reduction.hpp
@@ -99,7 +99,7 @@ transitive_reduction(const Graph& g, GraphTR& tr,
         {
             //and run through all vertices in topological order
             typename std::vector::reverse_iterator
-                rit = topo_order.rbegin();
+                rit = topo_order.rbegin(),
                 rend = topo_order.rend();
             for(; rit != rend; ++rit ) {
                 //looking if they are successors of *it