Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
1 //=======================================================================
2 // Copyright (c) 2005 Aaron Windsor
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)
8 //=======================================================================
10 #ifndef BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
11 #define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP
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>
30 namespace graph { namespace detail {
31 enum { V_EVEN, V_ODD, V_UNREACHED };
32 } } // end namespace graph::detail
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)
38 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
39 typedef typename graph_traits<Graph>::vertex_descriptor
41 typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
43 v_size_t size_of_matching = 0;
44 vertex_iterator_t vi, vi_end;
46 for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
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)))
53 return size_of_matching;
59 template <typename Graph, typename MateMap>
60 inline typename graph_traits<Graph>::vertices_size_type
61 matching_size(const Graph& g, MateMap mate)
63 return matching_size(g, mate, get(vertex_index,g));
69 template <typename Graph, typename MateMap, typename VertexIndexMap>
70 bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
72 typedef typename graph_traits<Graph>::vertex_descriptor
74 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
76 vertex_iterator_t vi, vi_end;
77 for( tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
79 vertex_descriptor_t v = *vi;
80 if (get(mate,v) != graph_traits<Graph>::null_vertex()
81 && v != get(mate,get(mate,v)))
90 template <typename Graph, typename MateMap>
91 inline bool is_a_matching(const Graph& g, MateMap mate)
93 return is_a_matching(g, mate, get(vertex_index,g));
99 //***************************************************************************
100 //***************************************************************************
101 // Maximum Cardinality Matching Functors
102 //***************************************************************************
103 //***************************************************************************
105 template <typename Graph, typename MateMap,
106 typename VertexIndexMap = dummy_property_map>
107 struct no_augmenting_path_finder
109 no_augmenting_path_finder(const Graph& g, MateMap mate, VertexIndexMap vm)
112 inline bool augment_matching() { return false; }
114 template <typename PropertyMap>
115 void get_current_matching(PropertyMap p) {}
121 template <typename Graph, typename MateMap, typename VertexIndexMap>
122 class edmonds_augmenting_path_finder
124 // This implementation of Edmonds' matching algorithm closely
125 // follows Tarjan's description of the algorithm in "Data
126 // Structures and Network Algorithms."
130 //generates the type of an iterator property map from vertices to type X
131 template <typename X>
132 struct map_vertex_to_
134 typedef boost::iterator_property_map<typename std::vector<X>::iterator,
135 VertexIndexMap> type;
138 typedef typename graph_traits<Graph>::vertex_descriptor
140 typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_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
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;
161 edmonds_augmenting_path_finder(const Graph& arg_g, MateMap arg_mate,
162 VertexIndexMap arg_vm) :
165 n_vertices(num_vertices(arg_g)),
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),
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),
187 ds(ds_rank_map, ds_parent_map)
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);
197 bool augment_matching()
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.
204 e_size_t timestamp = 0;
207 vertex_iterator_t vi, vi_end;
208 for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
210 vertex_descriptor_t u = *vi;
214 ancestor_of_v[u] = 0;
215 ancestor_of_w[u] = 0;
218 if (mate[u] == graph_traits<Graph>::null_vertex())
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 );
226 vertex_state[u] = graph::detail::V_UNREACHED;
229 //end initializations
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;
236 while(!even_edges.empty() && !found_alternating_path)
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();
244 v = source(current_edge,g);
245 w = target(current_edge,g);
247 vertex_descriptor_t v_prime = origin[ds.find_set(v)];
248 vertex_descriptor_t w_prime = origin[ds.find_set(w)];
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)
255 std::swap(v_prime,w_prime);
259 if (vertex_state[w_prime] == graph::detail::V_UNREACHED)
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);
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)
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();
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.
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()
295 ancestor_of_w[w_up] = timestamp;
296 ancestor_of_v[v_up] = timestamp;
298 if (w_free_ancestor == graph_traits<Graph>::null_vertex())
300 if (v_free_ancestor == graph_traits<Graph>::null_vertex())
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;
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;
317 if (nearest_common_ancestor == graph_traits<Graph>::null_vertex())
318 found_alternating_path = true; //to break out of the loop
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));
328 if (!found_alternating_path)
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);
335 // augment the matching along aug_path
336 vertex_descriptor_t a,b;
337 while (!aug_path.empty())
339 a = aug_path.front();
340 aug_path.pop_front();
341 b = aug_path.front();
342 aug_path.pop_front();
354 template <typename PropertyMap>
355 void get_current_matching(PropertyMap pm)
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]);
365 template <typename PropertyMap>
366 void get_vertex_state_map(PropertyMap pm)
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)]]);
378 vertex_descriptor_t parent(vertex_descriptor_t x)
380 if (vertex_state[x] == graph::detail::V_EVEN
381 && mate[x] != graph_traits<Graph>::null_vertex())
383 else if (vertex_state[x] == graph::detail::V_ODD)
384 return origin[ds.find_set(pred[x])];
392 void link_and_set_bridges(vertex_descriptor_t x,
393 vertex_descriptor_t stop_vertex,
394 vertex_pair_t the_bridge)
396 for(vertex_descriptor_t v = x; v != stop_vertex; v = parent(v))
398 ds.union_set(v, stop_vertex);
399 origin[ds.find_set(stop_vertex)] = stop_vertex;
401 if (vertex_state[v] == graph::detail::V_ODD)
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);
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:
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)
424 // These next two mutually recursive functions implement this definition.
426 void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w)
429 aug_path.push_back(v);
430 else if (vertex_state[v] == graph::detail::V_EVEN)
432 aug_path.push_back(v);
433 aug_path.push_back(mate[v]);
434 retrieve_augmenting_path(pred[mate[v]], w);
436 else //vertex_state[v] == graph::detail::V_ODD
438 aug_path.push_back(v);
439 reversed_retrieve_augmenting_path(bridge[v].first, mate[v]);
440 retrieve_augmenting_path(bridge[v].second, w);
445 void reversed_retrieve_augmenting_path(vertex_descriptor_t v,
446 vertex_descriptor_t w)
450 aug_path.push_back(v);
451 else if (vertex_state[v] == graph::detail::V_EVEN)
453 reversed_retrieve_augmenting_path(pred[mate[v]], w);
454 aug_path.push_back(mate[v]);
455 aug_path.push_back(v);
457 else //vertex_state[v] == graph::detail::V_ODD
459 reversed_retrieve_augmenting_path(bridge[v].second, w);
460 retrieve_augmenting_path(bridge[v].first, mate[v]);
461 aug_path.push_back(v);
468 //private data members
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;
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;
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;
505 //***************************************************************************
506 //***************************************************************************
507 // Initial Matching Functors
508 //***************************************************************************
509 //***************************************************************************
511 template <typename Graph, typename MateMap>
512 struct greedy_matching
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;
519 static void find_matching(const Graph& g, MateMap mate)
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());
525 edge_iterator_t ei, ei_end;
526 for( tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
528 edge_descriptor_t e = *ei;
529 vertex_descriptor_t u = source(e,g);
530 vertex_descriptor_t v = target(e,g);
532 if (get(mate,u) == get(mate,v))
533 //only way equality can hold is if
534 // mate[u] == mate[v] == null_vertex
546 template <typename Graph, typename MateMap>
547 struct extra_greedy_matching
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.
558 typedef typename graph_traits< Graph >::vertex_descriptor
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;
567 inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
573 inline static vertex_descriptor_t select_vertex(const vertex_pair_t p)
577 template <class PairSelector>
578 class less_than_by_degree
581 less_than_by_degree(const Graph& g): m_g(g) {}
582 bool operator() (const vertex_pair_t x, const vertex_pair_t y)
585 out_degree(PairSelector::select_vertex(x), m_g)
586 < out_degree(PairSelector::select_vertex(y), m_g);
593 static void find_matching(const Graph& g, MateMap mate)
595 typedef std::vector<std::pair<vertex_descriptor_t, vertex_descriptor_t> >
596 directed_edges_vector_t;
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());
603 edge_iterator_t ei, ei_end;
604 for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
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));
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));
620 //construct the extra greedy matching
621 for(typename directed_edges_vector_t::const_iterator itr = edge_list.begin(); itr != edge_list.end(); ++itr)
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
626 put(mate, itr->first, itr->second);
627 put(mate, itr->second, itr->first);
636 template <typename Graph, typename MateMap>
637 struct empty_matching
639 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
641 static void find_matching(const Graph& g, MateMap mate)
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());
652 //***************************************************************************
653 //***************************************************************************
654 // Matching Verifiers
655 //***************************************************************************
656 //***************************************************************************
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.
668 odd_components_counter(SizeType& c_count):
674 template <class Vertex, class Graph>
675 void start_vertex(Vertex v, Graph&)
680 template <class Vertex, class Graph>
681 void discover_vertex(Vertex u, Graph&)
700 template <typename Graph, typename MateMap,
701 typename VertexIndexMap = dummy_property_map>
702 struct no_matching_verifier
705 verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
712 template <typename Graph, typename MateMap, typename VertexIndexMap>
713 struct maximum_cardinality_matching_verifier
716 template <typename X>
717 struct map_vertex_to_
719 typedef boost::iterator_property_map<typename std::vector<X>::iterator,
720 VertexIndexMap> type;
723 typedef typename graph_traits<Graph>::vertex_descriptor
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;
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;
743 VertexStateMap* vertex_state;
746 static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
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
755 // 2 * M(G) = min ( |V(G)| + |U| + o(G - U) )
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.
764 //first, make sure it's a valid matching
765 if (!is_a_matching(g,mate,vm))
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
775 edmonds_augmenting_path_finder<Graph,MateMap,VertexIndexMap>
776 augmentor(g,mate,vm);
777 if (augmentor.augment_matching())
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);
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)
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);
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));
800 if (2 * matching_size(g,mate,vm) == num_vertices(g) + num_odd_vertices - num_odd_components)
810 template <typename Graph,
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)
819 InitialMatchingFinder<Graph,MateMap>::find_matching(g,mate);
821 AugmentingPathFinder<Graph,MateMap,VertexIndexMap> augmentor(g,mate,vm);
822 bool not_maximum_yet = true;
823 while(not_maximum_yet)
825 not_maximum_yet = augmentor.augment_matching();
827 augmentor.get_current_matching(mate);
829 return MatchingVerifier<Graph,MateMap,VertexIndexMap>::verify_matching(g,mate,vm);
836 template <typename Graph, typename MateMap, typename VertexIndexMap>
837 inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
840 < Graph, MateMap, VertexIndexMap,
841 edmonds_augmenting_path_finder, extra_greedy_matching, maximum_cardinality_matching_verifier>
848 template <typename Graph, typename MateMap>
849 inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate)
851 return checked_edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g));
857 template <typename Graph, typename MateMap, typename VertexIndexMap>
858 inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm)
860 matching < Graph, MateMap, VertexIndexMap,
861 edmonds_augmenting_path_finder, extra_greedy_matching, no_matching_verifier>
868 template <typename Graph, typename MateMap>
869 inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate)
871 edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g));
876 #endif //BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP