annotate DEPENDENCIES/generic/include/boost/graph/max_cardinality_matching.hpp @ 125:34e428693f5d vext

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