Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50160 - in sandbox/SOC/2008/graphs/trunk/libs/graphs: include/boost/graphs/adjacency_list test test/gen
From: asutton_at_[hidden]
Date: 2008-12-06 09:31:36


Author: asutton
Date: 2008-12-06 09:31:35 EST (Sat, 06 Dec 2008)
New Revision: 50160
URL: http://svn.boost.org/trac/boost/changeset/50160

Log:
Implementing (kind of badly) remove_edges(g,v)
Added:
   sandbox/SOC/2008/graphs/trunk/libs/graphs/test/gen/
   sandbox/SOC/2008/graphs/trunk/libs/graphs/test/gen/star.hpp (contents, props changed)
   sandbox/SOC/2008/graphs/trunk/libs/graphs/test/traits.hpp (contents, props changed)
Text files modified:
   sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/incidence_store.hpp | 39 +++++++++++++++++++++----------
   sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/undirected_graph.hpp | 38 ++++++++++++++++++++++++++++---
   sandbox/SOC/2008/graphs/trunk/libs/graphs/test/undirected.cpp | 48 ++++++++-------------------------------
   3 files changed, 70 insertions(+), 55 deletions(-)

Modified: sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/incidence_store.hpp
==============================================================================
--- sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/incidence_store.hpp (original)
+++ sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/incidence_store.hpp 2008-12-06 09:31:35 EST (Sat, 06 Dec 2008)
@@ -63,7 +63,7 @@
     { return store.find(v); }
 
     // A default visitor for the erase_all function.
- struct noop_erase_visitor
+ struct no_edge_erase
     {
         template <typename Pair> inline void operator()(Pair const&) { }
     };
@@ -145,7 +145,22 @@
 { return find(const_cast<Store&>(store), v); }
 //@}
 
-/** Remove the adjacenct/incident pair from the store. */
+// NOTE Reciprocating and Cascading Erasures
+//
+// Reciprocal erasure is the problem where removing an AI pair from one
+// vertex requires its reciprocal erasure from the incidence store of the
+// adjacent vertex.
+//
+// Cascading erasure is the problem where removing an AI pair from one
+// vertex should also require the erasure from the edge set.
+//
+// Note that reciprocating erasure can be fairly inefficient when erasing
+// multi-edges because it will result in multiple iterations of the adjacent
+// vertex's incidence store,
+
+/**
+ * Remove the adjacenct/incident pair from the store.
+ */
 template <typename Store>
 inline void
 erase(Store& store,
@@ -157,10 +172,10 @@
 }
 
 /**
- * Remove all incident edges with the given endpoint. A visitor parameter can
- * be provided to be invoked just prior to erasure.
+ * Remove all incident edges with the given endpoint. This operation supports
+ * cascading erases via a function object. By default, this is disabled.
  */
-template <typename Store, typename Visitor = detail::noop_erase_visitor>
+template <typename Store, typename Visitor = detail::no_edge_erase>
 inline void
 erase_all(Store& store,
           typename incidence_store_traits<Store>::vertex_descriptor v,
@@ -168,20 +183,18 @@
 { detail::dispatch_erase_all(store, v, vis, container_category(store)); }
 
 /**
- * Remove all incident edges from the edge set, invoking a visitor just prior
- * to erasing the edge.
+ * Remove all incident edges from the edge set. This operation supports
+ * reciprocation and cascading erases via function object. By default, this is
+ * disabled.
  */
-template <typename Store, typename Visitor = detail::noop_erase_visitor>
+template <typename Store, typename Visitor = detail::no_edge_erase>
 inline void
 clear(Store& store, Visitor vis = Visitor())
 {
- typename Store::iterator i, end = store.end();
- for(i = store.begin() ; i != end; ++i) {
- vis(*i);
- }
+ std::for_each(store.begin(), store.end(), vis);
+ store.clear();
 }
 
-
 /** Return the size of an adjacency list for the given vertex, its degree. */
 template <typename Store>
 inline typename incidence_store_traits<Store>::incident_edges_size_type

Modified: sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/undirected_graph.hpp
==============================================================================
--- sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/undirected_graph.hpp (original)
+++ sandbox/SOC/2008/graphs/trunk/libs/graphs/include/boost/graphs/adjacency_list/undirected_graph.hpp 2008-12-06 09:31:35 EST (Sat, 06 Dec 2008)
@@ -245,7 +245,6 @@
 namespace detail {
     // This functor automatically erases edges from the edge set when visited
     // during incident edge erasure.
- // TODO: Make this fail for vectors.
     template <typename EdgeList>
     struct edge_eraser
     {
@@ -276,14 +275,45 @@
     incs::erase_all(vs::edges(g.v, v), u);
 }
 
+namespace detail {
+ // Reciprocating and cascading erasure for remove_edges(g,v).
+ // TODO: This is not an efficient solution for multigraphs with sequential
+ // incidence stores. For associative incidence stores, this is probably
+ // fine.
+ template <typename Graph, typename Vertex>
+ struct edge_clearer
+ {
+ edge_clearer(Graph& g, Vertex v)
+ : g(g), v(v)
+ { }
+
+ template <typename Pair>
+ void operator()(Pair const& x)
+ {
+ // Don't erase self-loops. That would modify the sequence that
+ // this functor is visiting - which could have some pretty nasty
+ // side-effects.
+ if(v != x.first) {
+ incs::erase(vs::edges(g.v, x.first), v, x.second);
+ }
+ es::erase(g.e, x.second);
+ }
+
+ Graph& g;
+ Vertex v;
+ };
+
+ template <typename Graph, typename Vertex>
+ edge_clearer<Graph, Vertex> clear_edges(Graph& g, Vertex v)
+ { return edge_clearer<Graph, Vertex>(g, v); }
+}
+
 /** Remove all edges incident to the given vertex. */
 template <typename VL, typename EL, typename VS, typename ES, typename IS>
 inline void
 remove_edges(undirected_graph<VL,EL,VS,ES,IS>& g,
              typename undirected_graph<VL,EL,VS,ES,IS>::vertex_descriptor v)
-{
- incs::clear(vs::edges(g.v, v));
-}
+{ incs::clear(vs::edges(g.v, v), detail::clear_edges(g, v)); }
 
 /** Return the number of edges in the graph. */
 template <typename VL, typename EL, typename VS, typename ES, typename IS>

Added: sandbox/SOC/2008/graphs/trunk/libs/graphs/test/gen/star.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/graphs/trunk/libs/graphs/test/gen/star.hpp 2008-12-06 09:31:35 EST (Sat, 06 Dec 2008)
@@ -0,0 +1,25 @@
+
+#ifndef GEN_STAR_HPP
+#define GEN_STAR_HPP
+
+#include <vector>
+
+#include "../traits.hpp"
+
+// Generate an (n-1)-spoked star. Vertex 0 is the center. This assumes that
+//
+template <typename Graph>
+typename Graph::vertex_descriptor
+make_star(Graph& g, int n)
+{
+ std::vector<typename Graph::vertex_descriptor> v(n);
+ for(int i = 0; i < n; ++i) {
+ v[i] = detail::make_vertex(g, i);
+ }
+ for(int i = 1; i < n; ++i) {
+ add_edge(g, v[0], v[i], i - 1);
+ }
+ return v[0];
+}
+
+#endif

Added: sandbox/SOC/2008/graphs/trunk/libs/graphs/test/traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/graphs/trunk/libs/graphs/test/traits.hpp 2008-12-06 09:31:35 EST (Sat, 06 Dec 2008)
@@ -0,0 +1,76 @@
+
+#ifndef TRAITS_HPP
+#define TRAITS_HPP
+
+#include <boost/mpl/bool.hpp>
+
+// Forward declare our common label types.
+class node;
+class arc;
+
+/** @name Has Mapped Vertices */
+//@{
+template <typename Graph>
+struct _has_mapped_vertices
+{ typedef boost::mpl::false_ type; };
+
+template <
+ typename VL, typename EL,
+ typename K, template <typename> class C, template <typename> class A,
+ typename ES, typename IS>
+struct _has_mapped_vertices<
+ boost::graphs::adjacency_list::undirected_graph<
+ VL, EL, boost::graphs::adjacency_list::vertex_map<K,C,A>, ES, IS
+ >
+>
+{ typedef boost::mpl::true_ type; };
+
+template <typename Graph>
+typename _has_mapped_vertices<Graph>::type
+has_mapped_vertices(Graph const& g)
+{ return typename _has_mapped_vertices<Graph>::type(); }
+//@}
+
+/** @name Can Remove Vertices */
+//@{
+template <typename Graph>
+struct _can_remove_vertices
+{ typedef boost::mpl::true_ type; };
+
+template <
+ typename VL, typename EL,
+ template <typename> class A,
+ typename ES, typename IS>
+struct _can_remove_vertices<
+ boost::graphs::adjacency_list::undirected_graph<
+ VL, EL, boost::graphs::adjacency_list::vertex_vector<A>, ES, IS
+ >
+>
+{ typedef boost::mpl::false_ type; };
+
+template <typename Graph>
+typename _can_remove_vertices<Graph>::type
+can_remove_vertices(Graph const& g)
+{ return typename _can_remove_vertices<Graph>::type(); }
+//@}
+
+
+// Helper functions
+namespace detail {
+ template <typename Graph>
+ typename Graph::vertex_descriptor
+ do_make_vertex(Graph& g, int i, boost::mpl::false_)
+ { return add_vertex(g, node(i)); }
+
+ template <typename Graph>
+ typename Graph::vertex_descriptor
+ do_make_vertex(Graph& g, int i, boost::mpl::true_)
+ { return add_vertex(g, i, node(i)); }
+
+ template <typename Graph>
+ typename Graph::vertex_descriptor
+ make_vertex(Graph& g, int i)
+ { return do_make_vertex(g, i, has_mapped_vertices(g)); }
+}
+
+#endif

Modified: sandbox/SOC/2008/graphs/trunk/libs/graphs/test/undirected.cpp
==============================================================================
--- sandbox/SOC/2008/graphs/trunk/libs/graphs/test/undirected.cpp (original)
+++ sandbox/SOC/2008/graphs/trunk/libs/graphs/test/undirected.cpp 2008-12-06 09:31:35 EST (Sat, 06 Dec 2008)
@@ -4,51 +4,15 @@
 #include <iostream>
 
 #include <boost/assert.hpp>
-#include <boost/mpl/bool.hpp>
 #include <boost/graphs/adjacency_list/undirected_graph.hpp>
 
+#include "traits.hpp"
+#include "gen/star.hpp"
 
 using namespace std;
 using namespace boost;
 using namespace boost::graphs::adjacency_list;
 
-/** @name Has Mapped Vertices */
-//@{
-template <typename Graph>
-struct _has_mapped_vertices
-{ typedef mpl::false_ type; };
-
-template <
- typename VL, typename EL,
- typename K, template <typename> class C, template <typename> class A,
- typename ES, typename IS>
-struct _has_mapped_vertices<undirected_graph<VL, EL, vertex_map<K,C,A>, ES, IS>>
-{ typedef mpl::true_ type; };
-
-template <typename Graph>
-typename _has_mapped_vertices<Graph>::type
-has_mapped_vertices(Graph const& g)
-{ return typename _has_mapped_vertices<Graph>::type(); }
-//@}
-
-/** @name Can Remove Vertices */
-//@{
-template <typename Graph>
-struct _can_remove_vertices
-{ typedef mpl::true_ type; };
-
-template <
- typename VL, typename EL,
- template <typename> class A,
- typename ES, typename IS>
-struct _can_remove_vertices<undirected_graph<VL, EL, vertex_vector<A>, ES, IS>>
-{ typedef mpl::false_ type; };
-
-template <typename Graph>
-typename _can_remove_vertices<Graph>::type
-can_remove_vertices(Graph const& g)
-{ return typename _can_remove_vertices<Graph>::type(); }
-//@}
 
 struct node
 {
@@ -169,11 +133,19 @@
 template <typename Graph>
 void test()
 {
+ typedef typename Graph::vertex_descriptor Vertex;
     Graph g;
     BOOST_ASSERT(num_vertices(g) == 0);
 
     test_verts(g, has_mapped_vertices(g));
     test_edges(g);
+
+ Graph h;
+ Vertex v = make_star(h, 5);
+ BOOST_ASSERT(num_vertices(h) == 5);
+ BOOST_ASSERT(num_edges(h) == 4);
+ remove_edges(h, v);
+ BOOST_ASSERT(num_edges(h) == 0);
 }
 
 int main()


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