mcgregor_common_subgraphs.hpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  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. // Returning false from the callback will cancel iteration
  268. if (!subgraph_callback(correspondence_map_1_to_2,
  269. correspondence_map_2_to_1,
  270. new_graph_size)) {
  271. return (false);
  272. }
  273. // Depth-first search into the state space of possible sub-graphs
  274. bool continue_iteration =
  275. mcgregor_common_subgraphs_internal
  276. (graph1, graph2,
  277. vindex_map1, vindex_map2,
  278. correspondence_map_1_to_2, correspondence_map_2_to_1,
  279. vertex_stack1,
  280. edges_equivalent, vertices_equivalent,
  281. only_connected_subgraphs, subgraph_callback);
  282. if (!continue_iteration) {
  283. return (false);
  284. }
  285. // Restore previous state
  286. if (vertex_stack1.size() > old_graph_size) {
  287. VertexFirst stack_vertex1 = vertex_stack1.top();
  288. VertexSecond stack_vertex2 = get(correspondence_map_1_to_2,
  289. stack_vertex1);
  290. // Contract subgraph
  291. put(correspondence_map_1_to_2, stack_vertex1,
  292. graph_traits<GraphSecond>::null_vertex());
  293. put(correspondence_map_2_to_1, stack_vertex2,
  294. graph_traits<GraphFirst>::null_vertex());
  295. vertex_stack1.pop();
  296. }
  297. } // if can_extend_graph
  298. } // BGL_FORALL_VERTICES_T (graph2)
  299. } // BGL_FORALL_VERTICES_T (graph1)
  300. return (true);
  301. }
  302. // Internal method that initializes blank correspondence maps and
  303. // a vertex stack for use in mcgregor_common_subgraphs_internal.
  304. template <typename GraphFirst,
  305. typename GraphSecond,
  306. typename VertexIndexMapFirst,
  307. typename VertexIndexMapSecond,
  308. typename EdgeEquivalencePredicate,
  309. typename VertexEquivalencePredicate,
  310. typename SubGraphInternalCallback>
  311. inline void mcgregor_common_subgraphs_internal_init
  312. (const GraphFirst& graph1,
  313. const GraphSecond& graph2,
  314. const VertexIndexMapFirst vindex_map1,
  315. const VertexIndexMapSecond vindex_map2,
  316. EdgeEquivalencePredicate edges_equivalent,
  317. VertexEquivalencePredicate vertices_equivalent,
  318. bool only_connected_subgraphs,
  319. SubGraphInternalCallback subgraph_callback)
  320. {
  321. typedef mcgregor_common_subgraph_traits<GraphFirst,
  322. GraphSecond, VertexIndexMapFirst,
  323. VertexIndexMapSecond> SubGraphTraits;
  324. typename SubGraphTraits::correspondence_map_first_to_second_type
  325. correspondence_map_1_to_2(num_vertices(graph1), vindex_map1);
  326. BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) {
  327. put(correspondence_map_1_to_2, vertex1,
  328. graph_traits<GraphSecond>::null_vertex());
  329. }
  330. typename SubGraphTraits::correspondence_map_second_to_first_type
  331. correspondence_map_2_to_1(num_vertices(graph2), vindex_map2);
  332. BGL_FORALL_VERTICES_T(vertex2, graph2, GraphSecond) {
  333. put(correspondence_map_2_to_1, vertex2,
  334. graph_traits<GraphFirst>::null_vertex());
  335. }
  336. typedef typename graph_traits<GraphFirst>::vertex_descriptor
  337. VertexFirst;
  338. std::stack<VertexFirst> vertex_stack1;
  339. mcgregor_common_subgraphs_internal
  340. (graph1, graph2,
  341. vindex_map1, vindex_map2,
  342. correspondence_map_1_to_2, correspondence_map_2_to_1,
  343. vertex_stack1,
  344. edges_equivalent, vertices_equivalent,
  345. only_connected_subgraphs,
  346. subgraph_callback);
  347. }
  348. } // namespace detail
  349. // ==========================================================================
  350. // Enumerates all common subgraphs present in graph1 and graph2.
  351. // Continues until the search space has been fully explored or false
  352. // is returned from user_callback.
  353. template <typename GraphFirst,
  354. typename GraphSecond,
  355. typename VertexIndexMapFirst,
  356. typename VertexIndexMapSecond,
  357. typename EdgeEquivalencePredicate,
  358. typename VertexEquivalencePredicate,
  359. typename SubGraphCallback>
  360. void mcgregor_common_subgraphs
  361. (const GraphFirst& graph1,
  362. const GraphSecond& graph2,
  363. const VertexIndexMapFirst vindex_map1,
  364. const VertexIndexMapSecond vindex_map2,
  365. EdgeEquivalencePredicate edges_equivalent,
  366. VertexEquivalencePredicate vertices_equivalent,
  367. bool only_connected_subgraphs,
  368. SubGraphCallback user_callback)
  369. {
  370. detail::mcgregor_common_subgraphs_internal_init
  371. (graph1, graph2,
  372. vindex_map1, vindex_map2,
  373. edges_equivalent, vertices_equivalent,
  374. only_connected_subgraphs,
  375. user_callback);
  376. }
  377. // Variant of mcgregor_common_subgraphs with all default parameters
  378. template <typename GraphFirst,
  379. typename GraphSecond,
  380. typename SubGraphCallback>
  381. void mcgregor_common_subgraphs
  382. (const GraphFirst& graph1,
  383. const GraphSecond& graph2,
  384. bool only_connected_subgraphs,
  385. SubGraphCallback user_callback)
  386. {
  387. detail::mcgregor_common_subgraphs_internal_init
  388. (graph1, graph2,
  389. get(vertex_index, graph1), get(vertex_index, graph2),
  390. always_equivalent(), always_equivalent(),
  391. only_connected_subgraphs, user_callback);
  392. }
  393. // Named parameter variant of mcgregor_common_subgraphs
  394. template <typename GraphFirst,
  395. typename GraphSecond,
  396. typename SubGraphCallback,
  397. typename Param,
  398. typename Tag,
  399. typename Rest>
  400. void mcgregor_common_subgraphs
  401. (const GraphFirst& graph1,
  402. const GraphSecond& graph2,
  403. bool only_connected_subgraphs,
  404. SubGraphCallback user_callback,
  405. const bgl_named_params<Param, Tag, Rest>& params)
  406. {
  407. detail::mcgregor_common_subgraphs_internal_init
  408. (graph1, graph2,
  409. choose_const_pmap(get_param(params, vertex_index1),
  410. graph1, vertex_index),
  411. choose_const_pmap(get_param(params, vertex_index2),
  412. graph2, vertex_index),
  413. choose_param(get_param(params, edges_equivalent_t()),
  414. always_equivalent()),
  415. choose_param(get_param(params, vertices_equivalent_t()),
  416. always_equivalent()),
  417. only_connected_subgraphs, user_callback);
  418. }
  419. // ==========================================================================
  420. namespace detail {
  421. // Binary function object that intercepts subgraphs from
  422. // mcgregor_common_subgraphs_internal and maintains a cache of
  423. // unique subgraphs. The user callback is invoked for each unique
  424. // subgraph.
  425. template <typename GraphFirst,
  426. typename GraphSecond,
  427. typename VertexIndexMapFirst,
  428. typename VertexIndexMapSecond,
  429. typename SubGraphCallback>
  430. struct unique_subgraph_interceptor {
  431. typedef typename graph_traits<GraphFirst>::vertices_size_type
  432. VertexSizeFirst;
  433. typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
  434. VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
  435. typedef typename SubGraphTraits::correspondence_map_first_to_second_type
  436. CachedCorrespondenceMapFirstToSecond;
  437. typedef typename SubGraphTraits::correspondence_map_second_to_first_type
  438. CachedCorrespondenceMapSecondToFirst;
  439. typedef std::pair<VertexSizeFirst,
  440. std::pair<CachedCorrespondenceMapFirstToSecond,
  441. CachedCorrespondenceMapSecondToFirst> > SubGraph;
  442. typedef std::vector<SubGraph> SubGraphList;
  443. unique_subgraph_interceptor(const GraphFirst& graph1,
  444. const GraphSecond& graph2,
  445. const VertexIndexMapFirst vindex_map1,
  446. const VertexIndexMapSecond vindex_map2,
  447. SubGraphCallback user_callback) :
  448. m_graph1(graph1), m_graph2(graph2),
  449. m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
  450. m_subgraphs(make_shared<SubGraphList>()),
  451. m_user_callback(user_callback) { }
  452. template <typename CorrespondenceMapFirstToSecond,
  453. typename CorrespondenceMapSecondToFirst>
  454. bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
  455. CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
  456. VertexSizeFirst subgraph_size) {
  457. for (typename SubGraphList::const_iterator
  458. subgraph_iter = m_subgraphs->begin();
  459. subgraph_iter != m_subgraphs->end();
  460. ++subgraph_iter) {
  461. SubGraph subgraph_cached = *subgraph_iter;
  462. // Compare subgraph sizes
  463. if (subgraph_size != subgraph_cached.first) {
  464. continue;
  465. }
  466. if (!are_property_maps_different(correspondence_map_1_to_2,
  467. subgraph_cached.second.first,
  468. m_graph1)) {
  469. // New subgraph is a duplicate
  470. return (true);
  471. }
  472. }
  473. // Subgraph is unique, so make a cached copy
  474. CachedCorrespondenceMapFirstToSecond
  475. new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
  476. (num_vertices(m_graph1), m_vindex_map1);
  477. CachedCorrespondenceMapSecondToFirst
  478. new_subgraph_2_to_1 = CorrespondenceMapSecondToFirst
  479. (num_vertices(m_graph2), m_vindex_map2);
  480. BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
  481. put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
  482. }
  483. BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
  484. put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
  485. }
  486. m_subgraphs->push_back(std::make_pair(subgraph_size,
  487. std::make_pair(new_subgraph_1_to_2,
  488. new_subgraph_2_to_1)));
  489. return (m_user_callback(correspondence_map_1_to_2,
  490. correspondence_map_2_to_1,
  491. subgraph_size));
  492. }
  493. private:
  494. const GraphFirst& m_graph1;
  495. const GraphFirst& m_graph2;
  496. const VertexIndexMapFirst m_vindex_map1;
  497. const VertexIndexMapSecond m_vindex_map2;
  498. shared_ptr<SubGraphList> m_subgraphs;
  499. SubGraphCallback m_user_callback;
  500. };
  501. } // namespace detail
  502. // Enumerates all unique common subgraphs between graph1 and graph2.
  503. // The user callback is invoked for each unique subgraph as they are
  504. // discovered.
  505. template <typename GraphFirst,
  506. typename GraphSecond,
  507. typename VertexIndexMapFirst,
  508. typename VertexIndexMapSecond,
  509. typename EdgeEquivalencePredicate,
  510. typename VertexEquivalencePredicate,
  511. typename SubGraphCallback>
  512. void mcgregor_common_subgraphs_unique
  513. (const GraphFirst& graph1,
  514. const GraphSecond& graph2,
  515. const VertexIndexMapFirst vindex_map1,
  516. const VertexIndexMapSecond vindex_map2,
  517. EdgeEquivalencePredicate edges_equivalent,
  518. VertexEquivalencePredicate vertices_equivalent,
  519. bool only_connected_subgraphs,
  520. SubGraphCallback user_callback)
  521. {
  522. detail::unique_subgraph_interceptor<GraphFirst, GraphSecond,
  523. VertexIndexMapFirst, VertexIndexMapSecond,
  524. SubGraphCallback> unique_callback
  525. (graph1, graph2,
  526. vindex_map1, vindex_map2,
  527. user_callback);
  528. detail::mcgregor_common_subgraphs_internal_init
  529. (graph1, graph2,
  530. vindex_map1, vindex_map2,
  531. edges_equivalent, vertices_equivalent,
  532. only_connected_subgraphs, unique_callback);
  533. }
  534. // Variant of mcgregor_common_subgraphs_unique with all default
  535. // parameters.
  536. template <typename GraphFirst,
  537. typename GraphSecond,
  538. typename SubGraphCallback>
  539. void mcgregor_common_subgraphs_unique
  540. (const GraphFirst& graph1,
  541. const GraphSecond& graph2,
  542. bool only_connected_subgraphs,
  543. SubGraphCallback user_callback)
  544. {
  545. mcgregor_common_subgraphs_unique
  546. (graph1, graph2,
  547. get(vertex_index, graph1), get(vertex_index, graph2),
  548. always_equivalent(), always_equivalent(),
  549. only_connected_subgraphs, user_callback);
  550. }
  551. // Named parameter variant of mcgregor_common_subgraphs_unique
  552. template <typename GraphFirst,
  553. typename GraphSecond,
  554. typename SubGraphCallback,
  555. typename Param,
  556. typename Tag,
  557. typename Rest>
  558. void mcgregor_common_subgraphs_unique
  559. (const GraphFirst& graph1,
  560. const GraphSecond& graph2,
  561. bool only_connected_subgraphs,
  562. SubGraphCallback user_callback,
  563. const bgl_named_params<Param, Tag, Rest>& params)
  564. {
  565. mcgregor_common_subgraphs_unique
  566. (graph1, graph2,
  567. choose_const_pmap(get_param(params, vertex_index1),
  568. graph1, vertex_index),
  569. choose_const_pmap(get_param(params, vertex_index2),
  570. graph2, vertex_index),
  571. choose_param(get_param(params, edges_equivalent_t()),
  572. always_equivalent()),
  573. choose_param(get_param(params, vertices_equivalent_t()),
  574. always_equivalent()),
  575. only_connected_subgraphs, user_callback);
  576. }
  577. // ==========================================================================
  578. namespace detail {
  579. // Binary function object that intercepts subgraphs from
  580. // mcgregor_common_subgraphs_internal and maintains a cache of the
  581. // largest subgraphs.
  582. template <typename GraphFirst,
  583. typename GraphSecond,
  584. typename VertexIndexMapFirst,
  585. typename VertexIndexMapSecond,
  586. typename SubGraphCallback>
  587. struct maximum_subgraph_interceptor {
  588. typedef typename graph_traits<GraphFirst>::vertices_size_type
  589. VertexSizeFirst;
  590. typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
  591. VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
  592. typedef typename SubGraphTraits::correspondence_map_first_to_second_type
  593. CachedCorrespondenceMapFirstToSecond;
  594. typedef typename SubGraphTraits::correspondence_map_second_to_first_type
  595. CachedCorrespondenceMapSecondToFirst;
  596. typedef std::pair<VertexSizeFirst,
  597. std::pair<CachedCorrespondenceMapFirstToSecond,
  598. CachedCorrespondenceMapSecondToFirst> > SubGraph;
  599. typedef std::vector<SubGraph> SubGraphList;
  600. maximum_subgraph_interceptor(const GraphFirst& graph1,
  601. const GraphSecond& graph2,
  602. const VertexIndexMapFirst vindex_map1,
  603. const VertexIndexMapSecond vindex_map2,
  604. SubGraphCallback user_callback) :
  605. m_graph1(graph1), m_graph2(graph2),
  606. m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
  607. m_subgraphs(make_shared<SubGraphList>()),
  608. m_largest_size_so_far(make_shared<VertexSizeFirst>(0)),
  609. m_user_callback(user_callback) { }
  610. template <typename CorrespondenceMapFirstToSecond,
  611. typename CorrespondenceMapSecondToFirst>
  612. bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
  613. CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
  614. VertexSizeFirst subgraph_size) {
  615. if (subgraph_size > *m_largest_size_so_far) {
  616. m_subgraphs->clear();
  617. *m_largest_size_so_far = subgraph_size;
  618. }
  619. if (subgraph_size == *m_largest_size_so_far) {
  620. // Make a cached copy
  621. CachedCorrespondenceMapFirstToSecond
  622. new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
  623. (num_vertices(m_graph1), m_vindex_map1);
  624. CachedCorrespondenceMapSecondToFirst
  625. new_subgraph_2_to_1 = CachedCorrespondenceMapSecondToFirst
  626. (num_vertices(m_graph2), m_vindex_map2);
  627. BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
  628. put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
  629. }
  630. BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
  631. put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
  632. }
  633. m_subgraphs->push_back(std::make_pair(subgraph_size,
  634. std::make_pair(new_subgraph_1_to_2,
  635. new_subgraph_2_to_1)));
  636. }
  637. return (true);
  638. }
  639. void output_subgraphs() {
  640. for (typename SubGraphList::const_iterator
  641. subgraph_iter = m_subgraphs->begin();
  642. subgraph_iter != m_subgraphs->end();
  643. ++subgraph_iter) {
  644. SubGraph subgraph_cached = *subgraph_iter;
  645. m_user_callback(subgraph_cached.second.first,
  646. subgraph_cached.second.second,
  647. subgraph_cached.first);
  648. }
  649. }
  650. private:
  651. const GraphFirst& m_graph1;
  652. const GraphFirst& m_graph2;
  653. const VertexIndexMapFirst m_vindex_map1;
  654. const VertexIndexMapSecond m_vindex_map2;
  655. shared_ptr<SubGraphList> m_subgraphs;
  656. shared_ptr<VertexSizeFirst> m_largest_size_so_far;
  657. SubGraphCallback m_user_callback;
  658. };
  659. } // namespace detail
  660. // Enumerates the largest common subgraphs found between graph1
  661. // and graph2. Note that the ENTIRE search space is explored before
  662. // user_callback is actually invoked.
  663. template <typename GraphFirst,
  664. typename GraphSecond,
  665. typename VertexIndexMapFirst,
  666. typename VertexIndexMapSecond,
  667. typename EdgeEquivalencePredicate,
  668. typename VertexEquivalencePredicate,
  669. typename SubGraphCallback>
  670. void mcgregor_common_subgraphs_maximum
  671. (const GraphFirst& graph1,
  672. const GraphSecond& graph2,
  673. const VertexIndexMapFirst vindex_map1,
  674. const VertexIndexMapSecond vindex_map2,
  675. EdgeEquivalencePredicate edges_equivalent,
  676. VertexEquivalencePredicate vertices_equivalent,
  677. bool only_connected_subgraphs,
  678. SubGraphCallback user_callback)
  679. {
  680. detail::maximum_subgraph_interceptor<GraphFirst, GraphSecond,
  681. VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback>
  682. max_interceptor
  683. (graph1, graph2, vindex_map1, vindex_map2, user_callback);
  684. detail::mcgregor_common_subgraphs_internal_init
  685. (graph1, graph2,
  686. vindex_map1, vindex_map2,
  687. edges_equivalent, vertices_equivalent,
  688. only_connected_subgraphs, max_interceptor);
  689. // Only output the largest subgraphs
  690. max_interceptor.output_subgraphs();
  691. }
  692. // Variant of mcgregor_common_subgraphs_maximum with all default
  693. // parameters.
  694. template <typename GraphFirst,
  695. typename GraphSecond,
  696. typename SubGraphCallback>
  697. void mcgregor_common_subgraphs_maximum
  698. (const GraphFirst& graph1,
  699. const GraphSecond& graph2,
  700. bool only_connected_subgraphs,
  701. SubGraphCallback user_callback)
  702. {
  703. mcgregor_common_subgraphs_maximum
  704. (graph1, graph2,
  705. get(vertex_index, graph1), get(vertex_index, graph2),
  706. always_equivalent(), always_equivalent(),
  707. only_connected_subgraphs, user_callback);
  708. }
  709. // Named parameter variant of mcgregor_common_subgraphs_maximum
  710. template <typename GraphFirst,
  711. typename GraphSecond,
  712. typename SubGraphCallback,
  713. typename Param,
  714. typename Tag,
  715. typename Rest>
  716. void mcgregor_common_subgraphs_maximum
  717. (const GraphFirst& graph1,
  718. const GraphSecond& graph2,
  719. bool only_connected_subgraphs,
  720. SubGraphCallback user_callback,
  721. const bgl_named_params<Param, Tag, Rest>& params)
  722. {
  723. mcgregor_common_subgraphs_maximum
  724. (graph1, graph2,
  725. choose_const_pmap(get_param(params, vertex_index1),
  726. graph1, vertex_index),
  727. choose_const_pmap(get_param(params, vertex_index2),
  728. graph2, vertex_index),
  729. choose_param(get_param(params, edges_equivalent_t()),
  730. always_equivalent()),
  731. choose_param(get_param(params, vertices_equivalent_t()),
  732. always_equivalent()),
  733. only_connected_subgraphs, user_callback);
  734. }
  735. // ==========================================================================
  736. namespace detail {
  737. // Binary function object that intercepts subgraphs from
  738. // mcgregor_common_subgraphs_internal and maintains a cache of the
  739. // largest, unique subgraphs.
  740. template <typename GraphFirst,
  741. typename GraphSecond,
  742. typename VertexIndexMapFirst,
  743. typename VertexIndexMapSecond,
  744. typename SubGraphCallback>
  745. struct unique_maximum_subgraph_interceptor {
  746. typedef typename graph_traits<GraphFirst>::vertices_size_type
  747. VertexSizeFirst;
  748. typedef mcgregor_common_subgraph_traits<GraphFirst, GraphSecond,
  749. VertexIndexMapFirst, VertexIndexMapSecond> SubGraphTraits;
  750. typedef typename SubGraphTraits::correspondence_map_first_to_second_type
  751. CachedCorrespondenceMapFirstToSecond;
  752. typedef typename SubGraphTraits::correspondence_map_second_to_first_type
  753. CachedCorrespondenceMapSecondToFirst;
  754. typedef std::pair<VertexSizeFirst,
  755. std::pair<CachedCorrespondenceMapFirstToSecond,
  756. CachedCorrespondenceMapSecondToFirst> > SubGraph;
  757. typedef std::vector<SubGraph> SubGraphList;
  758. unique_maximum_subgraph_interceptor(const GraphFirst& graph1,
  759. const GraphSecond& graph2,
  760. const VertexIndexMapFirst vindex_map1,
  761. const VertexIndexMapSecond vindex_map2,
  762. SubGraphCallback user_callback) :
  763. m_graph1(graph1), m_graph2(graph2),
  764. m_vindex_map1(vindex_map1), m_vindex_map2(vindex_map2),
  765. m_subgraphs(make_shared<SubGraphList>()),
  766. m_largest_size_so_far(make_shared<VertexSizeFirst>(0)),
  767. m_user_callback(user_callback) { }
  768. template <typename CorrespondenceMapFirstToSecond,
  769. typename CorrespondenceMapSecondToFirst>
  770. bool operator()(CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
  771. CorrespondenceMapSecondToFirst correspondence_map_2_to_1,
  772. VertexSizeFirst subgraph_size) {
  773. if (subgraph_size > *m_largest_size_so_far) {
  774. m_subgraphs->clear();
  775. *m_largest_size_so_far = subgraph_size;
  776. }
  777. if (subgraph_size == *m_largest_size_so_far) {
  778. // Check if subgraph is unique
  779. for (typename SubGraphList::const_iterator
  780. subgraph_iter = m_subgraphs->begin();
  781. subgraph_iter != m_subgraphs->end();
  782. ++subgraph_iter) {
  783. SubGraph subgraph_cached = *subgraph_iter;
  784. if (!are_property_maps_different(correspondence_map_1_to_2,
  785. subgraph_cached.second.first,
  786. m_graph1)) {
  787. // New subgraph is a duplicate
  788. return (true);
  789. }
  790. }
  791. // Subgraph is unique, so make a cached copy
  792. CachedCorrespondenceMapFirstToSecond
  793. new_subgraph_1_to_2 = CachedCorrespondenceMapFirstToSecond
  794. (num_vertices(m_graph1), m_vindex_map1);
  795. CachedCorrespondenceMapSecondToFirst
  796. new_subgraph_2_to_1 = CachedCorrespondenceMapSecondToFirst
  797. (num_vertices(m_graph2), m_vindex_map2);
  798. BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) {
  799. put(new_subgraph_1_to_2, vertex1, get(correspondence_map_1_to_2, vertex1));
  800. }
  801. BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) {
  802. put(new_subgraph_2_to_1, vertex2, get(correspondence_map_2_to_1, vertex2));
  803. }
  804. m_subgraphs->push_back(std::make_pair(subgraph_size,
  805. std::make_pair(new_subgraph_1_to_2,
  806. new_subgraph_2_to_1)));
  807. }
  808. return (true);
  809. }
  810. void output_subgraphs() {
  811. for (typename SubGraphList::const_iterator
  812. subgraph_iter = m_subgraphs->begin();
  813. subgraph_iter != m_subgraphs->end();
  814. ++subgraph_iter) {
  815. SubGraph subgraph_cached = *subgraph_iter;
  816. m_user_callback(subgraph_cached.second.first,
  817. subgraph_cached.second.second,
  818. subgraph_cached.first);
  819. }
  820. }
  821. private:
  822. const GraphFirst& m_graph1;
  823. const GraphFirst& m_graph2;
  824. const VertexIndexMapFirst m_vindex_map1;
  825. const VertexIndexMapSecond m_vindex_map2;
  826. shared_ptr<SubGraphList> m_subgraphs;
  827. shared_ptr<VertexSizeFirst> m_largest_size_so_far;
  828. SubGraphCallback m_user_callback;
  829. };
  830. } // namespace detail
  831. // Enumerates the largest, unique common subgraphs found between
  832. // graph1 and graph2. Note that the ENTIRE search space is explored
  833. // before user_callback is actually invoked.
  834. template <typename GraphFirst,
  835. typename GraphSecond,
  836. typename VertexIndexMapFirst,
  837. typename VertexIndexMapSecond,
  838. typename EdgeEquivalencePredicate,
  839. typename VertexEquivalencePredicate,
  840. typename SubGraphCallback>
  841. void mcgregor_common_subgraphs_maximum_unique
  842. (const GraphFirst& graph1,
  843. const GraphSecond& graph2,
  844. const VertexIndexMapFirst vindex_map1,
  845. const VertexIndexMapSecond vindex_map2,
  846. EdgeEquivalencePredicate edges_equivalent,
  847. VertexEquivalencePredicate vertices_equivalent,
  848. bool only_connected_subgraphs,
  849. SubGraphCallback user_callback)
  850. {
  851. detail::unique_maximum_subgraph_interceptor<GraphFirst, GraphSecond,
  852. VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback>
  853. unique_max_interceptor
  854. (graph1, graph2, vindex_map1, vindex_map2, user_callback);
  855. detail::mcgregor_common_subgraphs_internal_init
  856. (graph1, graph2,
  857. vindex_map1, vindex_map2,
  858. edges_equivalent, vertices_equivalent,
  859. only_connected_subgraphs, unique_max_interceptor);
  860. // Only output the largest, unique subgraphs
  861. unique_max_interceptor.output_subgraphs();
  862. }
  863. // Variant of mcgregor_common_subgraphs_maximum_unique with all default parameters
  864. template <typename GraphFirst,
  865. typename GraphSecond,
  866. typename SubGraphCallback>
  867. void mcgregor_common_subgraphs_maximum_unique
  868. (const GraphFirst& graph1,
  869. const GraphSecond& graph2,
  870. bool only_connected_subgraphs,
  871. SubGraphCallback user_callback)
  872. {
  873. mcgregor_common_subgraphs_maximum_unique
  874. (graph1, graph2,
  875. get(vertex_index, graph1), get(vertex_index, graph2),
  876. always_equivalent(), always_equivalent(),
  877. only_connected_subgraphs, user_callback);
  878. }
  879. // Named parameter variant of
  880. // mcgregor_common_subgraphs_maximum_unique
  881. template <typename GraphFirst,
  882. typename GraphSecond,
  883. typename SubGraphCallback,
  884. typename Param,
  885. typename Tag,
  886. typename Rest>
  887. void mcgregor_common_subgraphs_maximum_unique
  888. (const GraphFirst& graph1,
  889. const GraphSecond& graph2,
  890. bool only_connected_subgraphs,
  891. SubGraphCallback user_callback,
  892. const bgl_named_params<Param, Tag, Rest>& params)
  893. {
  894. mcgregor_common_subgraphs_maximum_unique
  895. (graph1, graph2,
  896. choose_const_pmap(get_param(params, vertex_index1),
  897. graph1, vertex_index),
  898. choose_const_pmap(get_param(params, vertex_index2),
  899. graph2, vertex_index),
  900. choose_param(get_param(params, edges_equivalent_t()),
  901. always_equivalent()),
  902. choose_param(get_param(params, vertices_equivalent_t()),
  903. always_equivalent()),
  904. only_connected_subgraphs, user_callback);
  905. }
  906. // ==========================================================================
  907. // Fills a membership map (vertex -> bool) using the information
  908. // present in correspondence_map_1_to_2. Every vertex in a
  909. // membership map will have a true value only if it is not
  910. // associated with a null vertex in the correspondence map.
  911. template <typename GraphSecond,
  912. typename GraphFirst,
  913. typename CorrespondenceMapFirstToSecond,
  914. typename MembershipMapFirst>
  915. void fill_membership_map
  916. (const GraphFirst& graph1,
  917. const CorrespondenceMapFirstToSecond correspondence_map_1_to_2,
  918. MembershipMapFirst membership_map1) {
  919. BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) {
  920. put(membership_map1, vertex1,
  921. get(correspondence_map_1_to_2, vertex1) != graph_traits<GraphSecond>::null_vertex());
  922. }
  923. }
  924. // Traits associated with a membership map filtered graph. Provided
  925. // for convenience to access graph and vertex filter types.
  926. template <typename Graph,
  927. typename MembershipMap>
  928. struct membership_filtered_graph_traits {
  929. typedef property_map_filter<MembershipMap> vertex_filter_type;
  930. typedef filtered_graph<Graph, keep_all, vertex_filter_type> graph_type;
  931. };
  932. // Returns a filtered sub-graph of graph whose edge and vertex
  933. // inclusion is dictated by membership_map.
  934. template <typename Graph,
  935. typename MembershipMap>
  936. typename membership_filtered_graph_traits<Graph, MembershipMap>::graph_type
  937. make_membership_filtered_graph
  938. (const Graph& graph,
  939. MembershipMap& membership_map) {
  940. typedef membership_filtered_graph_traits<Graph, MembershipMap> MFGTraits;
  941. typedef typename MFGTraits::graph_type MembershipFilteredGraph;
  942. typename MFGTraits::vertex_filter_type v_filter(membership_map);
  943. return (MembershipFilteredGraph(graph, keep_all(), v_filter));
  944. }
  945. } // namespace boost
  946. #endif // BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP