Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/graph/max_cardinality_matching.hpp @ 35

Last change on this file since 35 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 28.3 KB
Line 
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
28namespace 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
Note: See TracBrowser for help on using the repository browser.