File indexing completed on 2025-01-18 09:37:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
0011 #define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
0012
0013 #include <vector>
0014 #include <list>
0015 #include <deque>
0016 #include <algorithm> // for std::sort and std::stable_sort
0017 #include <utility> // for std::pair
0018 #include <boost/property_map/property_map.hpp>
0019 #include <boost/graph/graph_traits.hpp>
0020 #include <boost/graph/visitors.hpp>
0021 #include <boost/graph/depth_first_search.hpp>
0022 #include <boost/graph/filtered_graph.hpp>
0023 #include <boost/pending/disjoint_sets.hpp>
0024 #include <boost/assert.hpp>
0025
0026 namespace boost
0027 {
0028 namespace graph
0029 {
0030 namespace detail
0031 {
0032 enum VERTEX_STATE
0033 {
0034 V_EVEN,
0035 V_ODD,
0036 V_UNREACHED
0037 };
0038 }
0039 }
0040
0041 template < typename Graph, typename MateMap, typename VertexIndexMap >
0042 typename graph_traits< Graph >::vertices_size_type matching_size(
0043 const Graph& g, MateMap mate, VertexIndexMap vm)
0044 {
0045 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0046 typedef
0047 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0048 typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
0049
0050 v_size_t size_of_matching = 0;
0051 vertex_iterator_t vi, vi_end;
0052
0053 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0054 {
0055 vertex_descriptor_t v = *vi;
0056 if (get(mate, v) != graph_traits< Graph >::null_vertex()
0057 && get(vm, v) < get(vm, get(mate, v)))
0058 ++size_of_matching;
0059 }
0060 return size_of_matching;
0061 }
0062
0063 template < typename Graph, typename MateMap >
0064 inline typename graph_traits< Graph >::vertices_size_type matching_size(
0065 const Graph& g, MateMap mate)
0066 {
0067 return matching_size(g, mate, get(vertex_index, g));
0068 }
0069
0070 template < typename Graph, typename MateMap, typename VertexIndexMap >
0071 bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap)
0072 {
0073 typedef
0074 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0075 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0076
0077 vertex_iterator_t vi, vi_end;
0078 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0079 {
0080 vertex_descriptor_t v = *vi;
0081 if (get(mate, v) != graph_traits< Graph >::null_vertex()
0082 && v != get(mate, get(mate, v)))
0083 return false;
0084 }
0085 return true;
0086 }
0087
0088 template < typename Graph, typename MateMap >
0089 inline bool is_a_matching(const Graph& g, MateMap mate)
0090 {
0091 return is_a_matching(g, mate, get(vertex_index, g));
0092 }
0093
0094
0095
0096
0097
0098
0099
0100 template < typename Graph, typename MateMap,
0101 typename VertexIndexMap = dummy_property_map >
0102 struct no_augmenting_path_finder
0103 {
0104 no_augmenting_path_finder(const Graph&, MateMap, VertexIndexMap) {}
0105
0106 inline bool augment_matching() { return false; }
0107
0108 template < typename PropertyMap > void get_current_matching(PropertyMap) {}
0109 };
0110
0111 template < typename Graph, typename MateMap, typename VertexIndexMap >
0112 class edmonds_augmenting_path_finder
0113 {
0114
0115
0116
0117
0118 public:
0119
0120 template < typename X > struct map_vertex_to_
0121 {
0122 typedef boost::iterator_property_map<
0123 typename std::vector< X >::iterator, VertexIndexMap >
0124 type;
0125 };
0126
0127 typedef
0128 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0129 typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_t >
0130 vertex_pair_t;
0131 typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
0132 typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
0133 typedef typename graph_traits< Graph >::edges_size_type e_size_t;
0134 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0135 typedef
0136 typename graph_traits< Graph >::out_edge_iterator out_edge_iterator_t;
0137 typedef typename std::deque< vertex_descriptor_t > vertex_list_t;
0138 typedef typename std::vector< edge_descriptor_t > edge_list_t;
0139 typedef typename map_vertex_to_< vertex_descriptor_t >::type
0140 vertex_to_vertex_map_t;
0141 typedef typename map_vertex_to_< int >::type vertex_to_int_map_t;
0142 typedef typename map_vertex_to_< vertex_pair_t >::type
0143 vertex_to_vertex_pair_map_t;
0144 typedef typename map_vertex_to_< v_size_t >::type vertex_to_vsize_map_t;
0145 typedef typename map_vertex_to_< e_size_t >::type vertex_to_esize_map_t;
0146
0147 edmonds_augmenting_path_finder(
0148 const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm)
0149 : g(arg_g)
0150 , vm(arg_vm)
0151 , n_vertices(num_vertices(arg_g))
0152 ,
0153
0154 mate_vector(n_vertices)
0155 , ancestor_of_v_vector(n_vertices)
0156 , ancestor_of_w_vector(n_vertices)
0157 , vertex_state_vector(n_vertices)
0158 , origin_vector(n_vertices)
0159 , pred_vector(n_vertices)
0160 , bridge_vector(n_vertices)
0161 , ds_parent_vector(n_vertices)
0162 , ds_rank_vector(n_vertices)
0163 ,
0164
0165 mate(mate_vector.begin(), vm)
0166 , ancestor_of_v(ancestor_of_v_vector.begin(), vm)
0167 , ancestor_of_w(ancestor_of_w_vector.begin(), vm)
0168 , vertex_state(vertex_state_vector.begin(), vm)
0169 , origin(origin_vector.begin(), vm)
0170 , pred(pred_vector.begin(), vm)
0171 , bridge(bridge_vector.begin(), vm)
0172 , ds_parent_map(ds_parent_vector.begin(), vm)
0173 , ds_rank_map(ds_rank_vector.begin(), vm)
0174 ,
0175
0176 ds(ds_rank_map, ds_parent_map)
0177 {
0178 vertex_iterator_t vi, vi_end;
0179 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0180 mate[*vi] = get(arg_mate, *vi);
0181 }
0182
0183 bool augment_matching()
0184 {
0185
0186
0187
0188
0189
0190 e_size_t timestamp = 0;
0191 even_edges.clear();
0192
0193 vertex_iterator_t vi, vi_end;
0194 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0195 {
0196 vertex_descriptor_t u = *vi;
0197
0198 origin[u] = u;
0199 pred[u] = u;
0200 ancestor_of_v[u] = 0;
0201 ancestor_of_w[u] = 0;
0202 ds.make_set(u);
0203
0204 if (mate[u] == graph_traits< Graph >::null_vertex())
0205 {
0206 vertex_state[u] = graph::detail::V_EVEN;
0207 out_edge_iterator_t ei, ei_end;
0208 for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end;
0209 ++ei)
0210 {
0211 if (target(*ei, g) != u)
0212 {
0213 even_edges.push_back(*ei);
0214 }
0215 }
0216 }
0217 else
0218 vertex_state[u] = graph::detail::V_UNREACHED;
0219 }
0220
0221
0222
0223 vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor;
0224 w_free_ancestor = graph_traits< Graph >::null_vertex();
0225 v_free_ancestor = graph_traits< Graph >::null_vertex();
0226 bool found_alternating_path = false;
0227
0228 while (!even_edges.empty() && !found_alternating_path)
0229 {
0230
0231
0232
0233 edge_descriptor_t current_edge = even_edges.back();
0234 even_edges.pop_back();
0235
0236 v = source(current_edge, g);
0237 w = target(current_edge, g);
0238
0239 vertex_descriptor_t v_prime = origin[ds.find_set(v)];
0240 vertex_descriptor_t w_prime = origin[ds.find_set(w)];
0241
0242
0243
0244
0245 if (vertex_state[v_prime] != graph::detail::V_EVEN)
0246 {
0247 std::swap(v_prime, w_prime);
0248 std::swap(v, w);
0249 }
0250
0251 if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
0252 {
0253 vertex_state[w_prime] = graph::detail::V_ODD;
0254 vertex_descriptor_t w_prime_mate = mate[w_prime];
0255 vertex_state[w_prime_mate] = graph::detail::V_EVEN;
0256 out_edge_iterator_t ei, ei_end;
0257 for (boost::tie(ei, ei_end) = out_edges(w_prime_mate, g);
0258 ei != ei_end; ++ei)
0259 {
0260 if (target(*ei, g) != w_prime_mate)
0261 {
0262 even_edges.push_back(*ei);
0263 }
0264 }
0265 pred[w_prime] = v;
0266 }
0267
0268
0269
0270 else if (vertex_state[w_prime] == graph::detail::V_EVEN
0271 && w_prime != v_prime)
0272 {
0273 vertex_descriptor_t w_up = w_prime;
0274 vertex_descriptor_t v_up = v_prime;
0275 vertex_descriptor_t nearest_common_ancestor
0276 = graph_traits< Graph >::null_vertex();
0277 w_free_ancestor = graph_traits< Graph >::null_vertex();
0278 v_free_ancestor = graph_traits< Graph >::null_vertex();
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288 ++timestamp;
0289
0290 while (nearest_common_ancestor
0291 == graph_traits< Graph >::null_vertex()
0292 && (v_free_ancestor == graph_traits< Graph >::null_vertex()
0293 || w_free_ancestor
0294 == graph_traits< Graph >::null_vertex()))
0295 {
0296 ancestor_of_w[w_up] = timestamp;
0297 ancestor_of_v[v_up] = timestamp;
0298
0299 if (w_free_ancestor == graph_traits< Graph >::null_vertex())
0300 w_up = parent(w_up);
0301 if (v_free_ancestor == graph_traits< Graph >::null_vertex())
0302 v_up = parent(v_up);
0303
0304 if (mate[v_up] == graph_traits< Graph >::null_vertex())
0305 v_free_ancestor = v_up;
0306 if (mate[w_up] == graph_traits< Graph >::null_vertex())
0307 w_free_ancestor = w_up;
0308
0309 if (ancestor_of_w[v_up] == timestamp)
0310 nearest_common_ancestor = v_up;
0311 else if (ancestor_of_v[w_up] == timestamp)
0312 nearest_common_ancestor = w_up;
0313 else if (v_free_ancestor == w_free_ancestor
0314 && v_free_ancestor
0315 != graph_traits< Graph >::null_vertex())
0316 nearest_common_ancestor = v_up;
0317 }
0318
0319 if (nearest_common_ancestor
0320 == graph_traits< Graph >::null_vertex())
0321 found_alternating_path = true;
0322 else
0323 {
0324
0325 link_and_set_bridges(
0326 w_prime, nearest_common_ancestor, std::make_pair(w, v));
0327 link_and_set_bridges(
0328 v_prime, nearest_common_ancestor, std::make_pair(v, w));
0329 }
0330 }
0331 }
0332
0333 if (!found_alternating_path)
0334 return false;
0335
0336
0337 reversed_retrieve_augmenting_path(v, v_free_ancestor);
0338 retrieve_augmenting_path(w, w_free_ancestor);
0339
0340
0341 vertex_descriptor_t a, b;
0342 while (!aug_path.empty())
0343 {
0344 a = aug_path.front();
0345 aug_path.pop_front();
0346 b = aug_path.front();
0347 aug_path.pop_front();
0348 mate[a] = b;
0349 mate[b] = a;
0350 }
0351
0352 return true;
0353 }
0354
0355 template < typename PropertyMap > void get_current_matching(PropertyMap pm)
0356 {
0357 vertex_iterator_t vi, vi_end;
0358 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0359 put(pm, *vi, mate[*vi]);
0360 }
0361
0362 template < typename PropertyMap > void get_vertex_state_map(PropertyMap pm)
0363 {
0364 vertex_iterator_t vi, vi_end;
0365 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0366 put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]);
0367 }
0368
0369 private:
0370 vertex_descriptor_t parent(vertex_descriptor_t x)
0371 {
0372 if (vertex_state[x] == graph::detail::V_EVEN
0373 && mate[x] != graph_traits< Graph >::null_vertex())
0374 return mate[x];
0375 else if (vertex_state[x] == graph::detail::V_ODD)
0376 return origin[ds.find_set(pred[x])];
0377 else
0378 return x;
0379 }
0380
0381 void link_and_set_bridges(vertex_descriptor_t x,
0382 vertex_descriptor_t stop_vertex, vertex_pair_t the_bridge)
0383 {
0384 for (vertex_descriptor_t v = x; v != stop_vertex; v = parent(v))
0385 {
0386 ds.union_set(v, stop_vertex);
0387 origin[ds.find_set(stop_vertex)] = stop_vertex;
0388
0389 if (vertex_state[v] == graph::detail::V_ODD)
0390 {
0391 bridge[v] = the_bridge;
0392 out_edge_iterator_t oei, oei_end;
0393 for (boost::tie(oei, oei_end) = out_edges(v, g); oei != oei_end;
0394 ++oei)
0395 {
0396 if (target(*oei, g) != v)
0397 {
0398 even_edges.push_back(*oei);
0399 }
0400 }
0401 }
0402 }
0403 }
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420 void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w)
0421 {
0422 if (v == w)
0423 aug_path.push_back(v);
0424 else if (vertex_state[v] == graph::detail::V_EVEN)
0425 {
0426 aug_path.push_back(v);
0427 aug_path.push_back(mate[v]);
0428 retrieve_augmenting_path(pred[mate[v]], w);
0429 }
0430 else
0431 {
0432 aug_path.push_back(v);
0433 reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
0434 retrieve_augmenting_path(bridge[v].second, w);
0435 }
0436 }
0437
0438 void reversed_retrieve_augmenting_path(
0439 vertex_descriptor_t v, vertex_descriptor_t w)
0440 {
0441
0442 if (v == w)
0443 aug_path.push_back(v);
0444 else if (vertex_state[v] == graph::detail::V_EVEN)
0445 {
0446 reversed_retrieve_augmenting_path(pred[mate[v]], w);
0447 aug_path.push_back(mate[v]);
0448 aug_path.push_back(v);
0449 }
0450 else
0451 {
0452 reversed_retrieve_augmenting_path(bridge[v].second, w);
0453 retrieve_augmenting_path(bridge[v].first, mate[v]);
0454 aug_path.push_back(v);
0455 }
0456 }
0457
0458
0459
0460 const Graph& g;
0461 VertexIndexMap vm;
0462 v_size_t n_vertices;
0463
0464
0465 std::vector< vertex_descriptor_t > mate_vector;
0466 std::vector< e_size_t > ancestor_of_v_vector;
0467 std::vector< e_size_t > ancestor_of_w_vector;
0468 std::vector< int > vertex_state_vector;
0469 std::vector< vertex_descriptor_t > origin_vector;
0470 std::vector< vertex_descriptor_t > pred_vector;
0471 std::vector< vertex_pair_t > bridge_vector;
0472 std::vector< vertex_descriptor_t > ds_parent_vector;
0473 std::vector< v_size_t > ds_rank_vector;
0474
0475
0476 vertex_to_vertex_map_t mate;
0477 vertex_to_esize_map_t ancestor_of_v;
0478 vertex_to_esize_map_t ancestor_of_w;
0479 vertex_to_int_map_t vertex_state;
0480 vertex_to_vertex_map_t origin;
0481 vertex_to_vertex_map_t pred;
0482 vertex_to_vertex_pair_map_t bridge;
0483 vertex_to_vertex_map_t ds_parent_map;
0484 vertex_to_vsize_map_t ds_rank_map;
0485
0486 vertex_list_t aug_path;
0487 edge_list_t even_edges;
0488 disjoint_sets< vertex_to_vsize_map_t, vertex_to_vertex_map_t > ds;
0489 };
0490
0491
0492
0493
0494
0495
0496
0497 template < typename Graph, typename MateMap > struct greedy_matching
0498 {
0499 typedef
0500 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0501 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0502 typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
0503 typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
0504
0505 static void find_matching(const Graph& g, MateMap mate)
0506 {
0507 vertex_iterator_t vi, vi_end;
0508 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0509 put(mate, *vi, graph_traits< Graph >::null_vertex());
0510
0511 edge_iterator_t ei, ei_end;
0512 for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
0513 {
0514 edge_descriptor_t e = *ei;
0515 vertex_descriptor_t u = source(e, g);
0516 vertex_descriptor_t v = target(e, g);
0517
0518 if (u != v && get(mate, u) == get(mate, v))
0519
0520
0521 {
0522 put(mate, u, v);
0523 put(mate, v, u);
0524 }
0525 }
0526 }
0527 };
0528
0529 template < typename Graph, typename MateMap > struct extra_greedy_matching
0530 {
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540 typedef
0541 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0542 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0543 typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t;
0544 typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t;
0545 typedef std::pair< vertex_descriptor_t, vertex_descriptor_t > vertex_pair_t;
0546
0547 struct select_first
0548 {
0549 inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
0550 {
0551 return p.first;
0552 }
0553 };
0554
0555 struct select_second
0556 {
0557 inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
0558 {
0559 return p.second;
0560 }
0561 };
0562
0563 template < class PairSelector > class less_than_by_degree
0564 {
0565 public:
0566 less_than_by_degree(const Graph& g) : m_g(g) {}
0567 bool operator()(const vertex_pair_t x, const vertex_pair_t y)
0568 {
0569 return out_degree(PairSelector::select_vertex(x), m_g)
0570 < out_degree(PairSelector::select_vertex(y), m_g);
0571 }
0572
0573 private:
0574 const Graph& m_g;
0575 };
0576
0577 static void find_matching(const Graph& g, MateMap mate)
0578 {
0579 typedef std::vector<
0580 std::pair< vertex_descriptor_t, vertex_descriptor_t > >
0581 directed_edges_vector_t;
0582
0583 directed_edges_vector_t edge_list;
0584 vertex_iterator_t vi, vi_end;
0585 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0586 put(mate, *vi, graph_traits< Graph >::null_vertex());
0587
0588 edge_iterator_t ei, ei_end;
0589 for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
0590 {
0591 edge_descriptor_t e = *ei;
0592 vertex_descriptor_t u = source(e, g);
0593 vertex_descriptor_t v = target(e, g);
0594 if (u == v)
0595 continue;
0596 edge_list.push_back(std::make_pair(u, v));
0597 edge_list.push_back(std::make_pair(v, u));
0598 }
0599
0600
0601
0602 std::sort(edge_list.begin(), edge_list.end(),
0603 less_than_by_degree< select_second >(g));
0604 std::stable_sort(edge_list.begin(), edge_list.end(),
0605 less_than_by_degree< select_first >(g));
0606
0607
0608 for (typename directed_edges_vector_t::const_iterator itr
0609 = edge_list.begin();
0610 itr != edge_list.end(); ++itr)
0611 {
0612 if (get(mate, itr->first) == get(mate, itr->second))
0613
0614
0615 {
0616 put(mate, itr->first, itr->second);
0617 put(mate, itr->second, itr->first);
0618 }
0619 }
0620 }
0621 };
0622
0623 template < typename Graph, typename MateMap > struct empty_matching
0624 {
0625 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0626
0627 static void find_matching(const Graph& g, MateMap mate)
0628 {
0629 vertex_iterator_t vi, vi_end;
0630 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0631 put(mate, *vi, graph_traits< Graph >::null_vertex());
0632 }
0633 };
0634
0635
0636
0637
0638
0639
0640
0641 namespace detail
0642 {
0643
0644 template < typename SizeType >
0645 class odd_components_counter : public dfs_visitor<>
0646
0647
0648
0649 {
0650 public:
0651 odd_components_counter(SizeType& c_count) : m_count(c_count)
0652 {
0653 m_count = 0;
0654 }
0655
0656 template < class Vertex, class Graph > void start_vertex(Vertex, Graph&)
0657 {
0658 m_parity = false;
0659 }
0660
0661 template < class Vertex, class Graph >
0662 void discover_vertex(Vertex, Graph&)
0663 {
0664 m_parity = !m_parity;
0665 m_parity ? ++m_count : --m_count;
0666 }
0667
0668 protected:
0669 SizeType& m_count;
0670
0671 private:
0672 bool m_parity;
0673 };
0674
0675 }
0676
0677 template < typename Graph, typename MateMap,
0678 typename VertexIndexMap = dummy_property_map >
0679 struct no_matching_verifier
0680 {
0681 inline static bool verify_matching(const Graph&, MateMap, VertexIndexMap)
0682 {
0683 return true;
0684 }
0685 };
0686
0687 template < typename Graph, typename MateMap, typename VertexIndexMap >
0688 struct maximum_cardinality_matching_verifier
0689 {
0690
0691 template < typename X > struct map_vertex_to_
0692 {
0693 typedef boost::iterator_property_map<
0694 typename std::vector< X >::iterator, VertexIndexMap >
0695 type;
0696 };
0697
0698 typedef
0699 typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t;
0700 typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
0701 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0702 typedef typename map_vertex_to_< int >::type vertex_to_int_map_t;
0703 typedef typename map_vertex_to_< vertex_descriptor_t >::type
0704 vertex_to_vertex_map_t;
0705
0706 template < typename VertexStateMap > struct non_odd_vertex
0707 {
0708
0709
0710 non_odd_vertex() : vertex_state(0) {}
0711
0712 non_odd_vertex(VertexStateMap* arg_vertex_state)
0713 : vertex_state(arg_vertex_state)
0714 {
0715 }
0716
0717 template < typename Vertex > bool operator()(const Vertex& v) const
0718 {
0719 BOOST_ASSERT(vertex_state);
0720 return get(*vertex_state, v) != graph::detail::V_ODD;
0721 }
0722
0723 VertexStateMap* vertex_state;
0724 };
0725
0726 static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
0727 {
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745 if (!is_a_matching(g, mate, vm))
0746 return false;
0747
0748
0749
0750
0751
0752
0753
0754
0755 edmonds_augmenting_path_finder< Graph, MateMap, VertexIndexMap >
0756 augmentor(g, mate, vm);
0757 if (augmentor.augment_matching())
0758 return false;
0759
0760 std::vector< int > vertex_state_vector(num_vertices(g));
0761 vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm);
0762 augmentor.get_vertex_state_map(vertex_state);
0763
0764
0765 v_size_t num_odd_vertices = 0;
0766 vertex_iterator_t vi, vi_end;
0767 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0768 if (vertex_state[*vi] == graph::detail::V_ODD)
0769 ++num_odd_vertices;
0770
0771
0772
0773 non_odd_vertex< vertex_to_int_map_t > filter(&vertex_state);
0774 filtered_graph< Graph, keep_all, non_odd_vertex< vertex_to_int_map_t > >
0775 fg(g, keep_all(), filter);
0776
0777 v_size_t num_odd_components;
0778 detail::odd_components_counter< v_size_t > occ(num_odd_components);
0779 depth_first_search(fg, visitor(occ).vertex_index_map(vm));
0780
0781 if (2 * matching_size(g, mate, vm)
0782 == num_vertices(g) + num_odd_vertices - num_odd_components)
0783 return true;
0784 else
0785 return false;
0786 }
0787 };
0788
0789 template < typename Graph, typename MateMap, typename VertexIndexMap,
0790 template < typename, typename, typename > class AugmentingPathFinder,
0791 template < typename, typename > class InitialMatchingFinder,
0792 template < typename, typename, typename > class MatchingVerifier >
0793 bool matching(const Graph& g, MateMap mate, VertexIndexMap vm)
0794 {
0795
0796 InitialMatchingFinder< Graph, MateMap >::find_matching(g, mate);
0797
0798 AugmentingPathFinder< Graph, MateMap, VertexIndexMap > augmentor(
0799 g, mate, vm);
0800 bool not_maximum_yet = true;
0801 while (not_maximum_yet)
0802 {
0803 not_maximum_yet = augmentor.augment_matching();
0804 }
0805 augmentor.get_current_matching(mate);
0806
0807 return MatchingVerifier< Graph, MateMap, VertexIndexMap >::verify_matching(
0808 g, mate, vm);
0809 }
0810
0811 template < typename Graph, typename MateMap, typename VertexIndexMap >
0812 inline bool checked_edmonds_maximum_cardinality_matching(
0813 const Graph& g, MateMap mate, VertexIndexMap vm)
0814 {
0815 return matching< Graph, MateMap, VertexIndexMap,
0816 edmonds_augmenting_path_finder, extra_greedy_matching,
0817 maximum_cardinality_matching_verifier >(g, mate, vm);
0818 }
0819
0820 template < typename Graph, typename MateMap >
0821 inline bool checked_edmonds_maximum_cardinality_matching(
0822 const Graph& g, MateMap mate)
0823 {
0824 return checked_edmonds_maximum_cardinality_matching(
0825 g, mate, get(vertex_index, g));
0826 }
0827
0828 template < typename Graph, typename MateMap, typename VertexIndexMap >
0829 inline void edmonds_maximum_cardinality_matching(
0830 const Graph& g, MateMap mate, VertexIndexMap vm)
0831 {
0832 matching< Graph, MateMap, VertexIndexMap, edmonds_augmenting_path_finder,
0833 extra_greedy_matching, no_matching_verifier >(g, mate, vm);
0834 }
0835
0836 template < typename Graph, typename MateMap >
0837 inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate)
0838 {
0839 edmonds_maximum_cardinality_matching(g, mate, get(vertex_index, g));
0840 }
0841
0842 }
0843
0844 #endif