Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:32

0001 //=======================================================================
0002 // Copyright (c) 2005 Aaron Windsor
0003 //
0004 // Distributed under the Boost Software License, Version 1.0.
0005 // (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
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 } // end namespace graph::detail
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 //               Maximum Cardinality Matching Functors
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     // This implementation of Edmonds' matching algorithm closely
0115     // follows Tarjan's description of the algorithm in "Data
0116     // Structures and Network Algorithms."
0117 
0118 public:
0119     // generates the type of an iterator property map from vertices to type X
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         // As an optimization, some of these values can be saved from one
0186         // iteration to the next instead of being re-initialized each
0187         // iteration, allowing for "lazy blossom expansion." This is not
0188         // currently implemented.
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         // end initializations
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             // since we push even edges onto the back of the list as
0231             // they're discovered, taking them off the back will search
0232             // for augmenting paths depth-first.
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             // because of the way we put all of the edges on the queue,
0243             // v_prime should be labeled V_EVEN; the following is a
0244             // little paranoid but it could happen...
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             // w_prime == v_prime can happen below if we get an edge that has
0269             // been shrunk into a blossom
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                 // We now need to distinguish between the case that
0281                 // w_prime and v_prime share an ancestor under the
0282                 // "parent" relation, in which case we've found a
0283                 // blossom and should shrink it, or the case that
0284                 // w_prime and v_prime both have distinct ancestors that
0285                 // are free, in which case we've found an alternating
0286                 // path between those two ancestors.
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; // to break out of the loop
0322                 else
0323                 {
0324                     // shrink the blossom
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         // retrieve the augmenting path and put it in aug_path
0337         reversed_retrieve_augmenting_path(v, v_free_ancestor);
0338         retrieve_augmenting_path(w, w_free_ancestor);
0339 
0340         // augment the matching along aug_path
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     // Since none of the STL containers support both constant-time
0406     // concatenation and reversal, the process of expanding an
0407     // augmenting path once we know one exists is a little more
0408     // complicated than it has to be. If we know the path is from v to
0409     // w, then the augmenting path is recursively defined as:
0410     //
0411     // path(v,w) = [v], if v = w
0412     //           = concat([v, mate[v]], path(pred[mate[v]], w),
0413     //                if v != w and vertex_state[v] == graph::detail::V_EVEN
0414     //           = concat([v], reverse(path(x,mate[v])), path(y,w)),
0415     //                if v != w, vertex_state[v] == graph::detail::V_ODD, and
0416     //                bridge[v] = (x,y)
0417     //
0418     // These next two mutually recursive functions implement this definition.
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 // vertex_state[v] == graph::detail::V_ODD
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 // vertex_state[v] == graph::detail::V_ODD
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     // private data members
0459 
0460     const Graph& g;
0461     VertexIndexMap vm;
0462     v_size_t n_vertices;
0463 
0464     // storage for the property maps below
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     // iterator property maps
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 //               Initial Matching Functors
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             // only way equality can hold is if
0520             //   mate[u] == mate[v] == null_vertex
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     // The "extra greedy matching" is formed by repeating the
0532     // following procedure as many times as possible: Choose the
0533     // unmatched vertex v of minimum non-zero degree.  Choose the
0534     // neighbor w of v which is unmatched and has minimum degree over
0535     // all of v's neighbors. Add (u,v) to the matching. Ties for
0536     // either choice are broken arbitrarily. This procedure takes time
0537     // O(m log n), where m is the number of edges in the graph and n
0538     // is the number of vertices.
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         // sort the edges by the degree of the target, then (using a
0601         // stable sort) by degree of the source
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         // construct the extra greedy matching
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             // only way equality can hold is if mate[itr->first] ==
0614             // mate[itr->second] == null_vertex
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 //               Matching Verifiers
0638 //***************************************************************************
0639 //***************************************************************************
0640 
0641 namespace detail
0642 {
0643 
0644     template < typename SizeType >
0645     class odd_components_counter : public dfs_visitor<>
0646     // This depth-first search visitor will count the number of connected
0647     // components with an odd number of vertices. It's used by
0648     // maximum_matching_verifier.
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 } // namespace detail
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         // this predicate is used to create a filtered graph that
0709         // excludes vertices labeled "graph::detail::V_ODD"
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         // For any graph G, let o(G) be the number of connected
0729         // components in G of odd size. For a subset S of G's vertex set
0730         // V(G), let (G - S) represent the subgraph of G induced by
0731         // removing all vertices in S from G. Let M(G) be the size of the
0732         // maximum cardinality matching in G. Then the Tutte-Berge
0733         // formula guarantees that
0734         //
0735         //           2 * M(G) = min ( |V(G)| + |U| + o(G - U) )
0736         //
0737         // where the minimum is taken over all subsets U of
0738         // V(G). Edmonds' algorithm finds a set U that achieves the
0739         // minimum in the above formula, namely the vertices labeled
0740         //"ODD." This function runs one iteration of Edmonds' algorithm
0741         // to find U, then verifies that the size of the matching given
0742         // by mate satisfies the Tutte-Berge formula.
0743 
0744         // first, make sure it's a valid matching
0745         if (!is_a_matching(g, mate, vm))
0746             return false;
0747 
0748         // We'll try to augment the matching once. This serves two
0749         // purposes: first, if we find some augmenting path, the matching
0750         // is obviously non-maximum. Second, running edmonds' algorithm
0751         // on a graph with no augmenting path will create the
0752         // Edmonds-Gallai decomposition that we need as a certificate of
0753         // maximality - we can get it by looking at the vertex_state map
0754         // that results.
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         // count the number of graph::detail::V_ODD vertices
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         // count the number of connected components with odd cardinality
0772         // in the graph without graph::detail::V_ODD vertices
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 } // namespace boost
0843 
0844 #endif // BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP