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
|