mcgregor_common_subgraphs.hpp 42 KB

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