|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r54315 - in trunk: boost/graph libs/graph/test
From: jewillco_at_[hidden]
Date: 2009-06-24 16:31:51
Author: jewillco
Date: 2009-06-24 16:31:50 EDT (Wed, 24 Jun 2009)
New Revision: 54315
URL: http://svn.boost.org/trac/boost/changeset/54315
Log:
Added McGregor updates from Michael Hansen; refs #3134
Text files modified:
trunk/boost/graph/mcgregor_common_subgraphs.hpp | 299 +++++++++++++++++++++++----------------
trunk/libs/graph/test/mcgregor_subgraphs_test.cpp | 139 ++++++++++++++++++
2 files changed, 313 insertions(+), 125 deletions(-)
Modified: trunk/boost/graph/mcgregor_common_subgraphs.hpp
==============================================================================
--- trunk/boost/graph/mcgregor_common_subgraphs.hpp (original)
+++ trunk/boost/graph/mcgregor_common_subgraphs.hpp 2009-06-24 16:31:50 EDT (Wed, 24 Jun 2009)
@@ -14,13 +14,13 @@
#include <vector>
#include <stack>
+#include <boost/make_shared.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/properties.hpp>
#include <boost/property_map/shared_array_property_map.hpp>
-#include <boost/test/minimal.hpp>
namespace boost {
@@ -37,10 +37,10 @@
typedef typename graph_traits<GraphSecond>::vertex_descriptor vertex_second_type;
typedef shared_array_property_map<vertex_second_type, VertexIndexMapFirst>
- correspondence_map_first_to_second_type;
+ correspondence_map_first_to_second_type;
typedef shared_array_property_map<vertex_first_type, VertexIndexMapSecond>
- correspondence_map_second_to_first_type;
+ correspondence_map_second_to_first_type;
};
} // namespace detail
@@ -119,7 +119,8 @@
typename graph_traits<GraphFirst>::vertex_descriptor new_vertex1,
typename graph_traits<GraphSecond>::vertex_descriptor new_vertex2,
EdgeEquivalencePredicate edges_equivalent,
- VertexEquivalencePredicate vertices_equivalent)
+ VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs)
{
typedef typename graph_traits<GraphFirst>::vertex_descriptor VertexFirst;
typedef typename graph_traits<GraphSecond>::vertex_descriptor VertexSecond;
@@ -239,7 +240,7 @@
} // BGL_FORALL_VERTICES_T
// Make sure new vertices are connected to the existing subgraph
- if (!has_one_edge) {
+ if (only_connected_subgraphs && !has_one_edge) {
return (false);
}
@@ -274,6 +275,7 @@
VertexStackFirst& vertex_stack1,
EdgeEquivalencePredicate edges_equivalent,
VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs,
SubGraphInternalCallback subgraph_callback)
{
typedef typename graph_traits<GraphFirst>::vertex_descriptor VertexFirst;
@@ -315,7 +317,8 @@
correspondence_map_1_to_2, correspondence_map_2_to_1,
(VertexSizeFirst)vertex_stack1.size(),
new_vertex1, new_vertex2,
- edges_equivalent, vertices_equivalent)) {
+ edges_equivalent, vertices_equivalent,
+ only_connected_subgraphs)) {
// Keep track of old graph size for restoring later
VertexSizeFirst old_graph_size = (VertexSizeFirst)vertex_stack1.size(),
@@ -345,7 +348,7 @@
correspondence_map_1_to_2, correspondence_map_2_to_1,
vertex_stack1,
edges_equivalent, vertices_equivalent,
- subgraph_callback);
+ only_connected_subgraphs, subgraph_callback);
if (!continue_iteration) {
return (false);
@@ -366,7 +369,7 @@
graph_traits<GraphFirst>::null_vertex());
vertex_stack1.pop();
- }
+ }
} // if can_extend_graph
@@ -383,8 +386,8 @@
typename GraphSecond,
typename VertexIndexMapFirst,
typename VertexIndexMapSecond,
- typename VertexEquivalencePredicate,
typename EdgeEquivalencePredicate,
+ typename VertexEquivalencePredicate,
typename SubGraphInternalCallback>
inline void mcgregor_common_subgraphs_internal_init
(const GraphFirst& graph1,
@@ -393,6 +396,7 @@
const VertexIndexMapSecond vindex_map2,
EdgeEquivalencePredicate edges_equivalent,
VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs,
SubGraphInternalCallback subgraph_callback)
{
typedef mcgregor_common_subgraph_traits<GraphFirst,
@@ -426,6 +430,7 @@
correspondence_map_1_to_2, correspondence_map_2_to_1,
vertex_stack1,
edges_equivalent, vertices_equivalent,
+ only_connected_subgraphs,
subgraph_callback);
}
@@ -450,6 +455,7 @@
const VertexIndexMapSecond vindex_map2,
EdgeEquivalencePredicate edges_equivalent,
VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
@@ -457,6 +463,7 @@
(graph1, graph2,
vindex_map1, vindex_map2,
edges_equivalent, vertices_equivalent,
+ only_connected_subgraphs,
user_callback);
}
@@ -467,6 +474,7 @@
void mcgregor_common_subgraphs
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
@@ -474,7 +482,7 @@
(graph1, graph2,
get(vertex_index, graph1), get(vertex_index, graph2),
always_equivalent(), always_equivalent(),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// Named parameter variant of mcgregor_common_subgraphs
@@ -487,6 +495,7 @@
void mcgregor_common_subgraphs
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback,
const bgl_named_params<Param, Tag, Rest>& params)
{
@@ -501,7 +510,7 @@
always_equivalent()),
choose_param(get_param(params, vertices_equivalent_t()),
always_equivalent()),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// ==========================================================================
@@ -519,36 +528,43 @@
typename SubGraphCallback>
struct unique_subgraph_interceptor {
+ typedef typename graph_traits<GraphFirst>::vertices_size_type
+ VertexSizeFirst;
+
typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
typedef typename SubGraphTraits::correspondence_map_first_to_second_type
- CorrespondenceMapFirstToSecond;
+ CachedCorrespondenceMapFirstToSecond;
typedef typename SubGraphTraits::correspondence_map_second_to_first_type
- CorrespondenceMapSecondToFirst;
+ CachedCorrespondenceMapSecondToFirst;
- typedef std::pair<std::size_t, std::pair<CorrespondenceMapFirstToSecond,
- CorrespondenceMapSecondToFirst> > SubGraph;
+ typedef std::pair<VertexSizeFirst,
+ std::pair<CachedCorrespondenceMapFirstToSecond,
+ CachedCorrespondenceMapSecondToFirst> > SubGraph;
typedef std::vector<SubGraph> SubGraphList;
unique_subgraph_interceptor(const GraphFirst& graph1,
const GraphSecond& graph2,
- const VertexIndexMapFirst& vindex_map1,
- const VertexIndexMapSecond& vindex_map2,
+ const VertexIndexMapFirst vindex_map1,
+ const VertexIndexMapSecond vindex_map2,
SubGraphCallback user_callback) :
m_graph1(graph1), m_graph2(graph2),
m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
+ m_subgraphs(make_shared<SubGraphList>()),
m_user_callback(user_callback) { }
- bool operator()(CorrespondenceMapFirstToSecond& correspondence_map_1_to_2,
- CorrespondenceMapSecondToFirst& correspondence_map_2_to_1,
- std::size_t subgraph_size) {
+ template <typename CorrespondenceMapFirstToSecond,
+ typename CorrespondenceMapSecondToFirst>
+ bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
+ CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
+ VertexSizeFirst subgraph_size) {
for (typename SubGraphList::const_iterator
- subgraph_iter = m_subgraphs.begin();
- subgraph_iter != m_subgraphs.end();
+ subgraph_iter = m_subgraphs->begin();
+ subgraph_iter != m_subgraphs->end();
++subgraph_iter) {
SubGraph subgraph_cached = *subgraph_iter;
@@ -558,11 +574,8 @@
continue;
}
- CorrespondenceMapFirstToSecond correspondence_map_1_to_2_cached =
- subgraph_cached.second.first;
-
if (!are_property_maps_different(correspondence_map_1_to_2,
- correspondence_map_1_to_2_cached,
+ subgraph_cached.second.first,
m_graph1)) {
// New subgraph is a duplicate
@@ -571,18 +584,25 @@
}
// Subgraph is unique, so make a cached copy
- SubGraph new_subgraph = make_pair(subgraph_size,
- std::make_pair
- (CorrespondenceMapFirstToSecond(num_vertices(m_graph1), m_vindex_map1),
- CorrespondenceMapSecondToFirst(num_vertices(m_graph2), m_vindex_map2)));
-
- copy_vertex_property(correspondence_map_1_to_2,
- new_subgraph.second.first, m_graph1);
+ CachedCorrespondenceMapFirstToSecond
+ new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
+ (num_vertices(m_graph1), m_vindex_map1);
+
+ CachedCorrespondenceMapSecondToFirst
+ new_subgraph_2_to_1 = CorrespondenceMapSecondToFirst
+ (num_vertices(m_graph2), m_vindex_map2);
- copy_vertex_property(correspondence_map_2_to_1,
- new_subgraph.second.second, m_graph1);
-
- m_subgraphs.push_back(new_subgraph);
+ BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
+ put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
+ }
+
+ BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
+ put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
+ }
+
+ m_subgraphs->push_back(std::make_pair(subgraph_size,
+ std::make_pair(new_subgraph_1_to_2,
+ new_subgraph_2_to_1)));
return (m_user_callback(correspondence_map_1_to_2,
correspondence_map_2_to_1,
@@ -594,7 +614,7 @@
const GraphFirst& m_graph2;
const VertexIndexMapFirst m_vindex_map1;
const VertexIndexMapSecond m_vindex_map2;
- SubGraphList m_subgraphs;
+ shared_ptr<SubGraphList> m_subgraphs;
SubGraphCallback m_user_callback;
};
@@ -617,6 +637,7 @@
const VertexIndexMapSecond vindex_map2,
EdgeEquivalencePredicate edges_equivalent,
VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
detail::unique_subgraph_interceptor<GraphFirst, GraphSecond,
@@ -630,7 +651,7 @@
(graph1, graph2,
vindex_map1, vindex_map2,
edges_equivalent, vertices_equivalent,
- unique_callback);
+ only_connected_subgraphs, unique_callback);
}
// Variant of mcgregor_common_subgraphs_unique with all default
@@ -641,13 +662,14 @@
void mcgregor_common_subgraphs_unique
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
mcgregor_common_subgraphs_unique
(graph1, graph2,
get(vertex_index, graph1), get(vertex_index, graph2),
always_equivalent(), always_equivalent(),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// Named parameter variant of mcgregor_common_subgraphs_unique
@@ -660,6 +682,7 @@
void mcgregor_common_subgraphs_unique
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback,
const bgl_named_params<Param, Tag, Rest>& params)
{
@@ -673,7 +696,7 @@
always_equivalent()),
choose_param(get_param(params, vertices_equivalent_t()),
always_equivalent()),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// ==========================================================================
@@ -690,63 +713,77 @@
typename SubGraphCallback>
struct maximum_subgraph_interceptor {
+ typedef typename graph_traits<GraphFirst>::vertices_size_type
+ VertexSizeFirst;
+
typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
typedef typename SubGraphTraits::correspondence_map_first_to_second_type
- CorrespondenceMapFirstToSecond;
+ CachedCorrespondenceMapFirstToSecond;
typedef typename SubGraphTraits::correspondence_map_second_to_first_type
- CorrespondenceMapSecondToFirst;
+ CachedCorrespondenceMapSecondToFirst;
+
+ typedef std::pair<VertexSizeFirst,
+ std::pair<CachedCorrespondenceMapFirstToSecond,
+ CachedCorrespondenceMapSecondToFirst> > SubGraph;
- typedef std::pair<std::size_t,
- std::pair<CorrespondenceMapFirstToSecond,
- CorrespondenceMapSecondToFirst> > SubGraph;
-
typedef std::vector<SubGraph> SubGraphList;
maximum_subgraph_interceptor(const GraphFirst& graph1,
const GraphSecond& graph2,
const VertexIndexMapFirst vindex_map1,
const VertexIndexMapSecond vindex_map2,
- SubGraphCallback user_callback) :
+ SubGraphCallback user_callback) :
m_graph1(graph1), m_graph2(graph2),
m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
- m_user_callback(user_callback),
- m_largest_size_so_far(0) { }
-
- bool operator()(CorrespondenceMapFirstToSecond& correspondence_map_1_to_2,
- CorrespondenceMapSecondToFirst& correspondence_map_2_to_1,
- std::size_t subgraph_size) {
-
- if (subgraph_size > m_largest_size_so_far) {
- m_subgraphs.clear();
- m_largest_size_so_far = subgraph_size;
+ m_subgraphs(make_shared<SubGraphList>()),
+ m_largest_size_so_far(make_shared<VertexSizeFirst>(0)),
+ m_user_callback(user_callback) { }
+
+ template <typename CorrespondenceMapFirstToSecond,
+ typename CorrespondenceMapSecondToFirst>
+ bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
+ CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
+ VertexSizeFirst subgraph_size) {
+
+ if (subgraph_size > *m_largest_size_so_far) {
+ m_subgraphs->clear();
+ *m_largest_size_so_far = subgraph_size;
}
- if (subgraph_size == m_largest_size_so_far) {
+ if (subgraph_size == *m_largest_size_so_far) {
// Make a cached copy
- SubGraph new_subgraph = make_pair(subgraph_size,
- std::make_pair(CorrespondenceMapFirstToSecond(num_vertices(m_graph1), m_vindex_map1),
- CorrespondenceMapSecondToFirst(num_vertices(m_graph2), m_vindex_map2)));
-
- copy_vertex_property(correspondence_map_1_to_2,
- new_subgraph.second.first, m_graph1);
-
- copy_vertex_property(correspondence_map_2_to_1,
- new_subgraph.second.second, m_graph2);
-
- m_subgraphs.push_back(new_subgraph);
+ CachedCorrespondenceMapFirstToSecond
+ new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
+ (num_vertices(m_graph1), m_vindex_map1);
+
+ CachedCorrespondenceMapSecondToFirst
+ new_subgraph_2_to_1 = CachedCorrespondenceMapSecondToFirst
+ (num_vertices(m_graph2), m_vindex_map2);
+
+ BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
+ put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
+ }
+
+ BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
+ put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
+ }
+
+ m_subgraphs->push_back(std::make_pair(subgraph_size,
+ std::make_pair(new_subgraph_1_to_2,
+ new_subgraph_2_to_1)));
}
return (true);
}
- void output_cached_subgraphs() {
+ void output_subgraphs() {
for (typename SubGraphList::const_iterator
- subgraph_iter = m_subgraphs.begin();
- subgraph_iter != m_subgraphs.end();
+ subgraph_iter = m_subgraphs->begin();
+ subgraph_iter != m_subgraphs->end();
++subgraph_iter) {
SubGraph subgraph_cached = *subgraph_iter;
@@ -755,15 +792,15 @@
subgraph_cached.first);
}
}
-
+
private:
const GraphFirst& m_graph1;
const GraphFirst& m_graph2;
const VertexIndexMapFirst m_vindex_map1;
const VertexIndexMapSecond m_vindex_map2;
- SubGraphList m_subgraphs;
+ shared_ptr<SubGraphList> m_subgraphs;
+ shared_ptr<VertexSizeFirst> m_largest_size_so_far;
SubGraphCallback m_user_callback;
- typename graph_traits<GraphFirst>::vertices_size_type m_largest_size_so_far;
};
} // namespace detail
@@ -785,6 +822,7 @@
const VertexIndexMapSecond vindex_map2,
EdgeEquivalencePredicate edges_equivalent,
VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
detail::maximum_subgraph_interceptor<GraphFirst, GraphSecond,
@@ -796,10 +834,10 @@
(graph1, graph2,
vindex_map1, vindex_map2,
edges_equivalent, vertices_equivalent,
- max_interceptor);
+ only_connected_subgraphs, max_interceptor);
// Only output the largest subgraphs
- max_interceptor.output_cached_subgraphs();
+ max_interceptor.output_subgraphs();
}
// Variant of mcgregor_common_subgraphs_maximum with all default
@@ -810,13 +848,14 @@
void mcgregor_common_subgraphs_maximum
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
mcgregor_common_subgraphs_maximum
(graph1, graph2,
get(vertex_index, graph1), get(vertex_index, graph2),
always_equivalent(), always_equivalent(),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// Named parameter variant of mcgregor_common_subgraphs_maximum
@@ -829,6 +868,7 @@
void mcgregor_common_subgraphs_maximum
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback,
const bgl_named_params<Param, Tag, Rest>& params)
{
@@ -842,7 +882,7 @@
always_equivalent()),
choose_param(get_param(params, vertices_equivalent_t()),
always_equivalent()),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// ==========================================================================
@@ -859,19 +899,22 @@
typename SubGraphCallback>
struct unique_maximum_subgraph_interceptor {
+ typedef typename graph_traits<GraphFirst>::vertices_size_type
+ VertexSizeFirst;
+
typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
typedef typename SubGraphTraits::correspondence_map_first_to_second_type
- CorrespondenceMapFirstToSecond;
+ CachedCorrespondenceMapFirstToSecond;
typedef typename SubGraphTraits::correspondence_map_second_to_first_type
- CorrespondenceMapSecondToFirst;
+ CachedCorrespondenceMapSecondToFirst;
+
+ typedef std::pair<VertexSizeFirst,
+ std::pair<CachedCorrespondenceMapFirstToSecond,
+ CachedCorrespondenceMapSecondToFirst> > SubGraph;
- typedef std::pair<std::size_t,
- std::pair<CorrespondenceMapFirstToSecond,
- CorrespondenceMapSecondToFirst> > SubGraph;
-
typedef std::vector<SubGraph> SubGraphList;
unique_maximum_subgraph_interceptor(const GraphFirst& graph1,
@@ -881,33 +924,33 @@
SubGraphCallback user_callback) :
m_graph1(graph1), m_graph2(graph2),
m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
- m_user_callback(user_callback),
- m_largest_size_so_far(0) { }
+ m_subgraphs(make_shared<SubGraphList>()),
+ m_largest_size_so_far(make_shared<VertexSizeFirst>(0)),
+ m_user_callback(user_callback) { }
- bool operator()(CorrespondenceMapFirstToSecond& correspondence_map_1_to_2,
- CorrespondenceMapSecondToFirst& correspondence_map_2_to_1,
- std::size_t subgraph_size) {
-
- if (subgraph_size > m_largest_size_so_far) {
- m_subgraphs.clear();
- m_largest_size_so_far = subgraph_size;
+ template <typename CorrespondenceMapFirstToSecond,
+ typename CorrespondenceMapSecondToFirst>
+ bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
+ CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
+ VertexSizeFirst subgraph_size) {
+
+ if (subgraph_size > *m_largest_size_so_far) {
+ m_subgraphs->clear();
+ *m_largest_size_so_far = subgraph_size;
}
- if (subgraph_size == m_largest_size_so_far) {
+ if (subgraph_size == *m_largest_size_so_far) {
// Check if subgraph is unique
for (typename SubGraphList::const_iterator
- subgraph_iter = m_subgraphs.begin();
- subgraph_iter != m_subgraphs.end();
+ subgraph_iter = m_subgraphs->begin();
+ subgraph_iter != m_subgraphs->end();
++subgraph_iter) {
SubGraph subgraph_cached = *subgraph_iter;
- CorrespondenceMapFirstToSecond correspondence_map_1_to_2_cached =
- subgraph_cached.second.first;
-
if (!are_property_maps_different(correspondence_map_1_to_2,
- correspondence_map_1_to_2_cached,
+ subgraph_cached.second.first,
m_graph1)) {
// New subgraph is a duplicate
@@ -916,27 +959,34 @@
}
// Subgraph is unique, so make a cached copy
- SubGraph new_subgraph = std::make_pair(subgraph_size,
- std::make_pair
- (CorrespondenceMapFirstToSecond(num_vertices(m_graph1), m_vindex_map1),
- CorrespondenceMapSecondToFirst(num_vertices(m_graph2), m_vindex_map2)));
-
- copy_vertex_property(correspondence_map_1_to_2,
- new_subgraph.second.first, m_graph1);
-
- copy_vertex_property(correspondence_map_2_to_1,
- new_subgraph.second.second, m_graph2);
-
- m_subgraphs.push_back(new_subgraph);
+ CachedCorrespondenceMapFirstToSecond
+ new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
+ (num_vertices(m_graph1), m_vindex_map1);
+
+ CachedCorrespondenceMapSecondToFirst
+ new_subgraph_2_to_1 = CachedCorrespondenceMapSecondToFirst
+ (num_vertices(m_graph2), m_vindex_map2);
+
+ BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
+ put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
+ }
+
+ BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
+ put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
+ }
+
+ m_subgraphs->push_back(std::make_pair(subgraph_size,
+ std::make_pair(new_subgraph_1_to_2,
+ new_subgraph_2_to_1)));
}
return (true);
}
- void output_cached_subgraphs() {
+ void output_subgraphs() {
for (typename SubGraphList::const_iterator
- subgraph_iter = m_subgraphs.begin();
- subgraph_iter != m_subgraphs.end();
+ subgraph_iter = m_subgraphs->begin();
+ subgraph_iter != m_subgraphs->end();
++subgraph_iter) {
SubGraph subgraph_cached = *subgraph_iter;
@@ -951,9 +1001,9 @@
const GraphFirst& m_graph2;
const VertexIndexMapFirst m_vindex_map1;
const VertexIndexMapSecond m_vindex_map2;
- SubGraphList m_subgraphs;
+ shared_ptr<SubGraphList> m_subgraphs;
+ shared_ptr<VertexSizeFirst> m_largest_size_so_far;
SubGraphCallback m_user_callback;
- typename graph_traits<GraphFirst>::vertices_size_type m_largest_size_so_far;
};
} // namespace detail
@@ -975,6 +1025,7 @@
const VertexIndexMapSecond vindex_map2,
EdgeEquivalencePredicate edges_equivalent,
VertexEquivalencePredicate vertices_equivalent,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
detail::unique_maximum_subgraph_interceptor<GraphFirst, GraphSecond,
@@ -986,10 +1037,10 @@
(graph1, graph2,
vindex_map1, vindex_map2,
edges_equivalent, vertices_equivalent,
- unique_max_interceptor);
+ only_connected_subgraphs, unique_max_interceptor);
// Only output the largest, unique subgraphs
- unique_max_interceptor.output_cached_subgraphs();
+ unique_max_interceptor.output_subgraphs();
}
// Variant of mcgregor_common_subgraphs_maximum_unique with all default parameters
@@ -999,6 +1050,7 @@
void mcgregor_common_subgraphs_maximum_unique
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback)
{
@@ -1006,7 +1058,7 @@
(graph1, graph2,
get(vertex_index, graph1), get(vertex_index, graph2),
always_equivalent(), always_equivalent(),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// Named parameter variant of
@@ -1020,6 +1072,7 @@
void mcgregor_common_subgraphs_maximum_unique
(const GraphFirst& graph1,
const GraphSecond& graph2,
+ bool only_connected_subgraphs,
SubGraphCallback user_callback,
const bgl_named_params<Param, Tag, Rest>& params)
{
@@ -1033,7 +1086,7 @@
always_equivalent()),
choose_param(get_param(params, vertices_equivalent_t()),
always_equivalent()),
- user_callback);
+ only_connected_subgraphs, user_callback);
}
// ==========================================================================
Modified: trunk/libs/graph/test/mcgregor_subgraphs_test.cpp
==============================================================================
--- trunk/libs/graph/test/mcgregor_subgraphs_test.cpp (original)
+++ trunk/libs/graph/test/mcgregor_subgraphs_test.cpp 2009-06-24 16:31:50 EDT (Wed, 24 Jun 2009)
@@ -1,7 +1,17 @@
+//=======================================================================
+// Copyright 2009 Trustees of Indiana University.
+// Authors: Michael Hansen
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+
+#include <cmath>
#include <iostream>
#include <fstream>
+#include <sstream>
#include <vector>
-#include <cmath>
#include <boost/lexical_cast.hpp>
#include <boost/random.hpp>
@@ -13,10 +23,12 @@
#include <boost/graph/random.hpp>
#include <boost/graph/mcgregor_common_subgraphs.hpp>
#include <boost/property_map/shared_array_property_map.hpp>
+#include <boost/test/minimal.hpp>
using namespace boost;
bool was_common_subgraph_found = false, output_graphs = false;
+std::vector<std::string> simple_subgraph_list;
// Callback that compares incoming graphs to the supplied common
// subgraph.
@@ -172,6 +184,46 @@
Graph& m_common_subgraph;
};
+template <typename Graph>
+struct simple_callback {
+
+ simple_callback(const Graph& graph1) :
+ m_graph1(graph1) { }
+
+ template <typename CorrespondenceMapFirstToSecond,
+ typename CorrespondenceMapSecondToFirst>
+ bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
+ CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
+ typename graph_traits<Graph>::vertices_size_type subgraph_size) {
+
+ typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
+
+ typedef typename property_map<Graph, vertex_index_t>::type VertexIndexMap;
+ typedef typename property_map<Graph, vertex_name_t>::type VertexNameMap;
+ typedef typename property_map<Graph, edge_name_t>::type EdgeNameMap;
+
+ std::stringstream subgraph_string;
+
+ BGL_FORALL_VERTICES_T(vertex1, m_graph1, Graph) {
+
+ Vertex vertex2 = get(correspondence_map_1_to_2, vertex1);
+
+ if (vertex2 != graph_traits<Graph>::null_vertex()) {
+ subgraph_string << vertex1 << "," << vertex2 << " ";
+ }
+
+ }
+
+ simple_subgraph_list.push_back(subgraph_string.str());
+
+ return (true);
+ }
+
+private:
+ const Graph& m_graph1;
+
+};
+
template <typename Graph,
typename RandomNumberGenerator,
typename VertexNameMap,
@@ -224,6 +276,11 @@
}
}
+bool has_subgraph_string(std::string set_string) {
+ return (std::find(simple_subgraph_list.begin(), simple_subgraph_list.end(),
+ set_string) != simple_subgraph_list.end());
+}
+
int test_main (int argc, char *argv[]) {
int vertices_to_create = 10;
int max_edges_per_vertex = 2;
@@ -326,11 +383,89 @@
test_callback<Graph> user_callback(common_subgraph, graph1, graph2);
- mcgregor_common_subgraphs(graph1, graph2, user_callback,
+ mcgregor_common_subgraphs(graph1, graph2, true, user_callback,
edges_equivalent(make_property_map_equivalent(ename_map1, ename_map2)).
vertices_equivalent(make_property_map_equivalent(vname_map1, vname_map2)));
BOOST_CHECK(was_common_subgraph_found);
+ // Test maximum and unique variants on known graphs
+ Graph graph_simple1, graph_simple2;
+ simple_callback<Graph> user_callback_simple(graph_simple1);
+
+ VertexNameMap vname_map_simple1 = get(vertex_name, graph_simple1);
+ VertexNameMap vname_map_simple2 = get(vertex_name, graph_simple2);
+
+ put(vname_map_simple1, add_vertex(graph_simple1), 1);
+ put(vname_map_simple1, add_vertex(graph_simple1), 2);
+ put(vname_map_simple1, add_vertex(graph_simple1), 3);
+
+ add_edge(0, 1, graph_simple1);
+ add_edge(0, 2, graph_simple1);
+ add_edge(1, 2, graph_simple1);
+
+ put(vname_map_simple2, add_vertex(graph_simple2), 1);
+ put(vname_map_simple2, add_vertex(graph_simple2), 2);
+ put(vname_map_simple2, add_vertex(graph_simple2), 3);
+ put(vname_map_simple2, add_vertex(graph_simple2), 4);
+
+ add_edge(0, 1, graph_simple2);
+ add_edge(0, 2, graph_simple2);
+ add_edge(1, 2, graph_simple2);
+ add_edge(1, 3, graph_simple2);
+
+ // Unique subgraphs
+ std::cout << "Searching for unique subgraphs" << std::endl;
+ mcgregor_common_subgraphs_unique(graph_simple1, graph_simple2,
+ true, user_callback_simple,
+ vertices_equivalent(make_property_map_equivalent(vname_map_simple1, vname_map_simple2)));
+
+ BOOST_CHECK(has_subgraph_string("0,0 1,1 "));
+ BOOST_CHECK(has_subgraph_string("0,0 1,1 2,2 "));
+ BOOST_CHECK(has_subgraph_string("0,0 2,2 "));
+ BOOST_CHECK(has_subgraph_string("1,1 2,2 "));
+
+ if (output_graphs) {
+ std::copy(simple_subgraph_list.begin(), simple_subgraph_list.end(),
+ std::ostream_iterator<std::string>(std::cout, "\n"));
+
+ std::cout << std::endl;
+ }
+
+ simple_subgraph_list.clear();
+
+ // Maximum subgraphs
+ std::cout << "Searching for maximum subgraphs" << std::endl;
+ mcgregor_common_subgraphs_maximum(graph_simple1, graph_simple2,
+ true, user_callback_simple,
+ vertices_equivalent(make_property_map_equivalent(vname_map_simple1, vname_map_simple2)));
+
+ BOOST_CHECK(has_subgraph_string("0,0 1,1 2,2 "));
+
+ if (output_graphs) {
+ std::copy(simple_subgraph_list.begin(), simple_subgraph_list.end(),
+ std::ostream_iterator<std::string>(std::cout, "\n"));
+
+ std::cout << std::endl;
+ }
+
+ simple_subgraph_list.clear();
+
+ // Maximum, unique subgraphs
+ std::cout << "Searching for maximum unique subgraphs" << std::endl;
+ mcgregor_common_subgraphs_maximum_unique(graph_simple1, graph_simple2,
+ true, user_callback_simple,
+ vertices_equivalent(make_property_map_equivalent(vname_map_simple1, vname_map_simple2)));
+
+ BOOST_CHECK(simple_subgraph_list.size() == 1);
+ BOOST_CHECK(has_subgraph_string("0,0 1,1 2,2 "));
+
+ if (output_graphs) {
+ std::copy(simple_subgraph_list.begin(), simple_subgraph_list.end(),
+ std::ostream_iterator<std::string>(std::cout, "\n"));
+
+ std::cout << std::endl;
+ }
+
return 0;
}
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