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