isomorphism.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. // Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_GRAPH_ISOMORPHISM_HPP
  7. #define BOOST_GRAPH_ISOMORPHISM_HPP
  8. #include <utility>
  9. #include <vector>
  10. #include <iterator>
  11. #include <algorithm>
  12. #include <boost/config.hpp>
  13. #include <boost/assert.hpp>
  14. #include <boost/smart_ptr.hpp>
  15. #include <boost/graph/depth_first_search.hpp>
  16. #include <boost/detail/algorithm.hpp>
  17. #include <boost/pending/indirect_cmp.hpp> // for make_indirect_pmap
  18. #include <boost/concept/assert.hpp>
  19. #ifndef BOOST_GRAPH_ITERATION_MACROS_HPP
  20. #define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file
  21. #include <boost/graph/iteration_macros.hpp>
  22. #endif
  23. namespace boost
  24. {
  25. namespace detail
  26. {
  27. template < typename Graph1, typename Graph2, typename IsoMapping,
  28. typename Invariant1, typename Invariant2, typename IndexMap1,
  29. typename IndexMap2 >
  30. class isomorphism_algo
  31. {
  32. typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_t;
  33. typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_t;
  34. typedef typename graph_traits< Graph1 >::edge_descriptor edge1_t;
  35. typedef typename graph_traits< Graph1 >::vertices_size_type size_type;
  36. typedef typename Invariant1::result_type invar1_value;
  37. typedef typename Invariant2::result_type invar2_value;
  38. const Graph1& G1;
  39. const Graph2& G2;
  40. IsoMapping f;
  41. Invariant1 invariant1;
  42. Invariant2 invariant2;
  43. std::size_t max_invariant;
  44. IndexMap1 index_map1;
  45. IndexMap2 index_map2;
  46. std::vector< vertex1_t > dfs_vertices;
  47. typedef typename std::vector< vertex1_t >::iterator vertex_iter;
  48. std::vector< int > dfs_num_vec;
  49. typedef safe_iterator_property_map<
  50. typename std::vector< int >::iterator, IndexMap1
  51. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  52. ,
  53. int, int&
  54. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  55. >
  56. DFSNumMap;
  57. DFSNumMap dfs_num;
  58. std::vector< edge1_t > ordered_edges;
  59. typedef typename std::vector< edge1_t >::iterator edge_iter;
  60. std::vector< char > in_S_vec;
  61. typedef safe_iterator_property_map<
  62. typename std::vector< char >::iterator, IndexMap2
  63. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  64. ,
  65. char, char&
  66. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  67. >
  68. InSMap;
  69. InSMap in_S;
  70. int num_edges_on_k;
  71. friend struct compare_multiplicity;
  72. struct compare_multiplicity
  73. {
  74. compare_multiplicity(Invariant1 invariant1, size_type* multiplicity)
  75. : invariant1(invariant1), multiplicity(multiplicity)
  76. {
  77. }
  78. bool operator()(const vertex1_t& x, const vertex1_t& y) const
  79. {
  80. return multiplicity[invariant1(x)]
  81. < multiplicity[invariant1(y)];
  82. }
  83. Invariant1 invariant1;
  84. size_type* multiplicity;
  85. };
  86. struct record_dfs_order : default_dfs_visitor
  87. {
  88. record_dfs_order(
  89. std::vector< vertex1_t >& v, std::vector< edge1_t >& e)
  90. : vertices(v), edges(e)
  91. {
  92. }
  93. void discover_vertex(vertex1_t v, const Graph1&) const
  94. {
  95. vertices.push_back(v);
  96. }
  97. void examine_edge(edge1_t e, const Graph1&) const
  98. {
  99. edges.push_back(e);
  100. }
  101. std::vector< vertex1_t >& vertices;
  102. std::vector< edge1_t >& edges;
  103. };
  104. struct edge_cmp
  105. {
  106. edge_cmp(const Graph1& G1, DFSNumMap dfs_num)
  107. : G1(G1), dfs_num(dfs_num)
  108. {
  109. }
  110. bool operator()(const edge1_t& e1, const edge1_t& e2) const
  111. {
  112. using namespace std;
  113. int u1 = dfs_num[source(e1, G1)], v1 = dfs_num[target(e1, G1)];
  114. int u2 = dfs_num[source(e2, G1)], v2 = dfs_num[target(e2, G1)];
  115. int m1 = (max)(u1, v1);
  116. int m2 = (max)(u2, v2);
  117. // lexicographical comparison
  118. return std::make_pair(m1, std::make_pair(u1, v1))
  119. < std::make_pair(m2, std::make_pair(u2, v2));
  120. }
  121. const Graph1& G1;
  122. DFSNumMap dfs_num;
  123. };
  124. public:
  125. isomorphism_algo(const Graph1& G1, const Graph2& G2, IsoMapping f,
  126. Invariant1 invariant1, Invariant2 invariant2,
  127. std::size_t max_invariant, IndexMap1 index_map1,
  128. IndexMap2 index_map2)
  129. : G1(G1)
  130. , G2(G2)
  131. , f(f)
  132. , invariant1(invariant1)
  133. , invariant2(invariant2)
  134. , max_invariant(max_invariant)
  135. , index_map1(index_map1)
  136. , index_map2(index_map2)
  137. {
  138. in_S_vec.resize(num_vertices(G1));
  139. in_S = make_safe_iterator_property_map(
  140. in_S_vec.begin(), in_S_vec.size(), index_map2
  141. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  142. ,
  143. in_S_vec.front()
  144. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  145. );
  146. }
  147. bool test_isomorphism()
  148. {
  149. // reset isomapping
  150. BGL_FORALL_VERTICES_T(v, G1, Graph1)
  151. f[v] = graph_traits< Graph2 >::null_vertex();
  152. {
  153. std::vector< invar1_value > invar1_array;
  154. BGL_FORALL_VERTICES_T(v, G1, Graph1)
  155. invar1_array.push_back(invariant1(v));
  156. sort(invar1_array);
  157. std::vector< invar2_value > invar2_array;
  158. BGL_FORALL_VERTICES_T(v, G2, Graph2)
  159. invar2_array.push_back(invariant2(v));
  160. sort(invar2_array);
  161. if (!equal(invar1_array, invar2_array))
  162. return false;
  163. }
  164. std::vector< vertex1_t > V_mult;
  165. BGL_FORALL_VERTICES_T(v, G1, Graph1)
  166. V_mult.push_back(v);
  167. {
  168. std::vector< size_type > multiplicity(max_invariant, 0);
  169. BGL_FORALL_VERTICES_T(v, G1, Graph1)
  170. ++multiplicity.at(invariant1(v));
  171. sort(
  172. V_mult, compare_multiplicity(invariant1, &multiplicity[0]));
  173. }
  174. std::vector< default_color_type > color_vec(num_vertices(G1));
  175. safe_iterator_property_map<
  176. std::vector< default_color_type >::iterator, IndexMap1
  177. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  178. ,
  179. default_color_type, default_color_type&
  180. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  181. >
  182. color_map(color_vec.begin(), color_vec.size(), index_map1);
  183. record_dfs_order dfs_visitor(dfs_vertices, ordered_edges);
  184. typedef color_traits< default_color_type > Color;
  185. for (vertex_iter u = V_mult.begin(); u != V_mult.end(); ++u)
  186. {
  187. if (color_map[*u] == Color::white())
  188. {
  189. dfs_visitor.start_vertex(*u, G1);
  190. depth_first_visit(G1, *u, dfs_visitor, color_map);
  191. }
  192. }
  193. // Create the dfs_num array and dfs_num_map
  194. dfs_num_vec.resize(num_vertices(G1));
  195. dfs_num = make_safe_iterator_property_map(
  196. dfs_num_vec.begin(), dfs_num_vec.size(), index_map1
  197. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  198. ,
  199. dfs_num_vec.front()
  200. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  201. );
  202. size_type n = 0;
  203. for (vertex_iter v = dfs_vertices.begin(); v != dfs_vertices.end();
  204. ++v)
  205. dfs_num[*v] = n++;
  206. sort(ordered_edges, edge_cmp(G1, dfs_num));
  207. int dfs_num_k = -1;
  208. return this->match(ordered_edges.begin(), dfs_num_k);
  209. }
  210. private:
  211. struct match_continuation
  212. {
  213. enum
  214. {
  215. pos_G2_vertex_loop,
  216. pos_fi_adj_loop,
  217. pos_dfs_num
  218. } position;
  219. typedef typename graph_traits< Graph2 >::vertex_iterator
  220. vertex_iterator;
  221. std::pair< vertex_iterator, vertex_iterator > G2_verts;
  222. typedef typename graph_traits< Graph2 >::adjacency_iterator
  223. adjacency_iterator;
  224. std::pair< adjacency_iterator, adjacency_iterator > fi_adj;
  225. edge_iter iter;
  226. int dfs_num_k;
  227. };
  228. bool match(edge_iter iter, int dfs_num_k)
  229. {
  230. std::vector< match_continuation > k;
  231. typedef typename graph_traits< Graph2 >::vertex_iterator
  232. vertex_iterator;
  233. std::pair< vertex_iterator, vertex_iterator > G2_verts(
  234. vertices(G2));
  235. typedef typename graph_traits< Graph2 >::adjacency_iterator
  236. adjacency_iterator;
  237. std::pair< adjacency_iterator, adjacency_iterator > fi_adj;
  238. vertex1_t i, j;
  239. recur:
  240. if (iter != ordered_edges.end())
  241. {
  242. i = source(*iter, G1);
  243. j = target(*iter, G1);
  244. if (dfs_num[i] > dfs_num_k)
  245. {
  246. G2_verts = vertices(G2);
  247. while (G2_verts.first != G2_verts.second)
  248. {
  249. {
  250. vertex2_t u = *G2_verts.first;
  251. vertex1_t kp1 = dfs_vertices[dfs_num_k + 1];
  252. if (invariant1(kp1) == invariant2(u)
  253. && in_S[u] == false)
  254. {
  255. {
  256. f[kp1] = u;
  257. in_S[u] = true;
  258. num_edges_on_k = 0;
  259. match_continuation new_k;
  260. new_k.position = match_continuation::
  261. pos_G2_vertex_loop;
  262. new_k.G2_verts = G2_verts;
  263. new_k.iter = iter;
  264. new_k.dfs_num_k = dfs_num_k;
  265. k.push_back(new_k);
  266. ++dfs_num_k;
  267. goto recur;
  268. }
  269. }
  270. }
  271. G2_loop_k:
  272. ++G2_verts.first;
  273. }
  274. }
  275. else if (dfs_num[j] > dfs_num_k)
  276. {
  277. {
  278. vertex1_t vk = dfs_vertices[dfs_num_k];
  279. num_edges_on_k -= count_if(adjacent_vertices(f[vk], G2),
  280. make_indirect_pmap(in_S));
  281. for (int jj = 0; jj < dfs_num_k; ++jj)
  282. {
  283. vertex1_t j = dfs_vertices[jj];
  284. num_edges_on_k
  285. -= count(adjacent_vertices(f[j], G2), f[vk]);
  286. }
  287. }
  288. if (num_edges_on_k != 0)
  289. goto return_point_false;
  290. fi_adj = adjacent_vertices(f[i], G2);
  291. while (fi_adj.first != fi_adj.second)
  292. {
  293. {
  294. vertex2_t v = *fi_adj.first;
  295. if (invariant2(v) == invariant1(j)
  296. && in_S[v] == false)
  297. {
  298. f[j] = v;
  299. in_S[v] = true;
  300. num_edges_on_k = 1;
  301. BOOST_USING_STD_MAX();
  302. int next_k
  303. = max BOOST_PREVENT_MACRO_SUBSTITUTION(
  304. dfs_num_k,
  305. max BOOST_PREVENT_MACRO_SUBSTITUTION(
  306. dfs_num[i], dfs_num[j]));
  307. match_continuation new_k;
  308. new_k.position
  309. = match_continuation::pos_fi_adj_loop;
  310. new_k.fi_adj = fi_adj;
  311. new_k.iter = iter;
  312. new_k.dfs_num_k = dfs_num_k;
  313. ++iter;
  314. dfs_num_k = next_k;
  315. k.push_back(new_k);
  316. goto recur;
  317. }
  318. }
  319. fi_adj_loop_k:
  320. ++fi_adj.first;
  321. }
  322. }
  323. else
  324. {
  325. if (container_contains(adjacent_vertices(f[i], G2), f[j]))
  326. {
  327. ++num_edges_on_k;
  328. match_continuation new_k;
  329. new_k.position = match_continuation::pos_dfs_num;
  330. k.push_back(new_k);
  331. ++iter;
  332. goto recur;
  333. }
  334. }
  335. }
  336. else
  337. goto return_point_true;
  338. goto return_point_false;
  339. {
  340. return_point_true:
  341. return true;
  342. return_point_false:
  343. if (k.empty())
  344. return false;
  345. const match_continuation& this_k = k.back();
  346. switch (this_k.position)
  347. {
  348. case match_continuation::pos_G2_vertex_loop:
  349. {
  350. G2_verts = this_k.G2_verts;
  351. iter = this_k.iter;
  352. dfs_num_k = this_k.dfs_num_k;
  353. k.pop_back();
  354. in_S[*G2_verts.first] = false;
  355. i = source(*iter, G1);
  356. j = target(*iter, G1);
  357. goto G2_loop_k;
  358. }
  359. case match_continuation::pos_fi_adj_loop:
  360. {
  361. fi_adj = this_k.fi_adj;
  362. iter = this_k.iter;
  363. dfs_num_k = this_k.dfs_num_k;
  364. k.pop_back();
  365. in_S[*fi_adj.first] = false;
  366. i = source(*iter, G1);
  367. j = target(*iter, G1);
  368. goto fi_adj_loop_k;
  369. }
  370. case match_continuation::pos_dfs_num:
  371. {
  372. k.pop_back();
  373. goto return_point_false;
  374. }
  375. default:
  376. {
  377. BOOST_ASSERT(!"Bad position");
  378. #ifdef UNDER_CE
  379. exit(-1);
  380. #else
  381. abort();
  382. #endif
  383. }
  384. }
  385. }
  386. }
  387. };
  388. template < typename Graph, typename InDegreeMap >
  389. void compute_in_degree(const Graph& g, InDegreeMap in_degree_map)
  390. {
  391. BGL_FORALL_VERTICES_T(v, g, Graph)
  392. put(in_degree_map, v, 0);
  393. BGL_FORALL_VERTICES_T(u, g, Graph)
  394. BGL_FORALL_ADJ_T(u, v, g, Graph)
  395. put(in_degree_map, v, get(in_degree_map, v) + 1);
  396. }
  397. } // namespace detail
  398. template < typename InDegreeMap, typename Graph > class degree_vertex_invariant
  399. {
  400. typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
  401. typedef typename graph_traits< Graph >::degree_size_type size_type;
  402. public:
  403. typedef vertex_t argument_type;
  404. typedef size_type result_type;
  405. degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g)
  406. : m_in_degree_map(in_degree_map)
  407. , m_max_vertex_in_degree(0)
  408. , m_max_vertex_out_degree(0)
  409. , m_g(g)
  410. {
  411. BGL_FORALL_VERTICES_T(v, g, Graph)
  412. {
  413. m_max_vertex_in_degree
  414. = (std::max)(m_max_vertex_in_degree, get(m_in_degree_map, v));
  415. m_max_vertex_out_degree
  416. = (std::max)(m_max_vertex_out_degree, out_degree(v, g));
  417. }
  418. }
  419. size_type operator()(vertex_t v) const
  420. {
  421. return (m_max_vertex_in_degree + 1) * out_degree(v, m_g)
  422. + get(m_in_degree_map, v);
  423. }
  424. // The largest possible vertex invariant number
  425. size_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const
  426. {
  427. return (m_max_vertex_in_degree + 1) * (m_max_vertex_out_degree + 1);
  428. }
  429. private:
  430. InDegreeMap m_in_degree_map;
  431. size_type m_max_vertex_in_degree;
  432. size_type m_max_vertex_out_degree;
  433. const Graph& m_g;
  434. };
  435. // Count actual number of vertices, even in filtered graphs.
  436. template < typename Graph > size_t count_vertices(const Graph& g)
  437. {
  438. size_t n = 0;
  439. BGL_FORALL_VERTICES_T(v, g, Graph)
  440. {
  441. (void)v;
  442. ++n;
  443. }
  444. return n;
  445. }
  446. template < typename Graph1, typename Graph2, typename IsoMapping,
  447. typename Invariant1, typename Invariant2, typename IndexMap1,
  448. typename IndexMap2 >
  449. bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f,
  450. Invariant1 invariant1, Invariant2 invariant2, std::size_t max_invariant,
  451. IndexMap1 index_map1, IndexMap2 index_map2)
  452. {
  453. // Graph requirements
  454. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph1 >));
  455. BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph1 >));
  456. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph2 >));
  457. // BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph2> ));
  458. typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_t;
  459. typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_t;
  460. typedef typename graph_traits< Graph1 >::vertices_size_type size_type;
  461. // Vertex invariant requirement
  462. BOOST_CONCEPT_ASSERT(
  463. (AdaptableUnaryFunctionConcept< Invariant1, size_type, vertex1_t >));
  464. BOOST_CONCEPT_ASSERT(
  465. (AdaptableUnaryFunctionConcept< Invariant2, size_type, vertex2_t >));
  466. // Property map requirements
  467. BOOST_CONCEPT_ASSERT(
  468. (ReadWritePropertyMapConcept< IsoMapping, vertex1_t >));
  469. typedef typename property_traits< IsoMapping >::value_type IsoMappingValue;
  470. BOOST_STATIC_ASSERT((is_convertible< IsoMappingValue, vertex2_t >::value));
  471. BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< IndexMap1, vertex1_t >));
  472. typedef typename property_traits< IndexMap1 >::value_type IndexMap1Value;
  473. BOOST_STATIC_ASSERT((is_convertible< IndexMap1Value, size_type >::value));
  474. BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< IndexMap2, vertex2_t >));
  475. typedef typename property_traits< IndexMap2 >::value_type IndexMap2Value;
  476. BOOST_STATIC_ASSERT((is_convertible< IndexMap2Value, size_type >::value));
  477. if (count_vertices(G1) != count_vertices(G2))
  478. return false;
  479. if (count_vertices(G1) == 0 && count_vertices(G2) == 0)
  480. return true;
  481. detail::isomorphism_algo< Graph1, Graph2, IsoMapping, Invariant1,
  482. Invariant2, IndexMap1, IndexMap2 >
  483. algo(G1, G2, f, invariant1, invariant2, max_invariant, index_map1,
  484. index_map2);
  485. return algo.test_isomorphism();
  486. }
  487. namespace detail
  488. {
  489. template < typename Graph1, typename Graph2, typename IsoMapping,
  490. typename IndexMap1, typename IndexMap2, typename P, typename T,
  491. typename R >
  492. bool isomorphism_impl(const Graph1& G1, const Graph2& G2, IsoMapping f,
  493. IndexMap1 index_map1, IndexMap2 index_map2,
  494. const bgl_named_params< P, T, R >& params)
  495. {
  496. std::vector< std::size_t > in_degree1_vec(num_vertices(G1));
  497. typedef safe_iterator_property_map<
  498. std::vector< std::size_t >::iterator, IndexMap1
  499. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  500. ,
  501. std::size_t, std::size_t&
  502. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  503. >
  504. InDeg1;
  505. InDeg1 in_degree1(
  506. in_degree1_vec.begin(), in_degree1_vec.size(), index_map1);
  507. compute_in_degree(G1, in_degree1);
  508. std::vector< std::size_t > in_degree2_vec(num_vertices(G2));
  509. typedef safe_iterator_property_map<
  510. std::vector< std::size_t >::iterator, IndexMap2
  511. #ifdef BOOST_NO_STD_ITERATOR_TRAITS
  512. ,
  513. std::size_t, std::size_t&
  514. #endif /* BOOST_NO_STD_ITERATOR_TRAITS */
  515. >
  516. InDeg2;
  517. InDeg2 in_degree2(
  518. in_degree2_vec.begin(), in_degree2_vec.size(), index_map2);
  519. compute_in_degree(G2, in_degree2);
  520. degree_vertex_invariant< InDeg1, Graph1 > invariant1(in_degree1, G1);
  521. degree_vertex_invariant< InDeg2, Graph2 > invariant2(in_degree2, G2);
  522. return isomorphism(G1, G2, f,
  523. choose_param(get_param(params, vertex_invariant1_t()), invariant1),
  524. choose_param(get_param(params, vertex_invariant2_t()), invariant2),
  525. choose_param(get_param(params, vertex_max_invariant_t()),
  526. (invariant2.max)()),
  527. index_map1, index_map2);
  528. }
  529. template < typename G, typename Index > struct make_degree_invariant
  530. {
  531. const G& g;
  532. const Index& index;
  533. make_degree_invariant(const G& g, const Index& index)
  534. : g(g), index(index)
  535. {
  536. }
  537. typedef typename boost::graph_traits< G >::degree_size_type
  538. degree_size_type;
  539. typedef shared_array_property_map< degree_size_type, Index >
  540. prop_map_type;
  541. typedef degree_vertex_invariant< prop_map_type, G > result_type;
  542. result_type operator()() const
  543. {
  544. prop_map_type pm = make_shared_array_property_map(
  545. num_vertices(g), degree_size_type(), index);
  546. compute_in_degree(g, pm);
  547. return result_type(pm, g);
  548. }
  549. };
  550. } // namespace detail
  551. namespace graph
  552. {
  553. namespace detail
  554. {
  555. template < typename Graph1, typename Graph2 > struct isomorphism_impl
  556. {
  557. typedef bool result_type;
  558. typedef result_type type;
  559. template < typename ArgPack >
  560. bool operator()(const Graph1& g1, const Graph2& g2,
  561. const ArgPack& arg_pack) const
  562. {
  563. using namespace boost::graph::keywords;
  564. typedef typename boost::detail::override_const_property_result<
  565. ArgPack, tag::vertex_index1_map, boost::vertex_index_t,
  566. Graph1 >::type index1_map_type;
  567. typedef typename boost::detail::override_const_property_result<
  568. ArgPack, tag::vertex_index2_map, boost::vertex_index_t,
  569. Graph2 >::type index2_map_type;
  570. index1_map_type index1_map
  571. = boost::detail::override_const_property(
  572. arg_pack, _vertex_index1_map, g1, boost::vertex_index);
  573. index2_map_type index2_map
  574. = boost::detail::override_const_property(
  575. arg_pack, _vertex_index2_map, g2, boost::vertex_index);
  576. typedef typename graph_traits< Graph2 >::vertex_descriptor
  577. vertex2_t;
  578. typename std::vector< vertex2_t >::size_type n
  579. = (typename std::vector< vertex2_t >::size_type)
  580. num_vertices(g1);
  581. std::vector< vertex2_t > f(n);
  582. typename boost::parameter::lazy_binding< ArgPack,
  583. tag::vertex_invariant1,
  584. boost::detail::make_degree_invariant< Graph1,
  585. index1_map_type > >::type invariant1
  586. = arg_pack[_vertex_invariant1
  587. || boost::detail::make_degree_invariant< Graph1,
  588. index1_map_type >(g1, index1_map)];
  589. typename boost::parameter::lazy_binding< ArgPack,
  590. tag::vertex_invariant2,
  591. boost::detail::make_degree_invariant< Graph2,
  592. index2_map_type > >::type invariant2
  593. = arg_pack[_vertex_invariant2
  594. || boost::detail::make_degree_invariant< Graph2,
  595. index2_map_type >(g2, index2_map)];
  596. return boost::isomorphism(g1, g2,
  597. choose_param(
  598. arg_pack[_isomorphism_map | boost::param_not_found()],
  599. make_shared_array_property_map(
  600. num_vertices(g1), vertex2_t(), index1_map)),
  601. invariant1, invariant2,
  602. arg_pack[_vertex_max_invariant | (invariant2.max)()],
  603. index1_map, index2_map);
  604. }
  605. };
  606. }
  607. BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(isomorphism, 2, 6)
  608. }
  609. // Named parameter interface
  610. BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(isomorphism, 2)
  611. // Verify that the given mapping iso_map from the vertices of g1 to the
  612. // vertices of g2 describes an isomorphism.
  613. // Note: this could be made much faster by specializing based on the graph
  614. // concepts modeled, but since we're verifying an O(n^(lg n)) algorithm,
  615. // O(n^4) won't hurt us.
  616. template < typename Graph1, typename Graph2, typename IsoMap >
  617. inline bool verify_isomorphism(
  618. const Graph1& g1, const Graph2& g2, IsoMap iso_map)
  619. {
  620. #if 0
  621. // problematic for filtered_graph!
  622. if (num_vertices(g1) != num_vertices(g2) || num_edges(g1) != num_edges(g2))
  623. return false;
  624. #endif
  625. BGL_FORALL_EDGES_T(e1, g1, Graph1)
  626. {
  627. bool found_edge = false;
  628. BGL_FORALL_EDGES_T(e2, g2, Graph2)
  629. {
  630. if (source(e2, g2) == get(iso_map, source(e1, g1))
  631. && target(e2, g2) == get(iso_map, target(e1, g1)))
  632. {
  633. found_edge = true;
  634. }
  635. }
  636. if (!found_edge)
  637. return false;
  638. }
  639. return true;
  640. }
  641. } // namespace boost
  642. #ifdef BOOST_ISO_INCLUDED_ITER_MACROS
  643. #undef BOOST_ISO_INCLUDED_ITER_MACROS
  644. #include <boost/graph/iteration_macros_undef.hpp>
  645. #endif
  646. #endif // BOOST_GRAPH_ISOMORPHISM_HPP