|
Boost-Commit : |
From: asutton_at_[hidden]
Date: 2007-08-21 14:05:04
Author: asutton
Date: 2007-08-21 14:05:03 EDT (Tue, 21 Aug 2007)
New Revision: 38830
URL: http://svn.boost.org/trac/boost/changeset/38830
Log:
Concept checks in bron kerbosch
Bug fixes in directed graph (broken renumber edges)
Added null_property_map that basically does noops.
Added:
sandbox/SOC/2007/graphs/boost/graph/null_property_map.hpp (contents, props changed)
Text files modified:
sandbox/SOC/2007/graphs/boost/graph/bron_kerbosch_all_cliques.hpp | 91 +++++++++++++++++++++++++++++++++------
sandbox/SOC/2007/graphs/boost/graph/directed_graph.hpp | 58 ++++++++++++++++++++++--
sandbox/SOC/2007/graphs/boost/graph/tiernan_all_cycles.hpp | 7 ++
sandbox/SOC/2007/graphs/boost/graph/undirected_graph.hpp | 39 +++++++++++++++-
4 files changed, 169 insertions(+), 26 deletions(-)
Modified: sandbox/SOC/2007/graphs/boost/graph/bron_kerbosch_all_cliques.hpp
==============================================================================
--- sandbox/SOC/2007/graphs/boost/graph/bron_kerbosch_all_cliques.hpp (original)
+++ sandbox/SOC/2007/graphs/boost/graph/bron_kerbosch_all_cliques.hpp 2007-08-21 14:05:03 EDT (Tue, 21 Aug 2007)
@@ -7,7 +7,10 @@
#ifndef BOOST_GRAPH_CLIQUE_HXX
#define BOOST_GRAPH_CLIQUE_HXX
-#include <limits>
+#include <vector>
+#include <deque>
+
+#include <boost/graph/new_graph_concepts.hpp>
namespace boost
{
@@ -60,7 +63,7 @@
// year = {2006},
// pages = {28-42}
// ee = {http://dx.doi.org/10.1016/j.tcs.2006.06.015}
- // }
+ // }
struct clique_visitor
{
@@ -69,6 +72,23 @@
{ }
};
+ struct max_clique_visitor
+ {
+ max_clique_visitor(std::size_t& max)
+ : maximum(max)
+ { }
+
+ template <typename Clique, typename Graph>
+ inline void clique(const Clique& p, const Graph& g)
+ {
+ maximum = std::max(maximum, p.size());
+ }
+ std::size_t& maximum;
+ };
+
+ inline max_clique_visitor find_max_clique(std::size_t& max)
+ { return max_clique_visitor(max); }
+
namespace detail
{
template <typename Graph>
@@ -78,6 +98,8 @@
typename graph_traits<Graph>::vertex_descriptor v,
typename graph_traits<Graph>::undirected_category)
{
+ function_requires< AdjacencyMatrixConcept<Graph> >();
+
return edge(u, v, g).second;
}
@@ -88,6 +110,7 @@
typename graph_traits<Graph>::vertex_descriptor v,
typename graph_traits<Graph>::directed_category)
{
+ function_requires< AdjacencyMatrixConcept<Graph> >();
// Note that this could alternate between using an || to determine
// full connectivity. I believe that this should produce strongly
// connected components. Note that using && instead of || will
@@ -103,6 +126,8 @@
const Container& in,
Container& out)
{
+ function_requires< GraphConcept<Graph> >();
+
typename graph_traits<Graph>::directed_category cat;
typename Container::const_iterator i, end = in.end();
for(i = in.begin(); i != end; ++i) {
@@ -120,13 +145,17 @@
Clique& clique,
Container& cands,
Container& nots,
- Visitor vis)
+ Visitor vis,
+ std::size_t min)
{
+ function_requires< GraphConcept<Graph> >();
+ function_requires< CliqueVisitorConcept<Visitor,Clique,Graph> >();
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
+ // Is there vertex in nots that is connected to all vertices
+ // in the candidate set? If so, no clique can ever be found.
+ // This could be broken out into a separate function.
{
- // is there vertex in nots that is connected to all vertices
- // in the candidate set? if so, no clique can ever be found.
typename Container::iterator ni, nend = nots.end();
typename Container::iterator ci, cend = cands.end();
for(ni = nots.begin(); ni != nend; ++ni) {
@@ -161,6 +190,10 @@
// there's some other stuff about using the number of disconnects
// as a counter, but i'm jot really sure i followed it.
+ // TODO: If we min-sized cliques to visit, then theoretically, we
+ // should be able to stop recursing if the clique falls below that
+ // size - maybe?
+
// otherwise, iterate over candidates and and test
// for maxmimal cliquiness.
typename Container::iterator i, j, end = cands.end();
@@ -168,8 +201,8 @@
Vertex candidate = *i;
// add the candidate to the clique (keeping the iterator!)
- typename Clique::iterator ci =
- clique.insert(clique.end(), candidate);
+ // typename Clique::iterator ci = clique.insert(clique.end(), candidate);
+ clique.push_back(candidate);
// remove it from the candidate set
i = cands.erase(i);
@@ -184,38 +217,66 @@
if(new_cands.empty() && new_nots.empty()) {
// our current clique is maximal since there's nothing
- // that's connected that we haven't already visited
- vis.clique(clique, g);
+ // that's connected that we haven't already visited. If
+ // the clique is below our radar, then we won't visit it.
+ if(clique.size() >= min) {
+ vis.clique(clique, g);
+ }
}
else {
// recurse to explore the new candidates
- extend_clique(g, clique, new_cands, new_nots, vis);
+ extend_clique(g, clique, new_cands, new_nots, vis, min);
}
// we're done with this vertex, so we need to move it
// to the nots, and remove the candidate from the clique.
nots.push_back(candidate);
- clique.erase(ci);
+ clique.pop_back();
}
}
}
template <typename Graph, typename Visitor>
inline void
- bron_kerbosch_all_cliques(const Graph& g, Visitor vis)
+ bron_kerbosch_all_cliques(const Graph& g, Visitor vis, std::size_t min)
{
+ function_requires< IncidenceGraphConcept<Graph> >();
+ function_requires< VertexListGraphConcept<Graph> >();
+ function_requires< VertexIndexGraphConcept<Graph> >();
+ function_requires< AdjacencyMatrixConcept<Graph> >(); // Structural requirement only
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;
typedef std::vector<Vertex> VertexSet;
- typedef std::list<Vertex> Clique;
+ typedef std::deque<Vertex> Clique;
+ function_requires< CliqueVisitorConcept<Visitor,Clique,Graph> >();
+
+ // NOTE: We're using a deque to implement the clique, because it provides
+ // constant inserts and removals at the end and also a constant size.
VertexIterator i, end;
tie(i, end) = vertices(g);
-
VertexSet cands(i, end); // start with all vertices as candidates
VertexSet nots; // start with no vertices visited
+
Clique clique; // the first clique is an empty vertex set
- detail::extend_clique(g, clique, cands, nots, vis);
+ detail::extend_clique(g, clique, cands, nots, vis, min);
+ }
+
+ template <typename Graph, typename Visitor>
+ inline void
+ bron_kerbosch_all_cliques(const Graph& g, Visitor vis)
+ {
+ // Default is 2 since a single vertex isn't connected to anything.
+ bron_kerbosch_all_cliques(g, vis, 2);
+ }
+
+ template <typename Graph>
+ inline std::size_t
+ bron_kerbosch_clique_number(const Graph& g)
+ {
+ std::size_t ret = 0;
+ bron_kerbosch_all_cliques(g, find_max_clique(ret));
+ return ret;
}
}
Modified: sandbox/SOC/2007/graphs/boost/graph/directed_graph.hpp
==============================================================================
--- sandbox/SOC/2007/graphs/boost/graph/directed_graph.hpp (original)
+++ sandbox/SOC/2007/graphs/boost/graph/directed_graph.hpp 2007-08-21 14:05:03 EDT (Tue, 21 Aug 2007)
@@ -13,7 +13,7 @@
namespace boost
{
- struct directed_graph_tag {};
+ struct directed_graph_tag { };
template <
typename VertexProperty = no_property,
@@ -80,7 +80,7 @@
, m_num_edges(0)
, m_max_vertex_index(0)
, m_max_edge_index(0)
- {}
+ { }
inline directed_graph(const directed_graph& x)
: m_graph(x)
@@ -88,7 +88,7 @@
, m_num_edges(x.m_num_edges)
, m_max_vertex_index(x.m_max_vertex_index)
, m_max_edge_index(x.m_max_edge_index)
- {}
+ { }
inline directed_graph(vertices_size_type n,
const GraphProperty& p = GraphProperty())
@@ -97,7 +97,24 @@
, m_num_edges(0)
, m_max_vertex_index(n)
, m_max_edge_index(0)
- {}
+ { }
+
+ template <typename EdgeIterator>
+ inline directed_graph(EdgeIterator f,
+ EdgeIterator l,
+ vertices_size_type n,
+ edges_size_type m = 0,
+ const GraphProperty& p = GraphProperty())
+ : m_graph(f, l, n, m, p)
+ , m_num_vertices(n)
+ , m_num_edges(0)
+ , m_max_vertex_index(n)
+ , m_max_edge_index(0)
+ {
+ // Can't always guarantee that the number of edges is actually
+ // m if distance(f, l) != m (or is undefined).
+ m_num_edges = m_max_edge_index = boost::num_edges(m_graph);
+ }
inline directed_graph& operator =(const directed_graph& g)
{
@@ -221,14 +238,14 @@
renumber_edge_indices()
{
edge_iterator i, end;
- tie(i, end) = vertices(m_graph);
+ tie(i, end) = edges(m_graph);
m_max_edge_index = renumber_edge_indices(i, end, 0);
}
inline void
remove_edge_and_renumber_indices(edge_iterator i)
{
- edge_iterator j = next(i), end = vertices(m_graph).second;
+ edge_iterator j = next(i), end = edges(m_graph).second;
edge_index_type n = get(edge_index, m_graph, *i);
// remove the offending edge and renumber everything after
@@ -236,6 +253,13 @@
m_max_edge_index = renumber_edge_indices(j, end, n);
}
+ inline void
+ renumber_indices()
+ {
+ renumber_vertex_indices();
+ renumber_edge_indices();
+ }
+
// bundled property support
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
vertex_bundled& operator [](vertex_descriptor v)
@@ -255,6 +279,22 @@
static inline vertex_descriptor null_vertex()
{ return graph_type::null_vertex(); }
+ inline void clear()
+ {
+ m_graph.clear();
+ m_num_vertices = m_max_vertex_index = 0;
+ m_num_edges = m_max_edge_index = 0;
+ }
+
+ inline void swap(directed_graph& g)
+ {
+ m_graph.swap(g);
+ std::swap(m_num_vertices, g.m_num_vertices);
+ std::swap(m_max_vertex_index, g.m_max_vertex_index);
+ std::swap(m_num_edges, g.m_num_edges);
+ std::swap(m_max_edge_index, g.m_max_edge_index);
+ }
+
private:
inline vertices_size_type
renumber_vertex_indices(vertex_iterator i,
@@ -686,6 +726,12 @@
remove_edge_and_renumber_indices(typename directed_graph<VP,EP,GP>::edge_iterator i,
directed_graph<VP,EP,GP>& g)
{ g.remove_edge_and_renumber_indices(i); }
+
+ // Index management
+ template <class VP, class EP, class GP>
+ inline void
+ renumber_indices(directed_graph<VP,EP,GP>& g)
+ { g.renumber_indices(); }
}
#endif
Added: sandbox/SOC/2007/graphs/boost/graph/null_property_map.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/graphs/boost/graph/null_property_map.hpp 2007-08-21 14:05:03 EDT (Tue, 21 Aug 2007)
@@ -0,0 +1,38 @@
+// (C) Copyright Andrew Sutton 2007
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0 (See accompanying file
+// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GRAPH_NULL_PROPERTY_HPP
+#define BOOST_GRAPH_NULL_PROPERTY_HPP
+
+#include <boost/property_map.hpp>
+
+namespace boost
+{
+ // A null property is somewhat like the inverse of the constant
+ // property map except that instead of returning a single value,
+ // this eats any writes and cannot be read from.
+
+ template <typename Key, typename Value>
+ struct null_property_map
+ {
+ typedef Key key_type;
+ typedef Value value_type;
+ typedef void reference;
+ typedef boost::writable_property_map_tag category;
+ };
+
+ // The null_property_map<K,V> only has a put() function.
+ template <typename K, typename V>
+ void put(null_property_map<K,V>& pm, const K& key, const V& value)
+ { }
+
+ // A helper function for intantiating null property maps.
+ template <typename Key, typename Value>
+ inline null_property_map<Key, Value> make_null_property()
+ { return null_property_map<Key, Value>(); }
+}
+
+#endif
Modified: sandbox/SOC/2007/graphs/boost/graph/tiernan_all_cycles.hpp
==============================================================================
--- sandbox/SOC/2007/graphs/boost/graph/tiernan_all_cycles.hpp (original)
+++ sandbox/SOC/2007/graphs/boost/graph/tiernan_all_cycles.hpp 2007-08-21 14:05:03 EDT (Tue, 21 Aug 2007)
@@ -86,6 +86,10 @@
std::size_t& maximum;
};
+ inline min_max_cycle_visitor
+ find_min_max_cycle(std::size_t& min, std::size_t& max)
+ { return min_max_cycle_visitor(min, max); }
+
namespace detail
{
template <typename Graph, typename Path>
@@ -318,8 +322,7 @@
std::size_t
min = std::numeric_limits<std::size_t>::max(),
max = 0;
- min_max_cycle_visitor vis(min, max);
- tiernan_all_cycles(g, vis);
+ tiernan_all_cycles(g, find_min_max_cycle(min, max));
// if this is the case, the graph is acyclic...
if(max == 0) max = min;
Modified: sandbox/SOC/2007/graphs/boost/graph/undirected_graph.hpp
==============================================================================
--- sandbox/SOC/2007/graphs/boost/graph/undirected_graph.hpp (original)
+++ sandbox/SOC/2007/graphs/boost/graph/undirected_graph.hpp 2007-08-21 14:05:03 EDT (Tue, 21 Aug 2007)
@@ -77,7 +77,7 @@
, m_num_edges(0)
, m_max_vertex_index(0)
, m_max_edge_index(0)
- {}
+ { }
inline undirected_graph(const undirected_graph& x)
: m_graph(x)
@@ -85,7 +85,7 @@
, m_num_edges(x.m_num_edges)
, m_max_vertex_index(x.m_max_vertex_index)
, m_max_edge_index(x.m_max_edge_index)
- {}
+ { }
inline undirected_graph(vertices_size_type n,
const GraphProperty& p = GraphProperty())
@@ -94,7 +94,24 @@
, m_num_edges(0)
, m_max_vertex_index(n)
, m_max_edge_index(0)
- {}
+ { }
+
+ template <typename EdgeIterator>
+ inline undirected_graph(EdgeIterator f,
+ EdgeIterator l,
+ vertices_size_type n,
+ edges_size_type m = 0,
+ const GraphProperty& p = GraphProperty())
+ : m_graph(f, l, n, m, p)
+ , m_num_vertices(n)
+ , m_num_edges(0)
+ , m_max_vertex_index(n)
+ , m_max_edge_index(0)
+ {
+ // Can't always guarantee that the number of edges is actually
+ // m if distance(f, l) != m (or is undefined).
+ m_num_edges = m_max_edge_index = boost::num_edges(m_graph);
+ }
inline undirected_graph& operator =(const undirected_graph& g)
{
@@ -255,6 +272,22 @@
static inline vertex_descriptor null_vertex()
{ return graph_type::null_vertex(); }
+ inline void clear()
+ {
+ m_graph.clear();
+ m_num_vertices = m_max_vertex_index = 0;
+ m_num_edges = m_max_edge_index = 0;
+ }
+
+ inline void swap(undirected_graph& g)
+ {
+ m_graph.swap(g);
+ std::swap(m_num_vertices, g.m_num_vertices);
+ std::swap(m_max_vertex_index, g.m_max_vertex_index);
+ std::swap(m_num_edges, g.m_num_edges);
+ std::swap(m_max_edge_index, g.m_max_edge_index);
+ }
+
private:
inline vertices_size_type
renumber_vertex_indices(vertex_iterator i,
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