maximum_weighted_matching.hpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. //=======================================================================
  2. // Copyright (c) 2018 Yi Ji
  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_WEIGHTED_MATCHING_HPP
  10. #define BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP
  11. #include <algorithm> // for std::iter_swap
  12. #include <boost/shared_ptr.hpp>
  13. #include <boost/make_shared.hpp>
  14. #include <boost/graph/max_cardinality_matching.hpp>
  15. namespace boost
  16. {
  17. template <typename Graph, typename MateMap, typename VertexIndexMap>
  18. typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type
  19. matching_weight_sum(const Graph& g, MateMap mate, VertexIndexMap vm)
  20. {
  21. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
  22. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor_t;
  23. typedef typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type edge_property_t;
  24. edge_property_t weight_sum = 0;
  25. vertex_iterator_t vi, vi_end;
  26. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  27. {
  28. vertex_descriptor_t v = *vi;
  29. if (get(mate, v) != graph_traits<Graph>::null_vertex() && get(vm, v) < get(vm, get(mate,v)))
  30. weight_sum += get(edge_weight, g, edge(v,mate[v],g).first);
  31. }
  32. return weight_sum;
  33. }
  34. template <typename Graph, typename MateMap>
  35. inline typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type
  36. matching_weight_sum(const Graph& g, MateMap mate)
  37. {
  38. return matching_weight_sum(g, mate, get(vertex_index,g));
  39. }
  40. template <typename Graph, typename MateMap, typename VertexIndexMap>
  41. class weighted_augmenting_path_finder
  42. {
  43. public:
  44. template <typename T>
  45. struct map_vertex_to_
  46. {
  47. typedef boost::iterator_property_map<typename std::vector<T>::iterator, VertexIndexMap> type;
  48. };
  49. typedef typename graph::detail::VERTEX_STATE vertex_state_t;
  50. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
  51. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor_t;
  52. typedef typename std::vector<vertex_descriptor_t>::const_iterator vertex_vec_iter_t;
  53. typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iterator_t;
  54. typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor_t;
  55. typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
  56. typedef typename property_traits<typename property_map<Graph, edge_weight_t>::type>::value_type edge_property_t;
  57. typedef std::deque<vertex_descriptor_t> vertex_list_t;
  58. typedef std::vector<edge_descriptor_t> edge_list_t;
  59. typedef typename map_vertex_to_<vertex_descriptor_t>::type vertex_to_vertex_map_t;
  60. typedef typename map_vertex_to_<edge_property_t>::type vertex_to_weight_map_t;
  61. typedef typename map_vertex_to_<bool>::type vertex_to_bool_map_t;
  62. typedef typename map_vertex_to_<std::pair<vertex_descriptor_t, vertex_descriptor_t> >::type vertex_to_pair_map_t;
  63. typedef typename map_vertex_to_<std::pair<edge_descriptor_t, bool> >::type vertex_to_edge_map_t;
  64. typedef typename map_vertex_to_<vertex_to_edge_map_t>::type vertex_pair_to_edge_map_t;
  65. class blossom
  66. {
  67. public:
  68. typedef boost::shared_ptr<blossom> blossom_ptr_t;
  69. std::vector<blossom_ptr_t> sub_blossoms;
  70. edge_property_t dual_var;
  71. blossom_ptr_t father;
  72. blossom() : dual_var(0), father(blossom_ptr_t()) {}
  73. // get the base vertex of a blossom by recursively getting
  74. // its base sub-blossom, which is always the first one in
  75. // sub_blossoms because of how we create and maintain blossoms
  76. virtual vertex_descriptor_t get_base() const
  77. {
  78. const blossom* b = this;
  79. while (!b->sub_blossoms.empty())
  80. b = b->sub_blossoms[0].get();
  81. return b->get_base();
  82. }
  83. // set a sub-blossom as a blossom's base by exchanging it
  84. // with its first sub-blossom
  85. void set_base(const blossom_ptr_t& sub)
  86. {
  87. for (blossom_iterator_t bi = sub_blossoms.begin(); bi != sub_blossoms.end(); ++bi)
  88. {
  89. if (sub.get() == bi->get())
  90. {
  91. std::iter_swap(sub_blossoms.begin(), bi);
  92. break;
  93. }
  94. }
  95. }
  96. // get all vertices inside recursively
  97. virtual std::vector<vertex_descriptor_t> vertices() const
  98. {
  99. std::vector<vertex_descriptor_t> all_vertices;
  100. for (typename std::vector<blossom_ptr_t>::const_iterator bi = sub_blossoms.begin(); bi != sub_blossoms.end(); ++bi)
  101. {
  102. std::vector<vertex_descriptor_t> some_vertices = (*bi)->vertices();
  103. all_vertices.insert(all_vertices.end(), some_vertices.begin(), some_vertices.end());
  104. }
  105. return all_vertices;
  106. }
  107. };
  108. // a trivial_blossom only has one vertex and no sub-blossom;
  109. // for each vertex v, in_blossom[v] is the trivial_blossom that contains it directly
  110. class trivial_blossom : public blossom
  111. {
  112. public:
  113. trivial_blossom(vertex_descriptor_t v) : trivial_vertex(v) {}
  114. virtual vertex_descriptor_t get_base() const
  115. {
  116. return trivial_vertex;
  117. }
  118. virtual std::vector<vertex_descriptor_t> vertices() const
  119. {
  120. std::vector<vertex_descriptor_t> all_vertices;
  121. all_vertices.push_back(trivial_vertex);
  122. return all_vertices;
  123. }
  124. private:
  125. vertex_descriptor_t trivial_vertex;
  126. };
  127. typedef boost::shared_ptr<blossom> blossom_ptr_t;
  128. typedef typename std::vector<blossom_ptr_t>::iterator blossom_iterator_t;
  129. typedef typename map_vertex_to_<blossom_ptr_t>::type vertex_to_blossom_map_t;
  130. weighted_augmenting_path_finder(const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) :
  131. g(arg_g),
  132. vm(arg_vm),
  133. null_edge(std::pair<edge_descriptor_t, bool>(num_edges(g) == 0 ? edge_descriptor_t() : *edges(g).first, false)),
  134. mate_vector(num_vertices(g)),
  135. label_S_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
  136. label_T_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
  137. outlet_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
  138. tau_idx_vector(num_vertices(g), graph_traits<Graph>::null_vertex()),
  139. dual_var_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::min())),
  140. pi_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::max())),
  141. gamma_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::max())),
  142. tau_vector(std::vector<edge_property_t>(num_vertices(g), std::numeric_limits<edge_property_t>::max())),
  143. in_blossom_vector(num_vertices(g)),
  144. old_label_vector(num_vertices(g)),
  145. critical_edge_vectors(num_vertices(g), std::vector<std::pair<edge_descriptor_t, bool> >(num_vertices(g), null_edge)),
  146. mate(mate_vector.begin(), vm),
  147. label_S(label_S_vector.begin(), vm),
  148. label_T(label_T_vector.begin(), vm),
  149. outlet(outlet_vector.begin(), vm),
  150. tau_idx(tau_idx_vector.begin(), vm),
  151. dual_var(dual_var_vector.begin(), vm),
  152. pi(pi_vector.begin(), vm),
  153. gamma(gamma_vector.begin(), vm),
  154. tau(tau_vector.begin(), vm),
  155. in_blossom(in_blossom_vector.begin(), vm),
  156. old_label(old_label_vector.begin(), vm)
  157. {
  158. vertex_iterator_t vi, vi_end;
  159. edge_iterator_t ei, ei_end;
  160. edge_property_t max_weight = std::numeric_limits<edge_property_t>::min();
  161. for (boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
  162. max_weight = std::max(max_weight, get(edge_weight, g, *ei));
  163. typename std::vector<std::vector<std::pair<edge_descriptor_t, bool> > >::iterator vei;
  164. for (boost::tie(vi,vi_end) = vertices(g), vei = critical_edge_vectors.begin(); vi != vi_end; ++vi, ++vei)
  165. {
  166. vertex_descriptor_t u = *vi;
  167. mate[u] = get(arg_mate, u);
  168. dual_var[u] = 2*max_weight;
  169. in_blossom[u] = boost::make_shared<trivial_blossom>(u);
  170. outlet[u] = u;
  171. critical_edge_vector.push_back(vertex_to_edge_map_t(vei->begin(), vm));
  172. }
  173. critical_edge = vertex_pair_to_edge_map_t(critical_edge_vector.begin(), vm);
  174. init();
  175. }
  176. // return the top blossom where v is contained inside
  177. blossom_ptr_t in_top_blossom(vertex_descriptor_t v) const
  178. {
  179. blossom_ptr_t b = in_blossom[v];
  180. while (b->father != blossom_ptr_t())
  181. b = b->father;
  182. return b;
  183. }
  184. // check if vertex v is in blossom b
  185. bool is_in_blossom(blossom_ptr_t b, vertex_descriptor_t v) const
  186. {
  187. if (v == graph_traits<Graph>::null_vertex())
  188. return false;
  189. blossom_ptr_t vb = in_blossom[v]->father;
  190. while (vb != blossom_ptr_t())
  191. {
  192. if (vb.get() == b.get())
  193. return true;
  194. vb = vb->father;
  195. }
  196. return false;
  197. }
  198. // return the base vertex of the top blossom that contains v
  199. inline vertex_descriptor_t base_vertex(vertex_descriptor_t v) const
  200. {
  201. return in_top_blossom(v)->get_base();
  202. }
  203. // add an existed top blossom of base vertex v into new top
  204. // blossom b as its sub-blossom
  205. void add_sub_blossom(blossom_ptr_t b, vertex_descriptor_t v)
  206. {
  207. blossom_ptr_t sub = in_top_blossom(v);
  208. sub->father = b;
  209. b->sub_blossoms.push_back(sub);
  210. if (sub->sub_blossoms.empty())
  211. return;
  212. for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end(); ++bi)
  213. {
  214. if (bi->get() == sub.get())
  215. {
  216. top_blossoms.erase(bi);
  217. break;
  218. }
  219. }
  220. }
  221. // when a top blossom is created or its base vertex getting an S-label,
  222. // add all edges incident to this blossom into even_edges
  223. void bloom(blossom_ptr_t b)
  224. {
  225. std::vector<vertex_descriptor_t> vertices_of_b = b->vertices();
  226. vertex_vec_iter_t vi;
  227. for (vi = vertices_of_b.begin(); vi != vertices_of_b.end(); ++vi)
  228. {
  229. out_edge_iterator_t oei, oei_end;
  230. for (boost::tie(oei,oei_end) = out_edges(*vi, g); oei != oei_end; ++oei)
  231. {
  232. if (target(*oei,g) != *vi && mate[*vi] != target(*oei,g))
  233. even_edges.push_back(*oei);
  234. }
  235. }
  236. }
  237. // assigning a T-label to a non S-vertex, along with outlet and updating pi value
  238. // if updated pi[v] equals zero, augment the matching from its mate vertex
  239. void put_T_label(vertex_descriptor_t v, vertex_descriptor_t T_label,
  240. vertex_descriptor_t outlet_v, edge_property_t pi_v)
  241. {
  242. if (label_S[v] != graph_traits<Graph>::null_vertex())
  243. return;
  244. label_T[v] = T_label;
  245. outlet[v] = outlet_v;
  246. pi[v] = pi_v;
  247. vertex_descriptor_t v_mate = mate[v];
  248. if (pi[v] == 0)
  249. {
  250. label_T[v_mate] = graph_traits<Graph>::null_vertex();
  251. label_S[v_mate] = v;
  252. bloom(in_top_blossom(v_mate));
  253. }
  254. }
  255. // get the missing T-label for a to-be-expanded base vertex
  256. // the missing T-label is the last vertex of the path from outlet[v] to v
  257. std::pair<vertex_descriptor_t, vertex_descriptor_t> missing_label(vertex_descriptor_t b_base)
  258. {
  259. vertex_descriptor_t missing_outlet = outlet[b_base];
  260. if (outlet[b_base] == b_base)
  261. return std::make_pair(graph_traits<Graph>::null_vertex(), missing_outlet);
  262. vertex_iterator_t vi, vi_end;
  263. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  264. old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]);
  265. std::pair<vertex_descriptor_t, vertex_state_t> child(outlet[b_base], graph::detail::V_EVEN);
  266. blossom_ptr_t b = in_blossom[child.first];
  267. for (; b->father->father != blossom_ptr_t(); b = b->father);
  268. child.first = b->get_base();
  269. if (child.first == b_base)
  270. return std::make_pair(graph_traits<Graph>::null_vertex(), missing_outlet);
  271. while (true)
  272. {
  273. std::pair<vertex_descriptor_t, vertex_state_t> child_parent = parent(child, true);
  274. for (b = in_blossom[child_parent.first]; b->father->father != blossom_ptr_t(); b = b->father);
  275. missing_outlet = child_parent.first;
  276. child_parent.first = b->get_base();
  277. if (child_parent.first == b_base)
  278. break;
  279. else
  280. child = child_parent;
  281. }
  282. return std::make_pair(child.first, missing_outlet);
  283. }
  284. // expand a top blossom, put all its non-trivial sub-blossoms into top_blossoms
  285. blossom_iterator_t expand_blossom(blossom_iterator_t bi, std::vector<blossom_ptr_t>& new_ones)
  286. {
  287. blossom_ptr_t b = *bi;
  288. for (blossom_iterator_t i = b->sub_blossoms.begin(); i != b->sub_blossoms.end(); ++i)
  289. {
  290. blossom_ptr_t sub_blossom = *i;
  291. vertex_descriptor_t sub_base = sub_blossom->get_base();
  292. label_S[sub_base] = label_T[sub_base] = graph_traits<Graph>::null_vertex();
  293. outlet[sub_base] = sub_base;
  294. sub_blossom->father = blossom_ptr_t();
  295. // new top blossoms cannot be pushed back into top_blossoms immediately,
  296. // because push_back() may cause reallocation and then invalid iterators
  297. if (!sub_blossom->sub_blossoms.empty())
  298. new_ones.push_back(sub_blossom);
  299. }
  300. return top_blossoms.erase(bi);
  301. }
  302. // when expanding a T-blossom with base v, it requires more operations:
  303. // supply the missing T-labels for new base vertices by picking the minimum tau from vertices of
  304. // each corresponding new top-blossoms; when label_T[v] is null or we have a smaller tau from
  305. // missing_label(v), replace T-label and outlet of v (but don't bloom v)
  306. blossom_iterator_t expand_T_blossom(blossom_iterator_t bi, std::vector<blossom_ptr_t>& new_ones)
  307. {
  308. blossom_ptr_t b = *bi;
  309. vertex_descriptor_t b_base = b->get_base();
  310. std::pair<vertex_descriptor_t, vertex_descriptor_t> T_and_outlet = missing_label(b_base);
  311. blossom_iterator_t next_bi = expand_blossom(bi, new_ones);
  312. for (blossom_iterator_t i = b->sub_blossoms.begin(); i != b->sub_blossoms.end(); ++i)
  313. {
  314. blossom_ptr_t sub_blossom = *i;
  315. vertex_descriptor_t sub_base = sub_blossom->get_base();
  316. vertex_descriptor_t min_tau_v = graph_traits<Graph>::null_vertex();
  317. edge_property_t min_tau = std::numeric_limits<edge_property_t>::max();
  318. std::vector<vertex_descriptor_t> sub_vertices = sub_blossom->vertices();
  319. for (vertex_vec_iter_t v = sub_vertices.begin(); v != sub_vertices.end(); ++v)
  320. {
  321. if (tau[*v] < min_tau)
  322. {
  323. min_tau = tau[*v];
  324. min_tau_v = *v;
  325. }
  326. }
  327. if (min_tau < std::numeric_limits<edge_property_t>::max())
  328. put_T_label(sub_base, tau_idx[min_tau_v], min_tau_v, tau[min_tau_v]);
  329. }
  330. if (label_T[b_base] == graph_traits<Graph>::null_vertex() || tau[old_label[b_base].second] < pi[b_base])
  331. boost::tie(label_T[b_base], outlet[b_base]) = T_and_outlet;
  332. return next_bi;
  333. }
  334. // when vertices v and w are matched to each other by augmenting,
  335. // we must set v/w as base vertex of any blossom who contains v/w and
  336. // is a sub-blossom of their lowest (smallest) common blossom
  337. void adjust_blossom(vertex_descriptor_t v, vertex_descriptor_t w)
  338. {
  339. blossom_ptr_t vb = in_blossom[v], wb = in_blossom[w], lowest_common_blossom;
  340. std::vector<blossom_ptr_t> v_ancestors, w_ancestors;
  341. while (vb->father != blossom_ptr_t())
  342. {
  343. v_ancestors.push_back(vb->father);
  344. vb = vb->father;
  345. }
  346. while (wb->father != blossom_ptr_t())
  347. {
  348. w_ancestors.push_back(wb->father);
  349. wb = wb->father;
  350. }
  351. typename std::vector<blossom_ptr_t>::reverse_iterator i, j;
  352. i = v_ancestors.rbegin();
  353. j = w_ancestors.rbegin();
  354. while (i != v_ancestors.rend() && j != w_ancestors.rend() && i->get() == j->get())
  355. {
  356. lowest_common_blossom = *i;
  357. ++i;++j;
  358. }
  359. vb = in_blossom[v];
  360. wb = in_blossom[w];
  361. while (vb->father != lowest_common_blossom)
  362. {
  363. vb->father->set_base(vb);
  364. vb = vb->father;
  365. }
  366. while (wb->father != lowest_common_blossom)
  367. {
  368. wb->father->set_base(wb);
  369. wb = wb->father;
  370. }
  371. }
  372. // every edge weight is multiplied by 4 to ensure integer weights
  373. // throughout the algorithm if all input weights are integers
  374. inline edge_property_t slack(const edge_descriptor_t& e) const
  375. {
  376. vertex_descriptor_t v, w;
  377. v = source(e, g);
  378. w = target(e, g);
  379. return dual_var[v] + dual_var[w] - 4*get(edge_weight, g, e);
  380. }
  381. // backtrace one step on vertex v along the augmenting path
  382. // by its labels and its vertex state;
  383. // boolean parameter "use_old" means whether we are updating labels,
  384. // if we are, then we use old labels to backtrace and also we
  385. // don't jump to its base vertex when we reach an odd vertex
  386. std::pair<vertex_descriptor_t, vertex_state_t> parent(std::pair<vertex_descriptor_t, vertex_state_t> v,
  387. bool use_old = false) const
  388. {
  389. if (v.second == graph::detail::V_EVEN)
  390. {
  391. // a paranoid check: label_S shoule be the same as mate in backtracing
  392. if (label_S[v.first] == graph_traits<Graph>::null_vertex())
  393. label_S[v.first] = mate[v.first];
  394. return std::make_pair(label_S[v.first], graph::detail::V_ODD);
  395. }
  396. else if (v.second == graph::detail::V_ODD)
  397. {
  398. vertex_descriptor_t w = use_old ? old_label[v.first].first : base_vertex(label_T[v.first]);
  399. return std::make_pair(w, graph::detail::V_EVEN);
  400. }
  401. return std::make_pair(v.first, graph::detail::V_UNREACHED);
  402. }
  403. // backtrace from vertices v and w to their free (unmatched) ancesters,
  404. // return the nearest common ancestor (null_vertex if none) of v and w
  405. vertex_descriptor_t nearest_common_ancestor(vertex_descriptor_t v, vertex_descriptor_t w,
  406. vertex_descriptor_t& v_free_ancestor,
  407. vertex_descriptor_t& w_free_ancestor) const
  408. {
  409. std::pair<vertex_descriptor_t, vertex_state_t> v_up(v, graph::detail::V_EVEN);
  410. std::pair<vertex_descriptor_t, vertex_state_t> w_up(w, graph::detail::V_EVEN);
  411. vertex_descriptor_t nca;
  412. nca = w_free_ancestor = v_free_ancestor = graph_traits<Graph>::null_vertex();
  413. std::vector<bool> ancestor_of_w_vector(num_vertices(g), false);
  414. std::vector<bool> ancestor_of_v_vector(num_vertices(g), false);
  415. vertex_to_bool_map_t ancestor_of_w(ancestor_of_w_vector.begin(), vm);
  416. vertex_to_bool_map_t ancestor_of_v(ancestor_of_v_vector.begin(), vm);
  417. while (nca == graph_traits<Graph>::null_vertex() &&
  418. (v_free_ancestor == graph_traits<Graph>::null_vertex() ||
  419. w_free_ancestor == graph_traits<Graph>::null_vertex()))
  420. {
  421. ancestor_of_w[w_up.first] = true;
  422. ancestor_of_v[v_up.first] = true;
  423. if (w_free_ancestor == graph_traits<Graph>::null_vertex())
  424. w_up = parent(w_up);
  425. if (v_free_ancestor == graph_traits<Graph>::null_vertex())
  426. v_up = parent(v_up);
  427. if (mate[v_up.first] == graph_traits<Graph>::null_vertex())
  428. v_free_ancestor = v_up.first;
  429. if (mate[w_up.first] == graph_traits<Graph>::null_vertex())
  430. w_free_ancestor = w_up.first;
  431. if (ancestor_of_w[v_up.first] == true || v_up.first == w_up.first)
  432. nca = v_up.first;
  433. else if (ancestor_of_v[w_up.first] == true)
  434. nca = w_up.first;
  435. else if (v_free_ancestor == w_free_ancestor &&
  436. v_free_ancestor != graph_traits<Graph>::null_vertex())
  437. nca = v_up.first;
  438. }
  439. return nca;
  440. }
  441. // when a new top blossom b is created by connecting (v, w), we add sub-blossoms into
  442. // b along backtracing from v_prime and w_prime to stop_vertex (the base vertex);
  443. // also, we set labels and outlet for each base vertex we pass by
  444. void make_blossom(blossom_ptr_t b, vertex_descriptor_t w_prime,
  445. vertex_descriptor_t v_prime, vertex_descriptor_t stop_vertex)
  446. {
  447. std::pair<vertex_descriptor_t, vertex_state_t> u(v_prime, graph::detail::V_ODD);
  448. std::pair<vertex_descriptor_t, vertex_state_t> u_up(w_prime, graph::detail::V_EVEN);
  449. for (; u_up.first != stop_vertex; u = u_up, u_up = parent(u))
  450. {
  451. if (u_up.second == graph::detail::V_EVEN)
  452. {
  453. if (!in_top_blossom(u_up.first)->sub_blossoms.empty())
  454. outlet[u_up.first] = label_T[u.first];
  455. label_T[u_up.first] = outlet[u.first];
  456. }
  457. else if (u_up.second == graph::detail::V_ODD)
  458. label_S[u_up.first] = u.first;
  459. add_sub_blossom(b, u_up.first);
  460. }
  461. }
  462. // the design of recursively expanding augmenting path in (reversed_)retrieve_augmenting_path
  463. // functions is inspired by same functions in max_cardinality_matching.hpp;
  464. // except that in weighted matching, we use "outlet" vertices instead of "bridge" vertex pairs:
  465. // if blossom b is the smallest non-trivial blossom that contains its base vertex v, then
  466. // v and outlet[v] are where augmenting path enters and leaves b
  467. void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state)
  468. {
  469. if (v == w)
  470. aug_path.push_back(v);
  471. else if (v_state == graph::detail::V_EVEN)
  472. {
  473. aug_path.push_back(v);
  474. retrieve_augmenting_path(label_S[v], w, graph::detail::V_ODD);
  475. }
  476. else if (v_state == graph::detail::V_ODD)
  477. {
  478. if (outlet[v] == v)
  479. aug_path.push_back(v);
  480. else
  481. reversed_retrieve_augmenting_path(outlet[v], v, graph::detail::V_EVEN);
  482. retrieve_augmenting_path(label_T[v], w, graph::detail::V_EVEN);
  483. }
  484. }
  485. void reversed_retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state)
  486. {
  487. if (v == w)
  488. aug_path.push_back(v);
  489. else if (v_state == graph::detail::V_EVEN)
  490. {
  491. reversed_retrieve_augmenting_path(label_S[v], w, graph::detail::V_ODD);
  492. aug_path.push_back(v);
  493. }
  494. else if (v_state == graph::detail::V_ODD)
  495. {
  496. reversed_retrieve_augmenting_path(label_T[v], w, graph::detail::V_EVEN);
  497. if (outlet[v] != v)
  498. retrieve_augmenting_path(outlet[v], v, graph::detail::V_EVEN);
  499. else
  500. aug_path.push_back(v);
  501. }
  502. }
  503. // correct labels for vertices in the augmenting path
  504. void relabel(vertex_descriptor_t v)
  505. {
  506. blossom_ptr_t b = in_blossom[v]->father;
  507. if (!is_in_blossom(b, mate[v]))
  508. { // if v is a new base vertex
  509. std::pair<vertex_descriptor_t, vertex_state_t> u(v, graph::detail::V_EVEN);
  510. while (label_S[u.first] != u.first && is_in_blossom(b, label_S[u.first]))
  511. u = parent(u, true);
  512. vertex_descriptor_t old_base = u.first;
  513. if (label_S[old_base] != old_base)
  514. { // if old base is not exposed
  515. label_T[v] = label_S[old_base];
  516. outlet[v] = old_base;
  517. }
  518. else
  519. { // if old base is exposed then new label_T[v] is not in b,
  520. // we must (i) make b2 the smallest blossom containing v but not as base vertex
  521. // (ii) backtrace from b2's new base vertex to b
  522. label_T[v] = graph_traits<Graph>::null_vertex();
  523. for (b = b->father; b != blossom_ptr_t() && b->get_base() == v; b = b->father);
  524. if (b != blossom_ptr_t())
  525. {
  526. u = std::make_pair(b->get_base(), graph::detail::V_ODD);
  527. while (!is_in_blossom(in_blossom[v]->father, old_label[u.first].first))
  528. u = parent(u, true);
  529. label_T[v] = u.first;
  530. outlet[v] = old_label[u.first].first;
  531. }
  532. }
  533. }
  534. else if (label_S[v] == v || !is_in_blossom(b, label_S[v]))
  535. { // if v is an old base vertex
  536. // let u be the new base vertex; backtrace from u's old T-label
  537. std::pair<vertex_descriptor_t, vertex_state_t> u(b->get_base(), graph::detail::V_ODD);
  538. while (old_label[u.first].first != graph_traits<Graph>::null_vertex() && old_label[u.first].first != v)
  539. u = parent(u, true);
  540. label_T[v] = old_label[u.first].second;
  541. outlet[v] = v;
  542. }
  543. else // if v is neither a new nor an old base vertex
  544. label_T[v] = label_S[v];
  545. }
  546. void augmenting(vertex_descriptor_t v, vertex_descriptor_t v_free_ancestor,
  547. vertex_descriptor_t w, vertex_descriptor_t w_free_ancestor)
  548. {
  549. vertex_iterator_t vi, vi_end;
  550. // retrieve the augmenting path and put it in aug_path
  551. reversed_retrieve_augmenting_path(v, v_free_ancestor, graph::detail::V_EVEN);
  552. retrieve_augmenting_path(w, w_free_ancestor, graph::detail::V_EVEN);
  553. // augment the matching along aug_path
  554. vertex_descriptor_t a, b;
  555. vertex_list_t reversed_aug_path;
  556. while (!aug_path.empty())
  557. {
  558. a = aug_path.front();
  559. aug_path.pop_front();
  560. reversed_aug_path.push_back(a);
  561. b = aug_path.front();
  562. aug_path.pop_front();
  563. reversed_aug_path.push_back(b);
  564. mate[a] = b;
  565. mate[b] = a;
  566. // reset base vertex for every blossom in augment path
  567. adjust_blossom(a, b);
  568. }
  569. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  570. old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]);
  571. // correct labels for in-blossom vertices along aug_path
  572. while (!reversed_aug_path.empty())
  573. {
  574. a = reversed_aug_path.front();
  575. reversed_aug_path.pop_front();
  576. if (in_blossom[a]->father != blossom_ptr_t())
  577. relabel(a);
  578. }
  579. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  580. {
  581. vertex_descriptor_t u = *vi;
  582. if (mate[u] != graph_traits<Graph>::null_vertex())
  583. label_S[u] = mate[u];
  584. }
  585. // expand blossoms with zero dual variables
  586. std::vector<blossom_ptr_t> new_top_blossoms;
  587. for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end();)
  588. {
  589. if ((*bi)->dual_var <= 0)
  590. bi = expand_blossom(bi, new_top_blossoms);
  591. else
  592. ++bi;
  593. }
  594. top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(), new_top_blossoms.end());
  595. init();
  596. }
  597. // create a new blossom and set labels for vertices inside
  598. void blossoming(vertex_descriptor_t v, vertex_descriptor_t v_prime,
  599. vertex_descriptor_t w, vertex_descriptor_t w_prime,
  600. vertex_descriptor_t nca)
  601. {
  602. vertex_iterator_t vi, vi_end;
  603. std::vector<bool> is_old_base_vector(num_vertices(g));
  604. vertex_to_bool_map_t is_old_base(is_old_base_vector.begin(), vm);
  605. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  606. {
  607. if (*vi == base_vertex(*vi))
  608. is_old_base[*vi] = true;
  609. }
  610. blossom_ptr_t b = boost::make_shared<blossom>();
  611. add_sub_blossom(b, nca);
  612. label_T[w_prime] = v;
  613. label_T[v_prime] = w;
  614. outlet[w_prime] = w;
  615. outlet[v_prime] = v;
  616. make_blossom(b, w_prime, v_prime, nca);
  617. make_blossom(b, v_prime, w_prime, nca);
  618. label_T[nca] = graph_traits<Graph>::null_vertex();
  619. outlet[nca] = nca;
  620. top_blossoms.push_back(b);
  621. bloom(b);
  622. // set gamma[b_base] = min_slack{critical_edge(b_base, other_base)} where each critical edge
  623. // is updated before, by argmin{slack(old_bases_in_b, other_base)};
  624. vertex_vec_iter_t i, j;
  625. std::vector<vertex_descriptor_t> b_vertices = b->vertices(), old_base_in_b, other_base;
  626. vertex_descriptor_t b_base = b->get_base();
  627. for (i = b_vertices.begin(); i != b_vertices.end(); ++i)
  628. {
  629. if (is_old_base[*i])
  630. old_base_in_b.push_back(*i);
  631. }
  632. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  633. {
  634. if (*vi != b_base && *vi == base_vertex(*vi))
  635. other_base.push_back(*vi);
  636. }
  637. for (i = other_base.begin(); i != other_base.end(); ++i)
  638. {
  639. edge_property_t min_slack = std::numeric_limits<edge_property_t>::max();
  640. std::pair<edge_descriptor_t, bool> b_vi = null_edge;
  641. for (j = old_base_in_b.begin(); j != old_base_in_b.end(); ++j)
  642. {
  643. if (critical_edge[*j][*i] != null_edge && min_slack > slack(critical_edge[*j][*i].first))
  644. {
  645. min_slack = slack(critical_edge[*j][*i].first);
  646. b_vi = critical_edge[*j][*i];
  647. }
  648. }
  649. critical_edge[b_base][*i] = critical_edge[*i][b_base] = b_vi;
  650. }
  651. gamma[b_base] = std::numeric_limits<edge_property_t>::max();
  652. for (i = other_base.begin(); i != other_base.end(); ++i)
  653. {
  654. if (critical_edge[b_base][*i] != null_edge)
  655. gamma[b_base] = std::min(gamma[b_base], slack(critical_edge[b_base][*i].first));
  656. }
  657. }
  658. void init()
  659. {
  660. even_edges.clear();
  661. vertex_iterator_t vi, vi_end;
  662. typename std::vector<std::vector<std::pair<edge_descriptor_t, bool> > >::iterator vei;
  663. for (boost::tie(vi,vi_end) = vertices(g), vei = critical_edge_vectors.begin(); vi != vi_end; ++vi, ++vei)
  664. {
  665. vertex_descriptor_t u = *vi;
  666. out_edge_iterator_t ei, ei_end;
  667. gamma[u] = tau[u] = pi[u] = std::numeric_limits<edge_property_t>::max();
  668. std::fill(vei->begin(), vei->end(), null_edge);
  669. if (base_vertex(u) != u)
  670. continue;
  671. label_S[u] = label_T[u] = graph_traits<Graph>::null_vertex();
  672. outlet[u] = u;
  673. if (mate[u] == graph_traits<Graph>::null_vertex())
  674. {
  675. label_S[u] = u;
  676. bloom(in_top_blossom(u));
  677. }
  678. }
  679. }
  680. bool augment_matching()
  681. {
  682. vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor;
  683. v = w = w_free_ancestor = v_free_ancestor = graph_traits<Graph>::null_vertex();
  684. bool found_alternating_path = false;
  685. // note that we only use edges of zero slack value for augmenting
  686. while (!even_edges.empty() && !found_alternating_path)
  687. {
  688. // search for augmenting paths depth-first
  689. edge_descriptor_t current_edge = even_edges.back();
  690. even_edges.pop_back();
  691. v = source(current_edge, g);
  692. w = target(current_edge, g);
  693. vertex_descriptor_t v_prime = base_vertex(v);
  694. vertex_descriptor_t w_prime = base_vertex(w);
  695. // w_prime == v_prime implies that we get an edge that has been shrunk into a blossom
  696. if (v_prime == w_prime)
  697. continue;
  698. // a paranoid check
  699. if (label_S[v_prime] == graph_traits<Graph>::null_vertex())
  700. {
  701. std::swap(v_prime, w_prime);
  702. std::swap(v, w);
  703. }
  704. // w_prime may be unlabeled or have a T-label; replace the existed T-label if the edge slack
  705. // is smaller than current pi[w_prime] and update it. Note that a T-label is "deserved" only when pi equals zero.
  706. // also update tau and tau_idx so that tau_idx becomes T-label when a T-blossom is expanded
  707. if (label_S[w_prime] == graph_traits<Graph>::null_vertex())
  708. {
  709. if (slack(current_edge) < pi[w_prime])
  710. put_T_label(w_prime, v, w, slack(current_edge));
  711. if (slack(current_edge) < tau[w])
  712. {
  713. if (in_blossom[w]->father == blossom_ptr_t() || label_T[w_prime] == v ||
  714. label_T[w_prime] == graph_traits<Graph>::null_vertex() ||
  715. nearest_common_ancestor(v_prime, label_T[w_prime],
  716. v_free_ancestor, w_free_ancestor) == graph_traits<Graph>::null_vertex())
  717. {
  718. tau[w] = slack(current_edge);
  719. tau_idx[w] = v;
  720. }
  721. }
  722. }
  723. else
  724. {
  725. if (slack(current_edge) > 0)
  726. {
  727. // update gamma and critical_edges when we have a smaller edge slack
  728. gamma[v_prime] = std::min(gamma[v_prime], slack(current_edge));
  729. gamma[w_prime] = std::min(gamma[w_prime], slack(current_edge));
  730. if (critical_edge[v_prime][w_prime] == null_edge ||
  731. slack(critical_edge[v_prime][w_prime].first) > slack(current_edge))
  732. {
  733. critical_edge[v_prime][w_prime] = std::pair<edge_descriptor_t, bool>(current_edge, true);
  734. critical_edge[w_prime][v_prime] = std::pair<edge_descriptor_t, bool>(current_edge, true);
  735. }
  736. continue;
  737. }
  738. else if (slack(current_edge) == 0)
  739. {
  740. // if nca is null_vertex then we have an augmenting path; otherwise we have
  741. // a new top blossom with nca as its base vertex
  742. vertex_descriptor_t nca = nearest_common_ancestor(v_prime, w_prime, v_free_ancestor, w_free_ancestor);
  743. if (nca == graph_traits<Graph>::null_vertex())
  744. found_alternating_path = true; //to break out of the loop
  745. else
  746. blossoming(v, v_prime, w, w_prime, nca);
  747. }
  748. }
  749. }
  750. if (!found_alternating_path)
  751. return false;
  752. augmenting(v, v_free_ancestor, w, w_free_ancestor);
  753. return true;
  754. }
  755. // slack the vertex and blossom dual variables when there is no augmenting path found
  756. // according to the primal-dual method
  757. bool adjust_dual()
  758. {
  759. edge_property_t delta1, delta2, delta3, delta4, delta;
  760. delta1 = delta2 = delta3 = delta4 = std::numeric_limits<edge_property_t>::max();
  761. vertex_iterator_t vi, vi_end;
  762. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  763. {
  764. delta1 = std::min(delta1, dual_var[*vi]);
  765. delta4 = pi[*vi] > 0 ? std::min(delta4, pi[*vi]) : delta4;
  766. if (*vi == base_vertex(*vi))
  767. delta3 = std::min(delta3, gamma[*vi]/2);
  768. }
  769. for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end(); ++bi)
  770. {
  771. vertex_descriptor_t b_base = (*bi)->get_base();
  772. if (label_T[b_base] != graph_traits<Graph>::null_vertex() && pi[b_base] == 0)
  773. delta2 = std::min(delta2, (*bi)->dual_var/2);
  774. }
  775. delta = std::min(std::min(delta1, delta2), std::min(delta3, delta4));
  776. // start updating dual variables, note that the order is important
  777. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  778. {
  779. vertex_descriptor_t v = *vi, v_prime = base_vertex(v);
  780. if (label_S[v_prime] != graph_traits<Graph>::null_vertex())
  781. dual_var[v] -= delta;
  782. else if (label_T[v_prime] != graph_traits<Graph>::null_vertex() && pi[v_prime] == 0)
  783. dual_var[v] += delta;
  784. if (v == v_prime)
  785. gamma[v] -= 2*delta;
  786. }
  787. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  788. {
  789. vertex_descriptor_t v_prime = base_vertex(*vi);
  790. if (pi[v_prime] > 0)
  791. tau[*vi] -= delta;
  792. }
  793. for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end(); ++bi)
  794. {
  795. vertex_descriptor_t b_base = (*bi)->get_base();
  796. if (label_T[b_base] != graph_traits<Graph>::null_vertex() && pi[b_base] == 0)
  797. (*bi)->dual_var -= 2*delta;
  798. if (label_S[b_base] != graph_traits<Graph>::null_vertex())
  799. (*bi)->dual_var += 2*delta;
  800. }
  801. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  802. {
  803. vertex_descriptor_t v = *vi;
  804. if (pi[v] > 0)
  805. pi[v] -= delta;
  806. // when some T-vertices have zero pi value, bloom their mates so that matching can be further augmented
  807. if (label_T[v] != graph_traits<Graph>::null_vertex() && pi[v] == 0)
  808. put_T_label(v, label_T[v], outlet[v], pi[v]);
  809. }
  810. // optimal solution reached, halt
  811. if (delta == delta1)
  812. return false;
  813. // expand odd blossoms with zero dual variables and zero pi value of their base vertices
  814. if (delta == delta2 && delta != delta3)
  815. {
  816. std::vector<blossom_ptr_t> new_top_blossoms;
  817. for (blossom_iterator_t bi = top_blossoms.begin(); bi != top_blossoms.end();)
  818. {
  819. const blossom_ptr_t b = *bi;
  820. vertex_descriptor_t b_base = b->get_base();
  821. if (b->dual_var == 0 && label_T[b_base] != graph_traits<Graph>::null_vertex() && pi[b_base] == 0)
  822. bi = expand_T_blossom(bi, new_top_blossoms);
  823. else
  824. ++bi;
  825. }
  826. top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(), new_top_blossoms.end());
  827. }
  828. while (true)
  829. {
  830. // find a zero-slack critical edge (v, w) of zero gamma values
  831. std::pair<edge_descriptor_t, bool> best_edge = null_edge;
  832. std::vector<vertex_descriptor_t> base_nodes;
  833. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  834. {
  835. if (*vi == base_vertex(*vi))
  836. base_nodes.push_back(*vi);
  837. }
  838. for (vertex_vec_iter_t i = base_nodes.begin(); i != base_nodes.end(); ++i)
  839. {
  840. if (gamma[*i] == 0)
  841. {
  842. for (vertex_vec_iter_t j = base_nodes.begin(); j != base_nodes.end(); ++j)
  843. {
  844. if (critical_edge[*i][*j] != null_edge && slack(critical_edge[*i][*j].first) == 0)
  845. best_edge = critical_edge[*i][*j];
  846. }
  847. }
  848. }
  849. // if not found, continue finding other augment matching
  850. if (best_edge == null_edge)
  851. {
  852. bool augmented = augment_matching();
  853. return augmented || delta != delta1;
  854. }
  855. // if found, determine either augmenting or blossoming
  856. vertex_descriptor_t v = source(best_edge.first, g), w = target(best_edge.first, g);
  857. vertex_descriptor_t v_prime = base_vertex(v), w_prime = base_vertex(w), v_free_ancestor, w_free_ancestor;
  858. vertex_descriptor_t nca = nearest_common_ancestor(v_prime, w_prime, v_free_ancestor, w_free_ancestor);
  859. if (nca == graph_traits<Graph>::null_vertex())
  860. {
  861. augmenting(v, v_free_ancestor, w, w_free_ancestor);
  862. return true;
  863. }
  864. else
  865. blossoming(v, v_prime, w, w_prime, nca);
  866. }
  867. return false;
  868. }
  869. template <typename PropertyMap>
  870. void get_current_matching(PropertyMap pm)
  871. {
  872. vertex_iterator_t vi, vi_end;
  873. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  874. put(pm, *vi, mate[*vi]);
  875. }
  876. private:
  877. const Graph& g;
  878. VertexIndexMap vm;
  879. const std::pair<edge_descriptor_t, bool> null_edge;
  880. // storage for the property maps below
  881. std::vector<vertex_descriptor_t> mate_vector;
  882. std::vector<vertex_descriptor_t> label_S_vector, label_T_vector;
  883. std::vector<vertex_descriptor_t> outlet_vector;
  884. std::vector<vertex_descriptor_t> tau_idx_vector;
  885. std::vector<edge_property_t> dual_var_vector;
  886. std::vector<edge_property_t> pi_vector, gamma_vector, tau_vector;
  887. std::vector<blossom_ptr_t> in_blossom_vector;
  888. std::vector<std::pair<vertex_descriptor_t, vertex_descriptor_t> > old_label_vector;
  889. std::vector<vertex_to_edge_map_t> critical_edge_vector;
  890. std::vector<std::vector<std::pair<edge_descriptor_t, bool> > > critical_edge_vectors;
  891. // iterator property maps
  892. vertex_to_vertex_map_t mate;
  893. vertex_to_vertex_map_t label_S; // v has an S-label -> v can be an even vertex, label_S[v] is its mate
  894. vertex_to_vertex_map_t label_T; // v has a T-label -> v can be an odd vertex, label_T[v] is its predecessor in aug_path
  895. vertex_to_vertex_map_t outlet;
  896. vertex_to_vertex_map_t tau_idx;
  897. vertex_to_weight_map_t dual_var;
  898. vertex_to_weight_map_t pi, gamma, tau;
  899. vertex_to_blossom_map_t in_blossom; // map any vertex v to the trivial blossom containing v
  900. vertex_to_pair_map_t old_label; // <old T-label, old outlet> before relabeling or expanding T-blossoms
  901. vertex_pair_to_edge_map_t critical_edge; // an not matched edge (v, w) is critical if v and w belongs to different S-blossoms
  902. vertex_list_t aug_path;
  903. edge_list_t even_edges;
  904. std::vector<blossom_ptr_t> top_blossoms;
  905. };
  906. template <typename Graph, typename MateMap, typename VertexIndexMap>
  907. void maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
  908. {
  909. empty_matching<Graph, MateMap>::find_matching(g, mate);
  910. weighted_augmenting_path_finder<Graph, MateMap, VertexIndexMap> augmentor(g, mate, vm);
  911. // can have |V| times augmenting at most
  912. for (std::size_t t = 0; t < num_vertices(g); ++t)
  913. {
  914. bool augmented = false;
  915. while (!augmented)
  916. {
  917. augmented = augmentor.augment_matching();
  918. if (!augmented)
  919. {
  920. // halt if adjusting dual variables can't bring potential augment
  921. if (!augmentor.adjust_dual())
  922. break;
  923. }
  924. }
  925. if (!augmented)
  926. break;
  927. }
  928. augmentor.get_current_matching(mate);
  929. }
  930. template <typename Graph, typename MateMap>
  931. inline void maximum_weighted_matching(const Graph& g, MateMap mate)
  932. {
  933. maximum_weighted_matching(g, mate, get(vertex_index,g));
  934. }
  935. // brute-force matcher searches all possible combinations of matched edges to get the maximum weighted matching
  936. // which can be used for testing on small graphs (within dozens vertices)
  937. template <typename Graph, typename MateMap, typename VertexIndexMap>
  938. class brute_force_matching
  939. {
  940. public:
  941. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor_t;
  942. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
  943. typedef typename std::vector<vertex_descriptor_t>::iterator vertex_vec_iter_t;
  944. typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
  945. typedef boost::iterator_property_map<vertex_vec_iter_t, VertexIndexMap> vertex_to_vertex_map_t;
  946. brute_force_matching(const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) :
  947. g(arg_g),
  948. vm(arg_vm),
  949. mate_vector(num_vertices(g)),
  950. best_mate_vector(num_vertices(g)),
  951. mate(mate_vector.begin(), vm),
  952. best_mate(best_mate_vector.begin(), vm)
  953. {
  954. vertex_iterator_t vi,vi_end;
  955. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  956. best_mate[*vi] = mate[*vi] = get(arg_mate, *vi);
  957. }
  958. template <typename PropertyMap>
  959. void find_matching(PropertyMap pm)
  960. {
  961. edge_iterator_t ei;
  962. boost::tie(ei, ei_end) = edges(g);
  963. select_edge(ei);
  964. vertex_iterator_t vi,vi_end;
  965. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  966. put(pm, *vi, best_mate[*vi]);
  967. }
  968. private:
  969. const Graph& g;
  970. VertexIndexMap vm;
  971. std::vector<vertex_descriptor_t> mate_vector, best_mate_vector;
  972. vertex_to_vertex_map_t mate, best_mate;
  973. edge_iterator_t ei_end;
  974. void select_edge(edge_iterator_t ei)
  975. {
  976. if (ei == ei_end)
  977. {
  978. if (matching_weight_sum(g, mate) > matching_weight_sum(g, best_mate))
  979. {
  980. vertex_iterator_t vi, vi_end;
  981. for (boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  982. best_mate[*vi] = mate[*vi];
  983. }
  984. return;
  985. }
  986. vertex_descriptor_t v, w;
  987. v = source(*ei, g);
  988. w = target(*ei, g);
  989. select_edge(++ei);
  990. if (mate[v] == graph_traits<Graph>::null_vertex() &&
  991. mate[w] == graph_traits<Graph>::null_vertex())
  992. {
  993. mate[v] = w;
  994. mate[w] = v;
  995. select_edge(ei);
  996. mate[v] = mate[w] = graph_traits<Graph>::null_vertex();
  997. }
  998. }
  999. };
  1000. template <typename Graph, typename MateMap, typename VertexIndexMap>
  1001. void brute_force_maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
  1002. {
  1003. empty_matching<Graph, MateMap>::find_matching(g, mate);
  1004. brute_force_matching<Graph, MateMap, VertexIndexMap> brute_force_matcher(g, mate, vm);
  1005. brute_force_matcher.find_matching(mate);
  1006. }
  1007. template <typename Graph, typename MateMap>
  1008. inline void brute_force_maximum_weighted_matching(const Graph& g, MateMap mate)
  1009. {
  1010. brute_force_maximum_weighted_matching(g, mate, get(vertex_index, g));
  1011. }
  1012. }
  1013. #endif