From a728a94caa3c2bb65ea32e85bd0fbf7f39e19a6d Mon Sep 17 00:00:00 2001 From: Aaron Windsor Date: Thu, 14 Dec 2006 00:45:34 +0000 Subject: [PATCH] merged filename change for maximum_cardinality_matching from HEAD to RC_1_34_0 [SVN r36365] --- .../graph/maximum_cardinality_matching.hpp | 876 ------------------ 1 file changed, 876 deletions(-) delete mode 100755 include/boost/graph/maximum_cardinality_matching.hpp diff --git a/include/boost/graph/maximum_cardinality_matching.hpp b/include/boost/graph/maximum_cardinality_matching.hpp deleted file mode 100755 index 48cb053b..00000000 --- a/include/boost/graph/maximum_cardinality_matching.hpp +++ /dev/null @@ -1,876 +0,0 @@ -//======================================================================= -// Copyright (c) 2005 Aaron Windsor -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -//======================================================================= - -#ifndef BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP -#define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP - -#include -#include -#include -#include // for std::sort and std::stable_sort -#include // for std::pair -#include -#include // for boost::tie -#include -#include -#include -#include -#include -#include - - -namespace boost -{ - namespace graph { namespace detail { - enum { V_EVEN, V_ODD, V_UNREACHED }; - } } // end namespace graph::detail - - template - typename graph_traits::vertices_size_type - matching_size(const Graph& g, MateMap mate, VertexIndexMap vm) - { - typedef typename graph_traits::vertex_iterator vertex_iterator_t; - typedef typename graph_traits::vertex_descriptor - vertex_descriptor_t; - typedef typename graph_traits::vertices_size_type v_size_t; - - v_size_t size_of_matching = 0; - vertex_iterator_t vi, vi_end; - - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - { - vertex_descriptor_t v = *vi; - if (get(mate,v) != graph_traits::null_vertex() - && get(vm,v) < get(vm,get(mate,v))) - ++size_of_matching; - } - return size_of_matching; - } - - - - - template - inline typename graph_traits::vertices_size_type - matching_size(const Graph& g, MateMap mate) - { - return matching_size(g, mate, get(vertex_index,g)); - } - - - - - template - bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap vm) - { - typedef typename graph_traits::vertex_descriptor - vertex_descriptor_t; - typedef typename graph_traits::vertex_iterator vertex_iterator_t; - - vertex_iterator_t vi, vi_end; - for( tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - { - vertex_descriptor_t v = *vi; - if (get(mate,v) != graph_traits::null_vertex() - && v != get(mate,get(mate,v))) - return false; - } - return true; - } - - - - - template - inline bool is_a_matching(const Graph& g, MateMap mate) - { - return is_a_matching(g, mate, get(vertex_index,g)); - } - - - - - //*************************************************************************** - //*************************************************************************** - // Maximum Cardinality Matching Functors - //*************************************************************************** - //*************************************************************************** - - template - struct no_augmenting_path_finder - { - no_augmenting_path_finder(const Graph& g, MateMap mate, VertexIndexMap vm) - { } - - inline bool augment_matching() { return false; } - - template - void get_current_matching(PropertyMap p) {} - }; - - - - - template - class edmonds_augmenting_path_finder - { - // This implementation of Edmonds' matching algorithm closely - // follows Tarjan's description of the algorithm in "Data - // Structures and Network Algorithms." - - public: - - //generates the type of an iterator property map from vertices to type X - template - struct map_vertex_to_ - { - typedef boost::iterator_property_map::iterator, - VertexIndexMap> type; - }; - - typedef typename graph_traits::vertex_descriptor - vertex_descriptor_t; - typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_t > - vertex_pair_t; - typedef typename graph_traits::edge_descriptor edge_descriptor_t; - typedef typename graph_traits::vertices_size_type v_size_t; - typedef typename graph_traits::edges_size_type e_size_t; - typedef typename graph_traits::vertex_iterator vertex_iterator_t; - typedef typename graph_traits::out_edge_iterator - out_edge_iterator_t; - typedef typename std::deque vertex_list_t; - typedef typename std::vector edge_list_t; - typedef typename map_vertex_to_::type - vertex_to_vertex_map_t; - typedef typename map_vertex_to_::type vertex_to_int_map_t; - typedef typename map_vertex_to_::type - vertex_to_vertex_pair_map_t; - typedef typename map_vertex_to_::type vertex_to_vsize_map_t; - typedef typename map_vertex_to_::type vertex_to_esize_map_t; - - - - - edmonds_augmenting_path_finder(const Graph& arg_g, MateMap arg_mate, - VertexIndexMap arg_vm) : - g(arg_g), - vm(arg_vm), - n_vertices(num_vertices(arg_g)), - - mate_vector(n_vertices), - ancestor_of_v_vector(n_vertices), - ancestor_of_w_vector(n_vertices), - vertex_state_vector(n_vertices), - origin_vector(n_vertices), - pred_vector(n_vertices), - bridge_vector(n_vertices), - ds_parent_vector(n_vertices), - ds_rank_vector(n_vertices), - - mate(mate_vector.begin(), vm), - ancestor_of_v(ancestor_of_v_vector.begin(), vm), - ancestor_of_w(ancestor_of_w_vector.begin(), vm), - vertex_state(vertex_state_vector.begin(), vm), - origin(origin_vector.begin(), vm), - pred(pred_vector.begin(), vm), - bridge(bridge_vector.begin(), vm), - ds_parent_map(ds_parent_vector.begin(), vm), - ds_rank_map(ds_rank_vector.begin(), vm), - - ds(ds_rank_map, ds_parent_map) - { - vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - mate[*vi] = get(arg_mate, *vi); - } - - - - - bool augment_matching() - { - //As an optimization, some of these values can be saved from one - //iteration to the next instead of being re-initialized each - //iteration, allowing for "lazy blossom expansion." This is not - //currently implemented. - - e_size_t timestamp = 0; - even_edges.clear(); - - vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - { - vertex_descriptor_t u = *vi; - - origin[u] = u; - pred[u] = u; - ancestor_of_v[u] = 0; - ancestor_of_w[u] = 0; - ds.make_set(u); - - if (mate[u] == graph_traits::null_vertex()) - { - vertex_state[u] = graph::detail::V_EVEN; - out_edge_iterator_t ei, ei_end; - for(tie(ei,ei_end) = out_edges(u,g); ei != ei_end; ++ei) - even_edges.push_back( *ei ); - } - else - vertex_state[u] = graph::detail::V_UNREACHED; - } - - //end initializations - - vertex_descriptor_t v,w,w_free_ancestor,v_free_ancestor; - w_free_ancestor = graph_traits::null_vertex(); - v_free_ancestor = graph_traits::null_vertex(); - bool found_alternating_path = false; - - while(!even_edges.empty() && !found_alternating_path) - { - // since we push even edges onto the back of the list as - // they're discovered, taking them off the back will search - // for augmenting paths depth-first. - edge_descriptor_t current_edge = even_edges.back(); - even_edges.pop_back(); - - v = source(current_edge,g); - w = target(current_edge,g); - - vertex_descriptor_t v_prime = origin[ds.find_set(v)]; - vertex_descriptor_t w_prime = origin[ds.find_set(w)]; - - // because of the way we put all of the edges on the queue, - // v_prime should be labeled V_EVEN; the following is a - // little paranoid but it could happen... - if (vertex_state[v_prime] != graph::detail::V_EVEN) - { - std::swap(v_prime,w_prime); - std::swap(v,w); - } - - if (vertex_state[w_prime] == graph::detail::V_UNREACHED) - { - vertex_state[w_prime] = graph::detail::V_ODD; - vertex_state[mate[w_prime]] = graph::detail::V_EVEN; - out_edge_iterator_t ei, ei_end; - for( tie(ei,ei_end) = out_edges(mate[w_prime], g); ei != ei_end; ++ei) - even_edges.push_back(*ei); - pred[w_prime] = v; - } - //w_prime == v_prime can happen below if we get an edge that has been - //shrunk into a blossom - else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime) - { - vertex_descriptor_t w_up = w_prime; - vertex_descriptor_t v_up = v_prime; - vertex_descriptor_t nearest_common_ancestor - = graph_traits::null_vertex(); - w_free_ancestor = graph_traits::null_vertex(); - v_free_ancestor = graph_traits::null_vertex(); - - // We now need to distinguish between the case that - // w_prime and v_prime share an ancestor under the - // "parent" relation, in which case we've found a - // blossom and should shrink it, or the case that - // w_prime and v_prime both have distinct ancestors that - // are free, in which case we've found an alternating - // path between those two ancestors. - - ++timestamp; - - while (nearest_common_ancestor == graph_traits::null_vertex() && - (v_free_ancestor == graph_traits::null_vertex() || - w_free_ancestor == graph_traits::null_vertex() - ) - ) - { - ancestor_of_w[w_up] = timestamp; - ancestor_of_v[v_up] = timestamp; - - if (w_free_ancestor == graph_traits::null_vertex()) - w_up = parent(w_up); - if (v_free_ancestor == graph_traits::null_vertex()) - v_up = parent(v_up); - - if (mate[v_up] == graph_traits::null_vertex()) - v_free_ancestor = v_up; - if (mate[w_up] == graph_traits::null_vertex()) - w_free_ancestor = w_up; - - if (ancestor_of_w[v_up] == timestamp) - nearest_common_ancestor = v_up; - else if (ancestor_of_v[w_up] == timestamp) - nearest_common_ancestor = w_up; - else if (v_free_ancestor == w_free_ancestor && - v_free_ancestor != graph_traits::null_vertex()) - nearest_common_ancestor = v_up; - } - - if (nearest_common_ancestor == graph_traits::null_vertex()) - found_alternating_path = true; //to break out of the loop - else - { - //shrink the blossom - link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v)); - link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w)); - } - } - } - - if (!found_alternating_path) - return false; - - // retrieve the augmenting path and put it in aug_path - reversed_retrieve_augmenting_path(v, v_free_ancestor); - retrieve_augmenting_path(w, w_free_ancestor); - - // augment the matching along aug_path - vertex_descriptor_t a,b; - while (!aug_path.empty()) - { - a = aug_path.front(); - aug_path.pop_front(); - b = aug_path.front(); - aug_path.pop_front(); - mate[a] = b; - mate[b] = a; - } - - return true; - - } - - - - - template - void get_current_matching(PropertyMap pm) - { - vertex_iterator_t vi,vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - put(pm, *vi, mate[*vi]); - } - - - - - template - void get_vertex_state_map(PropertyMap pm) - { - vertex_iterator_t vi,vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]); - } - - - - - private: - - vertex_descriptor_t parent(vertex_descriptor_t x) - { - if (vertex_state[x] == graph::detail::V_EVEN - && mate[x] != graph_traits::null_vertex()) - return mate[x]; - else if (vertex_state[x] == graph::detail::V_ODD) - return origin[ds.find_set(pred[x])]; - else - return x; - } - - - - - void link_and_set_bridges(vertex_descriptor_t x, - vertex_descriptor_t stop_vertex, - vertex_pair_t the_bridge) - { - for(vertex_descriptor_t v = x; v != stop_vertex; v = parent(v)) - { - ds.union_set(v, stop_vertex); - origin[ds.find_set(stop_vertex)] = stop_vertex; - - if (vertex_state[v] == graph::detail::V_ODD) - { - bridge[v] = the_bridge; - out_edge_iterator_t oei, oei_end; - for(tie(oei, oei_end) = out_edges(v,g); oei != oei_end; ++oei) - even_edges.push_back(*oei); - } - } - } - - - // Since none of the STL containers support both constant-time - // concatenation and reversal, the process of expanding an - // augmenting path once we know one exists is a little more - // complicated than it has to be. If we know the path is from v to - // w, then the augmenting path is recursively defined as: - // - // path(v,w) = [v], if v = w - // = concat([v, mate[v]], path(pred[mate[v]], w), - // if v != w and vertex_state[v] == graph::detail::V_EVEN - // = concat([v], reverse(path(x,mate[v])), path(y,w)), - // if v != w, vertex_state[v] == graph::detail::V_ODD, and bridge[v] = (x,y) - // - // These next two mutually recursive functions implement this definition. - - void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w) - { - if (v == w) - aug_path.push_back(v); - else if (vertex_state[v] == graph::detail::V_EVEN) - { - aug_path.push_back(v); - aug_path.push_back(mate[v]); - retrieve_augmenting_path(pred[mate[v]], w); - } - else //vertex_state[v] == graph::detail::V_ODD - { - aug_path.push_back(v); - reversed_retrieve_augmenting_path(bridge[v].first, mate[v]); - retrieve_augmenting_path(bridge[v].second, w); - } - } - - - void reversed_retrieve_augmenting_path(vertex_descriptor_t v, - vertex_descriptor_t w) - { - - if (v == w) - aug_path.push_back(v); - else if (vertex_state[v] == graph::detail::V_EVEN) - { - reversed_retrieve_augmenting_path(pred[mate[v]], w); - aug_path.push_back(mate[v]); - aug_path.push_back(v); - } - else //vertex_state[v] == graph::detail::V_ODD - { - reversed_retrieve_augmenting_path(bridge[v].second, w); - retrieve_augmenting_path(bridge[v].first, mate[v]); - aug_path.push_back(v); - } - } - - - - - //private data members - - const Graph& g; - VertexIndexMap vm; - v_size_t n_vertices; - - //storage for the property maps below - std::vector mate_vector; - std::vector ancestor_of_v_vector; - std::vector ancestor_of_w_vector; - std::vector vertex_state_vector; - std::vector origin_vector; - std::vector pred_vector; - std::vector bridge_vector; - std::vector ds_parent_vector; - std::vector ds_rank_vector; - - //iterator property maps - vertex_to_vertex_map_t mate; - vertex_to_esize_map_t ancestor_of_v; - vertex_to_esize_map_t ancestor_of_w; - vertex_to_int_map_t vertex_state; - vertex_to_vertex_map_t origin; - vertex_to_vertex_map_t pred; - vertex_to_vertex_pair_map_t bridge; - vertex_to_vertex_map_t ds_parent_map; - vertex_to_vsize_map_t ds_rank_map; - - vertex_list_t aug_path; - edge_list_t even_edges; - disjoint_sets< vertex_to_vsize_map_t, vertex_to_vertex_map_t > ds; - - }; - - - - - //*************************************************************************** - //*************************************************************************** - // Initial Matching Functors - //*************************************************************************** - //*************************************************************************** - - template - struct greedy_matching - { - typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; - typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; - typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; - typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; - - static void find_matching(const Graph& g, MateMap mate) - { - vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - put(mate, *vi, graph_traits::null_vertex()); - - edge_iterator_t ei, ei_end; - for( tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) - { - edge_descriptor_t e = *ei; - vertex_descriptor_t u = source(e,g); - vertex_descriptor_t v = target(e,g); - - if (get(mate,u) == get(mate,v)) - //only way equality can hold is if - // mate[u] == mate[v] == null_vertex - { - put(mate,u,v); - put(mate,v,u); - } - } - } - }; - - - - - template - struct extra_greedy_matching - { - // The "extra greedy matching" is formed by repeating the - // following procedure as many times as possible: Choose the - // unmatched vertex v of minimum non-zero degree. Choose the - // neighbor w of v which is unmatched and has minimum degree over - // all of v's neighbors. Add (u,v) to the matching. Ties for - // either choice are broken arbitrarily. This procedure takes time - // O(m log n), where m is the number of edges in the graph and n - // is the number of vertices. - - typedef typename graph_traits< Graph >::vertex_descriptor - vertex_descriptor_t; - typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; - typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; - typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; - typedef std::pair vertex_pair_t; - - struct select_first - { - inline static vertex_descriptor_t select_vertex(const vertex_pair_t p) - {return p.first;} - }; - - struct select_second - { - inline static vertex_descriptor_t select_vertex(const vertex_pair_t p) - {return p.second;} - }; - - template - class less_than_by_degree - { - public: - less_than_by_degree(const Graph& g): m_g(g) {} - bool operator() (const vertex_pair_t x, const vertex_pair_t y) - { - return - out_degree(PairSelector::select_vertex(x), m_g) - < out_degree(PairSelector::select_vertex(y), m_g); - } - private: - const Graph& m_g; - }; - - - static void find_matching(const Graph& g, MateMap mate) - { - typedef std::vector > - directed_edges_vector_t; - - directed_edges_vector_t edge_list; - vertex_iterator_t vi, vi_end; - for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) - put(mate, *vi, graph_traits::null_vertex()); - - edge_iterator_t ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) - { - edge_descriptor_t e = *ei; - vertex_descriptor_t u = source(e,g); - vertex_descriptor_t v = target(e,g); - edge_list.push_back(std::make_pair(u,v)); - edge_list.push_back(std::make_pair(v,u)); - } - - //sort the edges by the degree of the target, then (using a - //stable sort) by degree of the source - std::sort(edge_list.begin(), edge_list.end(), - less_than_by_degree(g)); - std::stable_sort(edge_list.begin(), edge_list.end(), - less_than_by_degree(g)); - - //construct the extra greedy matching - for(typename directed_edges_vector_t::const_iterator itr = edge_list.begin(); itr != edge_list.end(); ++itr) - { - if (get(mate,itr->first) == get(mate,itr->second)) - //only way equality can hold is if mate[itr->first] == mate[itr->second] == null_vertex - { - put(mate, itr->first, itr->second); - put(mate, itr->second, itr->first); - } - } - } - }; - - - - - template - struct empty_matching - { - typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; - - static void find_matching(const Graph& g, MateMap mate) - { - vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - put(mate, *vi, graph_traits::null_vertex()); - } - }; - - - - - //*************************************************************************** - //*************************************************************************** - // Matching Verifiers - //*************************************************************************** - //*************************************************************************** - - namespace detail - { - - template - class odd_components_counter : public dfs_visitor<> - // This depth-first search visitor will count the number of connected - // components with an odd number of vertices. It's used by - // maximum_matching_verifier. - { - public: - odd_components_counter(SizeType& c_count): - m_count(c_count) - { - m_count = 0; - } - - template - void start_vertex(Vertex v, Graph&) - { - addend = -1; - } - - template - void discover_vertex(Vertex u, Graph&) - { - addend *= -1; - m_count += addend; - } - - protected: - SizeType& m_count; - - private: - SizeType addend; - - }; - - }//namespace detail - - - - - template - struct no_matching_verifier - { - inline static bool - verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm) - { return true;} - }; - - - - - template - struct maximum_cardinality_matching_verifier - { - - template - struct map_vertex_to_ - { - typedef boost::iterator_property_map::iterator, - VertexIndexMap> type; - }; - - typedef typename graph_traits::vertex_descriptor - vertex_descriptor_t; - typedef typename graph_traits::vertices_size_type v_size_t; - typedef typename graph_traits::vertex_iterator vertex_iterator_t; - typedef typename map_vertex_to_::type vertex_to_int_map_t; - typedef typename map_vertex_to_::type - vertex_to_vertex_map_t; - - template - struct non_odd_vertex { - //this predicate is used to create a filtered graph that - //excludes vertices labeled "graph::detail::V_ODD" - non_odd_vertex() : vertex_state(0) { } - non_odd_vertex(VertexStateMap* arg_vertex_state) - : vertex_state(arg_vertex_state) { } - template - bool operator()(const Vertex& v) const { - BOOST_ASSERT(vertex_state); - return get(*vertex_state, v) != graph::detail::V_ODD; - } - VertexStateMap* vertex_state; - }; - - static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm) - { - //For any graph G, let o(G) be the number of connected - //components in G of odd size. For a subset S of G's vertex set - //V(G), let (G - S) represent the subgraph of G induced by - //removing all vertices in S from G. Let M(G) be the size of the - //maximum cardinality matching in G. Then the Tutte-Berge - //formula guarantees that - // - // 2 * M(G) = min ( |V(G)| + |U| + o(G - U) ) - // - //where the minimum is taken over all subsets U of - //V(G). Edmonds' algorithm finds a set U that achieves the - //minimum in the above formula, namely the vertices labeled - //"ODD." This function runs one iteration of Edmonds' algorithm - //to find U, then verifies that the size of the matching given - //by mate satisfies the Tutte-Berge formula. - - //first, make sure it's a valid matching - if (!is_a_matching(g,mate,vm)) - return false; - - //We'll try to augment the matching once. This serves two - //purposes: first, if we find some augmenting path, the matching - //is obviously non-maximum. Second, running edmonds' algorithm - //on a graph with no augmenting path will create the - //Edmonds-Gallai decomposition that we need as a certificate of - //maximality - we can get it by looking at the vertex_state map - //that results. - edmonds_augmenting_path_finder - augmentor(g,mate,vm); - if (augmentor.augment_matching()) - return false; - - std::vector vertex_state_vector(num_vertices(g)); - vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm); - augmentor.get_vertex_state_map(vertex_state); - - //count the number of graph::detail::V_ODD vertices - v_size_t num_odd_vertices = 0; - vertex_iterator_t vi, vi_end; - for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) - if (vertex_state[*vi] == graph::detail::V_ODD) - ++num_odd_vertices; - - //count the number of connected components with odd cardinality - //in the graph without graph::detail::V_ODD vertices - non_odd_vertex filter(&vertex_state); - filtered_graph > fg(g, keep_all(), filter); - - v_size_t num_odd_components; - detail::odd_components_counter occ(num_odd_components); - depth_first_search(fg, visitor(occ).vertex_index_map(vm)); - - if (2 * matching_size(g,mate,vm) == num_vertices(g) + num_odd_vertices - num_odd_components) - return true; - else - return false; - } - }; - - - - - template class AugmentingPathFinder, - template class InitialMatchingFinder, - template class MatchingVerifier> - bool matching(const Graph& g, MateMap mate, VertexIndexMap vm) - { - - InitialMatchingFinder::find_matching(g,mate); - - AugmentingPathFinder augmentor(g,mate,vm); - bool not_maximum_yet = true; - while(not_maximum_yet) - { - not_maximum_yet = augmentor.augment_matching(); - } - augmentor.get_current_matching(mate); - - return MatchingVerifier::verify_matching(g,mate,vm); - - } - - - - - template - inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm) - { - return matching - < Graph, MateMap, VertexIndexMap, - edmonds_augmenting_path_finder, extra_greedy_matching, maximum_cardinality_matching_verifier> - (g, mate, vm); - } - - - - - template - inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate) - { - return checked_edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g)); - } - - - - - template - inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm) - { - matching < Graph, MateMap, VertexIndexMap, - edmonds_augmenting_path_finder, extra_greedy_matching, no_matching_verifier> - (g, mate, vm); - } - - - - - template - inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate) - { - edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g)); - } - -}//namespace boost - -#endif //BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP