max_cardinality_matching.hpp 29 KB

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