annotate DEPENDENCIES/generic/include/boost/graph/mcgregor_common_subgraphs.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //=======================================================================
Chris@16 2 // Copyright 2009 Trustees of Indiana University.
Chris@16 3 // Authors: Michael Hansen, Andrew Lumsdaine
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //=======================================================================
Chris@16 9
Chris@16 10 #ifndef BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP
Chris@16 11 #define BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP
Chris@16 12
Chris@16 13 #include <algorithm>
Chris@16 14 #include <vector>
Chris@16 15 #include <stack>
Chris@16 16
Chris@16 17 #include <boost/make_shared.hpp>
Chris@16 18 #include <boost/graph/adjacency_list.hpp>
Chris@16 19 #include <boost/graph/filtered_graph.hpp>
Chris@16 20 #include <boost/graph/graph_utility.hpp>
Chris@16 21 #include <boost/graph/iteration_macros.hpp>
Chris@16 22 #include <boost/graph/properties.hpp>
Chris@16 23 #include <boost/property_map/shared_array_property_map.hpp>
Chris@16 24
Chris@16 25 namespace boost {
Chris@16 26
Chris@16 27 namespace detail {
Chris@16 28
Chris@16 29 // Traits associated with common subgraphs, used mainly to keep a
Chris@16 30 // consistent type for the correspondence maps.
Chris@16 31 template <typename GraphFirst,
Chris@16 32 typename GraphSecond,
Chris@16 33 typename VertexIndexMapFirst,
Chris@16 34 typename VertexIndexMapSecond>
Chris@16 35 struct mcgregor_common_subgraph_traits {
Chris@16 36 typedef typename graph_traits<GraphFirst>::vertex_descriptor vertex_first_type;
Chris@16 37 typedef typename graph_traits<GraphSecond>::vertex_descriptor vertex_second_type;
Chris@16 38
Chris@16 39 typedef shared_array_property_map<vertex_second_type, VertexIndexMapFirst>
Chris@16 40 correspondence_map_first_to_second_type;
Chris@16 41
Chris@16 42 typedef shared_array_property_map<vertex_first_type, VertexIndexMapSecond>
Chris@16 43 correspondence_map_second_to_first_type;
Chris@16 44 };
Chris@16 45
Chris@16 46 } // namespace detail
Chris@16 47
Chris@16 48 // ==========================================================================
Chris@16 49
Chris@16 50 // Binary function object that returns true if the values for item1
Chris@16 51 // in property_map1 and item2 in property_map2 are equivalent.
Chris@16 52 template <typename PropertyMapFirst,
Chris@16 53 typename PropertyMapSecond>
Chris@16 54 struct property_map_equivalent {
Chris@16 55
Chris@16 56 property_map_equivalent(const PropertyMapFirst property_map1,
Chris@16 57 const PropertyMapSecond property_map2) :
Chris@16 58 m_property_map1(property_map1),
Chris@16 59 m_property_map2(property_map2) { }
Chris@16 60
Chris@16 61 template <typename ItemFirst,
Chris@16 62 typename ItemSecond>
Chris@16 63 bool operator()(const ItemFirst item1, const ItemSecond item2) {
Chris@16 64 return (get(m_property_map1, item1) == get(m_property_map2, item2));
Chris@16 65 }
Chris@16 66
Chris@16 67 private:
Chris@16 68 const PropertyMapFirst m_property_map1;
Chris@16 69 const PropertyMapSecond m_property_map2;
Chris@16 70 };
Chris@16 71
Chris@16 72 // Returns a property_map_equivalent object that compares the values
Chris@16 73 // of property_map1 and property_map2.
Chris@16 74 template <typename PropertyMapFirst,
Chris@16 75 typename PropertyMapSecond>
Chris@16 76 property_map_equivalent<PropertyMapFirst,
Chris@16 77 PropertyMapSecond>
Chris@16 78 make_property_map_equivalent
Chris@16 79 (const PropertyMapFirst property_map1,
Chris@16 80 const PropertyMapSecond property_map2) {
Chris@16 81
Chris@16 82 return (property_map_equivalent<PropertyMapFirst, PropertyMapSecond>
Chris@16 83 (property_map1, property_map2));
Chris@16 84 }
Chris@16 85
Chris@16 86 // Binary function object that always returns true. Used when
Chris@16 87 // vertices or edges are always equivalent (i.e. have no labels).
Chris@16 88 struct always_equivalent {
Chris@16 89
Chris@16 90 template <typename ItemFirst,
Chris@16 91 typename ItemSecond>
Chris@16 92 bool operator()(const ItemFirst&, const ItemSecond&) {
Chris@16 93 return (true);
Chris@16 94 }
Chris@16 95 };
Chris@16 96
Chris@16 97 // ==========================================================================
Chris@16 98
Chris@16 99 namespace detail {
Chris@16 100
Chris@16 101 // Return true if new_vertex1 and new_vertex2 can extend the
Chris@16 102 // subgraph represented by correspondence_map_1_to_2 and
Chris@16 103 // correspondence_map_2_to_1. The vertices_equivalent and
Chris@16 104 // edges_equivalent predicates are used to test vertex and edge
Chris@16 105 // equivalency between the two graphs.
Chris@16 106 template <typename GraphFirst,
Chris@16 107 typename GraphSecond,
Chris@16 108 typename CorrespondenceMapFirstToSecond,
Chris@16 109 typename CorrespondenceMapSecondToFirst,
Chris@16 110 typename EdgeEquivalencePredicate,
Chris@16 111 typename VertexEquivalencePredicate>
Chris@16 112 bool can_extend_graph
Chris@16 113 (const GraphFirst& graph1,
Chris@16 114 const GraphSecond& graph2,
Chris@16 115 CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
Chris@16 116 CorrespondenceMapSecondToFirst /*correspondence_map_2_to_1*/,
Chris@16 117 typename graph_traits<GraphFirst>::vertices_size_type subgraph_size,
Chris@16 118 typename graph_traits<GraphFirst>::vertex_descriptor new_vertex1,
Chris@16 119 typename graph_traits<GraphSecond>::vertex_descriptor new_vertex2,
Chris@16 120 EdgeEquivalencePredicate edges_equivalent,
Chris@16 121 VertexEquivalencePredicate vertices_equivalent,
Chris@16 122 bool only_connected_subgraphs)
Chris@16 123 {
Chris@16 124 typedef typename graph_traits<GraphSecond>::vertex_descriptor VertexSecond;
Chris@16 125
Chris@16 126 typedef typename graph_traits<GraphFirst>::edge_descriptor EdgeFirst;
Chris@16 127 typedef typename graph_traits<GraphSecond>::edge_descriptor EdgeSecond;
Chris@16 128
Chris@16 129 // Check vertex equality
Chris@16 130 if (!vertices_equivalent(new_vertex1, new_vertex2)) {
Chris@16 131 return (false);
Chris@16 132 }
Chris@16 133
Chris@16 134 // Vertices match and graph is empty, so we can extend the subgraph
Chris@16 135 if (subgraph_size == 0) {
Chris@16 136 return (true);
Chris@16 137 }
Chris@16 138
Chris@16 139 bool has_one_edge = false;
Chris@16 140
Chris@16 141 // Verify edges with existing sub-graph
Chris@16 142 BGL_FORALL_VERTICES_T(existing_vertex1, graph1, GraphFirst) {
Chris@16 143
Chris@16 144 VertexSecond existing_vertex2 = get(correspondence_map_1_to_2, existing_vertex1);
Chris@16 145
Chris@16 146 // Skip unassociated vertices
Chris@16 147 if (existing_vertex2 == graph_traits<GraphSecond>::null_vertex()) {
Chris@16 148 continue;
Chris@16 149 }
Chris@16 150
Chris@16 151 // NOTE: This will not work with parallel edges, since the
Chris@16 152 // first matching edge is always chosen.
Chris@16 153 EdgeFirst edge_to_new1, edge_from_new1;
Chris@16 154 bool edge_to_new_exists1 = false, edge_from_new_exists1 = false;
Chris@16 155
Chris@16 156 EdgeSecond edge_to_new2, edge_from_new2;
Chris@16 157 bool edge_to_new_exists2 = false, edge_from_new_exists2 = false;
Chris@16 158
Chris@16 159 // Search for edge from existing to new vertex (graph1)
Chris@16 160 BGL_FORALL_OUTEDGES_T(existing_vertex1, edge1, graph1, GraphFirst) {
Chris@16 161 if (target(edge1, graph1) == new_vertex1) {
Chris@16 162 edge_to_new1 = edge1;
Chris@16 163 edge_to_new_exists1 = true;
Chris@16 164 break;
Chris@16 165 }
Chris@16 166 }
Chris@16 167
Chris@16 168 // Search for edge from existing to new vertex (graph2)
Chris@16 169 BGL_FORALL_OUTEDGES_T(existing_vertex2, edge2, graph2, GraphSecond) {
Chris@16 170 if (target(edge2, graph2) == new_vertex2) {
Chris@16 171 edge_to_new2 = edge2;
Chris@16 172 edge_to_new_exists2 = true;
Chris@16 173 break;
Chris@16 174 }
Chris@16 175 }
Chris@16 176
Chris@16 177 // Make sure edges from existing to new vertices are equivalent
Chris@16 178 if ((edge_to_new_exists1 != edge_to_new_exists2) ||
Chris@16 179 ((edge_to_new_exists1 && edge_to_new_exists2) &&
Chris@16 180 !edges_equivalent(edge_to_new1, edge_to_new2))) {
Chris@16 181
Chris@16 182 return (false);
Chris@16 183 }
Chris@16 184
Chris@16 185 bool is_undirected1 = is_undirected(graph1),
Chris@16 186 is_undirected2 = is_undirected(graph2);
Chris@16 187
Chris@16 188 if (is_undirected1 && is_undirected2) {
Chris@16 189
Chris@16 190 // Edge in both graphs exists and both graphs are undirected
Chris@16 191 if (edge_to_new_exists1 && edge_to_new_exists2) {
Chris@16 192 has_one_edge = true;
Chris@16 193 }
Chris@16 194
Chris@16 195 continue;
Chris@16 196 }
Chris@16 197 else {
Chris@16 198
Chris@16 199 if (!is_undirected1) {
Chris@16 200
Chris@16 201 // Search for edge from new to existing vertex (graph1)
Chris@16 202 BGL_FORALL_OUTEDGES_T(new_vertex1, edge1, graph1, GraphFirst) {
Chris@16 203 if (target(edge1, graph1) == existing_vertex1) {
Chris@16 204 edge_from_new1 = edge1;
Chris@16 205 edge_from_new_exists1 = true;
Chris@16 206 break;
Chris@16 207 }
Chris@16 208 }
Chris@16 209 }
Chris@16 210
Chris@16 211 if (!is_undirected2) {
Chris@16 212
Chris@16 213 // Search for edge from new to existing vertex (graph2)
Chris@16 214 BGL_FORALL_OUTEDGES_T(new_vertex2, edge2, graph2, GraphSecond) {
Chris@16 215 if (target(edge2, graph2) == existing_vertex2) {
Chris@16 216 edge_from_new2 = edge2;
Chris@16 217 edge_from_new_exists2 = true;
Chris@16 218 break;
Chris@16 219 }
Chris@16 220 }
Chris@16 221 }
Chris@16 222
Chris@16 223 // Make sure edges from new to existing vertices are equivalent
Chris@16 224 if ((edge_from_new_exists1 != edge_from_new_exists2) ||
Chris@16 225 ((edge_from_new_exists1 && edge_from_new_exists2) &&
Chris@16 226 !edges_equivalent(edge_from_new1, edge_from_new2))) {
Chris@16 227
Chris@16 228 return (false);
Chris@16 229 }
Chris@16 230
Chris@16 231 if ((edge_from_new_exists1 && edge_from_new_exists2) ||
Chris@16 232 (edge_to_new_exists1 && edge_to_new_exists2)) {
Chris@16 233 has_one_edge = true;
Chris@16 234 }
Chris@16 235
Chris@16 236 } // else
Chris@16 237
Chris@16 238 } // BGL_FORALL_VERTICES_T
Chris@16 239
Chris@16 240 // Make sure new vertices are connected to the existing subgraph
Chris@16 241 if (only_connected_subgraphs && !has_one_edge) {
Chris@16 242 return (false);
Chris@16 243 }
Chris@16 244
Chris@16 245 return (true);
Chris@16 246 }
Chris@16 247
Chris@16 248 // Recursive method that does a depth-first search in the space of
Chris@16 249 // potential subgraphs. At each level, every new vertex pair from
Chris@16 250 // both graphs is tested to see if it can extend the current
Chris@16 251 // subgraph. If so, the subgraph is output to subgraph_callback
Chris@16 252 // in the form of two correspondence maps (one for each graph).
Chris@16 253 // Returning false from subgraph_callback will terminate the
Chris@16 254 // search. Function returns true if the entire search space was
Chris@16 255 // explored.
Chris@16 256 template <typename GraphFirst,
Chris@16 257 typename GraphSecond,
Chris@16 258 typename VertexIndexMapFirst,
Chris@16 259 typename VertexIndexMapSecond,
Chris@16 260 typename CorrespondenceMapFirstToSecond,
Chris@16 261 typename CorrespondenceMapSecondToFirst,
Chris@16 262 typename VertexStackFirst,
Chris@16 263 typename EdgeEquivalencePredicate,
Chris@16 264 typename VertexEquivalencePredicate,
Chris@16 265 typename SubGraphInternalCallback>
Chris@16 266 bool mcgregor_common_subgraphs_internal
Chris@16 267 (const GraphFirst& graph1,
Chris@16 268 const GraphSecond& graph2,
Chris@16 269 const VertexIndexMapFirst& vindex_map1,
Chris@16 270 const VertexIndexMapSecond& vindex_map2,
Chris@16 271 CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
Chris@16 272 CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
Chris@16 273 VertexStackFirst& vertex_stack1,
Chris@16 274 EdgeEquivalencePredicate edges_equivalent,
Chris@16 275 VertexEquivalencePredicate vertices_equivalent,
Chris@16 276 bool only_connected_subgraphs,
Chris@16 277 SubGraphInternalCallback subgraph_callback)
Chris@16 278 {
Chris@16 279 typedef typename graph_traits<GraphFirst>::vertex_descriptor VertexFirst;
Chris@16 280 typedef typename graph_traits<GraphSecond>::vertex_descriptor VertexSecond;
Chris@16 281 typedef typename graph_traits<GraphFirst>::vertices_size_type VertexSizeFirst;
Chris@16 282
Chris@16 283 // Get iterators for vertices from both graphs
Chris@16 284 typename graph_traits<GraphFirst>::vertex_iterator
Chris@16 285 vertex1_iter, vertex1_end;
Chris@16 286
Chris@16 287 typename graph_traits<GraphSecond>::vertex_iterator
Chris@16 288 vertex2_begin, vertex2_end, vertex2_iter;
Chris@16 289
Chris@16 290 boost::tie(vertex1_iter, vertex1_end) = vertices(graph1);
Chris@16 291 boost::tie(vertex2_begin, vertex2_end) = vertices(graph2);
Chris@16 292 vertex2_iter = vertex2_begin;
Chris@16 293
Chris@16 294 // Iterate until all vertices have been visited
Chris@16 295 BGL_FORALL_VERTICES_T(new_vertex1, graph1, GraphFirst) {
Chris@16 296
Chris@16 297 VertexSecond existing_vertex2 = get(correspondence_map_1_to_2, new_vertex1);
Chris@16 298
Chris@16 299 // Skip already matched vertices in first graph
Chris@16 300 if (existing_vertex2 != graph_traits<GraphSecond>::null_vertex()) {
Chris@16 301 continue;
Chris@16 302 }
Chris@16 303
Chris@16 304 BGL_FORALL_VERTICES_T(new_vertex2, graph2, GraphSecond) {
Chris@16 305
Chris@16 306 VertexFirst existing_vertex1 = get(correspondence_map_2_to_1, new_vertex2);
Chris@16 307
Chris@16 308 // Skip already matched vertices in second graph
Chris@16 309 if (existing_vertex1 != graph_traits<GraphFirst>::null_vertex()) {
Chris@16 310 continue;
Chris@16 311 }
Chris@16 312
Chris@16 313 // Check if current sub-graph can be extended with the matched vertex pair
Chris@16 314 if (can_extend_graph(graph1, graph2,
Chris@16 315 correspondence_map_1_to_2, correspondence_map_2_to_1,
Chris@16 316 (VertexSizeFirst)vertex_stack1.size(),
Chris@16 317 new_vertex1, new_vertex2,
Chris@16 318 edges_equivalent, vertices_equivalent,
Chris@16 319 only_connected_subgraphs)) {
Chris@16 320
Chris@16 321 // Keep track of old graph size for restoring later
Chris@16 322 VertexSizeFirst old_graph_size = (VertexSizeFirst)vertex_stack1.size(),
Chris@16 323 new_graph_size = old_graph_size + 1;
Chris@16 324
Chris@16 325 // Extend subgraph
Chris@16 326 put(correspondence_map_1_to_2, new_vertex1, new_vertex2);
Chris@16 327 put(correspondence_map_2_to_1, new_vertex2, new_vertex1);
Chris@16 328 vertex_stack1.push(new_vertex1);
Chris@16 329
Chris@101 330 // Returning false from the callback will cancel iteration
Chris@101 331 if (!subgraph_callback(correspondence_map_1_to_2,
Chris@101 332 correspondence_map_2_to_1,
Chris@101 333 new_graph_size)) {
Chris@101 334 return (false);
Chris@16 335 }
Chris@16 336
Chris@16 337 // Depth-first search into the state space of possible sub-graphs
Chris@16 338 bool continue_iteration =
Chris@16 339 mcgregor_common_subgraphs_internal
Chris@16 340 (graph1, graph2,
Chris@16 341 vindex_map1, vindex_map2,
Chris@16 342 correspondence_map_1_to_2, correspondence_map_2_to_1,
Chris@16 343 vertex_stack1,
Chris@16 344 edges_equivalent, vertices_equivalent,
Chris@16 345 only_connected_subgraphs, subgraph_callback);
Chris@16 346
Chris@16 347 if (!continue_iteration) {
Chris@16 348 return (false);
Chris@16 349 }
Chris@16 350
Chris@16 351 // Restore previous state
Chris@16 352 if (vertex_stack1.size() > old_graph_size) {
Chris@16 353
Chris@16 354 VertexFirst stack_vertex1 = vertex_stack1.top();
Chris@16 355 VertexSecond stack_vertex2 = get(correspondence_map_1_to_2,
Chris@16 356 stack_vertex1);
Chris@16 357
Chris@16 358 // Contract subgraph
Chris@16 359 put(correspondence_map_1_to_2, stack_vertex1,
Chris@16 360 graph_traits<GraphSecond>::null_vertex());
Chris@16 361
Chris@16 362 put(correspondence_map_2_to_1, stack_vertex2,
Chris@16 363 graph_traits<GraphFirst>::null_vertex());
Chris@16 364
Chris@16 365 vertex_stack1.pop();
Chris@16 366 }
Chris@16 367
Chris@16 368 } // if can_extend_graph
Chris@16 369
Chris@16 370 } // BGL_FORALL_VERTICES_T (graph2)
Chris@16 371
Chris@16 372 } // BGL_FORALL_VERTICES_T (graph1)
Chris@16 373
Chris@16 374 return (true);
Chris@16 375 }
Chris@16 376
Chris@16 377 // Internal method that initializes blank correspondence maps and
Chris@16 378 // a vertex stack for use in mcgregor_common_subgraphs_internal.
Chris@16 379 template <typename GraphFirst,
Chris@16 380 typename GraphSecond,
Chris@16 381 typename VertexIndexMapFirst,
Chris@16 382 typename VertexIndexMapSecond,
Chris@16 383 typename EdgeEquivalencePredicate,
Chris@16 384 typename VertexEquivalencePredicate,
Chris@16 385 typename SubGraphInternalCallback>
Chris@16 386 inline void mcgregor_common_subgraphs_internal_init
Chris@16 387 (const GraphFirst& graph1,
Chris@16 388 const GraphSecond& graph2,
Chris@16 389 const VertexIndexMapFirst vindex_map1,
Chris@16 390 const VertexIndexMapSecond vindex_map2,
Chris@16 391 EdgeEquivalencePredicate edges_equivalent,
Chris@16 392 VertexEquivalencePredicate vertices_equivalent,
Chris@16 393 bool only_connected_subgraphs,
Chris@16 394 SubGraphInternalCallback subgraph_callback)
Chris@16 395 {
Chris@16 396 typedef mcgregor_common_subgraph_traits<GraphFirst,
Chris@16 397 GraphSecond, VertexIndexMapFirst,
Chris@16 398 VertexIndexMapSecond> SubGraphTraits;
Chris@16 399
Chris@16 400 typename SubGraphTraits::correspondence_map_first_to_second_type
Chris@16 401 correspondence_map_1_to_2(num_vertices(graph1), vindex_map1);
Chris@16 402
Chris@16 403 BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) {
Chris@16 404 put(correspondence_map_1_to_2, vertex1,
Chris@16 405 graph_traits<GraphSecond>::null_vertex());
Chris@16 406 }
Chris@16 407
Chris@16 408 typename SubGraphTraits::correspondence_map_second_to_first_type
Chris@16 409 correspondence_map_2_to_1(num_vertices(graph2), vindex_map2);
Chris@16 410
Chris@16 411 BGL_FORALL_VERTICES_T(vertex2, graph2, GraphSecond) {
Chris@16 412 put(correspondence_map_2_to_1, vertex2,
Chris@16 413 graph_traits<GraphFirst>::null_vertex());
Chris@16 414 }
Chris@16 415
Chris@16 416 typedef typename graph_traits<GraphFirst>::vertex_descriptor
Chris@16 417 VertexFirst;
Chris@16 418
Chris@16 419 std::stack<VertexFirst> vertex_stack1;
Chris@16 420
Chris@16 421 mcgregor_common_subgraphs_internal
Chris@16 422 (graph1, graph2,
Chris@16 423 vindex_map1, vindex_map2,
Chris@16 424 correspondence_map_1_to_2, correspondence_map_2_to_1,
Chris@16 425 vertex_stack1,
Chris@16 426 edges_equivalent, vertices_equivalent,
Chris@16 427 only_connected_subgraphs,
Chris@16 428 subgraph_callback);
Chris@16 429 }
Chris@16 430
Chris@16 431 } // namespace detail
Chris@16 432
Chris@16 433 // ==========================================================================
Chris@16 434
Chris@16 435 // Enumerates all common subgraphs present in graph1 and graph2.
Chris@16 436 // Continues until the search space has been fully explored or false
Chris@16 437 // is returned from user_callback.
Chris@16 438 template <typename GraphFirst,
Chris@16 439 typename GraphSecond,
Chris@16 440 typename VertexIndexMapFirst,
Chris@16 441 typename VertexIndexMapSecond,
Chris@16 442 typename EdgeEquivalencePredicate,
Chris@16 443 typename VertexEquivalencePredicate,
Chris@16 444 typename SubGraphCallback>
Chris@16 445 void mcgregor_common_subgraphs
Chris@16 446 (const GraphFirst& graph1,
Chris@16 447 const GraphSecond& graph2,
Chris@16 448 const VertexIndexMapFirst vindex_map1,
Chris@16 449 const VertexIndexMapSecond vindex_map2,
Chris@16 450 EdgeEquivalencePredicate edges_equivalent,
Chris@16 451 VertexEquivalencePredicate vertices_equivalent,
Chris@16 452 bool only_connected_subgraphs,
Chris@16 453 SubGraphCallback user_callback)
Chris@16 454 {
Chris@16 455
Chris@16 456 detail::mcgregor_common_subgraphs_internal_init
Chris@16 457 (graph1, graph2,
Chris@16 458 vindex_map1, vindex_map2,
Chris@16 459 edges_equivalent, vertices_equivalent,
Chris@16 460 only_connected_subgraphs,
Chris@16 461 user_callback);
Chris@16 462 }
Chris@16 463
Chris@16 464 // Variant of mcgregor_common_subgraphs with all default parameters
Chris@16 465 template <typename GraphFirst,
Chris@16 466 typename GraphSecond,
Chris@16 467 typename SubGraphCallback>
Chris@16 468 void mcgregor_common_subgraphs
Chris@16 469 (const GraphFirst& graph1,
Chris@16 470 const GraphSecond& graph2,
Chris@16 471 bool only_connected_subgraphs,
Chris@16 472 SubGraphCallback user_callback)
Chris@16 473 {
Chris@16 474
Chris@16 475 detail::mcgregor_common_subgraphs_internal_init
Chris@16 476 (graph1, graph2,
Chris@16 477 get(vertex_index, graph1), get(vertex_index, graph2),
Chris@16 478 always_equivalent(), always_equivalent(),
Chris@16 479 only_connected_subgraphs, user_callback);
Chris@16 480 }
Chris@16 481
Chris@16 482 // Named parameter variant of mcgregor_common_subgraphs
Chris@16 483 template <typename GraphFirst,
Chris@16 484 typename GraphSecond,
Chris@16 485 typename SubGraphCallback,
Chris@16 486 typename Param,
Chris@16 487 typename Tag,
Chris@16 488 typename Rest>
Chris@16 489 void mcgregor_common_subgraphs
Chris@16 490 (const GraphFirst& graph1,
Chris@16 491 const GraphSecond& graph2,
Chris@16 492 bool only_connected_subgraphs,
Chris@16 493 SubGraphCallback user_callback,
Chris@16 494 const bgl_named_params<Param, Tag, Rest>& params)
Chris@16 495 {
Chris@16 496
Chris@16 497 detail::mcgregor_common_subgraphs_internal_init
Chris@16 498 (graph1, graph2,
Chris@16 499 choose_const_pmap(get_param(params, vertex_index1),
Chris@16 500 graph1, vertex_index),
Chris@16 501 choose_const_pmap(get_param(params, vertex_index2),
Chris@16 502 graph2, vertex_index),
Chris@16 503 choose_param(get_param(params, edges_equivalent_t()),
Chris@16 504 always_equivalent()),
Chris@16 505 choose_param(get_param(params, vertices_equivalent_t()),
Chris@16 506 always_equivalent()),
Chris@16 507 only_connected_subgraphs, user_callback);
Chris@16 508 }
Chris@16 509
Chris@16 510 // ==========================================================================
Chris@16 511
Chris@16 512 namespace detail {
Chris@16 513
Chris@16 514 // Binary function object that intercepts subgraphs from
Chris@16 515 // mcgregor_common_subgraphs_internal and maintains a cache of
Chris@16 516 // unique subgraphs. The user callback is invoked for each unique
Chris@16 517 // subgraph.
Chris@16 518 template <typename GraphFirst,
Chris@16 519 typename GraphSecond,
Chris@16 520 typename VertexIndexMapFirst,
Chris@16 521 typename VertexIndexMapSecond,
Chris@16 522 typename SubGraphCallback>
Chris@16 523 struct unique_subgraph_interceptor {
Chris@16 524
Chris@16 525 typedef typename graph_traits<GraphFirst>::vertices_size_type
Chris@16 526 VertexSizeFirst;
Chris@16 527
Chris@16 528 typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
Chris@16 529 VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
Chris@16 530
Chris@16 531 typedef typename SubGraphTraits::correspondence_map_first_to_second_type
Chris@16 532 CachedCorrespondenceMapFirstToSecond;
Chris@16 533
Chris@16 534 typedef typename SubGraphTraits::correspondence_map_second_to_first_type
Chris@16 535 CachedCorrespondenceMapSecondToFirst;
Chris@16 536
Chris@16 537 typedef std::pair<VertexSizeFirst,
Chris@16 538 std::pair<CachedCorrespondenceMapFirstToSecond,
Chris@16 539 CachedCorrespondenceMapSecondToFirst> > SubGraph;
Chris@16 540
Chris@16 541 typedef std::vector<SubGraph> SubGraphList;
Chris@16 542
Chris@16 543 unique_subgraph_interceptor(const GraphFirst& graph1,
Chris@16 544 const GraphSecond& graph2,
Chris@16 545 const VertexIndexMapFirst vindex_map1,
Chris@16 546 const VertexIndexMapSecond vindex_map2,
Chris@16 547 SubGraphCallback user_callback) :
Chris@16 548 m_graph1(graph1), m_graph2(graph2),
Chris@16 549 m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
Chris@16 550 m_subgraphs(make_shared<SubGraphList>()),
Chris@16 551 m_user_callback(user_callback) { }
Chris@16 552
Chris@16 553 template <typename CorrespondenceMapFirstToSecond,
Chris@16 554 typename CorrespondenceMapSecondToFirst>
Chris@16 555 bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
Chris@16 556 CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
Chris@16 557 VertexSizeFirst subgraph_size) {
Chris@16 558
Chris@16 559 for (typename SubGraphList::const_iterator
Chris@16 560 subgraph_iter = m_subgraphs->begin();
Chris@16 561 subgraph_iter != m_subgraphs->end();
Chris@16 562 ++subgraph_iter) {
Chris@16 563
Chris@16 564 SubGraph subgraph_cached = *subgraph_iter;
Chris@16 565
Chris@16 566 // Compare subgraph sizes
Chris@16 567 if (subgraph_size != subgraph_cached.first) {
Chris@16 568 continue;
Chris@16 569 }
Chris@16 570
Chris@16 571 if (!are_property_maps_different(correspondence_map_1_to_2,
Chris@16 572 subgraph_cached.second.first,
Chris@16 573 m_graph1)) {
Chris@16 574
Chris@16 575 // New subgraph is a duplicate
Chris@16 576 return (true);
Chris@16 577 }
Chris@16 578 }
Chris@16 579
Chris@16 580 // Subgraph is unique, so make a cached copy
Chris@16 581 CachedCorrespondenceMapFirstToSecond
Chris@16 582 new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
Chris@16 583 (num_vertices(m_graph1), m_vindex_map1);
Chris@16 584
Chris@16 585 CachedCorrespondenceMapSecondToFirst
Chris@16 586 new_subgraph_2_to_1 = CorrespondenceMapSecondToFirst
Chris@16 587 (num_vertices(m_graph2), m_vindex_map2);
Chris@16 588
Chris@16 589 BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
Chris@16 590 put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
Chris@16 591 }
Chris@16 592
Chris@16 593 BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
Chris@16 594 put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
Chris@16 595 }
Chris@16 596
Chris@16 597 m_subgraphs->push_back(std::make_pair(subgraph_size,
Chris@16 598 std::make_pair(new_subgraph_1_to_2,
Chris@16 599 new_subgraph_2_to_1)));
Chris@16 600
Chris@16 601 return (m_user_callback(correspondence_map_1_to_2,
Chris@16 602 correspondence_map_2_to_1,
Chris@16 603 subgraph_size));
Chris@16 604 }
Chris@16 605
Chris@16 606 private:
Chris@16 607 const GraphFirst& m_graph1;
Chris@16 608 const GraphFirst& m_graph2;
Chris@16 609 const VertexIndexMapFirst m_vindex_map1;
Chris@16 610 const VertexIndexMapSecond m_vindex_map2;
Chris@16 611 shared_ptr<SubGraphList> m_subgraphs;
Chris@16 612 SubGraphCallback m_user_callback;
Chris@16 613 };
Chris@16 614
Chris@16 615 } // namespace detail
Chris@16 616
Chris@16 617 // Enumerates all unique common subgraphs between graph1 and graph2.
Chris@16 618 // The user callback is invoked for each unique subgraph as they are
Chris@16 619 // discovered.
Chris@16 620 template <typename GraphFirst,
Chris@16 621 typename GraphSecond,
Chris@16 622 typename VertexIndexMapFirst,
Chris@16 623 typename VertexIndexMapSecond,
Chris@16 624 typename EdgeEquivalencePredicate,
Chris@16 625 typename VertexEquivalencePredicate,
Chris@16 626 typename SubGraphCallback>
Chris@16 627 void mcgregor_common_subgraphs_unique
Chris@16 628 (const GraphFirst& graph1,
Chris@16 629 const GraphSecond& graph2,
Chris@16 630 const VertexIndexMapFirst vindex_map1,
Chris@16 631 const VertexIndexMapSecond vindex_map2,
Chris@16 632 EdgeEquivalencePredicate edges_equivalent,
Chris@16 633 VertexEquivalencePredicate vertices_equivalent,
Chris@16 634 bool only_connected_subgraphs,
Chris@16 635 SubGraphCallback user_callback)
Chris@16 636 {
Chris@16 637 detail::unique_subgraph_interceptor<GraphFirst, GraphSecond,
Chris@16 638 VertexIndexMapFirst, VertexIndexMapSecond,
Chris@16 639 SubGraphCallback> unique_callback
Chris@16 640 (graph1, graph2,
Chris@16 641 vindex_map1, vindex_map2,
Chris@16 642 user_callback);
Chris@16 643
Chris@16 644 detail::mcgregor_common_subgraphs_internal_init
Chris@16 645 (graph1, graph2,
Chris@16 646 vindex_map1, vindex_map2,
Chris@16 647 edges_equivalent, vertices_equivalent,
Chris@16 648 only_connected_subgraphs, unique_callback);
Chris@16 649 }
Chris@16 650
Chris@16 651 // Variant of mcgregor_common_subgraphs_unique with all default
Chris@16 652 // parameters.
Chris@16 653 template <typename GraphFirst,
Chris@16 654 typename GraphSecond,
Chris@16 655 typename SubGraphCallback>
Chris@16 656 void mcgregor_common_subgraphs_unique
Chris@16 657 (const GraphFirst& graph1,
Chris@16 658 const GraphSecond& graph2,
Chris@16 659 bool only_connected_subgraphs,
Chris@16 660 SubGraphCallback user_callback)
Chris@16 661 {
Chris@16 662 mcgregor_common_subgraphs_unique
Chris@16 663 (graph1, graph2,
Chris@16 664 get(vertex_index, graph1), get(vertex_index, graph2),
Chris@16 665 always_equivalent(), always_equivalent(),
Chris@16 666 only_connected_subgraphs, user_callback);
Chris@16 667 }
Chris@16 668
Chris@16 669 // Named parameter variant of mcgregor_common_subgraphs_unique
Chris@16 670 template <typename GraphFirst,
Chris@16 671 typename GraphSecond,
Chris@16 672 typename SubGraphCallback,
Chris@16 673 typename Param,
Chris@16 674 typename Tag,
Chris@16 675 typename Rest>
Chris@16 676 void mcgregor_common_subgraphs_unique
Chris@16 677 (const GraphFirst& graph1,
Chris@16 678 const GraphSecond& graph2,
Chris@16 679 bool only_connected_subgraphs,
Chris@16 680 SubGraphCallback user_callback,
Chris@16 681 const bgl_named_params<Param, Tag, Rest>& params)
Chris@16 682 {
Chris@16 683 mcgregor_common_subgraphs_unique
Chris@16 684 (graph1, graph2,
Chris@16 685 choose_const_pmap(get_param(params, vertex_index1),
Chris@16 686 graph1, vertex_index),
Chris@16 687 choose_const_pmap(get_param(params, vertex_index2),
Chris@16 688 graph2, vertex_index),
Chris@16 689 choose_param(get_param(params, edges_equivalent_t()),
Chris@16 690 always_equivalent()),
Chris@16 691 choose_param(get_param(params, vertices_equivalent_t()),
Chris@16 692 always_equivalent()),
Chris@16 693 only_connected_subgraphs, user_callback);
Chris@16 694 }
Chris@16 695
Chris@16 696 // ==========================================================================
Chris@16 697
Chris@16 698 namespace detail {
Chris@16 699
Chris@16 700 // Binary function object that intercepts subgraphs from
Chris@16 701 // mcgregor_common_subgraphs_internal and maintains a cache of the
Chris@16 702 // largest subgraphs.
Chris@16 703 template <typename GraphFirst,
Chris@16 704 typename GraphSecond,
Chris@16 705 typename VertexIndexMapFirst,
Chris@16 706 typename VertexIndexMapSecond,
Chris@16 707 typename SubGraphCallback>
Chris@16 708 struct maximum_subgraph_interceptor {
Chris@16 709
Chris@16 710 typedef typename graph_traits<GraphFirst>::vertices_size_type
Chris@16 711 VertexSizeFirst;
Chris@16 712
Chris@16 713 typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
Chris@16 714 VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
Chris@16 715
Chris@16 716 typedef typename SubGraphTraits::correspondence_map_first_to_second_type
Chris@16 717 CachedCorrespondenceMapFirstToSecond;
Chris@16 718
Chris@16 719 typedef typename SubGraphTraits::correspondence_map_second_to_first_type
Chris@16 720 CachedCorrespondenceMapSecondToFirst;
Chris@16 721
Chris@16 722 typedef std::pair<VertexSizeFirst,
Chris@16 723 std::pair<CachedCorrespondenceMapFirstToSecond,
Chris@16 724 CachedCorrespondenceMapSecondToFirst> > SubGraph;
Chris@16 725
Chris@16 726 typedef std::vector<SubGraph> SubGraphList;
Chris@16 727
Chris@16 728 maximum_subgraph_interceptor(const GraphFirst& graph1,
Chris@16 729 const GraphSecond& graph2,
Chris@16 730 const VertexIndexMapFirst vindex_map1,
Chris@16 731 const VertexIndexMapSecond vindex_map2,
Chris@16 732 SubGraphCallback user_callback) :
Chris@16 733 m_graph1(graph1), m_graph2(graph2),
Chris@16 734 m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
Chris@16 735 m_subgraphs(make_shared<SubGraphList>()),
Chris@16 736 m_largest_size_so_far(make_shared<VertexSizeFirst>(0)),
Chris@16 737 m_user_callback(user_callback) { }
Chris@16 738
Chris@16 739 template <typename CorrespondenceMapFirstToSecond,
Chris@16 740 typename CorrespondenceMapSecondToFirst>
Chris@16 741 bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
Chris@16 742 CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
Chris@16 743 VertexSizeFirst subgraph_size) {
Chris@16 744
Chris@16 745 if (subgraph_size > *m_largest_size_so_far) {
Chris@16 746 m_subgraphs->clear();
Chris@16 747 *m_largest_size_so_far = subgraph_size;
Chris@16 748 }
Chris@16 749
Chris@16 750 if (subgraph_size == *m_largest_size_so_far) {
Chris@16 751
Chris@16 752 // Make a cached copy
Chris@16 753 CachedCorrespondenceMapFirstToSecond
Chris@16 754 new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
Chris@16 755 (num_vertices(m_graph1), m_vindex_map1);
Chris@16 756
Chris@16 757 CachedCorrespondenceMapSecondToFirst
Chris@16 758 new_subgraph_2_to_1 = CachedCorrespondenceMapSecondToFirst
Chris@16 759 (num_vertices(m_graph2), m_vindex_map2);
Chris@16 760
Chris@16 761 BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
Chris@16 762 put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
Chris@16 763 }
Chris@16 764
Chris@16 765 BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
Chris@16 766 put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
Chris@16 767 }
Chris@16 768
Chris@16 769 m_subgraphs->push_back(std::make_pair(subgraph_size,
Chris@16 770 std::make_pair(new_subgraph_1_to_2,
Chris@16 771 new_subgraph_2_to_1)));
Chris@16 772 }
Chris@16 773
Chris@16 774 return (true);
Chris@16 775 }
Chris@16 776
Chris@16 777 void output_subgraphs() {
Chris@16 778 for (typename SubGraphList::const_iterator
Chris@16 779 subgraph_iter = m_subgraphs->begin();
Chris@16 780 subgraph_iter != m_subgraphs->end();
Chris@16 781 ++subgraph_iter) {
Chris@16 782
Chris@16 783 SubGraph subgraph_cached = *subgraph_iter;
Chris@16 784 m_user_callback(subgraph_cached.second.first,
Chris@16 785 subgraph_cached.second.second,
Chris@16 786 subgraph_cached.first);
Chris@16 787 }
Chris@16 788 }
Chris@16 789
Chris@16 790 private:
Chris@16 791 const GraphFirst& m_graph1;
Chris@16 792 const GraphFirst& m_graph2;
Chris@16 793 const VertexIndexMapFirst m_vindex_map1;
Chris@16 794 const VertexIndexMapSecond m_vindex_map2;
Chris@16 795 shared_ptr<SubGraphList> m_subgraphs;
Chris@16 796 shared_ptr<VertexSizeFirst> m_largest_size_so_far;
Chris@16 797 SubGraphCallback m_user_callback;
Chris@16 798 };
Chris@16 799
Chris@16 800 } // namespace detail
Chris@16 801
Chris@16 802 // Enumerates the largest common subgraphs found between graph1
Chris@16 803 // and graph2. Note that the ENTIRE search space is explored before
Chris@16 804 // user_callback is actually invoked.
Chris@16 805 template <typename GraphFirst,
Chris@16 806 typename GraphSecond,
Chris@16 807 typename VertexIndexMapFirst,
Chris@16 808 typename VertexIndexMapSecond,
Chris@16 809 typename EdgeEquivalencePredicate,
Chris@16 810 typename VertexEquivalencePredicate,
Chris@16 811 typename SubGraphCallback>
Chris@16 812 void mcgregor_common_subgraphs_maximum
Chris@16 813 (const GraphFirst& graph1,
Chris@16 814 const GraphSecond& graph2,
Chris@16 815 const VertexIndexMapFirst vindex_map1,
Chris@16 816 const VertexIndexMapSecond vindex_map2,
Chris@16 817 EdgeEquivalencePredicate edges_equivalent,
Chris@16 818 VertexEquivalencePredicate vertices_equivalent,
Chris@16 819 bool only_connected_subgraphs,
Chris@16 820 SubGraphCallback user_callback)
Chris@16 821 {
Chris@16 822 detail::maximum_subgraph_interceptor<GraphFirst, GraphSecond,
Chris@16 823 VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback>
Chris@16 824 max_interceptor
Chris@16 825 (graph1, graph2, vindex_map1, vindex_map2, user_callback);
Chris@16 826
Chris@16 827 detail::mcgregor_common_subgraphs_internal_init
Chris@16 828 (graph1, graph2,
Chris@16 829 vindex_map1, vindex_map2,
Chris@16 830 edges_equivalent, vertices_equivalent,
Chris@16 831 only_connected_subgraphs, max_interceptor);
Chris@16 832
Chris@16 833 // Only output the largest subgraphs
Chris@16 834 max_interceptor.output_subgraphs();
Chris@16 835 }
Chris@16 836
Chris@16 837 // Variant of mcgregor_common_subgraphs_maximum with all default
Chris@16 838 // parameters.
Chris@16 839 template <typename GraphFirst,
Chris@16 840 typename GraphSecond,
Chris@16 841 typename SubGraphCallback>
Chris@16 842 void mcgregor_common_subgraphs_maximum
Chris@16 843 (const GraphFirst& graph1,
Chris@16 844 const GraphSecond& graph2,
Chris@16 845 bool only_connected_subgraphs,
Chris@16 846 SubGraphCallback user_callback)
Chris@16 847 {
Chris@16 848 mcgregor_common_subgraphs_maximum
Chris@16 849 (graph1, graph2,
Chris@16 850 get(vertex_index, graph1), get(vertex_index, graph2),
Chris@16 851 always_equivalent(), always_equivalent(),
Chris@16 852 only_connected_subgraphs, user_callback);
Chris@16 853 }
Chris@16 854
Chris@16 855 // Named parameter variant of mcgregor_common_subgraphs_maximum
Chris@16 856 template <typename GraphFirst,
Chris@16 857 typename GraphSecond,
Chris@16 858 typename SubGraphCallback,
Chris@16 859 typename Param,
Chris@16 860 typename Tag,
Chris@16 861 typename Rest>
Chris@16 862 void mcgregor_common_subgraphs_maximum
Chris@16 863 (const GraphFirst& graph1,
Chris@16 864 const GraphSecond& graph2,
Chris@16 865 bool only_connected_subgraphs,
Chris@16 866 SubGraphCallback user_callback,
Chris@16 867 const bgl_named_params<Param, Tag, Rest>& params)
Chris@16 868 {
Chris@16 869 mcgregor_common_subgraphs_maximum
Chris@16 870 (graph1, graph2,
Chris@16 871 choose_const_pmap(get_param(params, vertex_index1),
Chris@16 872 graph1, vertex_index),
Chris@16 873 choose_const_pmap(get_param(params, vertex_index2),
Chris@16 874 graph2, vertex_index),
Chris@16 875 choose_param(get_param(params, edges_equivalent_t()),
Chris@16 876 always_equivalent()),
Chris@16 877 choose_param(get_param(params, vertices_equivalent_t()),
Chris@16 878 always_equivalent()),
Chris@16 879 only_connected_subgraphs, user_callback);
Chris@16 880 }
Chris@16 881
Chris@16 882 // ==========================================================================
Chris@16 883
Chris@16 884 namespace detail {
Chris@16 885
Chris@16 886 // Binary function object that intercepts subgraphs from
Chris@16 887 // mcgregor_common_subgraphs_internal and maintains a cache of the
Chris@16 888 // largest, unique subgraphs.
Chris@16 889 template <typename GraphFirst,
Chris@16 890 typename GraphSecond,
Chris@16 891 typename VertexIndexMapFirst,
Chris@16 892 typename VertexIndexMapSecond,
Chris@16 893 typename SubGraphCallback>
Chris@16 894 struct unique_maximum_subgraph_interceptor {
Chris@16 895
Chris@16 896 typedef typename graph_traits<GraphFirst>::vertices_size_type
Chris@16 897 VertexSizeFirst;
Chris@16 898
Chris@16 899 typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
Chris@16 900 VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
Chris@16 901
Chris@16 902 typedef typename SubGraphTraits::correspondence_map_first_to_second_type
Chris@16 903 CachedCorrespondenceMapFirstToSecond;
Chris@16 904
Chris@16 905 typedef typename SubGraphTraits::correspondence_map_second_to_first_type
Chris@16 906 CachedCorrespondenceMapSecondToFirst;
Chris@16 907
Chris@16 908 typedef std::pair<VertexSizeFirst,
Chris@16 909 std::pair<CachedCorrespondenceMapFirstToSecond,
Chris@16 910 CachedCorrespondenceMapSecondToFirst> > SubGraph;
Chris@16 911
Chris@16 912 typedef std::vector<SubGraph> SubGraphList;
Chris@16 913
Chris@16 914 unique_maximum_subgraph_interceptor(const GraphFirst& graph1,
Chris@16 915 const GraphSecond& graph2,
Chris@16 916 const VertexIndexMapFirst vindex_map1,
Chris@16 917 const VertexIndexMapSecond vindex_map2,
Chris@16 918 SubGraphCallback user_callback) :
Chris@16 919 m_graph1(graph1), m_graph2(graph2),
Chris@16 920 m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
Chris@16 921 m_subgraphs(make_shared<SubGraphList>()),
Chris@16 922 m_largest_size_so_far(make_shared<VertexSizeFirst>(0)),
Chris@16 923 m_user_callback(user_callback) { }
Chris@16 924
Chris@16 925 template <typename CorrespondenceMapFirstToSecond,
Chris@16 926 typename CorrespondenceMapSecondToFirst>
Chris@16 927 bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
Chris@16 928 CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
Chris@16 929 VertexSizeFirst subgraph_size) {
Chris@16 930
Chris@16 931 if (subgraph_size > *m_largest_size_so_far) {
Chris@16 932 m_subgraphs->clear();
Chris@16 933 *m_largest_size_so_far = subgraph_size;
Chris@16 934 }
Chris@16 935
Chris@16 936 if (subgraph_size == *m_largest_size_so_far) {
Chris@16 937
Chris@16 938 // Check if subgraph is unique
Chris@16 939 for (typename SubGraphList::const_iterator
Chris@16 940 subgraph_iter = m_subgraphs->begin();
Chris@16 941 subgraph_iter != m_subgraphs->end();
Chris@16 942 ++subgraph_iter) {
Chris@16 943
Chris@16 944 SubGraph subgraph_cached = *subgraph_iter;
Chris@16 945
Chris@16 946 if (!are_property_maps_different(correspondence_map_1_to_2,
Chris@16 947 subgraph_cached.second.first,
Chris@16 948 m_graph1)) {
Chris@16 949
Chris@16 950 // New subgraph is a duplicate
Chris@16 951 return (true);
Chris@16 952 }
Chris@16 953 }
Chris@16 954
Chris@16 955 // Subgraph is unique, so make a cached copy
Chris@16 956 CachedCorrespondenceMapFirstToSecond
Chris@16 957 new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
Chris@16 958 (num_vertices(m_graph1), m_vindex_map1);
Chris@16 959
Chris@16 960 CachedCorrespondenceMapSecondToFirst
Chris@16 961 new_subgraph_2_to_1 = CachedCorrespondenceMapSecondToFirst
Chris@16 962 (num_vertices(m_graph2), m_vindex_map2);
Chris@16 963
Chris@16 964 BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
Chris@16 965 put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
Chris@16 966 }
Chris@16 967
Chris@16 968 BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
Chris@16 969 put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
Chris@16 970 }
Chris@16 971
Chris@16 972 m_subgraphs->push_back(std::make_pair(subgraph_size,
Chris@16 973 std::make_pair(new_subgraph_1_to_2,
Chris@16 974 new_subgraph_2_to_1)));
Chris@16 975 }
Chris@16 976
Chris@16 977 return (true);
Chris@16 978 }
Chris@16 979
Chris@16 980 void output_subgraphs() {
Chris@16 981 for (typename SubGraphList::const_iterator
Chris@16 982 subgraph_iter = m_subgraphs->begin();
Chris@16 983 subgraph_iter != m_subgraphs->end();
Chris@16 984 ++subgraph_iter) {
Chris@16 985
Chris@16 986 SubGraph subgraph_cached = *subgraph_iter;
Chris@16 987 m_user_callback(subgraph_cached.second.first,
Chris@16 988 subgraph_cached.second.second,
Chris@16 989 subgraph_cached.first);
Chris@16 990 }
Chris@16 991 }
Chris@16 992
Chris@16 993 private:
Chris@16 994 const GraphFirst& m_graph1;
Chris@16 995 const GraphFirst& m_graph2;
Chris@16 996 const VertexIndexMapFirst m_vindex_map1;
Chris@16 997 const VertexIndexMapSecond m_vindex_map2;
Chris@16 998 shared_ptr<SubGraphList> m_subgraphs;
Chris@16 999 shared_ptr<VertexSizeFirst> m_largest_size_so_far;
Chris@16 1000 SubGraphCallback m_user_callback;
Chris@16 1001 };
Chris@16 1002
Chris@16 1003 } // namespace detail
Chris@16 1004
Chris@16 1005 // Enumerates the largest, unique common subgraphs found between
Chris@16 1006 // graph1 and graph2. Note that the ENTIRE search space is explored
Chris@16 1007 // before user_callback is actually invoked.
Chris@16 1008 template <typename GraphFirst,
Chris@16 1009 typename GraphSecond,
Chris@16 1010 typename VertexIndexMapFirst,
Chris@16 1011 typename VertexIndexMapSecond,
Chris@16 1012 typename EdgeEquivalencePredicate,
Chris@16 1013 typename VertexEquivalencePredicate,
Chris@16 1014 typename SubGraphCallback>
Chris@16 1015 void mcgregor_common_subgraphs_maximum_unique
Chris@16 1016 (const GraphFirst& graph1,
Chris@16 1017 const GraphSecond& graph2,
Chris@16 1018 const VertexIndexMapFirst vindex_map1,
Chris@16 1019 const VertexIndexMapSecond vindex_map2,
Chris@16 1020 EdgeEquivalencePredicate edges_equivalent,
Chris@16 1021 VertexEquivalencePredicate vertices_equivalent,
Chris@16 1022 bool only_connected_subgraphs,
Chris@16 1023 SubGraphCallback user_callback)
Chris@16 1024 {
Chris@16 1025 detail::unique_maximum_subgraph_interceptor<GraphFirst, GraphSecond,
Chris@16 1026 VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback>
Chris@16 1027 unique_max_interceptor
Chris@16 1028 (graph1, graph2, vindex_map1, vindex_map2, user_callback);
Chris@16 1029
Chris@16 1030 detail::mcgregor_common_subgraphs_internal_init
Chris@16 1031 (graph1, graph2,
Chris@16 1032 vindex_map1, vindex_map2,
Chris@16 1033 edges_equivalent, vertices_equivalent,
Chris@16 1034 only_connected_subgraphs, unique_max_interceptor);
Chris@16 1035
Chris@16 1036 // Only output the largest, unique subgraphs
Chris@16 1037 unique_max_interceptor.output_subgraphs();
Chris@16 1038 }
Chris@16 1039
Chris@16 1040 // Variant of mcgregor_common_subgraphs_maximum_unique with all default parameters
Chris@16 1041 template <typename GraphFirst,
Chris@16 1042 typename GraphSecond,
Chris@16 1043 typename SubGraphCallback>
Chris@16 1044 void mcgregor_common_subgraphs_maximum_unique
Chris@16 1045 (const GraphFirst& graph1,
Chris@16 1046 const GraphSecond& graph2,
Chris@16 1047 bool only_connected_subgraphs,
Chris@16 1048 SubGraphCallback user_callback)
Chris@16 1049 {
Chris@16 1050
Chris@16 1051 mcgregor_common_subgraphs_maximum_unique
Chris@16 1052 (graph1, graph2,
Chris@16 1053 get(vertex_index, graph1), get(vertex_index, graph2),
Chris@16 1054 always_equivalent(), always_equivalent(),
Chris@16 1055 only_connected_subgraphs, user_callback);
Chris@16 1056 }
Chris@16 1057
Chris@16 1058 // Named parameter variant of
Chris@16 1059 // mcgregor_common_subgraphs_maximum_unique
Chris@16 1060 template <typename GraphFirst,
Chris@16 1061 typename GraphSecond,
Chris@16 1062 typename SubGraphCallback,
Chris@16 1063 typename Param,
Chris@16 1064 typename Tag,
Chris@16 1065 typename Rest>
Chris@16 1066 void mcgregor_common_subgraphs_maximum_unique
Chris@16 1067 (const GraphFirst& graph1,
Chris@16 1068 const GraphSecond& graph2,
Chris@16 1069 bool only_connected_subgraphs,
Chris@16 1070 SubGraphCallback user_callback,
Chris@16 1071 const bgl_named_params<Param, Tag, Rest>& params)
Chris@16 1072 {
Chris@16 1073 mcgregor_common_subgraphs_maximum_unique
Chris@16 1074 (graph1, graph2,
Chris@16 1075 choose_const_pmap(get_param(params, vertex_index1),
Chris@16 1076 graph1, vertex_index),
Chris@16 1077 choose_const_pmap(get_param(params, vertex_index2),
Chris@16 1078 graph2, vertex_index),
Chris@16 1079 choose_param(get_param(params, edges_equivalent_t()),
Chris@16 1080 always_equivalent()),
Chris@16 1081 choose_param(get_param(params, vertices_equivalent_t()),
Chris@16 1082 always_equivalent()),
Chris@16 1083 only_connected_subgraphs, user_callback);
Chris@16 1084 }
Chris@16 1085
Chris@16 1086 // ==========================================================================
Chris@16 1087
Chris@16 1088 // Fills a membership map (vertex -> bool) using the information
Chris@16 1089 // present in correspondence_map_1_to_2. Every vertex in a
Chris@16 1090 // membership map will have a true value only if it is not
Chris@16 1091 // associated with a null vertex in the correspondence map.
Chris@16 1092 template <typename GraphSecond,
Chris@16 1093 typename GraphFirst,
Chris@16 1094 typename CorrespondenceMapFirstToSecond,
Chris@16 1095 typename MembershipMapFirst>
Chris@16 1096 void fill_membership_map
Chris@16 1097 (const GraphFirst& graph1,
Chris@16 1098 const CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
Chris@16 1099 MembershipMapFirst membership_map1) {
Chris@16 1100
Chris@16 1101 BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) {
Chris@16 1102 put(membership_map1, vertex1,
Chris@16 1103 get(correspondence_map_1_to_2, vertex1) != graph_traits<GraphSecond>::null_vertex());
Chris@16 1104 }
Chris@16 1105
Chris@16 1106 }
Chris@16 1107
Chris@16 1108 // Traits associated with a membership map filtered graph. Provided
Chris@16 1109 // for convenience to access graph and vertex filter types.
Chris@16 1110 template <typename Graph,
Chris@16 1111 typename MembershipMap>
Chris@16 1112 struct membership_filtered_graph_traits {
Chris@16 1113 typedef property_map_filter<MembershipMap> vertex_filter_type;
Chris@16 1114 typedef filtered_graph<Graph, keep_all, vertex_filter_type> graph_type;
Chris@16 1115 };
Chris@16 1116
Chris@16 1117 // Returns a filtered sub-graph of graph whose edge and vertex
Chris@16 1118 // inclusion is dictated by membership_map.
Chris@16 1119 template <typename Graph,
Chris@16 1120 typename MembershipMap>
Chris@16 1121 typename membership_filtered_graph_traits<Graph, MembershipMap>::graph_type
Chris@16 1122 make_membership_filtered_graph
Chris@16 1123 (const Graph& graph,
Chris@16 1124 MembershipMap& membership_map) {
Chris@16 1125
Chris@16 1126 typedef membership_filtered_graph_traits<Graph, MembershipMap> MFGTraits;
Chris@16 1127 typedef typename MFGTraits::graph_type MembershipFilteredGraph;
Chris@16 1128
Chris@16 1129 typename MFGTraits::vertex_filter_type v_filter(membership_map);
Chris@16 1130
Chris@16 1131 return (MembershipFilteredGraph(graph, keep_all(), v_filter));
Chris@16 1132
Chris@16 1133 }
Chris@16 1134
Chris@16 1135 } // namespace boost
Chris@16 1136
Chris@16 1137 #endif // BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP