/usr/include/boost/graph
NameSizeModeActions
detail/-0755rm
distributed/-0755rm
parallel/-0755rm
planar_detail/-0755rm
property_maps/-0755rm
accounting.hpp8760644editdlrm
adjacency_iterator.hpp28990644editdlrm
adjacency_list.hpp136920644editdlrm
adjacency_list_io.hpp118490644editdlrm
adjacency_matrix.hpp457430644editdlrm
adj_list_serialize.hpp45230644editdlrm
astar_search.hpp267360644editdlrm
bandwidth.hpp29920644editdlrm
bc_clustering.hpp59370644editdlrm
bellman_ford_shortest_paths.hpp82290644editdlrm
betweenness_centrality.hpp262900644editdlrm
biconnected_components.hpp167010644editdlrm
bipartite.hpp134920644editdlrm
boyer_myrvold_planar_test.hpp98490644editdlrm
boykov_kolmogorov_max_flow.hpp473420644editdlrm
breadth_first_search.hpp147510644editdlrm
bron_kerbosch_all_cliques.hpp117360644editdlrm
buffer_concepts.hpp24290644editdlrm
chrobak_payne_drawing.hpp86410644editdlrm
circle_layout.hpp19240644editdlrm
closeness_centrality.hpp60570644editdlrm
clustering_coefficient.hpp57260644editdlrm
compressed_sparse_row_graph.hpp698870644editdlrm
connected_components.hpp41340644editdlrm
copy.hpp212250644editdlrm
core_numbers.hpp136630644editdlrm
create_condensation_graph.hpp31590644editdlrm
cuthill_mckee_ordering.hpp59920644editdlrm
cycle_canceling.hpp66450644editdlrm
dag_shortest_paths.hpp60640644editdlrm
degree_centrality.hpp42360644editdlrm
depth_first_search.hpp154300644editdlrm
dijkstra_shortest_paths.hpp236870644editdlrm
dijkstra_shortest_paths_no_color_map.hpp96200644editdlrm
dimacs.hpp104480644editdlrm
directed_graph.hpp242140644editdlrm
dll_import_export.hpp8920644editdlrm
dominator_tree.hpp175530644editdlrm
eccentricity.hpp46110644editdlrm
edge_coloring.hpp68090644editdlrm
edge_connectivity.hpp67960644editdlrm
edge_list.hpp99480644editdlrm
edmonds_karp_max_flow.hpp101770644editdlrm
edmunds_karp_max_flow.hpp9820644editdlrm
erdos_renyi_generator.hpp72570644editdlrm
exception.hpp14660644editdlrm
exterior_property.hpp42890644editdlrm
filtered_graph.hpp200980644editdlrm
find_flow_cost.hpp18590644editdlrm
floyd_warshall_shortest.hpp85100644editdlrm
fruchterman_reingold.hpp173250644editdlrm
geodesic_distance.hpp80150644editdlrm
graphml.hpp134600644editdlrm
graphviz.hpp335030644editdlrm
graph_archetypes.hpp110080644editdlrm
graph_as_tree.hpp45320644editdlrm
graph_concepts.hpp197850644editdlrm
graph_mutability_traits.hpp49950644editdlrm
graph_selectors.hpp12740644editdlrm
graph_stats.hpp43940644editdlrm
graph_traits.hpp130650644editdlrm
graph_utility.hpp161820644editdlrm
grid_graph.hpp338300644editdlrm
gursoy_atun_layout.hpp132480644editdlrm
hawick_circuits.hpp145930644editdlrm
howard_cycle_ratio.hpp231070644editdlrm
incremental_components.hpp82240644editdlrm
isomorphism.hpp263080644editdlrm
is_kuratowski_subgraph.hpp102600644editdlrm
is_straight_line_drawing.hpp72300644editdlrm
iteration_macros.hpp116590644editdlrm
iteration_macros_undef.hpp6730644editdlrm
johnson_all_pairs_shortest.hpp76460644editdlrm
kamada_kawai_spring_layout.hpp280480644editdlrm
king_ordering.hpp121010644editdlrm
kruskal_min_spanning_tree.hpp57430644editdlrm
labeled_graph.hpp309140644editdlrm
leda_graph.hpp287890644editdlrm
lookup_edge.hpp18940644editdlrm
loop_erased_random_walk.hpp44360644editdlrm
make_biconnected_planar.hpp35130644editdlrm
make_connected.hpp26450644editdlrm
make_maximal_planar.hpp75780644editdlrm
matrix_as_graph.hpp72270644editdlrm
maximum_adjacency_search.hpp151250644editdlrm
maximum_weighted_matching.hpp497220644editdlrm
max_cardinality_matching.hpp310000644editdlrm
mcgregor_common_subgraphs.hpp434700644editdlrm
mesh_graph_generator.hpp56160644editdlrm
metis.hpp109820644editdlrm
metric_tsp_approx.hpp108090644editdlrm
minimum_degree_ordering.hpp270870644editdlrm
named_function_params.hpp396390644editdlrm
named_graph.hpp206140644editdlrm
neighbor_bfs.hpp117630644editdlrm
numeric_values.hpp18140644editdlrm
one_bit_color_map.hpp32770644editdlrm
overloading.hpp15840644editdlrm
page_rank.hpp61640644editdlrm
planar_canonical_ordering.hpp72030644editdlrm
planar_face_traversal.hpp60200644editdlrm
plod_generator.hpp77080644editdlrm
point_traits.hpp7820644editdlrm
prim_minimum_spanning_tree.hpp29600644editdlrm
profile.hpp13270644editdlrm
properties.hpp124170644editdlrm
property_iter_range.hpp43450644editdlrm
push_relabel_max_flow.hpp347370644editdlrm
random.hpp96720644editdlrm
random_layout.hpp9880644editdlrm
random_spanning_tree.hpp57750644editdlrm
read_dimacs.hpp120800644editdlrm
relax.hpp44000644editdlrm
reverse_graph.hpp224020644editdlrm
rmat_graph_generator.hpp192910644editdlrm
r_c_shortest_paths.hpp306730644editdlrm
sequential_vertex_coloring.hpp45620644editdlrm
simple_point.hpp6280644editdlrm
sloan_ordering.hpp155400644editdlrm
smallest_last_ordering.hpp54580644editdlrm
small_world_generator.hpp36700644editdlrm
ssca_graph_generator.hpp65640644editdlrm
stanford_graph.hpp201260644editdlrm
stoer_wagner_min_cut.hpp124150644editdlrm
strong_components.hpp130090644editdlrm
st_connected.hpp28520644editdlrm
subgraph.hpp399960644editdlrm
successive_shortest_path_nonnegative_weights.hpp104130644editdlrm
tiernan_all_cycles.hpp125470644editdlrm
topological_sort.hpp26110644editdlrm
topology.hpp203890644editdlrm
transitive_closure.hpp142600644editdlrm
transitive_reduction.hpp53260644editdlrm
transpose_graph.hpp11980644editdlrm
tree_traits.hpp13380644editdlrm
two_bit_color_map.hpp35100644editdlrm
two_graphs_common_spanning_trees.hpp349960644editdlrm
undirected_dfs.hpp106720644editdlrm
undirected_graph.hpp252760644editdlrm
use_mpi.hpp4370644editdlrm
vector_as_graph.hpp104740644editdlrm
vertex_and_edge_range.hpp55280644editdlrm
vf2_sub_graph_iso.hpp485850644editdlrm
visitors.hpp113180644editdlrm
wavefront.hpp39320644editdlrm
write_dimacs.hpp28890644editdlrm
Edit: /usr/include/boost/graph/mcgregor_common_subgraphs.hpp (43470B)
//======================================================================= // Copyright 2009 Trustees of Indiana University. // Authors: Michael Hansen, Andrew Lumsdaine // // 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) //======================================================================= #ifndef BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP #define BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP #include #include #include #include #include #include #include #include #include #include namespace boost { namespace detail { // Traits associated with common subgraphs, used mainly to keep a // consistent type for the correspondence maps. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond > struct mcgregor_common_subgraph_traits { typedef typename graph_traits< GraphFirst >::vertex_descriptor vertex_first_type; 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; typedef shared_array_property_map< vertex_first_type, VertexIndexMapSecond > correspondence_map_second_to_first_type; }; } // namespace detail // ========================================================================== // Binary function object that returns true if the values for item1 // in property_map1 and item2 in property_map2 are equivalent. template < typename PropertyMapFirst, typename PropertyMapSecond > struct property_map_equivalent { property_map_equivalent(const PropertyMapFirst property_map1, const PropertyMapSecond property_map2) : m_property_map1(property_map1), m_property_map2(property_map2) { } template < typename ItemFirst, typename ItemSecond > bool operator()(const ItemFirst item1, const ItemSecond item2) { return (get(m_property_map1, item1) == get(m_property_map2, item2)); } private: const PropertyMapFirst m_property_map1; const PropertyMapSecond m_property_map2; }; // Returns a property_map_equivalent object that compares the values // of property_map1 and property_map2. template < typename PropertyMapFirst, typename PropertyMapSecond > property_map_equivalent< PropertyMapFirst, PropertyMapSecond > make_property_map_equivalent( const PropertyMapFirst property_map1, const PropertyMapSecond property_map2) { return (property_map_equivalent< PropertyMapFirst, PropertyMapSecond >( property_map1, property_map2)); } // Binary function object that always returns true. Used when // vertices or edges are always equivalent (i.e. have no labels). struct always_equivalent { template < typename ItemFirst, typename ItemSecond > bool operator()(const ItemFirst&, const ItemSecond&) { return (true); } }; // ========================================================================== namespace detail { // Return true if new_vertex1 and new_vertex2 can extend the // subgraph represented by correspondence_map_1_to_2 and // correspondence_map_2_to_1. The vertices_equivalent and // edges_equivalent predicates are used to test vertex and edge // equivalency between the two graphs. template < typename GraphFirst, typename GraphSecond, typename CorrespondenceMapFirstToSecond, typename CorrespondenceMapSecondToFirst, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate > bool can_extend_graph(const GraphFirst& graph1, const GraphSecond& graph2, CorrespondenceMapFirstToSecond correspondence_map_1_to_2, CorrespondenceMapSecondToFirst /*correspondence_map_2_to_1*/, typename graph_traits< GraphFirst >::vertices_size_type subgraph_size, typename graph_traits< GraphFirst >::vertex_descriptor new_vertex1, typename graph_traits< GraphSecond >::vertex_descriptor new_vertex2, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs) { typedef typename graph_traits< GraphSecond >::vertex_descriptor VertexSecond; typedef typename graph_traits< GraphFirst >::edge_descriptor EdgeFirst; typedef typename graph_traits< GraphSecond >::edge_descriptor EdgeSecond; // Check vertex equality if (!vertices_equivalent(new_vertex1, new_vertex2)) { return (false); } // Vertices match and graph is empty, so we can extend the subgraph if (subgraph_size == 0) { return (true); } bool has_one_edge = false; // Verify edges with existing sub-graph BGL_FORALL_VERTICES_T(existing_vertex1, graph1, GraphFirst) { VertexSecond existing_vertex2 = get(correspondence_map_1_to_2, existing_vertex1); // Skip unassociated vertices if (existing_vertex2 == graph_traits< GraphSecond >::null_vertex()) { continue; } // NOTE: This will not work with parallel edges, since the // first matching edge is always chosen. EdgeFirst edge_to_new1, edge_from_new1; bool edge_to_new_exists1 = false, edge_from_new_exists1 = false; EdgeSecond edge_to_new2, edge_from_new2; bool edge_to_new_exists2 = false, edge_from_new_exists2 = false; // Search for edge from existing to new vertex (graph1) BGL_FORALL_OUTEDGES_T(existing_vertex1, edge1, graph1, GraphFirst) { if (target(edge1, graph1) == new_vertex1) { edge_to_new1 = edge1; edge_to_new_exists1 = true; break; } } // Search for edge from existing to new vertex (graph2) BGL_FORALL_OUTEDGES_T(existing_vertex2, edge2, graph2, GraphSecond) { if (target(edge2, graph2) == new_vertex2) { edge_to_new2 = edge2; edge_to_new_exists2 = true; break; } } // Make sure edges from existing to new vertices are equivalent if ((edge_to_new_exists1 != edge_to_new_exists2) || ((edge_to_new_exists1 && edge_to_new_exists2) && !edges_equivalent(edge_to_new1, edge_to_new2))) { return (false); } bool is_undirected1 = is_undirected(graph1), is_undirected2 = is_undirected(graph2); if (is_undirected1 && is_undirected2) { // Edge in both graphs exists and both graphs are undirected if (edge_to_new_exists1 && edge_to_new_exists2) { has_one_edge = true; } continue; } else { if (!is_undirected1) { // Search for edge from new to existing vertex (graph1) BGL_FORALL_OUTEDGES_T( new_vertex1, edge1, graph1, GraphFirst) { if (target(edge1, graph1) == existing_vertex1) { edge_from_new1 = edge1; edge_from_new_exists1 = true; break; } } } if (!is_undirected2) { // Search for edge from new to existing vertex (graph2) BGL_FORALL_OUTEDGES_T( new_vertex2, edge2, graph2, GraphSecond) { if (target(edge2, graph2) == existing_vertex2) { edge_from_new2 = edge2; edge_from_new_exists2 = true; break; } } } // Make sure edges from new to existing vertices are equivalent if ((edge_from_new_exists1 != edge_from_new_exists2) || ((edge_from_new_exists1 && edge_from_new_exists2) && !edges_equivalent(edge_from_new1, edge_from_new2))) { return (false); } if ((edge_from_new_exists1 && edge_from_new_exists2) || (edge_to_new_exists1 && edge_to_new_exists2)) { has_one_edge = true; } } // else } // BGL_FORALL_VERTICES_T // Make sure new vertices are connected to the existing subgraph if (only_connected_subgraphs && !has_one_edge) { return (false); } return (true); } // Recursive method that does a depth-first search in the space of // potential subgraphs. At each level, every new vertex pair from // both graphs is tested to see if it can extend the current // subgraph. If so, the subgraph is output to subgraph_callback // in the form of two correspondence maps (one for each graph). // Returning false from subgraph_callback will terminate the // search. Function returns true if the entire search space was // explored. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, typename CorrespondenceMapFirstToSecond, typename CorrespondenceMapSecondToFirst, typename VertexStackFirst, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, typename SubGraphInternalCallback > bool mcgregor_common_subgraphs_internal(const GraphFirst& graph1, const GraphSecond& graph2, const VertexIndexMapFirst& vindex_map1, const VertexIndexMapSecond& vindex_map2, CorrespondenceMapFirstToSecond correspondence_map_1_to_2, CorrespondenceMapSecondToFirst correspondence_map_2_to_1, VertexStackFirst& vertex_stack1, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs, SubGraphInternalCallback subgraph_callback) { typedef typename graph_traits< GraphFirst >::vertex_descriptor VertexFirst; typedef typename graph_traits< GraphSecond >::vertex_descriptor VertexSecond; typedef typename graph_traits< GraphFirst >::vertices_size_type VertexSizeFirst; // Get iterators for vertices from both graphs typename graph_traits< GraphFirst >::vertex_iterator vertex1_iter, vertex1_end; typename graph_traits< GraphSecond >::vertex_iterator vertex2_begin, vertex2_end, vertex2_iter; boost::tie(vertex1_iter, vertex1_end) = vertices(graph1); boost::tie(vertex2_begin, vertex2_end) = vertices(graph2); vertex2_iter = vertex2_begin; // Iterate until all vertices have been visited BGL_FORALL_VERTICES_T(new_vertex1, graph1, GraphFirst) { VertexSecond existing_vertex2 = get(correspondence_map_1_to_2, new_vertex1); // Skip already matched vertices in first graph if (existing_vertex2 != graph_traits< GraphSecond >::null_vertex()) { continue; } BGL_FORALL_VERTICES_T(new_vertex2, graph2, GraphSecond) { VertexFirst existing_vertex1 = get(correspondence_map_2_to_1, new_vertex2); // Skip already matched vertices in second graph if (existing_vertex1 != graph_traits< GraphFirst >::null_vertex()) { continue; } // Check if current sub-graph can be extended with the matched // vertex pair if (can_extend_graph(graph1, graph2, correspondence_map_1_to_2, correspondence_map_2_to_1, (VertexSizeFirst)vertex_stack1.size(), new_vertex1, new_vertex2, edges_equivalent, vertices_equivalent, only_connected_subgraphs)) { // Keep track of old graph size for restoring later VertexSizeFirst old_graph_size = (VertexSizeFirst)vertex_stack1.size(), new_graph_size = old_graph_size + 1; // Extend subgraph put(correspondence_map_1_to_2, new_vertex1, new_vertex2); put(correspondence_map_2_to_1, new_vertex2, new_vertex1); vertex_stack1.push(new_vertex1); // Returning false from the callback will cancel iteration if (!subgraph_callback(correspondence_map_1_to_2, correspondence_map_2_to_1, new_graph_size)) { return (false); } // Depth-first search into the state space of possible // sub-graphs bool continue_iteration = mcgregor_common_subgraphs_internal(graph1, graph2, vindex_map1, vindex_map2, correspondence_map_1_to_2, correspondence_map_2_to_1, vertex_stack1, edges_equivalent, vertices_equivalent, only_connected_subgraphs, subgraph_callback); if (!continue_iteration) { return (false); } // Restore previous state if (vertex_stack1.size() > old_graph_size) { VertexFirst stack_vertex1 = vertex_stack1.top(); VertexSecond stack_vertex2 = get(correspondence_map_1_to_2, stack_vertex1); // Contract subgraph put(correspondence_map_1_to_2, stack_vertex1, graph_traits< GraphSecond >::null_vertex()); put(correspondence_map_2_to_1, stack_vertex2, graph_traits< GraphFirst >::null_vertex()); vertex_stack1.pop(); } } // if can_extend_graph } // BGL_FORALL_VERTICES_T (graph2) } // BGL_FORALL_VERTICES_T (graph1) return (true); } // Internal method that initializes blank correspondence maps and // a vertex stack for use in mcgregor_common_subgraphs_internal. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, typename SubGraphInternalCallback > inline void mcgregor_common_subgraphs_internal_init( const GraphFirst& graph1, const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, const VertexIndexMapSecond vindex_map2, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs, SubGraphInternalCallback subgraph_callback) { typedef mcgregor_common_subgraph_traits< GraphFirst, GraphSecond, VertexIndexMapFirst, VertexIndexMapSecond > SubGraphTraits; typename SubGraphTraits::correspondence_map_first_to_second_type correspondence_map_1_to_2(num_vertices(graph1), vindex_map1); BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) { put(correspondence_map_1_to_2, vertex1, graph_traits< GraphSecond >::null_vertex()); } typename SubGraphTraits::correspondence_map_second_to_first_type correspondence_map_2_to_1(num_vertices(graph2), vindex_map2); BGL_FORALL_VERTICES_T(vertex2, graph2, GraphSecond) { put(correspondence_map_2_to_1, vertex2, graph_traits< GraphFirst >::null_vertex()); } typedef typename graph_traits< GraphFirst >::vertex_descriptor VertexFirst; std::stack< VertexFirst > vertex_stack1; mcgregor_common_subgraphs_internal(graph1, graph2, vindex_map1, vindex_map2, correspondence_map_1_to_2, correspondence_map_2_to_1, vertex_stack1, edges_equivalent, vertices_equivalent, only_connected_subgraphs, subgraph_callback); } } // namespace detail // ========================================================================== // Enumerates all common subgraphs present in graph1 and graph2. // Continues until the search space has been fully explored or false // is returned from user_callback. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, typename SubGraphCallback > void mcgregor_common_subgraphs(const GraphFirst& graph1, const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, const VertexIndexMapSecond vindex_map2, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs, SubGraphCallback user_callback) { detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, vindex_map2, edges_equivalent, vertices_equivalent, only_connected_subgraphs, user_callback); } // Variant of mcgregor_common_subgraphs with all default parameters template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback > void mcgregor_common_subgraphs(const GraphFirst& graph1, const GraphSecond& graph2, bool only_connected_subgraphs, SubGraphCallback user_callback) { detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, get(vertex_index, graph1), get(vertex_index, graph2), always_equivalent(), always_equivalent(), only_connected_subgraphs, user_callback); } // Named parameter variant of mcgregor_common_subgraphs template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, typename Param, typename Tag, typename Rest > 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) { detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, choose_const_pmap( get_param(params, vertex_index1), graph1, vertex_index), choose_const_pmap( get_param(params, vertex_index2), graph2, vertex_index), choose_param( get_param(params, edges_equivalent_t()), always_equivalent()), choose_param( get_param(params, vertices_equivalent_t()), always_equivalent()), only_connected_subgraphs, user_callback); } // ========================================================================== namespace detail { // Binary function object that intercepts subgraphs from // mcgregor_common_subgraphs_internal and maintains a cache of // unique subgraphs. The user callback is invoked for each unique // subgraph. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, 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 CachedCorrespondenceMapFirstToSecond; typedef typename SubGraphTraits::correspondence_map_second_to_first_type CachedCorrespondenceMapSecondToFirst; 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, 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) { } 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) { SubGraph subgraph_cached = *subgraph_iter; // Compare subgraph sizes if (subgraph_size != subgraph_cached.first) { continue; } if (!are_property_maps_different(correspondence_map_1_to_2, subgraph_cached.second.first, m_graph1)) { // New subgraph is a duplicate return (true); } } // Subgraph is unique, so make a cached copy 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); 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, subgraph_size)); } private: const GraphFirst& m_graph1; const GraphFirst& m_graph2; const VertexIndexMapFirst m_vindex_map1; const VertexIndexMapSecond m_vindex_map2; shared_ptr< SubGraphList > m_subgraphs; SubGraphCallback m_user_callback; }; } // namespace detail // Enumerates all unique common subgraphs between graph1 and graph2. // The user callback is invoked for each unique subgraph as they are // discovered. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, typename SubGraphCallback > void mcgregor_common_subgraphs_unique(const GraphFirst& graph1, const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, const VertexIndexMapSecond vindex_map2, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs, SubGraphCallback user_callback) { detail::unique_subgraph_interceptor< GraphFirst, GraphSecond, VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback > unique_callback( graph1, graph2, vindex_map1, vindex_map2, user_callback); detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, vindex_map2, edges_equivalent, vertices_equivalent, only_connected_subgraphs, unique_callback); } // Variant of mcgregor_common_subgraphs_unique with all default // parameters. template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback > 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(), only_connected_subgraphs, user_callback); } // Named parameter variant of mcgregor_common_subgraphs_unique template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, typename Param, typename Tag, typename Rest > 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) { mcgregor_common_subgraphs_unique(graph1, graph2, choose_const_pmap( get_param(params, vertex_index1), graph1, vertex_index), choose_const_pmap( get_param(params, vertex_index2), graph2, vertex_index), choose_param( get_param(params, edges_equivalent_t()), always_equivalent()), choose_param( get_param(params, vertices_equivalent_t()), always_equivalent()), only_connected_subgraphs, user_callback); } // ========================================================================== namespace detail { // Binary function object that intercepts subgraphs from // mcgregor_common_subgraphs_internal and maintains a cache of the // largest subgraphs. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, 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 CachedCorrespondenceMapFirstToSecond; typedef typename SubGraphTraits::correspondence_map_second_to_first_type CachedCorrespondenceMapSecondToFirst; typedef std::pair< VertexSizeFirst, std::pair< CachedCorrespondenceMapFirstToSecond, CachedCorrespondenceMapSecondToFirst > > 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) : m_graph1(graph1) , m_graph2(graph2) , m_vindex_map1(vindex_map1) , m_vindex_map2(vindex_map2) , 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) { // Make a cached copy 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_subgraphs() { for (typename SubGraphList::const_iterator subgraph_iter = m_subgraphs->begin(); subgraph_iter != m_subgraphs->end(); ++subgraph_iter) { SubGraph subgraph_cached = *subgraph_iter; m_user_callback(subgraph_cached.second.first, subgraph_cached.second.second, subgraph_cached.first); } } private: const GraphFirst& m_graph1; const GraphFirst& m_graph2; const VertexIndexMapFirst m_vindex_map1; const VertexIndexMapSecond m_vindex_map2; shared_ptr< SubGraphList > m_subgraphs; shared_ptr< VertexSizeFirst > m_largest_size_so_far; SubGraphCallback m_user_callback; }; } // namespace detail // Enumerates the largest common subgraphs found between graph1 // and graph2. Note that the ENTIRE search space is explored before // user_callback is actually invoked. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, typename SubGraphCallback > void mcgregor_common_subgraphs_maximum(const GraphFirst& graph1, const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, const VertexIndexMapSecond vindex_map2, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs, SubGraphCallback user_callback) { detail::maximum_subgraph_interceptor< GraphFirst, GraphSecond, VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback > max_interceptor( graph1, graph2, vindex_map1, vindex_map2, user_callback); detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, vindex_map2, edges_equivalent, vertices_equivalent, only_connected_subgraphs, max_interceptor); // Only output the largest subgraphs max_interceptor.output_subgraphs(); } // Variant of mcgregor_common_subgraphs_maximum with all default // parameters. template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback > 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(), only_connected_subgraphs, user_callback); } // Named parameter variant of mcgregor_common_subgraphs_maximum template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, typename Param, typename Tag, typename Rest > 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) { mcgregor_common_subgraphs_maximum(graph1, graph2, choose_const_pmap( get_param(params, vertex_index1), graph1, vertex_index), choose_const_pmap( get_param(params, vertex_index2), graph2, vertex_index), choose_param( get_param(params, edges_equivalent_t()), always_equivalent()), choose_param( get_param(params, vertices_equivalent_t()), always_equivalent()), only_connected_subgraphs, user_callback); } // ========================================================================== namespace detail { // Binary function object that intercepts subgraphs from // mcgregor_common_subgraphs_internal and maintains a cache of the // largest, unique subgraphs. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, 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 CachedCorrespondenceMapFirstToSecond; typedef typename SubGraphTraits::correspondence_map_second_to_first_type CachedCorrespondenceMapSecondToFirst; typedef std::pair< VertexSizeFirst, std::pair< CachedCorrespondenceMapFirstToSecond, CachedCorrespondenceMapSecondToFirst > > SubGraph; typedef std::vector< SubGraph > SubGraphList; unique_maximum_subgraph_interceptor(const GraphFirst& graph1, const GraphSecond& graph2, 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_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) { // Check if subgraph is unique for (typename SubGraphList::const_iterator subgraph_iter = m_subgraphs->begin(); subgraph_iter != m_subgraphs->end(); ++subgraph_iter) { SubGraph subgraph_cached = *subgraph_iter; if (!are_property_maps_different(correspondence_map_1_to_2, subgraph_cached.second.first, m_graph1)) { // New subgraph is a duplicate return (true); } } // Subgraph is unique, so make a cached copy 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_subgraphs() { for (typename SubGraphList::const_iterator subgraph_iter = m_subgraphs->begin(); subgraph_iter != m_subgraphs->end(); ++subgraph_iter) { SubGraph subgraph_cached = *subgraph_iter; m_user_callback(subgraph_cached.second.first, subgraph_cached.second.second, subgraph_cached.first); } } private: const GraphFirst& m_graph1; const GraphFirst& m_graph2; const VertexIndexMapFirst m_vindex_map1; const VertexIndexMapSecond m_vindex_map2; shared_ptr< SubGraphList > m_subgraphs; shared_ptr< VertexSizeFirst > m_largest_size_so_far; SubGraphCallback m_user_callback; }; } // namespace detail // Enumerates the largest, unique common subgraphs found between // graph1 and graph2. Note that the ENTIRE search space is explored // before user_callback is actually invoked. template < typename GraphFirst, typename GraphSecond, typename VertexIndexMapFirst, typename VertexIndexMapSecond, typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, typename SubGraphCallback > void mcgregor_common_subgraphs_maximum_unique(const GraphFirst& graph1, const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, const VertexIndexMapSecond vindex_map2, EdgeEquivalencePredicate edges_equivalent, VertexEquivalencePredicate vertices_equivalent, bool only_connected_subgraphs, SubGraphCallback user_callback) { detail::unique_maximum_subgraph_interceptor< GraphFirst, GraphSecond, VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback > unique_max_interceptor( graph1, graph2, vindex_map1, vindex_map2, user_callback); detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, vindex_map2, edges_equivalent, vertices_equivalent, only_connected_subgraphs, unique_max_interceptor); // Only output the largest, unique subgraphs unique_max_interceptor.output_subgraphs(); } // Variant of mcgregor_common_subgraphs_maximum_unique with all default // parameters template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback > void mcgregor_common_subgraphs_maximum_unique(const GraphFirst& graph1, const GraphSecond& graph2, bool only_connected_subgraphs, SubGraphCallback user_callback) { mcgregor_common_subgraphs_maximum_unique(graph1, graph2, get(vertex_index, graph1), get(vertex_index, graph2), always_equivalent(), always_equivalent(), only_connected_subgraphs, user_callback); } // Named parameter variant of // mcgregor_common_subgraphs_maximum_unique template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, typename Param, typename Tag, typename Rest > 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) { mcgregor_common_subgraphs_maximum_unique(graph1, graph2, choose_const_pmap( get_param(params, vertex_index1), graph1, vertex_index), choose_const_pmap( get_param(params, vertex_index2), graph2, vertex_index), choose_param( get_param(params, edges_equivalent_t()), always_equivalent()), choose_param( get_param(params, vertices_equivalent_t()), always_equivalent()), only_connected_subgraphs, user_callback); } // ========================================================================== // Fills a membership map (vertex -> bool) using the information // present in correspondence_map_1_to_2. Every vertex in a // membership map will have a true value only if it is not // associated with a null vertex in the correspondence map. template < typename GraphSecond, typename GraphFirst, typename CorrespondenceMapFirstToSecond, typename MembershipMapFirst > void fill_membership_map(const GraphFirst& graph1, const CorrespondenceMapFirstToSecond correspondence_map_1_to_2, MembershipMapFirst membership_map1) { BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) { put(membership_map1, vertex1, get(correspondence_map_1_to_2, vertex1) != graph_traits< GraphSecond >::null_vertex()); } } // Traits associated with a membership map filtered graph. Provided // for convenience to access graph and vertex filter types. template < typename Graph, typename MembershipMap > struct membership_filtered_graph_traits { typedef property_map_filter< MembershipMap > vertex_filter_type; typedef filtered_graph< Graph, keep_all, vertex_filter_type > graph_type; }; // Returns a filtered sub-graph of graph whose edge and vertex // inclusion is dictated by membership_map. template < typename Graph, typename MembershipMap > typename membership_filtered_graph_traits< Graph, MembershipMap >::graph_type make_membership_filtered_graph( const Graph& graph, MembershipMap& membership_map) { typedef membership_filtered_graph_traits< Graph, MembershipMap > MFGTraits; typedef typename MFGTraits::graph_type MembershipFilteredGraph; typename MFGTraits::vertex_filter_type v_filter(membership_map); return (MembershipFilteredGraph(graph, keep_all(), v_filter)); } } // namespace boost #endif // BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP