max_cardinality_matching.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. //=======================================================================
  2. // Copyright (c) 2005 Aaron Windsor
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. //=======================================================================
  9. #ifndef BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
  10. #define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
  11. #include <vector>
  12. #include <list>
  13. #include <deque>
  14. #include <algorithm> // for std::sort and std::stable_sort
  15. #include <utility> // for std::pair
  16. #include <boost/property_map/property_map.hpp>
  17. #include <boost/graph/graph_traits.hpp>
  18. #include <boost/graph/visitors.hpp>
  19. #include <boost/graph/depth_first_search.hpp>
  20. #include <boost/graph/filtered_graph.hpp>
  21. #include <boost/pending/disjoint_sets.hpp>
  22. #include <boost/assert.hpp>
  23. namespace boost
  24. {
  25. namespace graph
  26. {
  27. namespace detail
  28. {
  29. enum VERTEX_STATE
  30. {
  31. V_EVEN,
  32. V_ODD,
  33. V_UNREACHED
  34. };
  35. }
  36. } // end namespace graph::detail
  37. template < typename Graph, typename MateMap, typename VertexIndexMap >
  38. typename graph_traits< Graph >::vertices_size_type matching_size(
  39. const Graph& g, MateMap mate, VertexIndexMap vm)
  40. {
  41. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  42. typedef
  43. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
  44. typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
  45. v_size_t size_of_matching = 0;
  46. vertex_iterator_t vi, vi_end;
  47. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  48. {
  49. vertex_descriptor_t v = *vi;
  50. if (get(mate, v) != graph_traits< Graph >::null_vertex()
  51. && get(vm, v) < get(vm, get(mate, v)))
  52. ++size_of_matching;
  53. }
  54. return size_of_matching;
  55. }
  56. template < typename Graph, typename MateMap >
  57. inline typename graph_traits< Graph >::vertices_size_type matching_size(
  58. const Graph& g, MateMap mate)
  59. {
  60. return matching_size(g, mate, get(vertex_index, g));
  61. }
  62. template < typename Graph, typename MateMap, typename VertexIndexMap >
  63. bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap)
  64. {
  65. typedef
  66. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
  67. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  68. vertex_iterator_t vi, vi_end;
  69. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  70. {
  71. vertex_descriptor_t v = *vi;
  72. if (get(mate, v) != graph_traits< Graph >::null_vertex()
  73. && v != get(mate, get(mate, v)))
  74. return false;
  75. }
  76. return true;
  77. }
  78. template < typename Graph, typename MateMap >
  79. inline bool is_a_matching(const Graph& g, MateMap mate)
  80. {
  81. return is_a_matching(g, mate, get(vertex_index, g));
  82. }
  83. //***************************************************************************
  84. //***************************************************************************
  85. // Maximum Cardinality Matching Functors
  86. //***************************************************************************
  87. //***************************************************************************
  88. template < typename Graph, typename MateMap,
  89. typename VertexIndexMap = dummy_property_map >
  90. struct no_augmenting_path_finder
  91. {
  92. no_augmenting_path_finder(const Graph&, MateMap, VertexIndexMap) {}
  93. inline bool augment_matching() { return false; }
  94. template < typename PropertyMap > void get_current_matching(PropertyMap) {}
  95. };
  96. template < typename Graph, typename MateMap, typename VertexIndexMap >
  97. class edmonds_augmenting_path_finder
  98. {
  99. // This implementation of Edmonds' matching algorithm closely
  100. // follows Tarjan's description of the algorithm in "Data
  101. // Structures and Network Algorithms."
  102. public:
  103. // generates the type of an iterator property map from vertices to type X
  104. template < typename X > struct map_vertex_to_
  105. {
  106. typedef boost::iterator_property_map<
  107. typename std::vector< X >::iterator, VertexIndexMap >
  108. type;
  109. };
  110. typedef
  111. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
  112. typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_t >
  113. vertex_pair_t;
  114. typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
  115. typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
  116. typedef typename graph_traits< Graph >::edges_size_type e_size_t;
  117. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  118. typedef
  119. typename graph_traits< Graph >::out_edge_iterator out_edge_iterator_t;
  120. typedef typename std::deque< vertex_descriptor_t > vertex_list_t;
  121. typedef typename std::vector< edge_descriptor_t > edge_list_t;
  122. typedef typename map_vertex_to_< vertex_descriptor_t >::type
  123. vertex_to_vertex_map_t;
  124. typedef typename map_vertex_to_< int >::type vertex_to_int_map_t;
  125. typedef typename map_vertex_to_< vertex_pair_t >::type
  126. vertex_to_vertex_pair_map_t;
  127. typedef typename map_vertex_to_< v_size_t >::type vertex_to_vsize_map_t;
  128. typedef typename map_vertex_to_< e_size_t >::type vertex_to_esize_map_t;
  129. edmonds_augmenting_path_finder(
  130. const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm)
  131. : g(arg_g)
  132. , vm(arg_vm)
  133. , n_vertices(num_vertices(arg_g))
  134. ,
  135. mate_vector(n_vertices)
  136. , ancestor_of_v_vector(n_vertices)
  137. , ancestor_of_w_vector(n_vertices)
  138. , vertex_state_vector(n_vertices)
  139. , origin_vector(n_vertices)
  140. , pred_vector(n_vertices)
  141. , bridge_vector(n_vertices)
  142. , ds_parent_vector(n_vertices)
  143. , ds_rank_vector(n_vertices)
  144. ,
  145. mate(mate_vector.begin(), vm)
  146. , ancestor_of_v(ancestor_of_v_vector.begin(), vm)
  147. , ancestor_of_w(ancestor_of_w_vector.begin(), vm)
  148. , vertex_state(vertex_state_vector.begin(), vm)
  149. , origin(origin_vector.begin(), vm)
  150. , pred(pred_vector.begin(), vm)
  151. , bridge(bridge_vector.begin(), vm)
  152. , ds_parent_map(ds_parent_vector.begin(), vm)
  153. , ds_rank_map(ds_rank_vector.begin(), vm)
  154. ,
  155. ds(ds_rank_map, ds_parent_map)
  156. {
  157. vertex_iterator_t vi, vi_end;
  158. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  159. mate[*vi] = get(arg_mate, *vi);
  160. }
  161. bool augment_matching()
  162. {
  163. // As an optimization, some of these values can be saved from one
  164. // iteration to the next instead of being re-initialized each
  165. // iteration, allowing for "lazy blossom expansion." This is not
  166. // currently implemented.
  167. e_size_t timestamp = 0;
  168. even_edges.clear();
  169. vertex_iterator_t vi, vi_end;
  170. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  171. {
  172. vertex_descriptor_t u = *vi;
  173. origin[u] = u;
  174. pred[u] = u;
  175. ancestor_of_v[u] = 0;
  176. ancestor_of_w[u] = 0;
  177. ds.make_set(u);
  178. if (mate[u] == graph_traits< Graph >::null_vertex())
  179. {
  180. vertex_state[u] = graph::detail::V_EVEN;
  181. out_edge_iterator_t ei, ei_end;
  182. for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end;
  183. ++ei)
  184. {
  185. if (target(*ei, g) != u)
  186. {
  187. even_edges.push_back(*ei);
  188. }
  189. }
  190. }
  191. else
  192. vertex_state[u] = graph::detail::V_UNREACHED;
  193. }
  194. // end initializations
  195. vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor;
  196. w_free_ancestor = graph_traits< Graph >::null_vertex();
  197. v_free_ancestor = graph_traits< Graph >::null_vertex();
  198. bool found_alternating_path = false;
  199. while (!even_edges.empty() && !found_alternating_path)
  200. {
  201. // since we push even edges onto the back of the list as
  202. // they're discovered, taking them off the back will search
  203. // for augmenting paths depth-first.
  204. edge_descriptor_t current_edge = even_edges.back();
  205. even_edges.pop_back();
  206. v = source(current_edge, g);
  207. w = target(current_edge, g);
  208. vertex_descriptor_t v_prime = origin[ds.find_set(v)];
  209. vertex_descriptor_t w_prime = origin[ds.find_set(w)];
  210. // because of the way we put all of the edges on the queue,
  211. // v_prime should be labeled V_EVEN; the following is a
  212. // little paranoid but it could happen...
  213. if (vertex_state[v_prime] != graph::detail::V_EVEN)
  214. {
  215. std::swap(v_prime, w_prime);
  216. std::swap(v, w);
  217. }
  218. if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
  219. {
  220. vertex_state[w_prime] = graph::detail::V_ODD;
  221. vertex_descriptor_t w_prime_mate = mate[w_prime];
  222. vertex_state[w_prime_mate] = graph::detail::V_EVEN;
  223. out_edge_iterator_t ei, ei_end;
  224. for (boost::tie(ei, ei_end) = out_edges(w_prime_mate, g);
  225. ei != ei_end; ++ei)
  226. {
  227. if (target(*ei, g) != w_prime_mate)
  228. {
  229. even_edges.push_back(*ei);
  230. }
  231. }
  232. pred[w_prime] = v;
  233. }
  234. // w_prime == v_prime can happen below if we get an edge that has
  235. // been shrunk into a blossom
  236. else if (vertex_state[w_prime] == graph::detail::V_EVEN
  237. && w_prime != v_prime)
  238. {
  239. vertex_descriptor_t w_up = w_prime;
  240. vertex_descriptor_t v_up = v_prime;
  241. vertex_descriptor_t nearest_common_ancestor
  242. = graph_traits< Graph >::null_vertex();
  243. w_free_ancestor = graph_traits< Graph >::null_vertex();
  244. v_free_ancestor = graph_traits< Graph >::null_vertex();
  245. // We now need to distinguish between the case that
  246. // w_prime and v_prime share an ancestor under the
  247. // "parent" relation, in which case we've found a
  248. // blossom and should shrink it, or the case that
  249. // w_prime and v_prime both have distinct ancestors that
  250. // are free, in which case we've found an alternating
  251. // path between those two ancestors.
  252. ++timestamp;
  253. while (nearest_common_ancestor
  254. == graph_traits< Graph >::null_vertex()
  255. && (v_free_ancestor == graph_traits< Graph >::null_vertex()
  256. || w_free_ancestor
  257. == graph_traits< Graph >::null_vertex()))
  258. {
  259. ancestor_of_w[w_up] = timestamp;
  260. ancestor_of_v[v_up] = timestamp;
  261. if (w_free_ancestor == graph_traits< Graph >::null_vertex())
  262. w_up = parent(w_up);
  263. if (v_free_ancestor == graph_traits< Graph >::null_vertex())
  264. v_up = parent(v_up);
  265. if (mate[v_up] == graph_traits< Graph >::null_vertex())
  266. v_free_ancestor = v_up;
  267. if (mate[w_up] == graph_traits< Graph >::null_vertex())
  268. w_free_ancestor = w_up;
  269. if (ancestor_of_w[v_up] == timestamp)
  270. nearest_common_ancestor = v_up;
  271. else if (ancestor_of_v[w_up] == timestamp)
  272. nearest_common_ancestor = w_up;
  273. else if (v_free_ancestor == w_free_ancestor
  274. && v_free_ancestor
  275. != graph_traits< Graph >::null_vertex())
  276. nearest_common_ancestor = v_up;
  277. }
  278. if (nearest_common_ancestor
  279. == graph_traits< Graph >::null_vertex())
  280. found_alternating_path = true; // to break out of the loop
  281. else
  282. {
  283. // shrink the blossom
  284. link_and_set_bridges(
  285. w_prime, nearest_common_ancestor, std::make_pair(w, v));
  286. link_and_set_bridges(
  287. v_prime, nearest_common_ancestor, std::make_pair(v, w));
  288. }
  289. }
  290. }
  291. if (!found_alternating_path)
  292. return false;
  293. // retrieve the augmenting path and put it in aug_path
  294. reversed_retrieve_augmenting_path(v, v_free_ancestor);
  295. retrieve_augmenting_path(w, w_free_ancestor);
  296. // augment the matching along aug_path
  297. vertex_descriptor_t a, b;
  298. while (!aug_path.empty())
  299. {
  300. a = aug_path.front();
  301. aug_path.pop_front();
  302. b = aug_path.front();
  303. aug_path.pop_front();
  304. mate[a] = b;
  305. mate[b] = a;
  306. }
  307. return true;
  308. }
  309. template < typename PropertyMap > void get_current_matching(PropertyMap pm)
  310. {
  311. vertex_iterator_t vi, vi_end;
  312. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  313. put(pm, *vi, mate[*vi]);
  314. }
  315. template < typename PropertyMap > void get_vertex_state_map(PropertyMap pm)
  316. {
  317. vertex_iterator_t vi, vi_end;
  318. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  319. put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
  320. }
  321. private:
  322. vertex_descriptor_t parent(vertex_descriptor_t x)
  323. {
  324. if (vertex_state[x] == graph::detail::V_EVEN
  325. && mate[x] != graph_traits< Graph >::null_vertex())
  326. return mate[x];
  327. else if (vertex_state[x] == graph::detail::V_ODD)
  328. return origin[ds.find_set(pred[x])];
  329. else
  330. return x;
  331. }
  332. void link_and_set_bridges(vertex_descriptor_t x,
  333. vertex_descriptor_t stop_vertex, vertex_pair_t the_bridge)
  334. {
  335. for (vertex_descriptor_t v = x; v != stop_vertex; v = parent(v))
  336. {
  337. ds.union_set(v, stop_vertex);
  338. origin[ds.find_set(stop_vertex)] = stop_vertex;
  339. if (vertex_state[v] == graph::detail::V_ODD)
  340. {
  341. bridge[v] = the_bridge;
  342. out_edge_iterator_t oei, oei_end;
  343. for (boost::tie(oei, oei_end) = out_edges(v, g); oei != oei_end;
  344. ++oei)
  345. {
  346. if (target(*oei, g) != v)
  347. {
  348. even_edges.push_back(*oei);
  349. }
  350. }
  351. }
  352. }
  353. }
  354. // Since none of the STL containers support both constant-time
  355. // concatenation and reversal, the process of expanding an
  356. // augmenting path once we know one exists is a little more
  357. // complicated than it has to be. If we know the path is from v to
  358. // w, then the augmenting path is recursively defined as:
  359. //
  360. // path(v,w) = [v], if v = w
  361. // = concat([v, mate[v]], path(pred[mate[v]], w),
  362. // if v != w and vertex_state[v] == graph::detail::V_EVEN
  363. // = concat([v], reverse(path(x,mate[v])), path(y,w)),
  364. // if v != w, vertex_state[v] == graph::detail::V_ODD, and
  365. // bridge[v] = (x,y)
  366. //
  367. // These next two mutually recursive functions implement this definition.
  368. void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w)
  369. {
  370. if (v == w)
  371. aug_path.push_back(v);
  372. else if (vertex_state[v] == graph::detail::V_EVEN)
  373. {
  374. aug_path.push_back(v);
  375. aug_path.push_back(mate[v]);
  376. retrieve_augmenting_path(pred[mate[v]], w);
  377. }
  378. else // vertex_state[v] == graph::detail::V_ODD
  379. {
  380. aug_path.push_back(v);
  381. reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
  382. retrieve_augmenting_path(bridge[v].second, w);
  383. }
  384. }
  385. void reversed_retrieve_augmenting_path(
  386. vertex_descriptor_t v, vertex_descriptor_t w)
  387. {
  388. if (v == w)
  389. aug_path.push_back(v);
  390. else if (vertex_state[v] == graph::detail::V_EVEN)
  391. {
  392. reversed_retrieve_augmenting_path(pred[mate[v]], w);
  393. aug_path.push_back(mate[v]);
  394. aug_path.push_back(v);
  395. }
  396. else // vertex_state[v] == graph::detail::V_ODD
  397. {
  398. reversed_retrieve_augmenting_path(bridge[v].second, w);
  399. retrieve_augmenting_path(bridge[v].first, mate[v]);
  400. aug_path.push_back(v);
  401. }
  402. }
  403. // private data members
  404. const Graph& g;
  405. VertexIndexMap vm;
  406. v_size_t n_vertices;
  407. // storage for the property maps below
  408. std::vector< vertex_descriptor_t > mate_vector;
  409. std::vector< e_size_t > ancestor_of_v_vector;
  410. std::vector< e_size_t > ancestor_of_w_vector;
  411. std::vector< int > vertex_state_vector;
  412. std::vector< vertex_descriptor_t > origin_vector;
  413. std::vector< vertex_descriptor_t > pred_vector;
  414. std::vector< vertex_pair_t > bridge_vector;
  415. std::vector< vertex_descriptor_t > ds_parent_vector;
  416. std::vector< v_size_t > ds_rank_vector;
  417. // iterator property maps
  418. vertex_to_vertex_map_t mate;
  419. vertex_to_esize_map_t ancestor_of_v;
  420. vertex_to_esize_map_t ancestor_of_w;
  421. vertex_to_int_map_t vertex_state;
  422. vertex_to_vertex_map_t origin;
  423. vertex_to_vertex_map_t pred;
  424. vertex_to_vertex_pair_map_t bridge;
  425. vertex_to_vertex_map_t ds_parent_map;
  426. vertex_to_vsize_map_t ds_rank_map;
  427. vertex_list_t aug_path;
  428. edge_list_t even_edges;
  429. disjoint_sets< vertex_to_vsize_map_t, vertex_to_vertex_map_t > ds;
  430. };
  431. //***************************************************************************
  432. //***************************************************************************
  433. // Initial Matching Functors
  434. //***************************************************************************
  435. //***************************************************************************
  436. template < typename Graph, typename MateMap > struct greedy_matching
  437. {
  438. typedef
  439. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
  440. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  441. typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
  442. typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
  443. static void find_matching(const Graph& g, MateMap mate)
  444. {
  445. vertex_iterator_t vi, vi_end;
  446. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  447. put(mate, *vi, graph_traits< Graph >::null_vertex());
  448. edge_iterator_t ei, ei_end;
  449. for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
  450. {
  451. edge_descriptor_t e = *ei;
  452. vertex_descriptor_t u = source(e, g);
  453. vertex_descriptor_t v = target(e, g);
  454. if (u != v && get(mate, u) == get(mate, v))
  455. // only way equality can hold is if
  456. // mate[u] == mate[v] == null_vertex
  457. {
  458. put(mate, u, v);
  459. put(mate, v, u);
  460. }
  461. }
  462. }
  463. };
  464. template < typename Graph, typename MateMap > struct extra_greedy_matching
  465. {
  466. // The "extra greedy matching" is formed by repeating the
  467. // following procedure as many times as possible: Choose the
  468. // unmatched vertex v of minimum non-zero degree. Choose the
  469. // neighbor w of v which is unmatched and has minimum degree over
  470. // all of v's neighbors. Add (u,v) to the matching. Ties for
  471. // either choice are broken arbitrarily. This procedure takes time
  472. // O(m log n), where m is the number of edges in the graph and n
  473. // is the number of vertices.
  474. typedef
  475. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
  476. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  477. typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
  478. typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
  479. typedef std::pair< vertex_descriptor_t, vertex_descriptor_t > vertex_pair_t;
  480. struct select_first
  481. {
  482. inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
  483. {
  484. return p.first;
  485. }
  486. };
  487. struct select_second
  488. {
  489. inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
  490. {
  491. return p.second;
  492. }
  493. };
  494. template < class PairSelector > class less_than_by_degree
  495. {
  496. public:
  497. less_than_by_degree(const Graph& g) : m_g(g) {}
  498. bool operator()(const vertex_pair_t x, const vertex_pair_t y)
  499. {
  500. return out_degree(PairSelector::select_vertex(x), m_g)
  501. < out_degree(PairSelector::select_vertex(y), m_g);
  502. }
  503. private:
  504. const Graph& m_g;
  505. };
  506. static void find_matching(const Graph& g, MateMap mate)
  507. {
  508. typedef std::vector<
  509. std::pair< vertex_descriptor_t, vertex_descriptor_t > >
  510. directed_edges_vector_t;
  511. directed_edges_vector_t edge_list;
  512. vertex_iterator_t vi, vi_end;
  513. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  514. put(mate, *vi, graph_traits< Graph >::null_vertex());
  515. edge_iterator_t ei, ei_end;
  516. for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
  517. {
  518. edge_descriptor_t e = *ei;
  519. vertex_descriptor_t u = source(e, g);
  520. vertex_descriptor_t v = target(e, g);
  521. if (u == v)
  522. continue;
  523. edge_list.push_back(std::make_pair(u, v));
  524. edge_list.push_back(std::make_pair(v, u));
  525. }
  526. // sort the edges by the degree of the target, then (using a
  527. // stable sort) by degree of the source
  528. std::sort(edge_list.begin(), edge_list.end(),
  529. less_than_by_degree< select_second >(g));
  530. std::stable_sort(edge_list.begin(), edge_list.end(),
  531. less_than_by_degree< select_first >(g));
  532. // construct the extra greedy matching
  533. for (typename directed_edges_vector_t::const_iterator itr
  534. = edge_list.begin();
  535. itr != edge_list.end(); ++itr)
  536. {
  537. if (get(mate, itr->first) == get(mate, itr->second))
  538. // only way equality can hold is if mate[itr->first] ==
  539. // mate[itr->second] == null_vertex
  540. {
  541. put(mate, itr->first, itr->second);
  542. put(mate, itr->second, itr->first);
  543. }
  544. }
  545. }
  546. };
  547. template < typename Graph, typename MateMap > struct empty_matching
  548. {
  549. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  550. static void find_matching(const Graph& g, MateMap mate)
  551. {
  552. vertex_iterator_t vi, vi_end;
  553. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  554. put(mate, *vi, graph_traits< Graph >::null_vertex());
  555. }
  556. };
  557. //***************************************************************************
  558. //***************************************************************************
  559. // Matching Verifiers
  560. //***************************************************************************
  561. //***************************************************************************
  562. namespace detail
  563. {
  564. template < typename SizeType >
  565. class odd_components_counter : public dfs_visitor<>
  566. // This depth-first search visitor will count the number of connected
  567. // components with an odd number of vertices. It's used by
  568. // maximum_matching_verifier.
  569. {
  570. public:
  571. odd_components_counter(SizeType& c_count) : m_count(c_count)
  572. {
  573. m_count = 0;
  574. }
  575. template < class Vertex, class Graph > void start_vertex(Vertex, Graph&)
  576. {
  577. m_parity = false;
  578. }
  579. template < class Vertex, class Graph >
  580. void discover_vertex(Vertex, Graph&)
  581. {
  582. m_parity = !m_parity;
  583. m_parity ? ++m_count : --m_count;
  584. }
  585. protected:
  586. SizeType& m_count;
  587. private:
  588. bool m_parity;
  589. };
  590. } // namespace detail
  591. template < typename Graph, typename MateMap,
  592. typename VertexIndexMap = dummy_property_map >
  593. struct no_matching_verifier
  594. {
  595. inline static bool verify_matching(const Graph&, MateMap, VertexIndexMap)
  596. {
  597. return true;
  598. }
  599. };
  600. template < typename Graph, typename MateMap, typename VertexIndexMap >
  601. struct maximum_cardinality_matching_verifier
  602. {
  603. template < typename X > struct map_vertex_to_
  604. {
  605. typedef boost::iterator_property_map<
  606. typename std::vector< X >::iterator, VertexIndexMap >
  607. type;
  608. };
  609. typedef
  610. typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
  611. typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
  612. typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
  613. typedef typename map_vertex_to_< int >::type vertex_to_int_map_t;
  614. typedef typename map_vertex_to_< vertex_descriptor_t >::type
  615. vertex_to_vertex_map_t;
  616. template < typename VertexStateMap > struct non_odd_vertex
  617. {
  618. // this predicate is used to create a filtered graph that
  619. // excludes vertices labeled "graph::detail::V_ODD"
  620. non_odd_vertex() : vertex_state(0) {}
  621. non_odd_vertex(VertexStateMap* arg_vertex_state)
  622. : vertex_state(arg_vertex_state)
  623. {
  624. }
  625. template < typename Vertex > bool operator()(const Vertex& v) const
  626. {
  627. BOOST_ASSERT(vertex_state);
  628. return get(*vertex_state, v) != graph::detail::V_ODD;
  629. }
  630. VertexStateMap* vertex_state;
  631. };
  632. static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
  633. {
  634. // For any graph G, let o(G) be the number of connected
  635. // components in G of odd size. For a subset S of G's vertex set
  636. // V(G), let (G - S) represent the subgraph of G induced by
  637. // removing all vertices in S from G. Let M(G) be the size of the
  638. // maximum cardinality matching in G. Then the Tutte-Berge
  639. // formula guarantees that
  640. //
  641. // 2 * M(G) = min ( |V(G)| + |U| + o(G - U) )
  642. //
  643. // where the minimum is taken over all subsets U of
  644. // V(G). Edmonds' algorithm finds a set U that achieves the
  645. // minimum in the above formula, namely the vertices labeled
  646. //"ODD." This function runs one iteration of Edmonds' algorithm
  647. // to find U, then verifies that the size of the matching given
  648. // by mate satisfies the Tutte-Berge formula.
  649. // first, make sure it's a valid matching
  650. if (!is_a_matching(g, mate, vm))
  651. return false;
  652. // We'll try to augment the matching once. This serves two
  653. // purposes: first, if we find some augmenting path, the matching
  654. // is obviously non-maximum. Second, running edmonds' algorithm
  655. // on a graph with no augmenting path will create the
  656. // Edmonds-Gallai decomposition that we need as a certificate of
  657. // maximality - we can get it by looking at the vertex_state map
  658. // that results.
  659. edmonds_augmenting_path_finder< Graph, MateMap, VertexIndexMap >
  660. augmentor(g, mate, vm);
  661. if (augmentor.augment_matching())
  662. return false;
  663. std::vector< int > vertex_state_vector(num_vertices(g));
  664. vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm);
  665. augmentor.get_vertex_state_map(vertex_state);
  666. // count the number of graph::detail::V_ODD vertices
  667. v_size_t num_odd_vertices = 0;
  668. vertex_iterator_t vi, vi_end;
  669. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
  670. if (vertex_state[*vi] == graph::detail::V_ODD)
  671. ++num_odd_vertices;
  672. // count the number of connected components with odd cardinality
  673. // in the graph without graph::detail::V_ODD vertices
  674. non_odd_vertex< vertex_to_int_map_t > filter(&vertex_state);
  675. filtered_graph< Graph, keep_all, non_odd_vertex< vertex_to_int_map_t > >
  676. fg(g, keep_all(), filter);
  677. v_size_t num_odd_components;
  678. detail::odd_components_counter< v_size_t > occ(num_odd_components);
  679. depth_first_search(fg, visitor(occ).vertex_index_map(vm));
  680. if (2 * matching_size(g, mate, vm)
  681. == num_vertices(g) + num_odd_vertices - num_odd_components)
  682. return true;
  683. else
  684. return false;
  685. }
  686. };
  687. template < typename Graph, typename MateMap, typename VertexIndexMap,
  688. template < typename, typename, typename > class AugmentingPathFinder,
  689. template < typename, typename > class InitialMatchingFinder,
  690. template < typename, typename, typename > class MatchingVerifier >
  691. bool matching(const Graph& g, MateMap mate, VertexIndexMap vm)
  692. {
  693. InitialMatchingFinder< Graph, MateMap >::find_matching(g, mate);
  694. AugmentingPathFinder< Graph, MateMap, VertexIndexMap > augmentor(
  695. g, mate, vm);
  696. bool not_maximum_yet = true;
  697. while (not_maximum_yet)
  698. {
  699. not_maximum_yet = augmentor.augment_matching();
  700. }
  701. augmentor.get_current_matching(mate);
  702. return MatchingVerifier< Graph, MateMap, VertexIndexMap >::verify_matching(
  703. g, mate, vm);
  704. }
  705. template < typename Graph, typename MateMap, typename VertexIndexMap >
  706. inline bool checked_edmonds_maximum_cardinality_matching(
  707. const Graph& g, MateMap mate, VertexIndexMap vm)
  708. {
  709. return matching< Graph, MateMap, VertexIndexMap,
  710. edmonds_augmenting_path_finder, extra_greedy_matching,
  711. maximum_cardinality_matching_verifier >(g, mate, vm);
  712. }
  713. template < typename Graph, typename MateMap >
  714. inline bool checked_edmonds_maximum_cardinality_matching(
  715. const Graph& g, MateMap mate)
  716. {
  717. return checked_edmonds_maximum_cardinality_matching(
  718. g, mate, get(vertex_index, g));
  719. }
  720. template < typename Graph, typename MateMap, typename VertexIndexMap >
  721. inline void edmonds_maximum_cardinality_matching(
  722. const Graph& g, MateMap mate, VertexIndexMap vm)
  723. {
  724. matching< Graph, MateMap, VertexIndexMap, edmonds_augmenting_path_finder,
  725. extra_greedy_matching, no_matching_verifier >(g, mate, vm);
  726. }
  727. template < typename Graph, typename MateMap >
  728. inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate)
  729. {
  730. edmonds_maximum_cardinality_matching(g, mate, get(vertex_index, g));
  731. }
  732. } // namespace boost
  733. #endif // BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP