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