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