1 /* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
2 * |
|
3 * This file is a part of LEMON, a generic C++ optimization library. |
|
4 * |
|
5 * Copyright (C) 2003-2009 |
|
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
|
7 * (Egervary Research Group on Combinatorial Optimization, EGRES). |
|
8 * |
|
9 * Permission to use, modify and distribute this software is granted |
|
10 * provided that this copyright notice appears in all copies. For |
|
11 * precise terms see the accompanying LICENSE file. |
|
12 * |
|
13 * This software is provided "AS IS" with no warranty of any kind, |
|
14 * express or implied, and with no claim as to its suitability for any |
|
15 * purpose. |
|
16 * |
|
17 */ |
|
18 |
|
19 #ifndef LEMON_MAX_MATCHING_H |
|
20 #define LEMON_MAX_MATCHING_H |
|
21 |
|
22 #include <vector> |
|
23 #include <queue> |
|
24 #include <set> |
|
25 #include <limits> |
|
26 |
|
27 #include <lemon/core.h> |
|
28 #include <lemon/unionfind.h> |
|
29 #include <lemon/bin_heap.h> |
|
30 #include <lemon/maps.h> |
|
31 |
|
32 ///\ingroup matching |
|
33 ///\file |
|
34 ///\brief Maximum matching algorithms in general graphs. |
|
35 |
|
36 namespace lemon { |
|
37 |
|
38 /// \ingroup matching |
|
39 /// |
|
40 /// \brief Maximum cardinality matching in general graphs |
|
41 /// |
|
42 /// This class implements Edmonds' alternating forest matching algorithm |
|
43 /// for finding a maximum cardinality matching in a general undirected graph. |
|
44 /// It can be started from an arbitrary initial matching |
|
45 /// (the default is the empty one). |
|
46 /// |
|
47 /// The dual solution of the problem is a map of the nodes to |
|
48 /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D), |
|
49 /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds |
|
50 /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph |
|
51 /// with factor-critical components, the nodes in \c ODD/A form the |
|
52 /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having |
|
53 /// a perfect matching. The number of the factor-critical components |
|
54 /// minus the number of barrier nodes is a lower bound on the |
|
55 /// unmatched nodes, and the matching is optimal if and only if this bound is |
|
56 /// tight. This decomposition can be obtained using \ref status() or |
|
57 /// \ref statusMap() after running the algorithm. |
|
58 /// |
|
59 /// \tparam GR The undirected graph type the algorithm runs on. |
|
60 template <typename GR> |
|
61 class MaxMatching { |
|
62 public: |
|
63 |
|
64 /// The graph type of the algorithm |
|
65 typedef GR Graph; |
|
66 /// The type of the matching map |
|
67 typedef typename Graph::template NodeMap<typename Graph::Arc> |
|
68 MatchingMap; |
|
69 |
|
70 ///\brief Status constants for Gallai-Edmonds decomposition. |
|
71 /// |
|
72 ///These constants are used for indicating the Gallai-Edmonds |
|
73 ///decomposition of a graph. The nodes with status \c EVEN (or \c D) |
|
74 ///induce a subgraph with factor-critical components, the nodes with |
|
75 ///status \c ODD (or \c A) form the canonical barrier, and the nodes |
|
76 ///with status \c MATCHED (or \c C) induce a subgraph having a |
|
77 ///perfect matching. |
|
78 enum Status { |
|
79 EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.) |
|
80 D = 1, |
|
81 MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.) |
|
82 C = 0, |
|
83 ODD = -1, ///< = -1. (\c A is an alias for \c ODD.) |
|
84 A = -1, |
|
85 UNMATCHED = -2 ///< = -2. |
|
86 }; |
|
87 |
|
88 /// The type of the status map |
|
89 typedef typename Graph::template NodeMap<Status> StatusMap; |
|
90 |
|
91 private: |
|
92 |
|
93 TEMPLATE_GRAPH_TYPEDEFS(Graph); |
|
94 |
|
95 typedef UnionFindEnum<IntNodeMap> BlossomSet; |
|
96 typedef ExtendFindEnum<IntNodeMap> TreeSet; |
|
97 typedef RangeMap<Node> NodeIntMap; |
|
98 typedef MatchingMap EarMap; |
|
99 typedef std::vector<Node> NodeQueue; |
|
100 |
|
101 const Graph& _graph; |
|
102 MatchingMap* _matching; |
|
103 StatusMap* _status; |
|
104 |
|
105 EarMap* _ear; |
|
106 |
|
107 IntNodeMap* _blossom_set_index; |
|
108 BlossomSet* _blossom_set; |
|
109 NodeIntMap* _blossom_rep; |
|
110 |
|
111 IntNodeMap* _tree_set_index; |
|
112 TreeSet* _tree_set; |
|
113 |
|
114 NodeQueue _node_queue; |
|
115 int _process, _postpone, _last; |
|
116 |
|
117 int _node_num; |
|
118 |
|
119 private: |
|
120 |
|
121 void createStructures() { |
|
122 _node_num = countNodes(_graph); |
|
123 if (!_matching) { |
|
124 _matching = new MatchingMap(_graph); |
|
125 } |
|
126 if (!_status) { |
|
127 _status = new StatusMap(_graph); |
|
128 } |
|
129 if (!_ear) { |
|
130 _ear = new EarMap(_graph); |
|
131 } |
|
132 if (!_blossom_set) { |
|
133 _blossom_set_index = new IntNodeMap(_graph); |
|
134 _blossom_set = new BlossomSet(*_blossom_set_index); |
|
135 } |
|
136 if (!_blossom_rep) { |
|
137 _blossom_rep = new NodeIntMap(_node_num); |
|
138 } |
|
139 if (!_tree_set) { |
|
140 _tree_set_index = new IntNodeMap(_graph); |
|
141 _tree_set = new TreeSet(*_tree_set_index); |
|
142 } |
|
143 _node_queue.resize(_node_num); |
|
144 } |
|
145 |
|
146 void destroyStructures() { |
|
147 if (_matching) { |
|
148 delete _matching; |
|
149 } |
|
150 if (_status) { |
|
151 delete _status; |
|
152 } |
|
153 if (_ear) { |
|
154 delete _ear; |
|
155 } |
|
156 if (_blossom_set) { |
|
157 delete _blossom_set; |
|
158 delete _blossom_set_index; |
|
159 } |
|
160 if (_blossom_rep) { |
|
161 delete _blossom_rep; |
|
162 } |
|
163 if (_tree_set) { |
|
164 delete _tree_set_index; |
|
165 delete _tree_set; |
|
166 } |
|
167 } |
|
168 |
|
169 void processDense(const Node& n) { |
|
170 _process = _postpone = _last = 0; |
|
171 _node_queue[_last++] = n; |
|
172 |
|
173 while (_process != _last) { |
|
174 Node u = _node_queue[_process++]; |
|
175 for (OutArcIt a(_graph, u); a != INVALID; ++a) { |
|
176 Node v = _graph.target(a); |
|
177 if ((*_status)[v] == MATCHED) { |
|
178 extendOnArc(a); |
|
179 } else if ((*_status)[v] == UNMATCHED) { |
|
180 augmentOnArc(a); |
|
181 return; |
|
182 } |
|
183 } |
|
184 } |
|
185 |
|
186 while (_postpone != _last) { |
|
187 Node u = _node_queue[_postpone++]; |
|
188 |
|
189 for (OutArcIt a(_graph, u); a != INVALID ; ++a) { |
|
190 Node v = _graph.target(a); |
|
191 |
|
192 if ((*_status)[v] == EVEN) { |
|
193 if (_blossom_set->find(u) != _blossom_set->find(v)) { |
|
194 shrinkOnEdge(a); |
|
195 } |
|
196 } |
|
197 |
|
198 while (_process != _last) { |
|
199 Node w = _node_queue[_process++]; |
|
200 for (OutArcIt b(_graph, w); b != INVALID; ++b) { |
|
201 Node x = _graph.target(b); |
|
202 if ((*_status)[x] == MATCHED) { |
|
203 extendOnArc(b); |
|
204 } else if ((*_status)[x] == UNMATCHED) { |
|
205 augmentOnArc(b); |
|
206 return; |
|
207 } |
|
208 } |
|
209 } |
|
210 } |
|
211 } |
|
212 } |
|
213 |
|
214 void processSparse(const Node& n) { |
|
215 _process = _last = 0; |
|
216 _node_queue[_last++] = n; |
|
217 while (_process != _last) { |
|
218 Node u = _node_queue[_process++]; |
|
219 for (OutArcIt a(_graph, u); a != INVALID; ++a) { |
|
220 Node v = _graph.target(a); |
|
221 |
|
222 if ((*_status)[v] == EVEN) { |
|
223 if (_blossom_set->find(u) != _blossom_set->find(v)) { |
|
224 shrinkOnEdge(a); |
|
225 } |
|
226 } else if ((*_status)[v] == MATCHED) { |
|
227 extendOnArc(a); |
|
228 } else if ((*_status)[v] == UNMATCHED) { |
|
229 augmentOnArc(a); |
|
230 return; |
|
231 } |
|
232 } |
|
233 } |
|
234 } |
|
235 |
|
236 void shrinkOnEdge(const Edge& e) { |
|
237 Node nca = INVALID; |
|
238 |
|
239 { |
|
240 std::set<Node> left_set, right_set; |
|
241 |
|
242 Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))]; |
|
243 left_set.insert(left); |
|
244 |
|
245 Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))]; |
|
246 right_set.insert(right); |
|
247 |
|
248 while (true) { |
|
249 if ((*_matching)[left] == INVALID) break; |
|
250 left = _graph.target((*_matching)[left]); |
|
251 left = (*_blossom_rep)[_blossom_set-> |
|
252 find(_graph.target((*_ear)[left]))]; |
|
253 if (right_set.find(left) != right_set.end()) { |
|
254 nca = left; |
|
255 break; |
|
256 } |
|
257 left_set.insert(left); |
|
258 |
|
259 if ((*_matching)[right] == INVALID) break; |
|
260 right = _graph.target((*_matching)[right]); |
|
261 right = (*_blossom_rep)[_blossom_set-> |
|
262 find(_graph.target((*_ear)[right]))]; |
|
263 if (left_set.find(right) != left_set.end()) { |
|
264 nca = right; |
|
265 break; |
|
266 } |
|
267 right_set.insert(right); |
|
268 } |
|
269 |
|
270 if (nca == INVALID) { |
|
271 if ((*_matching)[left] == INVALID) { |
|
272 nca = right; |
|
273 while (left_set.find(nca) == left_set.end()) { |
|
274 nca = _graph.target((*_matching)[nca]); |
|
275 nca =(*_blossom_rep)[_blossom_set-> |
|
276 find(_graph.target((*_ear)[nca]))]; |
|
277 } |
|
278 } else { |
|
279 nca = left; |
|
280 while (right_set.find(nca) == right_set.end()) { |
|
281 nca = _graph.target((*_matching)[nca]); |
|
282 nca = (*_blossom_rep)[_blossom_set-> |
|
283 find(_graph.target((*_ear)[nca]))]; |
|
284 } |
|
285 } |
|
286 } |
|
287 } |
|
288 |
|
289 { |
|
290 |
|
291 Node node = _graph.u(e); |
|
292 Arc arc = _graph.direct(e, true); |
|
293 Node base = (*_blossom_rep)[_blossom_set->find(node)]; |
|
294 |
|
295 while (base != nca) { |
|
296 (*_ear)[node] = arc; |
|
297 |
|
298 Node n = node; |
|
299 while (n != base) { |
|
300 n = _graph.target((*_matching)[n]); |
|
301 Arc a = (*_ear)[n]; |
|
302 n = _graph.target(a); |
|
303 (*_ear)[n] = _graph.oppositeArc(a); |
|
304 } |
|
305 node = _graph.target((*_matching)[base]); |
|
306 _tree_set->erase(base); |
|
307 _tree_set->erase(node); |
|
308 _blossom_set->insert(node, _blossom_set->find(base)); |
|
309 (*_status)[node] = EVEN; |
|
310 _node_queue[_last++] = node; |
|
311 arc = _graph.oppositeArc((*_ear)[node]); |
|
312 node = _graph.target((*_ear)[node]); |
|
313 base = (*_blossom_rep)[_blossom_set->find(node)]; |
|
314 _blossom_set->join(_graph.target(arc), base); |
|
315 } |
|
316 } |
|
317 |
|
318 (*_blossom_rep)[_blossom_set->find(nca)] = nca; |
|
319 |
|
320 { |
|
321 |
|
322 Node node = _graph.v(e); |
|
323 Arc arc = _graph.direct(e, false); |
|
324 Node base = (*_blossom_rep)[_blossom_set->find(node)]; |
|
325 |
|
326 while (base != nca) { |
|
327 (*_ear)[node] = arc; |
|
328 |
|
329 Node n = node; |
|
330 while (n != base) { |
|
331 n = _graph.target((*_matching)[n]); |
|
332 Arc a = (*_ear)[n]; |
|
333 n = _graph.target(a); |
|
334 (*_ear)[n] = _graph.oppositeArc(a); |
|
335 } |
|
336 node = _graph.target((*_matching)[base]); |
|
337 _tree_set->erase(base); |
|
338 _tree_set->erase(node); |
|
339 _blossom_set->insert(node, _blossom_set->find(base)); |
|
340 (*_status)[node] = EVEN; |
|
341 _node_queue[_last++] = node; |
|
342 arc = _graph.oppositeArc((*_ear)[node]); |
|
343 node = _graph.target((*_ear)[node]); |
|
344 base = (*_blossom_rep)[_blossom_set->find(node)]; |
|
345 _blossom_set->join(_graph.target(arc), base); |
|
346 } |
|
347 } |
|
348 |
|
349 (*_blossom_rep)[_blossom_set->find(nca)] = nca; |
|
350 } |
|
351 |
|
352 void extendOnArc(const Arc& a) { |
|
353 Node base = _graph.source(a); |
|
354 Node odd = _graph.target(a); |
|
355 |
|
356 (*_ear)[odd] = _graph.oppositeArc(a); |
|
357 Node even = _graph.target((*_matching)[odd]); |
|
358 (*_blossom_rep)[_blossom_set->insert(even)] = even; |
|
359 (*_status)[odd] = ODD; |
|
360 (*_status)[even] = EVEN; |
|
361 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]); |
|
362 _tree_set->insert(odd, tree); |
|
363 _tree_set->insert(even, tree); |
|
364 _node_queue[_last++] = even; |
|
365 |
|
366 } |
|
367 |
|
368 void augmentOnArc(const Arc& a) { |
|
369 Node even = _graph.source(a); |
|
370 Node odd = _graph.target(a); |
|
371 |
|
372 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]); |
|
373 |
|
374 (*_matching)[odd] = _graph.oppositeArc(a); |
|
375 (*_status)[odd] = MATCHED; |
|
376 |
|
377 Arc arc = (*_matching)[even]; |
|
378 (*_matching)[even] = a; |
|
379 |
|
380 while (arc != INVALID) { |
|
381 odd = _graph.target(arc); |
|
382 arc = (*_ear)[odd]; |
|
383 even = _graph.target(arc); |
|
384 (*_matching)[odd] = arc; |
|
385 arc = (*_matching)[even]; |
|
386 (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]); |
|
387 } |
|
388 |
|
389 for (typename TreeSet::ItemIt it(*_tree_set, tree); |
|
390 it != INVALID; ++it) { |
|
391 if ((*_status)[it] == ODD) { |
|
392 (*_status)[it] = MATCHED; |
|
393 } else { |
|
394 int blossom = _blossom_set->find(it); |
|
395 for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom); |
|
396 jt != INVALID; ++jt) { |
|
397 (*_status)[jt] = MATCHED; |
|
398 } |
|
399 _blossom_set->eraseClass(blossom); |
|
400 } |
|
401 } |
|
402 _tree_set->eraseClass(tree); |
|
403 |
|
404 } |
|
405 |
|
406 public: |
|
407 |
|
408 /// \brief Constructor |
|
409 /// |
|
410 /// Constructor. |
|
411 MaxMatching(const Graph& graph) |
|
412 : _graph(graph), _matching(0), _status(0), _ear(0), |
|
413 _blossom_set_index(0), _blossom_set(0), _blossom_rep(0), |
|
414 _tree_set_index(0), _tree_set(0) {} |
|
415 |
|
416 ~MaxMatching() { |
|
417 destroyStructures(); |
|
418 } |
|
419 |
|
420 /// \name Execution Control |
|
421 /// The simplest way to execute the algorithm is to use the |
|
422 /// \c run() member function.\n |
|
423 /// If you need better control on the execution, you have to call |
|
424 /// one of the functions \ref init(), \ref greedyInit() or |
|
425 /// \ref matchingInit() first, then you can start the algorithm with |
|
426 /// \ref startSparse() or \ref startDense(). |
|
427 |
|
428 ///@{ |
|
429 |
|
430 /// \brief Set the initial matching to the empty matching. |
|
431 /// |
|
432 /// This function sets the initial matching to the empty matching. |
|
433 void init() { |
|
434 createStructures(); |
|
435 for(NodeIt n(_graph); n != INVALID; ++n) { |
|
436 (*_matching)[n] = INVALID; |
|
437 (*_status)[n] = UNMATCHED; |
|
438 } |
|
439 } |
|
440 |
|
441 /// \brief Find an initial matching in a greedy way. |
|
442 /// |
|
443 /// This function finds an initial matching in a greedy way. |
|
444 void greedyInit() { |
|
445 createStructures(); |
|
446 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
447 (*_matching)[n] = INVALID; |
|
448 (*_status)[n] = UNMATCHED; |
|
449 } |
|
450 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
451 if ((*_matching)[n] == INVALID) { |
|
452 for (OutArcIt a(_graph, n); a != INVALID ; ++a) { |
|
453 Node v = _graph.target(a); |
|
454 if ((*_matching)[v] == INVALID && v != n) { |
|
455 (*_matching)[n] = a; |
|
456 (*_status)[n] = MATCHED; |
|
457 (*_matching)[v] = _graph.oppositeArc(a); |
|
458 (*_status)[v] = MATCHED; |
|
459 break; |
|
460 } |
|
461 } |
|
462 } |
|
463 } |
|
464 } |
|
465 |
|
466 |
|
467 /// \brief Initialize the matching from a map. |
|
468 /// |
|
469 /// This function initializes the matching from a \c bool valued edge |
|
470 /// map. This map should have the property that there are no two incident |
|
471 /// edges with \c true value, i.e. it really contains a matching. |
|
472 /// \return \c true if the map contains a matching. |
|
473 template <typename MatchingMap> |
|
474 bool matchingInit(const MatchingMap& matching) { |
|
475 createStructures(); |
|
476 |
|
477 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
478 (*_matching)[n] = INVALID; |
|
479 (*_status)[n] = UNMATCHED; |
|
480 } |
|
481 for(EdgeIt e(_graph); e!=INVALID; ++e) { |
|
482 if (matching[e]) { |
|
483 |
|
484 Node u = _graph.u(e); |
|
485 if ((*_matching)[u] != INVALID) return false; |
|
486 (*_matching)[u] = _graph.direct(e, true); |
|
487 (*_status)[u] = MATCHED; |
|
488 |
|
489 Node v = _graph.v(e); |
|
490 if ((*_matching)[v] != INVALID) return false; |
|
491 (*_matching)[v] = _graph.direct(e, false); |
|
492 (*_status)[v] = MATCHED; |
|
493 } |
|
494 } |
|
495 return true; |
|
496 } |
|
497 |
|
498 /// \brief Start Edmonds' algorithm |
|
499 /// |
|
500 /// This function runs the original Edmonds' algorithm. |
|
501 /// |
|
502 /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be |
|
503 /// called before using this function. |
|
504 void startSparse() { |
|
505 for(NodeIt n(_graph); n != INVALID; ++n) { |
|
506 if ((*_status)[n] == UNMATCHED) { |
|
507 (*_blossom_rep)[_blossom_set->insert(n)] = n; |
|
508 _tree_set->insert(n); |
|
509 (*_status)[n] = EVEN; |
|
510 processSparse(n); |
|
511 } |
|
512 } |
|
513 } |
|
514 |
|
515 /// \brief Start Edmonds' algorithm with a heuristic improvement |
|
516 /// for dense graphs |
|
517 /// |
|
518 /// This function runs Edmonds' algorithm with a heuristic of postponing |
|
519 /// shrinks, therefore resulting in a faster algorithm for dense graphs. |
|
520 /// |
|
521 /// \pre \ref Init(), \ref greedyInit() or \ref matchingInit() must be |
|
522 /// called before using this function. |
|
523 void startDense() { |
|
524 for(NodeIt n(_graph); n != INVALID; ++n) { |
|
525 if ((*_status)[n] == UNMATCHED) { |
|
526 (*_blossom_rep)[_blossom_set->insert(n)] = n; |
|
527 _tree_set->insert(n); |
|
528 (*_status)[n] = EVEN; |
|
529 processDense(n); |
|
530 } |
|
531 } |
|
532 } |
|
533 |
|
534 |
|
535 /// \brief Run Edmonds' algorithm |
|
536 /// |
|
537 /// This function runs Edmonds' algorithm. An additional heuristic of |
|
538 /// postponing shrinks is used for relatively dense graphs |
|
539 /// (for which <tt>m>=2*n</tt> holds). |
|
540 void run() { |
|
541 if (countEdges(_graph) < 2 * countNodes(_graph)) { |
|
542 greedyInit(); |
|
543 startSparse(); |
|
544 } else { |
|
545 init(); |
|
546 startDense(); |
|
547 } |
|
548 } |
|
549 |
|
550 /// @} |
|
551 |
|
552 /// \name Primal Solution |
|
553 /// Functions to get the primal solution, i.e. the maximum matching. |
|
554 |
|
555 /// @{ |
|
556 |
|
557 /// \brief Return the size (cardinality) of the matching. |
|
558 /// |
|
559 /// This function returns the size (cardinality) of the current matching. |
|
560 /// After run() it returns the size of the maximum matching in the graph. |
|
561 int matchingSize() const { |
|
562 int size = 0; |
|
563 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
564 if ((*_matching)[n] != INVALID) { |
|
565 ++size; |
|
566 } |
|
567 } |
|
568 return size / 2; |
|
569 } |
|
570 |
|
571 /// \brief Return \c true if the given edge is in the matching. |
|
572 /// |
|
573 /// This function returns \c true if the given edge is in the current |
|
574 /// matching. |
|
575 bool matching(const Edge& edge) const { |
|
576 return edge == (*_matching)[_graph.u(edge)]; |
|
577 } |
|
578 |
|
579 /// \brief Return the matching arc (or edge) incident to the given node. |
|
580 /// |
|
581 /// This function returns the matching arc (or edge) incident to the |
|
582 /// given node in the current matching or \c INVALID if the node is |
|
583 /// not covered by the matching. |
|
584 Arc matching(const Node& n) const { |
|
585 return (*_matching)[n]; |
|
586 } |
|
587 |
|
588 /// \brief Return a const reference to the matching map. |
|
589 /// |
|
590 /// This function returns a const reference to a node map that stores |
|
591 /// the matching arc (or edge) incident to each node. |
|
592 const MatchingMap& matchingMap() const { |
|
593 return *_matching; |
|
594 } |
|
595 |
|
596 /// \brief Return the mate of the given node. |
|
597 /// |
|
598 /// This function returns the mate of the given node in the current |
|
599 /// matching or \c INVALID if the node is not covered by the matching. |
|
600 Node mate(const Node& n) const { |
|
601 return (*_matching)[n] != INVALID ? |
|
602 _graph.target((*_matching)[n]) : INVALID; |
|
603 } |
|
604 |
|
605 /// @} |
|
606 |
|
607 /// \name Dual Solution |
|
608 /// Functions to get the dual solution, i.e. the Gallai-Edmonds |
|
609 /// decomposition. |
|
610 |
|
611 /// @{ |
|
612 |
|
613 /// \brief Return the status of the given node in the Edmonds-Gallai |
|
614 /// decomposition. |
|
615 /// |
|
616 /// This function returns the \ref Status "status" of the given node |
|
617 /// in the Edmonds-Gallai decomposition. |
|
618 Status status(const Node& n) const { |
|
619 return (*_status)[n]; |
|
620 } |
|
621 |
|
622 /// \brief Return a const reference to the status map, which stores |
|
623 /// the Edmonds-Gallai decomposition. |
|
624 /// |
|
625 /// This function returns a const reference to a node map that stores the |
|
626 /// \ref Status "status" of each node in the Edmonds-Gallai decomposition. |
|
627 const StatusMap& statusMap() const { |
|
628 return *_status; |
|
629 } |
|
630 |
|
631 /// \brief Return \c true if the given node is in the barrier. |
|
632 /// |
|
633 /// This function returns \c true if the given node is in the barrier. |
|
634 bool barrier(const Node& n) const { |
|
635 return (*_status)[n] == ODD; |
|
636 } |
|
637 |
|
638 /// @} |
|
639 |
|
640 }; |
|
641 |
|
642 /// \ingroup matching |
|
643 /// |
|
644 /// \brief Weighted matching in general graphs |
|
645 /// |
|
646 /// This class provides an efficient implementation of Edmond's |
|
647 /// maximum weighted matching algorithm. The implementation is based |
|
648 /// on extensive use of priority queues and provides |
|
649 /// \f$O(nm\log n)\f$ time complexity. |
|
650 /// |
|
651 /// The maximum weighted matching problem is to find a subset of the |
|
652 /// edges in an undirected graph with maximum overall weight for which |
|
653 /// each node has at most one incident edge. |
|
654 /// It can be formulated with the following linear program. |
|
655 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f] |
|
656 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2} |
|
657 \quad \forall B\in\mathcal{O}\f] */ |
|
658 /// \f[x_e \ge 0\quad \forall e\in E\f] |
|
659 /// \f[\max \sum_{e\in E}x_ew_e\f] |
|
660 /// where \f$\delta(X)\f$ is the set of edges incident to a node in |
|
661 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in |
|
662 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality |
|
663 /// subsets of the nodes. |
|
664 /// |
|
665 /// The algorithm calculates an optimal matching and a proof of the |
|
666 /// optimality. The solution of the dual problem can be used to check |
|
667 /// the result of the algorithm. The dual linear problem is the |
|
668 /// following. |
|
669 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)} |
|
670 z_B \ge w_{uv} \quad \forall uv\in E\f] */ |
|
671 /// \f[y_u \ge 0 \quad \forall u \in V\f] |
|
672 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f] |
|
673 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}} |
|
674 \frac{\vert B \vert - 1}{2}z_B\f] */ |
|
675 /// |
|
676 /// The algorithm can be executed with the run() function. |
|
677 /// After it the matching (the primal solution) and the dual solution |
|
678 /// can be obtained using the query functions and the |
|
679 /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, |
|
680 /// which is able to iterate on the nodes of a blossom. |
|
681 /// If the value type is integer, then the dual solution is multiplied |
|
682 /// by \ref MaxWeightedMatching::dualScale "4". |
|
683 /// |
|
684 /// \tparam GR The undirected graph type the algorithm runs on. |
|
685 /// \tparam WM The type edge weight map. The default type is |
|
686 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>". |
|
687 #ifdef DOXYGEN |
|
688 template <typename GR, typename WM> |
|
689 #else |
|
690 template <typename GR, |
|
691 typename WM = typename GR::template EdgeMap<int> > |
|
692 #endif |
|
693 class MaxWeightedMatching { |
|
694 public: |
|
695 |
|
696 /// The graph type of the algorithm |
|
697 typedef GR Graph; |
|
698 /// The type of the edge weight map |
|
699 typedef WM WeightMap; |
|
700 /// The value type of the edge weights |
|
701 typedef typename WeightMap::Value Value; |
|
702 |
|
703 /// The type of the matching map |
|
704 typedef typename Graph::template NodeMap<typename Graph::Arc> |
|
705 MatchingMap; |
|
706 |
|
707 /// \brief Scaling factor for dual solution |
|
708 /// |
|
709 /// Scaling factor for dual solution. It is equal to 4 or 1 |
|
710 /// according to the value type. |
|
711 static const int dualScale = |
|
712 std::numeric_limits<Value>::is_integer ? 4 : 1; |
|
713 |
|
714 private: |
|
715 |
|
716 TEMPLATE_GRAPH_TYPEDEFS(Graph); |
|
717 |
|
718 typedef typename Graph::template NodeMap<Value> NodePotential; |
|
719 typedef std::vector<Node> BlossomNodeList; |
|
720 |
|
721 struct BlossomVariable { |
|
722 int begin, end; |
|
723 Value value; |
|
724 |
|
725 BlossomVariable(int _begin, int _end, Value _value) |
|
726 : begin(_begin), end(_end), value(_value) {} |
|
727 |
|
728 }; |
|
729 |
|
730 typedef std::vector<BlossomVariable> BlossomPotential; |
|
731 |
|
732 const Graph& _graph; |
|
733 const WeightMap& _weight; |
|
734 |
|
735 MatchingMap* _matching; |
|
736 |
|
737 NodePotential* _node_potential; |
|
738 |
|
739 BlossomPotential _blossom_potential; |
|
740 BlossomNodeList _blossom_node_list; |
|
741 |
|
742 int _node_num; |
|
743 int _blossom_num; |
|
744 |
|
745 typedef RangeMap<int> IntIntMap; |
|
746 |
|
747 enum Status { |
|
748 EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2 |
|
749 }; |
|
750 |
|
751 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet; |
|
752 struct BlossomData { |
|
753 int tree; |
|
754 Status status; |
|
755 Arc pred, next; |
|
756 Value pot, offset; |
|
757 Node base; |
|
758 }; |
|
759 |
|
760 IntNodeMap *_blossom_index; |
|
761 BlossomSet *_blossom_set; |
|
762 RangeMap<BlossomData>* _blossom_data; |
|
763 |
|
764 IntNodeMap *_node_index; |
|
765 IntArcMap *_node_heap_index; |
|
766 |
|
767 struct NodeData { |
|
768 |
|
769 NodeData(IntArcMap& node_heap_index) |
|
770 : heap(node_heap_index) {} |
|
771 |
|
772 int blossom; |
|
773 Value pot; |
|
774 BinHeap<Value, IntArcMap> heap; |
|
775 std::map<int, Arc> heap_index; |
|
776 |
|
777 int tree; |
|
778 }; |
|
779 |
|
780 RangeMap<NodeData>* _node_data; |
|
781 |
|
782 typedef ExtendFindEnum<IntIntMap> TreeSet; |
|
783 |
|
784 IntIntMap *_tree_set_index; |
|
785 TreeSet *_tree_set; |
|
786 |
|
787 IntNodeMap *_delta1_index; |
|
788 BinHeap<Value, IntNodeMap> *_delta1; |
|
789 |
|
790 IntIntMap *_delta2_index; |
|
791 BinHeap<Value, IntIntMap> *_delta2; |
|
792 |
|
793 IntEdgeMap *_delta3_index; |
|
794 BinHeap<Value, IntEdgeMap> *_delta3; |
|
795 |
|
796 IntIntMap *_delta4_index; |
|
797 BinHeap<Value, IntIntMap> *_delta4; |
|
798 |
|
799 Value _delta_sum; |
|
800 |
|
801 void createStructures() { |
|
802 _node_num = countNodes(_graph); |
|
803 _blossom_num = _node_num * 3 / 2; |
|
804 |
|
805 if (!_matching) { |
|
806 _matching = new MatchingMap(_graph); |
|
807 } |
|
808 if (!_node_potential) { |
|
809 _node_potential = new NodePotential(_graph); |
|
810 } |
|
811 if (!_blossom_set) { |
|
812 _blossom_index = new IntNodeMap(_graph); |
|
813 _blossom_set = new BlossomSet(*_blossom_index); |
|
814 _blossom_data = new RangeMap<BlossomData>(_blossom_num); |
|
815 } |
|
816 |
|
817 if (!_node_index) { |
|
818 _node_index = new IntNodeMap(_graph); |
|
819 _node_heap_index = new IntArcMap(_graph); |
|
820 _node_data = new RangeMap<NodeData>(_node_num, |
|
821 NodeData(*_node_heap_index)); |
|
822 } |
|
823 |
|
824 if (!_tree_set) { |
|
825 _tree_set_index = new IntIntMap(_blossom_num); |
|
826 _tree_set = new TreeSet(*_tree_set_index); |
|
827 } |
|
828 if (!_delta1) { |
|
829 _delta1_index = new IntNodeMap(_graph); |
|
830 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index); |
|
831 } |
|
832 if (!_delta2) { |
|
833 _delta2_index = new IntIntMap(_blossom_num); |
|
834 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index); |
|
835 } |
|
836 if (!_delta3) { |
|
837 _delta3_index = new IntEdgeMap(_graph); |
|
838 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index); |
|
839 } |
|
840 if (!_delta4) { |
|
841 _delta4_index = new IntIntMap(_blossom_num); |
|
842 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index); |
|
843 } |
|
844 } |
|
845 |
|
846 void destroyStructures() { |
|
847 _node_num = countNodes(_graph); |
|
848 _blossom_num = _node_num * 3 / 2; |
|
849 |
|
850 if (_matching) { |
|
851 delete _matching; |
|
852 } |
|
853 if (_node_potential) { |
|
854 delete _node_potential; |
|
855 } |
|
856 if (_blossom_set) { |
|
857 delete _blossom_index; |
|
858 delete _blossom_set; |
|
859 delete _blossom_data; |
|
860 } |
|
861 |
|
862 if (_node_index) { |
|
863 delete _node_index; |
|
864 delete _node_heap_index; |
|
865 delete _node_data; |
|
866 } |
|
867 |
|
868 if (_tree_set) { |
|
869 delete _tree_set_index; |
|
870 delete _tree_set; |
|
871 } |
|
872 if (_delta1) { |
|
873 delete _delta1_index; |
|
874 delete _delta1; |
|
875 } |
|
876 if (_delta2) { |
|
877 delete _delta2_index; |
|
878 delete _delta2; |
|
879 } |
|
880 if (_delta3) { |
|
881 delete _delta3_index; |
|
882 delete _delta3; |
|
883 } |
|
884 if (_delta4) { |
|
885 delete _delta4_index; |
|
886 delete _delta4; |
|
887 } |
|
888 } |
|
889 |
|
890 void matchedToEven(int blossom, int tree) { |
|
891 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
892 _delta2->erase(blossom); |
|
893 } |
|
894 |
|
895 if (!_blossom_set->trivial(blossom)) { |
|
896 (*_blossom_data)[blossom].pot -= |
|
897 2 * (_delta_sum - (*_blossom_data)[blossom].offset); |
|
898 } |
|
899 |
|
900 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
901 n != INVALID; ++n) { |
|
902 |
|
903 _blossom_set->increase(n, std::numeric_limits<Value>::max()); |
|
904 int ni = (*_node_index)[n]; |
|
905 |
|
906 (*_node_data)[ni].heap.clear(); |
|
907 (*_node_data)[ni].heap_index.clear(); |
|
908 |
|
909 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset; |
|
910 |
|
911 _delta1->push(n, (*_node_data)[ni].pot); |
|
912 |
|
913 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
914 Node v = _graph.source(e); |
|
915 int vb = _blossom_set->find(v); |
|
916 int vi = (*_node_index)[v]; |
|
917 |
|
918 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
919 dualScale * _weight[e]; |
|
920 |
|
921 if ((*_blossom_data)[vb].status == EVEN) { |
|
922 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) { |
|
923 _delta3->push(e, rw / 2); |
|
924 } |
|
925 } else if ((*_blossom_data)[vb].status == UNMATCHED) { |
|
926 if (_delta3->state(e) != _delta3->IN_HEAP) { |
|
927 _delta3->push(e, rw); |
|
928 } |
|
929 } else { |
|
930 typename std::map<int, Arc>::iterator it = |
|
931 (*_node_data)[vi].heap_index.find(tree); |
|
932 |
|
933 if (it != (*_node_data)[vi].heap_index.end()) { |
|
934 if ((*_node_data)[vi].heap[it->second] > rw) { |
|
935 (*_node_data)[vi].heap.replace(it->second, e); |
|
936 (*_node_data)[vi].heap.decrease(e, rw); |
|
937 it->second = e; |
|
938 } |
|
939 } else { |
|
940 (*_node_data)[vi].heap.push(e, rw); |
|
941 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e)); |
|
942 } |
|
943 |
|
944 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) { |
|
945 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio()); |
|
946 |
|
947 if ((*_blossom_data)[vb].status == MATCHED) { |
|
948 if (_delta2->state(vb) != _delta2->IN_HEAP) { |
|
949 _delta2->push(vb, _blossom_set->classPrio(vb) - |
|
950 (*_blossom_data)[vb].offset); |
|
951 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) - |
|
952 (*_blossom_data)[vb].offset){ |
|
953 _delta2->decrease(vb, _blossom_set->classPrio(vb) - |
|
954 (*_blossom_data)[vb].offset); |
|
955 } |
|
956 } |
|
957 } |
|
958 } |
|
959 } |
|
960 } |
|
961 (*_blossom_data)[blossom].offset = 0; |
|
962 } |
|
963 |
|
964 void matchedToOdd(int blossom) { |
|
965 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
966 _delta2->erase(blossom); |
|
967 } |
|
968 (*_blossom_data)[blossom].offset += _delta_sum; |
|
969 if (!_blossom_set->trivial(blossom)) { |
|
970 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 + |
|
971 (*_blossom_data)[blossom].offset); |
|
972 } |
|
973 } |
|
974 |
|
975 void evenToMatched(int blossom, int tree) { |
|
976 if (!_blossom_set->trivial(blossom)) { |
|
977 (*_blossom_data)[blossom].pot += 2 * _delta_sum; |
|
978 } |
|
979 |
|
980 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
981 n != INVALID; ++n) { |
|
982 int ni = (*_node_index)[n]; |
|
983 (*_node_data)[ni].pot -= _delta_sum; |
|
984 |
|
985 _delta1->erase(n); |
|
986 |
|
987 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
988 Node v = _graph.source(e); |
|
989 int vb = _blossom_set->find(v); |
|
990 int vi = (*_node_index)[v]; |
|
991 |
|
992 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
993 dualScale * _weight[e]; |
|
994 |
|
995 if (vb == blossom) { |
|
996 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
997 _delta3->erase(e); |
|
998 } |
|
999 } else if ((*_blossom_data)[vb].status == EVEN) { |
|
1000 |
|
1001 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
1002 _delta3->erase(e); |
|
1003 } |
|
1004 |
|
1005 int vt = _tree_set->find(vb); |
|
1006 |
|
1007 if (vt != tree) { |
|
1008 |
|
1009 Arc r = _graph.oppositeArc(e); |
|
1010 |
|
1011 typename std::map<int, Arc>::iterator it = |
|
1012 (*_node_data)[ni].heap_index.find(vt); |
|
1013 |
|
1014 if (it != (*_node_data)[ni].heap_index.end()) { |
|
1015 if ((*_node_data)[ni].heap[it->second] > rw) { |
|
1016 (*_node_data)[ni].heap.replace(it->second, r); |
|
1017 (*_node_data)[ni].heap.decrease(r, rw); |
|
1018 it->second = r; |
|
1019 } |
|
1020 } else { |
|
1021 (*_node_data)[ni].heap.push(r, rw); |
|
1022 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r)); |
|
1023 } |
|
1024 |
|
1025 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) { |
|
1026 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio()); |
|
1027 |
|
1028 if (_delta2->state(blossom) != _delta2->IN_HEAP) { |
|
1029 _delta2->push(blossom, _blossom_set->classPrio(blossom) - |
|
1030 (*_blossom_data)[blossom].offset); |
|
1031 } else if ((*_delta2)[blossom] > |
|
1032 _blossom_set->classPrio(blossom) - |
|
1033 (*_blossom_data)[blossom].offset){ |
|
1034 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) - |
|
1035 (*_blossom_data)[blossom].offset); |
|
1036 } |
|
1037 } |
|
1038 } |
|
1039 |
|
1040 } else if ((*_blossom_data)[vb].status == UNMATCHED) { |
|
1041 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
1042 _delta3->erase(e); |
|
1043 } |
|
1044 } else { |
|
1045 |
|
1046 typename std::map<int, Arc>::iterator it = |
|
1047 (*_node_data)[vi].heap_index.find(tree); |
|
1048 |
|
1049 if (it != (*_node_data)[vi].heap_index.end()) { |
|
1050 (*_node_data)[vi].heap.erase(it->second); |
|
1051 (*_node_data)[vi].heap_index.erase(it); |
|
1052 if ((*_node_data)[vi].heap.empty()) { |
|
1053 _blossom_set->increase(v, std::numeric_limits<Value>::max()); |
|
1054 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) { |
|
1055 _blossom_set->increase(v, (*_node_data)[vi].heap.prio()); |
|
1056 } |
|
1057 |
|
1058 if ((*_blossom_data)[vb].status == MATCHED) { |
|
1059 if (_blossom_set->classPrio(vb) == |
|
1060 std::numeric_limits<Value>::max()) { |
|
1061 _delta2->erase(vb); |
|
1062 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) - |
|
1063 (*_blossom_data)[vb].offset) { |
|
1064 _delta2->increase(vb, _blossom_set->classPrio(vb) - |
|
1065 (*_blossom_data)[vb].offset); |
|
1066 } |
|
1067 } |
|
1068 } |
|
1069 } |
|
1070 } |
|
1071 } |
|
1072 } |
|
1073 |
|
1074 void oddToMatched(int blossom) { |
|
1075 (*_blossom_data)[blossom].offset -= _delta_sum; |
|
1076 |
|
1077 if (_blossom_set->classPrio(blossom) != |
|
1078 std::numeric_limits<Value>::max()) { |
|
1079 _delta2->push(blossom, _blossom_set->classPrio(blossom) - |
|
1080 (*_blossom_data)[blossom].offset); |
|
1081 } |
|
1082 |
|
1083 if (!_blossom_set->trivial(blossom)) { |
|
1084 _delta4->erase(blossom); |
|
1085 } |
|
1086 } |
|
1087 |
|
1088 void oddToEven(int blossom, int tree) { |
|
1089 if (!_blossom_set->trivial(blossom)) { |
|
1090 _delta4->erase(blossom); |
|
1091 (*_blossom_data)[blossom].pot -= |
|
1092 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset); |
|
1093 } |
|
1094 |
|
1095 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
1096 n != INVALID; ++n) { |
|
1097 int ni = (*_node_index)[n]; |
|
1098 |
|
1099 _blossom_set->increase(n, std::numeric_limits<Value>::max()); |
|
1100 |
|
1101 (*_node_data)[ni].heap.clear(); |
|
1102 (*_node_data)[ni].heap_index.clear(); |
|
1103 (*_node_data)[ni].pot += |
|
1104 2 * _delta_sum - (*_blossom_data)[blossom].offset; |
|
1105 |
|
1106 _delta1->push(n, (*_node_data)[ni].pot); |
|
1107 |
|
1108 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
1109 Node v = _graph.source(e); |
|
1110 int vb = _blossom_set->find(v); |
|
1111 int vi = (*_node_index)[v]; |
|
1112 |
|
1113 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
1114 dualScale * _weight[e]; |
|
1115 |
|
1116 if ((*_blossom_data)[vb].status == EVEN) { |
|
1117 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) { |
|
1118 _delta3->push(e, rw / 2); |
|
1119 } |
|
1120 } else if ((*_blossom_data)[vb].status == UNMATCHED) { |
|
1121 if (_delta3->state(e) != _delta3->IN_HEAP) { |
|
1122 _delta3->push(e, rw); |
|
1123 } |
|
1124 } else { |
|
1125 |
|
1126 typename std::map<int, Arc>::iterator it = |
|
1127 (*_node_data)[vi].heap_index.find(tree); |
|
1128 |
|
1129 if (it != (*_node_data)[vi].heap_index.end()) { |
|
1130 if ((*_node_data)[vi].heap[it->second] > rw) { |
|
1131 (*_node_data)[vi].heap.replace(it->second, e); |
|
1132 (*_node_data)[vi].heap.decrease(e, rw); |
|
1133 it->second = e; |
|
1134 } |
|
1135 } else { |
|
1136 (*_node_data)[vi].heap.push(e, rw); |
|
1137 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e)); |
|
1138 } |
|
1139 |
|
1140 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) { |
|
1141 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio()); |
|
1142 |
|
1143 if ((*_blossom_data)[vb].status == MATCHED) { |
|
1144 if (_delta2->state(vb) != _delta2->IN_HEAP) { |
|
1145 _delta2->push(vb, _blossom_set->classPrio(vb) - |
|
1146 (*_blossom_data)[vb].offset); |
|
1147 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) - |
|
1148 (*_blossom_data)[vb].offset) { |
|
1149 _delta2->decrease(vb, _blossom_set->classPrio(vb) - |
|
1150 (*_blossom_data)[vb].offset); |
|
1151 } |
|
1152 } |
|
1153 } |
|
1154 } |
|
1155 } |
|
1156 } |
|
1157 (*_blossom_data)[blossom].offset = 0; |
|
1158 } |
|
1159 |
|
1160 |
|
1161 void matchedToUnmatched(int blossom) { |
|
1162 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
1163 _delta2->erase(blossom); |
|
1164 } |
|
1165 |
|
1166 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
1167 n != INVALID; ++n) { |
|
1168 int ni = (*_node_index)[n]; |
|
1169 |
|
1170 _blossom_set->increase(n, std::numeric_limits<Value>::max()); |
|
1171 |
|
1172 (*_node_data)[ni].heap.clear(); |
|
1173 (*_node_data)[ni].heap_index.clear(); |
|
1174 |
|
1175 for (OutArcIt e(_graph, n); e != INVALID; ++e) { |
|
1176 Node v = _graph.target(e); |
|
1177 int vb = _blossom_set->find(v); |
|
1178 int vi = (*_node_index)[v]; |
|
1179 |
|
1180 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
1181 dualScale * _weight[e]; |
|
1182 |
|
1183 if ((*_blossom_data)[vb].status == EVEN) { |
|
1184 if (_delta3->state(e) != _delta3->IN_HEAP) { |
|
1185 _delta3->push(e, rw); |
|
1186 } |
|
1187 } |
|
1188 } |
|
1189 } |
|
1190 } |
|
1191 |
|
1192 void unmatchedToMatched(int blossom) { |
|
1193 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
1194 n != INVALID; ++n) { |
|
1195 int ni = (*_node_index)[n]; |
|
1196 |
|
1197 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
1198 Node v = _graph.source(e); |
|
1199 int vb = _blossom_set->find(v); |
|
1200 int vi = (*_node_index)[v]; |
|
1201 |
|
1202 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
1203 dualScale * _weight[e]; |
|
1204 |
|
1205 if (vb == blossom) { |
|
1206 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
1207 _delta3->erase(e); |
|
1208 } |
|
1209 } else if ((*_blossom_data)[vb].status == EVEN) { |
|
1210 |
|
1211 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
1212 _delta3->erase(e); |
|
1213 } |
|
1214 |
|
1215 int vt = _tree_set->find(vb); |
|
1216 |
|
1217 Arc r = _graph.oppositeArc(e); |
|
1218 |
|
1219 typename std::map<int, Arc>::iterator it = |
|
1220 (*_node_data)[ni].heap_index.find(vt); |
|
1221 |
|
1222 if (it != (*_node_data)[ni].heap_index.end()) { |
|
1223 if ((*_node_data)[ni].heap[it->second] > rw) { |
|
1224 (*_node_data)[ni].heap.replace(it->second, r); |
|
1225 (*_node_data)[ni].heap.decrease(r, rw); |
|
1226 it->second = r; |
|
1227 } |
|
1228 } else { |
|
1229 (*_node_data)[ni].heap.push(r, rw); |
|
1230 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r)); |
|
1231 } |
|
1232 |
|
1233 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) { |
|
1234 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio()); |
|
1235 |
|
1236 if (_delta2->state(blossom) != _delta2->IN_HEAP) { |
|
1237 _delta2->push(blossom, _blossom_set->classPrio(blossom) - |
|
1238 (*_blossom_data)[blossom].offset); |
|
1239 } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)- |
|
1240 (*_blossom_data)[blossom].offset){ |
|
1241 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) - |
|
1242 (*_blossom_data)[blossom].offset); |
|
1243 } |
|
1244 } |
|
1245 |
|
1246 } else if ((*_blossom_data)[vb].status == UNMATCHED) { |
|
1247 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
1248 _delta3->erase(e); |
|
1249 } |
|
1250 } |
|
1251 } |
|
1252 } |
|
1253 } |
|
1254 |
|
1255 void alternatePath(int even, int tree) { |
|
1256 int odd; |
|
1257 |
|
1258 evenToMatched(even, tree); |
|
1259 (*_blossom_data)[even].status = MATCHED; |
|
1260 |
|
1261 while ((*_blossom_data)[even].pred != INVALID) { |
|
1262 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred)); |
|
1263 (*_blossom_data)[odd].status = MATCHED; |
|
1264 oddToMatched(odd); |
|
1265 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred; |
|
1266 |
|
1267 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred)); |
|
1268 (*_blossom_data)[even].status = MATCHED; |
|
1269 evenToMatched(even, tree); |
|
1270 (*_blossom_data)[even].next = |
|
1271 _graph.oppositeArc((*_blossom_data)[odd].pred); |
|
1272 } |
|
1273 |
|
1274 } |
|
1275 |
|
1276 void destroyTree(int tree) { |
|
1277 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) { |
|
1278 if ((*_blossom_data)[b].status == EVEN) { |
|
1279 (*_blossom_data)[b].status = MATCHED; |
|
1280 evenToMatched(b, tree); |
|
1281 } else if ((*_blossom_data)[b].status == ODD) { |
|
1282 (*_blossom_data)[b].status = MATCHED; |
|
1283 oddToMatched(b); |
|
1284 } |
|
1285 } |
|
1286 _tree_set->eraseClass(tree); |
|
1287 } |
|
1288 |
|
1289 |
|
1290 void unmatchNode(const Node& node) { |
|
1291 int blossom = _blossom_set->find(node); |
|
1292 int tree = _tree_set->find(blossom); |
|
1293 |
|
1294 alternatePath(blossom, tree); |
|
1295 destroyTree(tree); |
|
1296 |
|
1297 (*_blossom_data)[blossom].status = UNMATCHED; |
|
1298 (*_blossom_data)[blossom].base = node; |
|
1299 matchedToUnmatched(blossom); |
|
1300 } |
|
1301 |
|
1302 |
|
1303 void augmentOnEdge(const Edge& edge) { |
|
1304 |
|
1305 int left = _blossom_set->find(_graph.u(edge)); |
|
1306 int right = _blossom_set->find(_graph.v(edge)); |
|
1307 |
|
1308 if ((*_blossom_data)[left].status == EVEN) { |
|
1309 int left_tree = _tree_set->find(left); |
|
1310 alternatePath(left, left_tree); |
|
1311 destroyTree(left_tree); |
|
1312 } else { |
|
1313 (*_blossom_data)[left].status = MATCHED; |
|
1314 unmatchedToMatched(left); |
|
1315 } |
|
1316 |
|
1317 if ((*_blossom_data)[right].status == EVEN) { |
|
1318 int right_tree = _tree_set->find(right); |
|
1319 alternatePath(right, right_tree); |
|
1320 destroyTree(right_tree); |
|
1321 } else { |
|
1322 (*_blossom_data)[right].status = MATCHED; |
|
1323 unmatchedToMatched(right); |
|
1324 } |
|
1325 |
|
1326 (*_blossom_data)[left].next = _graph.direct(edge, true); |
|
1327 (*_blossom_data)[right].next = _graph.direct(edge, false); |
|
1328 } |
|
1329 |
|
1330 void extendOnArc(const Arc& arc) { |
|
1331 int base = _blossom_set->find(_graph.target(arc)); |
|
1332 int tree = _tree_set->find(base); |
|
1333 |
|
1334 int odd = _blossom_set->find(_graph.source(arc)); |
|
1335 _tree_set->insert(odd, tree); |
|
1336 (*_blossom_data)[odd].status = ODD; |
|
1337 matchedToOdd(odd); |
|
1338 (*_blossom_data)[odd].pred = arc; |
|
1339 |
|
1340 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next)); |
|
1341 (*_blossom_data)[even].pred = (*_blossom_data)[even].next; |
|
1342 _tree_set->insert(even, tree); |
|
1343 (*_blossom_data)[even].status = EVEN; |
|
1344 matchedToEven(even, tree); |
|
1345 } |
|
1346 |
|
1347 void shrinkOnEdge(const Edge& edge, int tree) { |
|
1348 int nca = -1; |
|
1349 std::vector<int> left_path, right_path; |
|
1350 |
|
1351 { |
|
1352 std::set<int> left_set, right_set; |
|
1353 int left = _blossom_set->find(_graph.u(edge)); |
|
1354 left_path.push_back(left); |
|
1355 left_set.insert(left); |
|
1356 |
|
1357 int right = _blossom_set->find(_graph.v(edge)); |
|
1358 right_path.push_back(right); |
|
1359 right_set.insert(right); |
|
1360 |
|
1361 while (true) { |
|
1362 |
|
1363 if ((*_blossom_data)[left].pred == INVALID) break; |
|
1364 |
|
1365 left = |
|
1366 _blossom_set->find(_graph.target((*_blossom_data)[left].pred)); |
|
1367 left_path.push_back(left); |
|
1368 left = |
|
1369 _blossom_set->find(_graph.target((*_blossom_data)[left].pred)); |
|
1370 left_path.push_back(left); |
|
1371 |
|
1372 left_set.insert(left); |
|
1373 |
|
1374 if (right_set.find(left) != right_set.end()) { |
|
1375 nca = left; |
|
1376 break; |
|
1377 } |
|
1378 |
|
1379 if ((*_blossom_data)[right].pred == INVALID) break; |
|
1380 |
|
1381 right = |
|
1382 _blossom_set->find(_graph.target((*_blossom_data)[right].pred)); |
|
1383 right_path.push_back(right); |
|
1384 right = |
|
1385 _blossom_set->find(_graph.target((*_blossom_data)[right].pred)); |
|
1386 right_path.push_back(right); |
|
1387 |
|
1388 right_set.insert(right); |
|
1389 |
|
1390 if (left_set.find(right) != left_set.end()) { |
|
1391 nca = right; |
|
1392 break; |
|
1393 } |
|
1394 |
|
1395 } |
|
1396 |
|
1397 if (nca == -1) { |
|
1398 if ((*_blossom_data)[left].pred == INVALID) { |
|
1399 nca = right; |
|
1400 while (left_set.find(nca) == left_set.end()) { |
|
1401 nca = |
|
1402 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
1403 right_path.push_back(nca); |
|
1404 nca = |
|
1405 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
1406 right_path.push_back(nca); |
|
1407 } |
|
1408 } else { |
|
1409 nca = left; |
|
1410 while (right_set.find(nca) == right_set.end()) { |
|
1411 nca = |
|
1412 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
1413 left_path.push_back(nca); |
|
1414 nca = |
|
1415 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
1416 left_path.push_back(nca); |
|
1417 } |
|
1418 } |
|
1419 } |
|
1420 } |
|
1421 |
|
1422 std::vector<int> subblossoms; |
|
1423 Arc prev; |
|
1424 |
|
1425 prev = _graph.direct(edge, true); |
|
1426 for (int i = 0; left_path[i] != nca; i += 2) { |
|
1427 subblossoms.push_back(left_path[i]); |
|
1428 (*_blossom_data)[left_path[i]].next = prev; |
|
1429 _tree_set->erase(left_path[i]); |
|
1430 |
|
1431 subblossoms.push_back(left_path[i + 1]); |
|
1432 (*_blossom_data)[left_path[i + 1]].status = EVEN; |
|
1433 oddToEven(left_path[i + 1], tree); |
|
1434 _tree_set->erase(left_path[i + 1]); |
|
1435 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred); |
|
1436 } |
|
1437 |
|
1438 int k = 0; |
|
1439 while (right_path[k] != nca) ++k; |
|
1440 |
|
1441 subblossoms.push_back(nca); |
|
1442 (*_blossom_data)[nca].next = prev; |
|
1443 |
|
1444 for (int i = k - 2; i >= 0; i -= 2) { |
|
1445 subblossoms.push_back(right_path[i + 1]); |
|
1446 (*_blossom_data)[right_path[i + 1]].status = EVEN; |
|
1447 oddToEven(right_path[i + 1], tree); |
|
1448 _tree_set->erase(right_path[i + 1]); |
|
1449 |
|
1450 (*_blossom_data)[right_path[i + 1]].next = |
|
1451 (*_blossom_data)[right_path[i + 1]].pred; |
|
1452 |
|
1453 subblossoms.push_back(right_path[i]); |
|
1454 _tree_set->erase(right_path[i]); |
|
1455 } |
|
1456 |
|
1457 int surface = |
|
1458 _blossom_set->join(subblossoms.begin(), subblossoms.end()); |
|
1459 |
|
1460 for (int i = 0; i < int(subblossoms.size()); ++i) { |
|
1461 if (!_blossom_set->trivial(subblossoms[i])) { |
|
1462 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum; |
|
1463 } |
|
1464 (*_blossom_data)[subblossoms[i]].status = MATCHED; |
|
1465 } |
|
1466 |
|
1467 (*_blossom_data)[surface].pot = -2 * _delta_sum; |
|
1468 (*_blossom_data)[surface].offset = 0; |
|
1469 (*_blossom_data)[surface].status = EVEN; |
|
1470 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred; |
|
1471 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred; |
|
1472 |
|
1473 _tree_set->insert(surface, tree); |
|
1474 _tree_set->erase(nca); |
|
1475 } |
|
1476 |
|
1477 void splitBlossom(int blossom) { |
|
1478 Arc next = (*_blossom_data)[blossom].next; |
|
1479 Arc pred = (*_blossom_data)[blossom].pred; |
|
1480 |
|
1481 int tree = _tree_set->find(blossom); |
|
1482 |
|
1483 (*_blossom_data)[blossom].status = MATCHED; |
|
1484 oddToMatched(blossom); |
|
1485 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
1486 _delta2->erase(blossom); |
|
1487 } |
|
1488 |
|
1489 std::vector<int> subblossoms; |
|
1490 _blossom_set->split(blossom, std::back_inserter(subblossoms)); |
|
1491 |
|
1492 Value offset = (*_blossom_data)[blossom].offset; |
|
1493 int b = _blossom_set->find(_graph.source(pred)); |
|
1494 int d = _blossom_set->find(_graph.source(next)); |
|
1495 |
|
1496 int ib = -1, id = -1; |
|
1497 for (int i = 0; i < int(subblossoms.size()); ++i) { |
|
1498 if (subblossoms[i] == b) ib = i; |
|
1499 if (subblossoms[i] == d) id = i; |
|
1500 |
|
1501 (*_blossom_data)[subblossoms[i]].offset = offset; |
|
1502 if (!_blossom_set->trivial(subblossoms[i])) { |
|
1503 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset; |
|
1504 } |
|
1505 if (_blossom_set->classPrio(subblossoms[i]) != |
|
1506 std::numeric_limits<Value>::max()) { |
|
1507 _delta2->push(subblossoms[i], |
|
1508 _blossom_set->classPrio(subblossoms[i]) - |
|
1509 (*_blossom_data)[subblossoms[i]].offset); |
|
1510 } |
|
1511 } |
|
1512 |
|
1513 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) { |
|
1514 for (int i = (id + 1) % subblossoms.size(); |
|
1515 i != ib; i = (i + 2) % subblossoms.size()) { |
|
1516 int sb = subblossoms[i]; |
|
1517 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
1518 (*_blossom_data)[sb].next = |
|
1519 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
1520 } |
|
1521 |
|
1522 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) { |
|
1523 int sb = subblossoms[i]; |
|
1524 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
1525 int ub = subblossoms[(i + 2) % subblossoms.size()]; |
|
1526 |
|
1527 (*_blossom_data)[sb].status = ODD; |
|
1528 matchedToOdd(sb); |
|
1529 _tree_set->insert(sb, tree); |
|
1530 (*_blossom_data)[sb].pred = pred; |
|
1531 (*_blossom_data)[sb].next = |
|
1532 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
1533 |
|
1534 pred = (*_blossom_data)[ub].next; |
|
1535 |
|
1536 (*_blossom_data)[tb].status = EVEN; |
|
1537 matchedToEven(tb, tree); |
|
1538 _tree_set->insert(tb, tree); |
|
1539 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next; |
|
1540 } |
|
1541 |
|
1542 (*_blossom_data)[subblossoms[id]].status = ODD; |
|
1543 matchedToOdd(subblossoms[id]); |
|
1544 _tree_set->insert(subblossoms[id], tree); |
|
1545 (*_blossom_data)[subblossoms[id]].next = next; |
|
1546 (*_blossom_data)[subblossoms[id]].pred = pred; |
|
1547 |
|
1548 } else { |
|
1549 |
|
1550 for (int i = (ib + 1) % subblossoms.size(); |
|
1551 i != id; i = (i + 2) % subblossoms.size()) { |
|
1552 int sb = subblossoms[i]; |
|
1553 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
1554 (*_blossom_data)[sb].next = |
|
1555 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
1556 } |
|
1557 |
|
1558 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) { |
|
1559 int sb = subblossoms[i]; |
|
1560 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
1561 int ub = subblossoms[(i + 2) % subblossoms.size()]; |
|
1562 |
|
1563 (*_blossom_data)[sb].status = ODD; |
|
1564 matchedToOdd(sb); |
|
1565 _tree_set->insert(sb, tree); |
|
1566 (*_blossom_data)[sb].next = next; |
|
1567 (*_blossom_data)[sb].pred = |
|
1568 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
1569 |
|
1570 (*_blossom_data)[tb].status = EVEN; |
|
1571 matchedToEven(tb, tree); |
|
1572 _tree_set->insert(tb, tree); |
|
1573 (*_blossom_data)[tb].pred = |
|
1574 (*_blossom_data)[tb].next = |
|
1575 _graph.oppositeArc((*_blossom_data)[ub].next); |
|
1576 next = (*_blossom_data)[ub].next; |
|
1577 } |
|
1578 |
|
1579 (*_blossom_data)[subblossoms[ib]].status = ODD; |
|
1580 matchedToOdd(subblossoms[ib]); |
|
1581 _tree_set->insert(subblossoms[ib], tree); |
|
1582 (*_blossom_data)[subblossoms[ib]].next = next; |
|
1583 (*_blossom_data)[subblossoms[ib]].pred = pred; |
|
1584 } |
|
1585 _tree_set->erase(blossom); |
|
1586 } |
|
1587 |
|
1588 void extractBlossom(int blossom, const Node& base, const Arc& matching) { |
|
1589 if (_blossom_set->trivial(blossom)) { |
|
1590 int bi = (*_node_index)[base]; |
|
1591 Value pot = (*_node_data)[bi].pot; |
|
1592 |
|
1593 (*_matching)[base] = matching; |
|
1594 _blossom_node_list.push_back(base); |
|
1595 (*_node_potential)[base] = pot; |
|
1596 } else { |
|
1597 |
|
1598 Value pot = (*_blossom_data)[blossom].pot; |
|
1599 int bn = _blossom_node_list.size(); |
|
1600 |
|
1601 std::vector<int> subblossoms; |
|
1602 _blossom_set->split(blossom, std::back_inserter(subblossoms)); |
|
1603 int b = _blossom_set->find(base); |
|
1604 int ib = -1; |
|
1605 for (int i = 0; i < int(subblossoms.size()); ++i) { |
|
1606 if (subblossoms[i] == b) { ib = i; break; } |
|
1607 } |
|
1608 |
|
1609 for (int i = 1; i < int(subblossoms.size()); i += 2) { |
|
1610 int sb = subblossoms[(ib + i) % subblossoms.size()]; |
|
1611 int tb = subblossoms[(ib + i + 1) % subblossoms.size()]; |
|
1612 |
|
1613 Arc m = (*_blossom_data)[tb].next; |
|
1614 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m)); |
|
1615 extractBlossom(tb, _graph.source(m), m); |
|
1616 } |
|
1617 extractBlossom(subblossoms[ib], base, matching); |
|
1618 |
|
1619 int en = _blossom_node_list.size(); |
|
1620 |
|
1621 _blossom_potential.push_back(BlossomVariable(bn, en, pot)); |
|
1622 } |
|
1623 } |
|
1624 |
|
1625 void extractMatching() { |
|
1626 std::vector<int> blossoms; |
|
1627 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) { |
|
1628 blossoms.push_back(c); |
|
1629 } |
|
1630 |
|
1631 for (int i = 0; i < int(blossoms.size()); ++i) { |
|
1632 if ((*_blossom_data)[blossoms[i]].status == MATCHED) { |
|
1633 |
|
1634 Value offset = (*_blossom_data)[blossoms[i]].offset; |
|
1635 (*_blossom_data)[blossoms[i]].pot += 2 * offset; |
|
1636 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]); |
|
1637 n != INVALID; ++n) { |
|
1638 (*_node_data)[(*_node_index)[n]].pot -= offset; |
|
1639 } |
|
1640 |
|
1641 Arc matching = (*_blossom_data)[blossoms[i]].next; |
|
1642 Node base = _graph.source(matching); |
|
1643 extractBlossom(blossoms[i], base, matching); |
|
1644 } else { |
|
1645 Node base = (*_blossom_data)[blossoms[i]].base; |
|
1646 extractBlossom(blossoms[i], base, INVALID); |
|
1647 } |
|
1648 } |
|
1649 } |
|
1650 |
|
1651 public: |
|
1652 |
|
1653 /// \brief Constructor |
|
1654 /// |
|
1655 /// Constructor. |
|
1656 MaxWeightedMatching(const Graph& graph, const WeightMap& weight) |
|
1657 : _graph(graph), _weight(weight), _matching(0), |
|
1658 _node_potential(0), _blossom_potential(), _blossom_node_list(), |
|
1659 _node_num(0), _blossom_num(0), |
|
1660 |
|
1661 _blossom_index(0), _blossom_set(0), _blossom_data(0), |
|
1662 _node_index(0), _node_heap_index(0), _node_data(0), |
|
1663 _tree_set_index(0), _tree_set(0), |
|
1664 |
|
1665 _delta1_index(0), _delta1(0), |
|
1666 _delta2_index(0), _delta2(0), |
|
1667 _delta3_index(0), _delta3(0), |
|
1668 _delta4_index(0), _delta4(0), |
|
1669 |
|
1670 _delta_sum() {} |
|
1671 |
|
1672 ~MaxWeightedMatching() { |
|
1673 destroyStructures(); |
|
1674 } |
|
1675 |
|
1676 /// \name Execution Control |
|
1677 /// The simplest way to execute the algorithm is to use the |
|
1678 /// \ref run() member function. |
|
1679 |
|
1680 ///@{ |
|
1681 |
|
1682 /// \brief Initialize the algorithm |
|
1683 /// |
|
1684 /// This function initializes the algorithm. |
|
1685 void init() { |
|
1686 createStructures(); |
|
1687 |
|
1688 for (ArcIt e(_graph); e != INVALID; ++e) { |
|
1689 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP; |
|
1690 } |
|
1691 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
1692 (*_delta1_index)[n] = _delta1->PRE_HEAP; |
|
1693 } |
|
1694 for (EdgeIt e(_graph); e != INVALID; ++e) { |
|
1695 (*_delta3_index)[e] = _delta3->PRE_HEAP; |
|
1696 } |
|
1697 for (int i = 0; i < _blossom_num; ++i) { |
|
1698 (*_delta2_index)[i] = _delta2->PRE_HEAP; |
|
1699 (*_delta4_index)[i] = _delta4->PRE_HEAP; |
|
1700 } |
|
1701 |
|
1702 int index = 0; |
|
1703 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
1704 Value max = 0; |
|
1705 for (OutArcIt e(_graph, n); e != INVALID; ++e) { |
|
1706 if (_graph.target(e) == n) continue; |
|
1707 if ((dualScale * _weight[e]) / 2 > max) { |
|
1708 max = (dualScale * _weight[e]) / 2; |
|
1709 } |
|
1710 } |
|
1711 (*_node_index)[n] = index; |
|
1712 (*_node_data)[index].pot = max; |
|
1713 _delta1->push(n, max); |
|
1714 int blossom = |
|
1715 _blossom_set->insert(n, std::numeric_limits<Value>::max()); |
|
1716 |
|
1717 _tree_set->insert(blossom); |
|
1718 |
|
1719 (*_blossom_data)[blossom].status = EVEN; |
|
1720 (*_blossom_data)[blossom].pred = INVALID; |
|
1721 (*_blossom_data)[blossom].next = INVALID; |
|
1722 (*_blossom_data)[blossom].pot = 0; |
|
1723 (*_blossom_data)[blossom].offset = 0; |
|
1724 ++index; |
|
1725 } |
|
1726 for (EdgeIt e(_graph); e != INVALID; ++e) { |
|
1727 int si = (*_node_index)[_graph.u(e)]; |
|
1728 int ti = (*_node_index)[_graph.v(e)]; |
|
1729 if (_graph.u(e) != _graph.v(e)) { |
|
1730 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot - |
|
1731 dualScale * _weight[e]) / 2); |
|
1732 } |
|
1733 } |
|
1734 } |
|
1735 |
|
1736 /// \brief Start the algorithm |
|
1737 /// |
|
1738 /// This function starts the algorithm. |
|
1739 /// |
|
1740 /// \pre \ref init() must be called before using this function. |
|
1741 void start() { |
|
1742 enum OpType { |
|
1743 D1, D2, D3, D4 |
|
1744 }; |
|
1745 |
|
1746 int unmatched = _node_num; |
|
1747 while (unmatched > 0) { |
|
1748 Value d1 = !_delta1->empty() ? |
|
1749 _delta1->prio() : std::numeric_limits<Value>::max(); |
|
1750 |
|
1751 Value d2 = !_delta2->empty() ? |
|
1752 _delta2->prio() : std::numeric_limits<Value>::max(); |
|
1753 |
|
1754 Value d3 = !_delta3->empty() ? |
|
1755 _delta3->prio() : std::numeric_limits<Value>::max(); |
|
1756 |
|
1757 Value d4 = !_delta4->empty() ? |
|
1758 _delta4->prio() : std::numeric_limits<Value>::max(); |
|
1759 |
|
1760 _delta_sum = d1; OpType ot = D1; |
|
1761 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; } |
|
1762 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; } |
|
1763 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; } |
|
1764 |
|
1765 |
|
1766 switch (ot) { |
|
1767 case D1: |
|
1768 { |
|
1769 Node n = _delta1->top(); |
|
1770 unmatchNode(n); |
|
1771 --unmatched; |
|
1772 } |
|
1773 break; |
|
1774 case D2: |
|
1775 { |
|
1776 int blossom = _delta2->top(); |
|
1777 Node n = _blossom_set->classTop(blossom); |
|
1778 Arc e = (*_node_data)[(*_node_index)[n]].heap.top(); |
|
1779 extendOnArc(e); |
|
1780 } |
|
1781 break; |
|
1782 case D3: |
|
1783 { |
|
1784 Edge e = _delta3->top(); |
|
1785 |
|
1786 int left_blossom = _blossom_set->find(_graph.u(e)); |
|
1787 int right_blossom = _blossom_set->find(_graph.v(e)); |
|
1788 |
|
1789 if (left_blossom == right_blossom) { |
|
1790 _delta3->pop(); |
|
1791 } else { |
|
1792 int left_tree; |
|
1793 if ((*_blossom_data)[left_blossom].status == EVEN) { |
|
1794 left_tree = _tree_set->find(left_blossom); |
|
1795 } else { |
|
1796 left_tree = -1; |
|
1797 ++unmatched; |
|
1798 } |
|
1799 int right_tree; |
|
1800 if ((*_blossom_data)[right_blossom].status == EVEN) { |
|
1801 right_tree = _tree_set->find(right_blossom); |
|
1802 } else { |
|
1803 right_tree = -1; |
|
1804 ++unmatched; |
|
1805 } |
|
1806 |
|
1807 if (left_tree == right_tree) { |
|
1808 shrinkOnEdge(e, left_tree); |
|
1809 } else { |
|
1810 augmentOnEdge(e); |
|
1811 unmatched -= 2; |
|
1812 } |
|
1813 } |
|
1814 } break; |
|
1815 case D4: |
|
1816 splitBlossom(_delta4->top()); |
|
1817 break; |
|
1818 } |
|
1819 } |
|
1820 extractMatching(); |
|
1821 } |
|
1822 |
|
1823 /// \brief Run the algorithm. |
|
1824 /// |
|
1825 /// This method runs the \c %MaxWeightedMatching algorithm. |
|
1826 /// |
|
1827 /// \note mwm.run() is just a shortcut of the following code. |
|
1828 /// \code |
|
1829 /// mwm.init(); |
|
1830 /// mwm.start(); |
|
1831 /// \endcode |
|
1832 void run() { |
|
1833 init(); |
|
1834 start(); |
|
1835 } |
|
1836 |
|
1837 /// @} |
|
1838 |
|
1839 /// \name Primal Solution |
|
1840 /// Functions to get the primal solution, i.e. the maximum weighted |
|
1841 /// matching.\n |
|
1842 /// Either \ref run() or \ref start() function should be called before |
|
1843 /// using them. |
|
1844 |
|
1845 /// @{ |
|
1846 |
|
1847 /// \brief Return the weight of the matching. |
|
1848 /// |
|
1849 /// This function returns the weight of the found matching. |
|
1850 /// |
|
1851 /// \pre Either run() or start() must be called before using this function. |
|
1852 Value matchingWeight() const { |
|
1853 Value sum = 0; |
|
1854 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
1855 if ((*_matching)[n] != INVALID) { |
|
1856 sum += _weight[(*_matching)[n]]; |
|
1857 } |
|
1858 } |
|
1859 return sum /= 2; |
|
1860 } |
|
1861 |
|
1862 /// \brief Return the size (cardinality) of the matching. |
|
1863 /// |
|
1864 /// This function returns the size (cardinality) of the found matching. |
|
1865 /// |
|
1866 /// \pre Either run() or start() must be called before using this function. |
|
1867 int matchingSize() const { |
|
1868 int num = 0; |
|
1869 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
1870 if ((*_matching)[n] != INVALID) { |
|
1871 ++num; |
|
1872 } |
|
1873 } |
|
1874 return num /= 2; |
|
1875 } |
|
1876 |
|
1877 /// \brief Return \c true if the given edge is in the matching. |
|
1878 /// |
|
1879 /// This function returns \c true if the given edge is in the found |
|
1880 /// matching. |
|
1881 /// |
|
1882 /// \pre Either run() or start() must be called before using this function. |
|
1883 bool matching(const Edge& edge) const { |
|
1884 return edge == (*_matching)[_graph.u(edge)]; |
|
1885 } |
|
1886 |
|
1887 /// \brief Return the matching arc (or edge) incident to the given node. |
|
1888 /// |
|
1889 /// This function returns the matching arc (or edge) incident to the |
|
1890 /// given node in the found matching or \c INVALID if the node is |
|
1891 /// not covered by the matching. |
|
1892 /// |
|
1893 /// \pre Either run() or start() must be called before using this function. |
|
1894 Arc matching(const Node& node) const { |
|
1895 return (*_matching)[node]; |
|
1896 } |
|
1897 |
|
1898 /// \brief Return a const reference to the matching map. |
|
1899 /// |
|
1900 /// This function returns a const reference to a node map that stores |
|
1901 /// the matching arc (or edge) incident to each node. |
|
1902 const MatchingMap& matchingMap() const { |
|
1903 return *_matching; |
|
1904 } |
|
1905 |
|
1906 /// \brief Return the mate of the given node. |
|
1907 /// |
|
1908 /// This function returns the mate of the given node in the found |
|
1909 /// matching or \c INVALID if the node is not covered by the matching. |
|
1910 /// |
|
1911 /// \pre Either run() or start() must be called before using this function. |
|
1912 Node mate(const Node& node) const { |
|
1913 return (*_matching)[node] != INVALID ? |
|
1914 _graph.target((*_matching)[node]) : INVALID; |
|
1915 } |
|
1916 |
|
1917 /// @} |
|
1918 |
|
1919 /// \name Dual Solution |
|
1920 /// Functions to get the dual solution.\n |
|
1921 /// Either \ref run() or \ref start() function should be called before |
|
1922 /// using them. |
|
1923 |
|
1924 /// @{ |
|
1925 |
|
1926 /// \brief Return the value of the dual solution. |
|
1927 /// |
|
1928 /// This function returns the value of the dual solution. |
|
1929 /// It should be equal to the primal value scaled by \ref dualScale |
|
1930 /// "dual scale". |
|
1931 /// |
|
1932 /// \pre Either run() or start() must be called before using this function. |
|
1933 Value dualValue() const { |
|
1934 Value sum = 0; |
|
1935 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
1936 sum += nodeValue(n); |
|
1937 } |
|
1938 for (int i = 0; i < blossomNum(); ++i) { |
|
1939 sum += blossomValue(i) * (blossomSize(i) / 2); |
|
1940 } |
|
1941 return sum; |
|
1942 } |
|
1943 |
|
1944 /// \brief Return the dual value (potential) of the given node. |
|
1945 /// |
|
1946 /// This function returns the dual value (potential) of the given node. |
|
1947 /// |
|
1948 /// \pre Either run() or start() must be called before using this function. |
|
1949 Value nodeValue(const Node& n) const { |
|
1950 return (*_node_potential)[n]; |
|
1951 } |
|
1952 |
|
1953 /// \brief Return the number of the blossoms in the basis. |
|
1954 /// |
|
1955 /// This function returns the number of the blossoms in the basis. |
|
1956 /// |
|
1957 /// \pre Either run() or start() must be called before using this function. |
|
1958 /// \see BlossomIt |
|
1959 int blossomNum() const { |
|
1960 return _blossom_potential.size(); |
|
1961 } |
|
1962 |
|
1963 /// \brief Return the number of the nodes in the given blossom. |
|
1964 /// |
|
1965 /// This function returns the number of the nodes in the given blossom. |
|
1966 /// |
|
1967 /// \pre Either run() or start() must be called before using this function. |
|
1968 /// \see BlossomIt |
|
1969 int blossomSize(int k) const { |
|
1970 return _blossom_potential[k].end - _blossom_potential[k].begin; |
|
1971 } |
|
1972 |
|
1973 /// \brief Return the dual value (ptential) of the given blossom. |
|
1974 /// |
|
1975 /// This function returns the dual value (ptential) of the given blossom. |
|
1976 /// |
|
1977 /// \pre Either run() or start() must be called before using this function. |
|
1978 Value blossomValue(int k) const { |
|
1979 return _blossom_potential[k].value; |
|
1980 } |
|
1981 |
|
1982 /// \brief Iterator for obtaining the nodes of a blossom. |
|
1983 /// |
|
1984 /// This class provides an iterator for obtaining the nodes of the |
|
1985 /// given blossom. It lists a subset of the nodes. |
|
1986 /// Before using this iterator, you must allocate a |
|
1987 /// MaxWeightedMatching class and execute it. |
|
1988 class BlossomIt { |
|
1989 public: |
|
1990 |
|
1991 /// \brief Constructor. |
|
1992 /// |
|
1993 /// Constructor to get the nodes of the given variable. |
|
1994 /// |
|
1995 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or |
|
1996 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be |
|
1997 /// called before initializing this iterator. |
|
1998 BlossomIt(const MaxWeightedMatching& algorithm, int variable) |
|
1999 : _algorithm(&algorithm) |
|
2000 { |
|
2001 _index = _algorithm->_blossom_potential[variable].begin; |
|
2002 _last = _algorithm->_blossom_potential[variable].end; |
|
2003 } |
|
2004 |
|
2005 /// \brief Conversion to \c Node. |
|
2006 /// |
|
2007 /// Conversion to \c Node. |
|
2008 operator Node() const { |
|
2009 return _algorithm->_blossom_node_list[_index]; |
|
2010 } |
|
2011 |
|
2012 /// \brief Increment operator. |
|
2013 /// |
|
2014 /// Increment operator. |
|
2015 BlossomIt& operator++() { |
|
2016 ++_index; |
|
2017 return *this; |
|
2018 } |
|
2019 |
|
2020 /// \brief Validity checking |
|
2021 /// |
|
2022 /// Checks whether the iterator is invalid. |
|
2023 bool operator==(Invalid) const { return _index == _last; } |
|
2024 |
|
2025 /// \brief Validity checking |
|
2026 /// |
|
2027 /// Checks whether the iterator is valid. |
|
2028 bool operator!=(Invalid) const { return _index != _last; } |
|
2029 |
|
2030 private: |
|
2031 const MaxWeightedMatching* _algorithm; |
|
2032 int _last; |
|
2033 int _index; |
|
2034 }; |
|
2035 |
|
2036 /// @} |
|
2037 |
|
2038 }; |
|
2039 |
|
2040 /// \ingroup matching |
|
2041 /// |
|
2042 /// \brief Weighted perfect matching in general graphs |
|
2043 /// |
|
2044 /// This class provides an efficient implementation of Edmond's |
|
2045 /// maximum weighted perfect matching algorithm. The implementation |
|
2046 /// is based on extensive use of priority queues and provides |
|
2047 /// \f$O(nm\log n)\f$ time complexity. |
|
2048 /// |
|
2049 /// The maximum weighted perfect matching problem is to find a subset of |
|
2050 /// the edges in an undirected graph with maximum overall weight for which |
|
2051 /// each node has exactly one incident edge. |
|
2052 /// It can be formulated with the following linear program. |
|
2053 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f] |
|
2054 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2} |
|
2055 \quad \forall B\in\mathcal{O}\f] */ |
|
2056 /// \f[x_e \ge 0\quad \forall e\in E\f] |
|
2057 /// \f[\max \sum_{e\in E}x_ew_e\f] |
|
2058 /// where \f$\delta(X)\f$ is the set of edges incident to a node in |
|
2059 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in |
|
2060 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality |
|
2061 /// subsets of the nodes. |
|
2062 /// |
|
2063 /// The algorithm calculates an optimal matching and a proof of the |
|
2064 /// optimality. The solution of the dual problem can be used to check |
|
2065 /// the result of the algorithm. The dual linear problem is the |
|
2066 /// following. |
|
2067 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge |
|
2068 w_{uv} \quad \forall uv\in E\f] */ |
|
2069 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f] |
|
2070 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}} |
|
2071 \frac{\vert B \vert - 1}{2}z_B\f] */ |
|
2072 /// |
|
2073 /// The algorithm can be executed with the run() function. |
|
2074 /// After it the matching (the primal solution) and the dual solution |
|
2075 /// can be obtained using the query functions and the |
|
2076 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, |
|
2077 /// which is able to iterate on the nodes of a blossom. |
|
2078 /// If the value type is integer, then the dual solution is multiplied |
|
2079 /// by \ref MaxWeightedMatching::dualScale "4". |
|
2080 /// |
|
2081 /// \tparam GR The undirected graph type the algorithm runs on. |
|
2082 /// \tparam WM The type edge weight map. The default type is |
|
2083 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>". |
|
2084 #ifdef DOXYGEN |
|
2085 template <typename GR, typename WM> |
|
2086 #else |
|
2087 template <typename GR, |
|
2088 typename WM = typename GR::template EdgeMap<int> > |
|
2089 #endif |
|
2090 class MaxWeightedPerfectMatching { |
|
2091 public: |
|
2092 |
|
2093 /// The graph type of the algorithm |
|
2094 typedef GR Graph; |
|
2095 /// The type of the edge weight map |
|
2096 typedef WM WeightMap; |
|
2097 /// The value type of the edge weights |
|
2098 typedef typename WeightMap::Value Value; |
|
2099 |
|
2100 /// \brief Scaling factor for dual solution |
|
2101 /// |
|
2102 /// Scaling factor for dual solution, it is equal to 4 or 1 |
|
2103 /// according to the value type. |
|
2104 static const int dualScale = |
|
2105 std::numeric_limits<Value>::is_integer ? 4 : 1; |
|
2106 |
|
2107 /// The type of the matching map |
|
2108 typedef typename Graph::template NodeMap<typename Graph::Arc> |
|
2109 MatchingMap; |
|
2110 |
|
2111 private: |
|
2112 |
|
2113 TEMPLATE_GRAPH_TYPEDEFS(Graph); |
|
2114 |
|
2115 typedef typename Graph::template NodeMap<Value> NodePotential; |
|
2116 typedef std::vector<Node> BlossomNodeList; |
|
2117 |
|
2118 struct BlossomVariable { |
|
2119 int begin, end; |
|
2120 Value value; |
|
2121 |
|
2122 BlossomVariable(int _begin, int _end, Value _value) |
|
2123 : begin(_begin), end(_end), value(_value) {} |
|
2124 |
|
2125 }; |
|
2126 |
|
2127 typedef std::vector<BlossomVariable> BlossomPotential; |
|
2128 |
|
2129 const Graph& _graph; |
|
2130 const WeightMap& _weight; |
|
2131 |
|
2132 MatchingMap* _matching; |
|
2133 |
|
2134 NodePotential* _node_potential; |
|
2135 |
|
2136 BlossomPotential _blossom_potential; |
|
2137 BlossomNodeList _blossom_node_list; |
|
2138 |
|
2139 int _node_num; |
|
2140 int _blossom_num; |
|
2141 |
|
2142 typedef RangeMap<int> IntIntMap; |
|
2143 |
|
2144 enum Status { |
|
2145 EVEN = -1, MATCHED = 0, ODD = 1 |
|
2146 }; |
|
2147 |
|
2148 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet; |
|
2149 struct BlossomData { |
|
2150 int tree; |
|
2151 Status status; |
|
2152 Arc pred, next; |
|
2153 Value pot, offset; |
|
2154 }; |
|
2155 |
|
2156 IntNodeMap *_blossom_index; |
|
2157 BlossomSet *_blossom_set; |
|
2158 RangeMap<BlossomData>* _blossom_data; |
|
2159 |
|
2160 IntNodeMap *_node_index; |
|
2161 IntArcMap *_node_heap_index; |
|
2162 |
|
2163 struct NodeData { |
|
2164 |
|
2165 NodeData(IntArcMap& node_heap_index) |
|
2166 : heap(node_heap_index) {} |
|
2167 |
|
2168 int blossom; |
|
2169 Value pot; |
|
2170 BinHeap<Value, IntArcMap> heap; |
|
2171 std::map<int, Arc> heap_index; |
|
2172 |
|
2173 int tree; |
|
2174 }; |
|
2175 |
|
2176 RangeMap<NodeData>* _node_data; |
|
2177 |
|
2178 typedef ExtendFindEnum<IntIntMap> TreeSet; |
|
2179 |
|
2180 IntIntMap *_tree_set_index; |
|
2181 TreeSet *_tree_set; |
|
2182 |
|
2183 IntIntMap *_delta2_index; |
|
2184 BinHeap<Value, IntIntMap> *_delta2; |
|
2185 |
|
2186 IntEdgeMap *_delta3_index; |
|
2187 BinHeap<Value, IntEdgeMap> *_delta3; |
|
2188 |
|
2189 IntIntMap *_delta4_index; |
|
2190 BinHeap<Value, IntIntMap> *_delta4; |
|
2191 |
|
2192 Value _delta_sum; |
|
2193 |
|
2194 void createStructures() { |
|
2195 _node_num = countNodes(_graph); |
|
2196 _blossom_num = _node_num * 3 / 2; |
|
2197 |
|
2198 if (!_matching) { |
|
2199 _matching = new MatchingMap(_graph); |
|
2200 } |
|
2201 if (!_node_potential) { |
|
2202 _node_potential = new NodePotential(_graph); |
|
2203 } |
|
2204 if (!_blossom_set) { |
|
2205 _blossom_index = new IntNodeMap(_graph); |
|
2206 _blossom_set = new BlossomSet(*_blossom_index); |
|
2207 _blossom_data = new RangeMap<BlossomData>(_blossom_num); |
|
2208 } |
|
2209 |
|
2210 if (!_node_index) { |
|
2211 _node_index = new IntNodeMap(_graph); |
|
2212 _node_heap_index = new IntArcMap(_graph); |
|
2213 _node_data = new RangeMap<NodeData>(_node_num, |
|
2214 NodeData(*_node_heap_index)); |
|
2215 } |
|
2216 |
|
2217 if (!_tree_set) { |
|
2218 _tree_set_index = new IntIntMap(_blossom_num); |
|
2219 _tree_set = new TreeSet(*_tree_set_index); |
|
2220 } |
|
2221 if (!_delta2) { |
|
2222 _delta2_index = new IntIntMap(_blossom_num); |
|
2223 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index); |
|
2224 } |
|
2225 if (!_delta3) { |
|
2226 _delta3_index = new IntEdgeMap(_graph); |
|
2227 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index); |
|
2228 } |
|
2229 if (!_delta4) { |
|
2230 _delta4_index = new IntIntMap(_blossom_num); |
|
2231 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index); |
|
2232 } |
|
2233 } |
|
2234 |
|
2235 void destroyStructures() { |
|
2236 _node_num = countNodes(_graph); |
|
2237 _blossom_num = _node_num * 3 / 2; |
|
2238 |
|
2239 if (_matching) { |
|
2240 delete _matching; |
|
2241 } |
|
2242 if (_node_potential) { |
|
2243 delete _node_potential; |
|
2244 } |
|
2245 if (_blossom_set) { |
|
2246 delete _blossom_index; |
|
2247 delete _blossom_set; |
|
2248 delete _blossom_data; |
|
2249 } |
|
2250 |
|
2251 if (_node_index) { |
|
2252 delete _node_index; |
|
2253 delete _node_heap_index; |
|
2254 delete _node_data; |
|
2255 } |
|
2256 |
|
2257 if (_tree_set) { |
|
2258 delete _tree_set_index; |
|
2259 delete _tree_set; |
|
2260 } |
|
2261 if (_delta2) { |
|
2262 delete _delta2_index; |
|
2263 delete _delta2; |
|
2264 } |
|
2265 if (_delta3) { |
|
2266 delete _delta3_index; |
|
2267 delete _delta3; |
|
2268 } |
|
2269 if (_delta4) { |
|
2270 delete _delta4_index; |
|
2271 delete _delta4; |
|
2272 } |
|
2273 } |
|
2274 |
|
2275 void matchedToEven(int blossom, int tree) { |
|
2276 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
2277 _delta2->erase(blossom); |
|
2278 } |
|
2279 |
|
2280 if (!_blossom_set->trivial(blossom)) { |
|
2281 (*_blossom_data)[blossom].pot -= |
|
2282 2 * (_delta_sum - (*_blossom_data)[blossom].offset); |
|
2283 } |
|
2284 |
|
2285 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
2286 n != INVALID; ++n) { |
|
2287 |
|
2288 _blossom_set->increase(n, std::numeric_limits<Value>::max()); |
|
2289 int ni = (*_node_index)[n]; |
|
2290 |
|
2291 (*_node_data)[ni].heap.clear(); |
|
2292 (*_node_data)[ni].heap_index.clear(); |
|
2293 |
|
2294 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset; |
|
2295 |
|
2296 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
2297 Node v = _graph.source(e); |
|
2298 int vb = _blossom_set->find(v); |
|
2299 int vi = (*_node_index)[v]; |
|
2300 |
|
2301 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
2302 dualScale * _weight[e]; |
|
2303 |
|
2304 if ((*_blossom_data)[vb].status == EVEN) { |
|
2305 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) { |
|
2306 _delta3->push(e, rw / 2); |
|
2307 } |
|
2308 } else { |
|
2309 typename std::map<int, Arc>::iterator it = |
|
2310 (*_node_data)[vi].heap_index.find(tree); |
|
2311 |
|
2312 if (it != (*_node_data)[vi].heap_index.end()) { |
|
2313 if ((*_node_data)[vi].heap[it->second] > rw) { |
|
2314 (*_node_data)[vi].heap.replace(it->second, e); |
|
2315 (*_node_data)[vi].heap.decrease(e, rw); |
|
2316 it->second = e; |
|
2317 } |
|
2318 } else { |
|
2319 (*_node_data)[vi].heap.push(e, rw); |
|
2320 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e)); |
|
2321 } |
|
2322 |
|
2323 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) { |
|
2324 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio()); |
|
2325 |
|
2326 if ((*_blossom_data)[vb].status == MATCHED) { |
|
2327 if (_delta2->state(vb) != _delta2->IN_HEAP) { |
|
2328 _delta2->push(vb, _blossom_set->classPrio(vb) - |
|
2329 (*_blossom_data)[vb].offset); |
|
2330 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) - |
|
2331 (*_blossom_data)[vb].offset){ |
|
2332 _delta2->decrease(vb, _blossom_set->classPrio(vb) - |
|
2333 (*_blossom_data)[vb].offset); |
|
2334 } |
|
2335 } |
|
2336 } |
|
2337 } |
|
2338 } |
|
2339 } |
|
2340 (*_blossom_data)[blossom].offset = 0; |
|
2341 } |
|
2342 |
|
2343 void matchedToOdd(int blossom) { |
|
2344 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
2345 _delta2->erase(blossom); |
|
2346 } |
|
2347 (*_blossom_data)[blossom].offset += _delta_sum; |
|
2348 if (!_blossom_set->trivial(blossom)) { |
|
2349 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 + |
|
2350 (*_blossom_data)[blossom].offset); |
|
2351 } |
|
2352 } |
|
2353 |
|
2354 void evenToMatched(int blossom, int tree) { |
|
2355 if (!_blossom_set->trivial(blossom)) { |
|
2356 (*_blossom_data)[blossom].pot += 2 * _delta_sum; |
|
2357 } |
|
2358 |
|
2359 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
2360 n != INVALID; ++n) { |
|
2361 int ni = (*_node_index)[n]; |
|
2362 (*_node_data)[ni].pot -= _delta_sum; |
|
2363 |
|
2364 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
2365 Node v = _graph.source(e); |
|
2366 int vb = _blossom_set->find(v); |
|
2367 int vi = (*_node_index)[v]; |
|
2368 |
|
2369 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
2370 dualScale * _weight[e]; |
|
2371 |
|
2372 if (vb == blossom) { |
|
2373 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
2374 _delta3->erase(e); |
|
2375 } |
|
2376 } else if ((*_blossom_data)[vb].status == EVEN) { |
|
2377 |
|
2378 if (_delta3->state(e) == _delta3->IN_HEAP) { |
|
2379 _delta3->erase(e); |
|
2380 } |
|
2381 |
|
2382 int vt = _tree_set->find(vb); |
|
2383 |
|
2384 if (vt != tree) { |
|
2385 |
|
2386 Arc r = _graph.oppositeArc(e); |
|
2387 |
|
2388 typename std::map<int, Arc>::iterator it = |
|
2389 (*_node_data)[ni].heap_index.find(vt); |
|
2390 |
|
2391 if (it != (*_node_data)[ni].heap_index.end()) { |
|
2392 if ((*_node_data)[ni].heap[it->second] > rw) { |
|
2393 (*_node_data)[ni].heap.replace(it->second, r); |
|
2394 (*_node_data)[ni].heap.decrease(r, rw); |
|
2395 it->second = r; |
|
2396 } |
|
2397 } else { |
|
2398 (*_node_data)[ni].heap.push(r, rw); |
|
2399 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r)); |
|
2400 } |
|
2401 |
|
2402 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) { |
|
2403 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio()); |
|
2404 |
|
2405 if (_delta2->state(blossom) != _delta2->IN_HEAP) { |
|
2406 _delta2->push(blossom, _blossom_set->classPrio(blossom) - |
|
2407 (*_blossom_data)[blossom].offset); |
|
2408 } else if ((*_delta2)[blossom] > |
|
2409 _blossom_set->classPrio(blossom) - |
|
2410 (*_blossom_data)[blossom].offset){ |
|
2411 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) - |
|
2412 (*_blossom_data)[blossom].offset); |
|
2413 } |
|
2414 } |
|
2415 } |
|
2416 } else { |
|
2417 |
|
2418 typename std::map<int, Arc>::iterator it = |
|
2419 (*_node_data)[vi].heap_index.find(tree); |
|
2420 |
|
2421 if (it != (*_node_data)[vi].heap_index.end()) { |
|
2422 (*_node_data)[vi].heap.erase(it->second); |
|
2423 (*_node_data)[vi].heap_index.erase(it); |
|
2424 if ((*_node_data)[vi].heap.empty()) { |
|
2425 _blossom_set->increase(v, std::numeric_limits<Value>::max()); |
|
2426 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) { |
|
2427 _blossom_set->increase(v, (*_node_data)[vi].heap.prio()); |
|
2428 } |
|
2429 |
|
2430 if ((*_blossom_data)[vb].status == MATCHED) { |
|
2431 if (_blossom_set->classPrio(vb) == |
|
2432 std::numeric_limits<Value>::max()) { |
|
2433 _delta2->erase(vb); |
|
2434 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) - |
|
2435 (*_blossom_data)[vb].offset) { |
|
2436 _delta2->increase(vb, _blossom_set->classPrio(vb) - |
|
2437 (*_blossom_data)[vb].offset); |
|
2438 } |
|
2439 } |
|
2440 } |
|
2441 } |
|
2442 } |
|
2443 } |
|
2444 } |
|
2445 |
|
2446 void oddToMatched(int blossom) { |
|
2447 (*_blossom_data)[blossom].offset -= _delta_sum; |
|
2448 |
|
2449 if (_blossom_set->classPrio(blossom) != |
|
2450 std::numeric_limits<Value>::max()) { |
|
2451 _delta2->push(blossom, _blossom_set->classPrio(blossom) - |
|
2452 (*_blossom_data)[blossom].offset); |
|
2453 } |
|
2454 |
|
2455 if (!_blossom_set->trivial(blossom)) { |
|
2456 _delta4->erase(blossom); |
|
2457 } |
|
2458 } |
|
2459 |
|
2460 void oddToEven(int blossom, int tree) { |
|
2461 if (!_blossom_set->trivial(blossom)) { |
|
2462 _delta4->erase(blossom); |
|
2463 (*_blossom_data)[blossom].pot -= |
|
2464 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset); |
|
2465 } |
|
2466 |
|
2467 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); |
|
2468 n != INVALID; ++n) { |
|
2469 int ni = (*_node_index)[n]; |
|
2470 |
|
2471 _blossom_set->increase(n, std::numeric_limits<Value>::max()); |
|
2472 |
|
2473 (*_node_data)[ni].heap.clear(); |
|
2474 (*_node_data)[ni].heap_index.clear(); |
|
2475 (*_node_data)[ni].pot += |
|
2476 2 * _delta_sum - (*_blossom_data)[blossom].offset; |
|
2477 |
|
2478 for (InArcIt e(_graph, n); e != INVALID; ++e) { |
|
2479 Node v = _graph.source(e); |
|
2480 int vb = _blossom_set->find(v); |
|
2481 int vi = (*_node_index)[v]; |
|
2482 |
|
2483 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - |
|
2484 dualScale * _weight[e]; |
|
2485 |
|
2486 if ((*_blossom_data)[vb].status == EVEN) { |
|
2487 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) { |
|
2488 _delta3->push(e, rw / 2); |
|
2489 } |
|
2490 } else { |
|
2491 |
|
2492 typename std::map<int, Arc>::iterator it = |
|
2493 (*_node_data)[vi].heap_index.find(tree); |
|
2494 |
|
2495 if (it != (*_node_data)[vi].heap_index.end()) { |
|
2496 if ((*_node_data)[vi].heap[it->second] > rw) { |
|
2497 (*_node_data)[vi].heap.replace(it->second, e); |
|
2498 (*_node_data)[vi].heap.decrease(e, rw); |
|
2499 it->second = e; |
|
2500 } |
|
2501 } else { |
|
2502 (*_node_data)[vi].heap.push(e, rw); |
|
2503 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e)); |
|
2504 } |
|
2505 |
|
2506 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) { |
|
2507 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio()); |
|
2508 |
|
2509 if ((*_blossom_data)[vb].status == MATCHED) { |
|
2510 if (_delta2->state(vb) != _delta2->IN_HEAP) { |
|
2511 _delta2->push(vb, _blossom_set->classPrio(vb) - |
|
2512 (*_blossom_data)[vb].offset); |
|
2513 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) - |
|
2514 (*_blossom_data)[vb].offset) { |
|
2515 _delta2->decrease(vb, _blossom_set->classPrio(vb) - |
|
2516 (*_blossom_data)[vb].offset); |
|
2517 } |
|
2518 } |
|
2519 } |
|
2520 } |
|
2521 } |
|
2522 } |
|
2523 (*_blossom_data)[blossom].offset = 0; |
|
2524 } |
|
2525 |
|
2526 void alternatePath(int even, int tree) { |
|
2527 int odd; |
|
2528 |
|
2529 evenToMatched(even, tree); |
|
2530 (*_blossom_data)[even].status = MATCHED; |
|
2531 |
|
2532 while ((*_blossom_data)[even].pred != INVALID) { |
|
2533 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred)); |
|
2534 (*_blossom_data)[odd].status = MATCHED; |
|
2535 oddToMatched(odd); |
|
2536 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred; |
|
2537 |
|
2538 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred)); |
|
2539 (*_blossom_data)[even].status = MATCHED; |
|
2540 evenToMatched(even, tree); |
|
2541 (*_blossom_data)[even].next = |
|
2542 _graph.oppositeArc((*_blossom_data)[odd].pred); |
|
2543 } |
|
2544 |
|
2545 } |
|
2546 |
|
2547 void destroyTree(int tree) { |
|
2548 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) { |
|
2549 if ((*_blossom_data)[b].status == EVEN) { |
|
2550 (*_blossom_data)[b].status = MATCHED; |
|
2551 evenToMatched(b, tree); |
|
2552 } else if ((*_blossom_data)[b].status == ODD) { |
|
2553 (*_blossom_data)[b].status = MATCHED; |
|
2554 oddToMatched(b); |
|
2555 } |
|
2556 } |
|
2557 _tree_set->eraseClass(tree); |
|
2558 } |
|
2559 |
|
2560 void augmentOnEdge(const Edge& edge) { |
|
2561 |
|
2562 int left = _blossom_set->find(_graph.u(edge)); |
|
2563 int right = _blossom_set->find(_graph.v(edge)); |
|
2564 |
|
2565 int left_tree = _tree_set->find(left); |
|
2566 alternatePath(left, left_tree); |
|
2567 destroyTree(left_tree); |
|
2568 |
|
2569 int right_tree = _tree_set->find(right); |
|
2570 alternatePath(right, right_tree); |
|
2571 destroyTree(right_tree); |
|
2572 |
|
2573 (*_blossom_data)[left].next = _graph.direct(edge, true); |
|
2574 (*_blossom_data)[right].next = _graph.direct(edge, false); |
|
2575 } |
|
2576 |
|
2577 void extendOnArc(const Arc& arc) { |
|
2578 int base = _blossom_set->find(_graph.target(arc)); |
|
2579 int tree = _tree_set->find(base); |
|
2580 |
|
2581 int odd = _blossom_set->find(_graph.source(arc)); |
|
2582 _tree_set->insert(odd, tree); |
|
2583 (*_blossom_data)[odd].status = ODD; |
|
2584 matchedToOdd(odd); |
|
2585 (*_blossom_data)[odd].pred = arc; |
|
2586 |
|
2587 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next)); |
|
2588 (*_blossom_data)[even].pred = (*_blossom_data)[even].next; |
|
2589 _tree_set->insert(even, tree); |
|
2590 (*_blossom_data)[even].status = EVEN; |
|
2591 matchedToEven(even, tree); |
|
2592 } |
|
2593 |
|
2594 void shrinkOnEdge(const Edge& edge, int tree) { |
|
2595 int nca = -1; |
|
2596 std::vector<int> left_path, right_path; |
|
2597 |
|
2598 { |
|
2599 std::set<int> left_set, right_set; |
|
2600 int left = _blossom_set->find(_graph.u(edge)); |
|
2601 left_path.push_back(left); |
|
2602 left_set.insert(left); |
|
2603 |
|
2604 int right = _blossom_set->find(_graph.v(edge)); |
|
2605 right_path.push_back(right); |
|
2606 right_set.insert(right); |
|
2607 |
|
2608 while (true) { |
|
2609 |
|
2610 if ((*_blossom_data)[left].pred == INVALID) break; |
|
2611 |
|
2612 left = |
|
2613 _blossom_set->find(_graph.target((*_blossom_data)[left].pred)); |
|
2614 left_path.push_back(left); |
|
2615 left = |
|
2616 _blossom_set->find(_graph.target((*_blossom_data)[left].pred)); |
|
2617 left_path.push_back(left); |
|
2618 |
|
2619 left_set.insert(left); |
|
2620 |
|
2621 if (right_set.find(left) != right_set.end()) { |
|
2622 nca = left; |
|
2623 break; |
|
2624 } |
|
2625 |
|
2626 if ((*_blossom_data)[right].pred == INVALID) break; |
|
2627 |
|
2628 right = |
|
2629 _blossom_set->find(_graph.target((*_blossom_data)[right].pred)); |
|
2630 right_path.push_back(right); |
|
2631 right = |
|
2632 _blossom_set->find(_graph.target((*_blossom_data)[right].pred)); |
|
2633 right_path.push_back(right); |
|
2634 |
|
2635 right_set.insert(right); |
|
2636 |
|
2637 if (left_set.find(right) != left_set.end()) { |
|
2638 nca = right; |
|
2639 break; |
|
2640 } |
|
2641 |
|
2642 } |
|
2643 |
|
2644 if (nca == -1) { |
|
2645 if ((*_blossom_data)[left].pred == INVALID) { |
|
2646 nca = right; |
|
2647 while (left_set.find(nca) == left_set.end()) { |
|
2648 nca = |
|
2649 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
2650 right_path.push_back(nca); |
|
2651 nca = |
|
2652 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
2653 right_path.push_back(nca); |
|
2654 } |
|
2655 } else { |
|
2656 nca = left; |
|
2657 while (right_set.find(nca) == right_set.end()) { |
|
2658 nca = |
|
2659 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
2660 left_path.push_back(nca); |
|
2661 nca = |
|
2662 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred)); |
|
2663 left_path.push_back(nca); |
|
2664 } |
|
2665 } |
|
2666 } |
|
2667 } |
|
2668 |
|
2669 std::vector<int> subblossoms; |
|
2670 Arc prev; |
|
2671 |
|
2672 prev = _graph.direct(edge, true); |
|
2673 for (int i = 0; left_path[i] != nca; i += 2) { |
|
2674 subblossoms.push_back(left_path[i]); |
|
2675 (*_blossom_data)[left_path[i]].next = prev; |
|
2676 _tree_set->erase(left_path[i]); |
|
2677 |
|
2678 subblossoms.push_back(left_path[i + 1]); |
|
2679 (*_blossom_data)[left_path[i + 1]].status = EVEN; |
|
2680 oddToEven(left_path[i + 1], tree); |
|
2681 _tree_set->erase(left_path[i + 1]); |
|
2682 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred); |
|
2683 } |
|
2684 |
|
2685 int k = 0; |
|
2686 while (right_path[k] != nca) ++k; |
|
2687 |
|
2688 subblossoms.push_back(nca); |
|
2689 (*_blossom_data)[nca].next = prev; |
|
2690 |
|
2691 for (int i = k - 2; i >= 0; i -= 2) { |
|
2692 subblossoms.push_back(right_path[i + 1]); |
|
2693 (*_blossom_data)[right_path[i + 1]].status = EVEN; |
|
2694 oddToEven(right_path[i + 1], tree); |
|
2695 _tree_set->erase(right_path[i + 1]); |
|
2696 |
|
2697 (*_blossom_data)[right_path[i + 1]].next = |
|
2698 (*_blossom_data)[right_path[i + 1]].pred; |
|
2699 |
|
2700 subblossoms.push_back(right_path[i]); |
|
2701 _tree_set->erase(right_path[i]); |
|
2702 } |
|
2703 |
|
2704 int surface = |
|
2705 _blossom_set->join(subblossoms.begin(), subblossoms.end()); |
|
2706 |
|
2707 for (int i = 0; i < int(subblossoms.size()); ++i) { |
|
2708 if (!_blossom_set->trivial(subblossoms[i])) { |
|
2709 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum; |
|
2710 } |
|
2711 (*_blossom_data)[subblossoms[i]].status = MATCHED; |
|
2712 } |
|
2713 |
|
2714 (*_blossom_data)[surface].pot = -2 * _delta_sum; |
|
2715 (*_blossom_data)[surface].offset = 0; |
|
2716 (*_blossom_data)[surface].status = EVEN; |
|
2717 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred; |
|
2718 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred; |
|
2719 |
|
2720 _tree_set->insert(surface, tree); |
|
2721 _tree_set->erase(nca); |
|
2722 } |
|
2723 |
|
2724 void splitBlossom(int blossom) { |
|
2725 Arc next = (*_blossom_data)[blossom].next; |
|
2726 Arc pred = (*_blossom_data)[blossom].pred; |
|
2727 |
|
2728 int tree = _tree_set->find(blossom); |
|
2729 |
|
2730 (*_blossom_data)[blossom].status = MATCHED; |
|
2731 oddToMatched(blossom); |
|
2732 if (_delta2->state(blossom) == _delta2->IN_HEAP) { |
|
2733 _delta2->erase(blossom); |
|
2734 } |
|
2735 |
|
2736 std::vector<int> subblossoms; |
|
2737 _blossom_set->split(blossom, std::back_inserter(subblossoms)); |
|
2738 |
|
2739 Value offset = (*_blossom_data)[blossom].offset; |
|
2740 int b = _blossom_set->find(_graph.source(pred)); |
|
2741 int d = _blossom_set->find(_graph.source(next)); |
|
2742 |
|
2743 int ib = -1, id = -1; |
|
2744 for (int i = 0; i < int(subblossoms.size()); ++i) { |
|
2745 if (subblossoms[i] == b) ib = i; |
|
2746 if (subblossoms[i] == d) id = i; |
|
2747 |
|
2748 (*_blossom_data)[subblossoms[i]].offset = offset; |
|
2749 if (!_blossom_set->trivial(subblossoms[i])) { |
|
2750 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset; |
|
2751 } |
|
2752 if (_blossom_set->classPrio(subblossoms[i]) != |
|
2753 std::numeric_limits<Value>::max()) { |
|
2754 _delta2->push(subblossoms[i], |
|
2755 _blossom_set->classPrio(subblossoms[i]) - |
|
2756 (*_blossom_data)[subblossoms[i]].offset); |
|
2757 } |
|
2758 } |
|
2759 |
|
2760 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) { |
|
2761 for (int i = (id + 1) % subblossoms.size(); |
|
2762 i != ib; i = (i + 2) % subblossoms.size()) { |
|
2763 int sb = subblossoms[i]; |
|
2764 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
2765 (*_blossom_data)[sb].next = |
|
2766 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
2767 } |
|
2768 |
|
2769 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) { |
|
2770 int sb = subblossoms[i]; |
|
2771 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
2772 int ub = subblossoms[(i + 2) % subblossoms.size()]; |
|
2773 |
|
2774 (*_blossom_data)[sb].status = ODD; |
|
2775 matchedToOdd(sb); |
|
2776 _tree_set->insert(sb, tree); |
|
2777 (*_blossom_data)[sb].pred = pred; |
|
2778 (*_blossom_data)[sb].next = |
|
2779 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
2780 |
|
2781 pred = (*_blossom_data)[ub].next; |
|
2782 |
|
2783 (*_blossom_data)[tb].status = EVEN; |
|
2784 matchedToEven(tb, tree); |
|
2785 _tree_set->insert(tb, tree); |
|
2786 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next; |
|
2787 } |
|
2788 |
|
2789 (*_blossom_data)[subblossoms[id]].status = ODD; |
|
2790 matchedToOdd(subblossoms[id]); |
|
2791 _tree_set->insert(subblossoms[id], tree); |
|
2792 (*_blossom_data)[subblossoms[id]].next = next; |
|
2793 (*_blossom_data)[subblossoms[id]].pred = pred; |
|
2794 |
|
2795 } else { |
|
2796 |
|
2797 for (int i = (ib + 1) % subblossoms.size(); |
|
2798 i != id; i = (i + 2) % subblossoms.size()) { |
|
2799 int sb = subblossoms[i]; |
|
2800 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
2801 (*_blossom_data)[sb].next = |
|
2802 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
2803 } |
|
2804 |
|
2805 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) { |
|
2806 int sb = subblossoms[i]; |
|
2807 int tb = subblossoms[(i + 1) % subblossoms.size()]; |
|
2808 int ub = subblossoms[(i + 2) % subblossoms.size()]; |
|
2809 |
|
2810 (*_blossom_data)[sb].status = ODD; |
|
2811 matchedToOdd(sb); |
|
2812 _tree_set->insert(sb, tree); |
|
2813 (*_blossom_data)[sb].next = next; |
|
2814 (*_blossom_data)[sb].pred = |
|
2815 _graph.oppositeArc((*_blossom_data)[tb].next); |
|
2816 |
|
2817 (*_blossom_data)[tb].status = EVEN; |
|
2818 matchedToEven(tb, tree); |
|
2819 _tree_set->insert(tb, tree); |
|
2820 (*_blossom_data)[tb].pred = |
|
2821 (*_blossom_data)[tb].next = |
|
2822 _graph.oppositeArc((*_blossom_data)[ub].next); |
|
2823 next = (*_blossom_data)[ub].next; |
|
2824 } |
|
2825 |
|
2826 (*_blossom_data)[subblossoms[ib]].status = ODD; |
|
2827 matchedToOdd(subblossoms[ib]); |
|
2828 _tree_set->insert(subblossoms[ib], tree); |
|
2829 (*_blossom_data)[subblossoms[ib]].next = next; |
|
2830 (*_blossom_data)[subblossoms[ib]].pred = pred; |
|
2831 } |
|
2832 _tree_set->erase(blossom); |
|
2833 } |
|
2834 |
|
2835 void extractBlossom(int blossom, const Node& base, const Arc& matching) { |
|
2836 if (_blossom_set->trivial(blossom)) { |
|
2837 int bi = (*_node_index)[base]; |
|
2838 Value pot = (*_node_data)[bi].pot; |
|
2839 |
|
2840 (*_matching)[base] = matching; |
|
2841 _blossom_node_list.push_back(base); |
|
2842 (*_node_potential)[base] = pot; |
|
2843 } else { |
|
2844 |
|
2845 Value pot = (*_blossom_data)[blossom].pot; |
|
2846 int bn = _blossom_node_list.size(); |
|
2847 |
|
2848 std::vector<int> subblossoms; |
|
2849 _blossom_set->split(blossom, std::back_inserter(subblossoms)); |
|
2850 int b = _blossom_set->find(base); |
|
2851 int ib = -1; |
|
2852 for (int i = 0; i < int(subblossoms.size()); ++i) { |
|
2853 if (subblossoms[i] == b) { ib = i; break; } |
|
2854 } |
|
2855 |
|
2856 for (int i = 1; i < int(subblossoms.size()); i += 2) { |
|
2857 int sb = subblossoms[(ib + i) % subblossoms.size()]; |
|
2858 int tb = subblossoms[(ib + i + 1) % subblossoms.size()]; |
|
2859 |
|
2860 Arc m = (*_blossom_data)[tb].next; |
|
2861 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m)); |
|
2862 extractBlossom(tb, _graph.source(m), m); |
|
2863 } |
|
2864 extractBlossom(subblossoms[ib], base, matching); |
|
2865 |
|
2866 int en = _blossom_node_list.size(); |
|
2867 |
|
2868 _blossom_potential.push_back(BlossomVariable(bn, en, pot)); |
|
2869 } |
|
2870 } |
|
2871 |
|
2872 void extractMatching() { |
|
2873 std::vector<int> blossoms; |
|
2874 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) { |
|
2875 blossoms.push_back(c); |
|
2876 } |
|
2877 |
|
2878 for (int i = 0; i < int(blossoms.size()); ++i) { |
|
2879 |
|
2880 Value offset = (*_blossom_data)[blossoms[i]].offset; |
|
2881 (*_blossom_data)[blossoms[i]].pot += 2 * offset; |
|
2882 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]); |
|
2883 n != INVALID; ++n) { |
|
2884 (*_node_data)[(*_node_index)[n]].pot -= offset; |
|
2885 } |
|
2886 |
|
2887 Arc matching = (*_blossom_data)[blossoms[i]].next; |
|
2888 Node base = _graph.source(matching); |
|
2889 extractBlossom(blossoms[i], base, matching); |
|
2890 } |
|
2891 } |
|
2892 |
|
2893 public: |
|
2894 |
|
2895 /// \brief Constructor |
|
2896 /// |
|
2897 /// Constructor. |
|
2898 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight) |
|
2899 : _graph(graph), _weight(weight), _matching(0), |
|
2900 _node_potential(0), _blossom_potential(), _blossom_node_list(), |
|
2901 _node_num(0), _blossom_num(0), |
|
2902 |
|
2903 _blossom_index(0), _blossom_set(0), _blossom_data(0), |
|
2904 _node_index(0), _node_heap_index(0), _node_data(0), |
|
2905 _tree_set_index(0), _tree_set(0), |
|
2906 |
|
2907 _delta2_index(0), _delta2(0), |
|
2908 _delta3_index(0), _delta3(0), |
|
2909 _delta4_index(0), _delta4(0), |
|
2910 |
|
2911 _delta_sum() {} |
|
2912 |
|
2913 ~MaxWeightedPerfectMatching() { |
|
2914 destroyStructures(); |
|
2915 } |
|
2916 |
|
2917 /// \name Execution Control |
|
2918 /// The simplest way to execute the algorithm is to use the |
|
2919 /// \ref run() member function. |
|
2920 |
|
2921 ///@{ |
|
2922 |
|
2923 /// \brief Initialize the algorithm |
|
2924 /// |
|
2925 /// This function initializes the algorithm. |
|
2926 void init() { |
|
2927 createStructures(); |
|
2928 |
|
2929 for (ArcIt e(_graph); e != INVALID; ++e) { |
|
2930 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP; |
|
2931 } |
|
2932 for (EdgeIt e(_graph); e != INVALID; ++e) { |
|
2933 (*_delta3_index)[e] = _delta3->PRE_HEAP; |
|
2934 } |
|
2935 for (int i = 0; i < _blossom_num; ++i) { |
|
2936 (*_delta2_index)[i] = _delta2->PRE_HEAP; |
|
2937 (*_delta4_index)[i] = _delta4->PRE_HEAP; |
|
2938 } |
|
2939 |
|
2940 int index = 0; |
|
2941 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
2942 Value max = - std::numeric_limits<Value>::max(); |
|
2943 for (OutArcIt e(_graph, n); e != INVALID; ++e) { |
|
2944 if (_graph.target(e) == n) continue; |
|
2945 if ((dualScale * _weight[e]) / 2 > max) { |
|
2946 max = (dualScale * _weight[e]) / 2; |
|
2947 } |
|
2948 } |
|
2949 (*_node_index)[n] = index; |
|
2950 (*_node_data)[index].pot = max; |
|
2951 int blossom = |
|
2952 _blossom_set->insert(n, std::numeric_limits<Value>::max()); |
|
2953 |
|
2954 _tree_set->insert(blossom); |
|
2955 |
|
2956 (*_blossom_data)[blossom].status = EVEN; |
|
2957 (*_blossom_data)[blossom].pred = INVALID; |
|
2958 (*_blossom_data)[blossom].next = INVALID; |
|
2959 (*_blossom_data)[blossom].pot = 0; |
|
2960 (*_blossom_data)[blossom].offset = 0; |
|
2961 ++index; |
|
2962 } |
|
2963 for (EdgeIt e(_graph); e != INVALID; ++e) { |
|
2964 int si = (*_node_index)[_graph.u(e)]; |
|
2965 int ti = (*_node_index)[_graph.v(e)]; |
|
2966 if (_graph.u(e) != _graph.v(e)) { |
|
2967 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot - |
|
2968 dualScale * _weight[e]) / 2); |
|
2969 } |
|
2970 } |
|
2971 } |
|
2972 |
|
2973 /// \brief Start the algorithm |
|
2974 /// |
|
2975 /// This function starts the algorithm. |
|
2976 /// |
|
2977 /// \pre \ref init() must be called before using this function. |
|
2978 bool start() { |
|
2979 enum OpType { |
|
2980 D2, D3, D4 |
|
2981 }; |
|
2982 |
|
2983 int unmatched = _node_num; |
|
2984 while (unmatched > 0) { |
|
2985 Value d2 = !_delta2->empty() ? |
|
2986 _delta2->prio() : std::numeric_limits<Value>::max(); |
|
2987 |
|
2988 Value d3 = !_delta3->empty() ? |
|
2989 _delta3->prio() : std::numeric_limits<Value>::max(); |
|
2990 |
|
2991 Value d4 = !_delta4->empty() ? |
|
2992 _delta4->prio() : std::numeric_limits<Value>::max(); |
|
2993 |
|
2994 _delta_sum = d2; OpType ot = D2; |
|
2995 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; } |
|
2996 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; } |
|
2997 |
|
2998 if (_delta_sum == std::numeric_limits<Value>::max()) { |
|
2999 return false; |
|
3000 } |
|
3001 |
|
3002 switch (ot) { |
|
3003 case D2: |
|
3004 { |
|
3005 int blossom = _delta2->top(); |
|
3006 Node n = _blossom_set->classTop(blossom); |
|
3007 Arc e = (*_node_data)[(*_node_index)[n]].heap.top(); |
|
3008 extendOnArc(e); |
|
3009 } |
|
3010 break; |
|
3011 case D3: |
|
3012 { |
|
3013 Edge e = _delta3->top(); |
|
3014 |
|
3015 int left_blossom = _blossom_set->find(_graph.u(e)); |
|
3016 int right_blossom = _blossom_set->find(_graph.v(e)); |
|
3017 |
|
3018 if (left_blossom == right_blossom) { |
|
3019 _delta3->pop(); |
|
3020 } else { |
|
3021 int left_tree = _tree_set->find(left_blossom); |
|
3022 int right_tree = _tree_set->find(right_blossom); |
|
3023 |
|
3024 if (left_tree == right_tree) { |
|
3025 shrinkOnEdge(e, left_tree); |
|
3026 } else { |
|
3027 augmentOnEdge(e); |
|
3028 unmatched -= 2; |
|
3029 } |
|
3030 } |
|
3031 } break; |
|
3032 case D4: |
|
3033 splitBlossom(_delta4->top()); |
|
3034 break; |
|
3035 } |
|
3036 } |
|
3037 extractMatching(); |
|
3038 return true; |
|
3039 } |
|
3040 |
|
3041 /// \brief Run the algorithm. |
|
3042 /// |
|
3043 /// This method runs the \c %MaxWeightedPerfectMatching algorithm. |
|
3044 /// |
|
3045 /// \note mwpm.run() is just a shortcut of the following code. |
|
3046 /// \code |
|
3047 /// mwpm.init(); |
|
3048 /// mwpm.start(); |
|
3049 /// \endcode |
|
3050 bool run() { |
|
3051 init(); |
|
3052 return start(); |
|
3053 } |
|
3054 |
|
3055 /// @} |
|
3056 |
|
3057 /// \name Primal Solution |
|
3058 /// Functions to get the primal solution, i.e. the maximum weighted |
|
3059 /// perfect matching.\n |
|
3060 /// Either \ref run() or \ref start() function should be called before |
|
3061 /// using them. |
|
3062 |
|
3063 /// @{ |
|
3064 |
|
3065 /// \brief Return the weight of the matching. |
|
3066 /// |
|
3067 /// This function returns the weight of the found matching. |
|
3068 /// |
|
3069 /// \pre Either run() or start() must be called before using this function. |
|
3070 Value matchingWeight() const { |
|
3071 Value sum = 0; |
|
3072 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
3073 if ((*_matching)[n] != INVALID) { |
|
3074 sum += _weight[(*_matching)[n]]; |
|
3075 } |
|
3076 } |
|
3077 return sum /= 2; |
|
3078 } |
|
3079 |
|
3080 /// \brief Return \c true if the given edge is in the matching. |
|
3081 /// |
|
3082 /// This function returns \c true if the given edge is in the found |
|
3083 /// matching. |
|
3084 /// |
|
3085 /// \pre Either run() or start() must be called before using this function. |
|
3086 bool matching(const Edge& edge) const { |
|
3087 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge; |
|
3088 } |
|
3089 |
|
3090 /// \brief Return the matching arc (or edge) incident to the given node. |
|
3091 /// |
|
3092 /// This function returns the matching arc (or edge) incident to the |
|
3093 /// given node in the found matching or \c INVALID if the node is |
|
3094 /// not covered by the matching. |
|
3095 /// |
|
3096 /// \pre Either run() or start() must be called before using this function. |
|
3097 Arc matching(const Node& node) const { |
|
3098 return (*_matching)[node]; |
|
3099 } |
|
3100 |
|
3101 /// \brief Return a const reference to the matching map. |
|
3102 /// |
|
3103 /// This function returns a const reference to a node map that stores |
|
3104 /// the matching arc (or edge) incident to each node. |
|
3105 const MatchingMap& matchingMap() const { |
|
3106 return *_matching; |
|
3107 } |
|
3108 |
|
3109 /// \brief Return the mate of the given node. |
|
3110 /// |
|
3111 /// This function returns the mate of the given node in the found |
|
3112 /// matching or \c INVALID if the node is not covered by the matching. |
|
3113 /// |
|
3114 /// \pre Either run() or start() must be called before using this function. |
|
3115 Node mate(const Node& node) const { |
|
3116 return _graph.target((*_matching)[node]); |
|
3117 } |
|
3118 |
|
3119 /// @} |
|
3120 |
|
3121 /// \name Dual Solution |
|
3122 /// Functions to get the dual solution.\n |
|
3123 /// Either \ref run() or \ref start() function should be called before |
|
3124 /// using them. |
|
3125 |
|
3126 /// @{ |
|
3127 |
|
3128 /// \brief Return the value of the dual solution. |
|
3129 /// |
|
3130 /// This function returns the value of the dual solution. |
|
3131 /// It should be equal to the primal value scaled by \ref dualScale |
|
3132 /// "dual scale". |
|
3133 /// |
|
3134 /// \pre Either run() or start() must be called before using this function. |
|
3135 Value dualValue() const { |
|
3136 Value sum = 0; |
|
3137 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
3138 sum += nodeValue(n); |
|
3139 } |
|
3140 for (int i = 0; i < blossomNum(); ++i) { |
|
3141 sum += blossomValue(i) * (blossomSize(i) / 2); |
|
3142 } |
|
3143 return sum; |
|
3144 } |
|
3145 |
|
3146 /// \brief Return the dual value (potential) of the given node. |
|
3147 /// |
|
3148 /// This function returns the dual value (potential) of the given node. |
|
3149 /// |
|
3150 /// \pre Either run() or start() must be called before using this function. |
|
3151 Value nodeValue(const Node& n) const { |
|
3152 return (*_node_potential)[n]; |
|
3153 } |
|
3154 |
|
3155 /// \brief Return the number of the blossoms in the basis. |
|
3156 /// |
|
3157 /// This function returns the number of the blossoms in the basis. |
|
3158 /// |
|
3159 /// \pre Either run() or start() must be called before using this function. |
|
3160 /// \see BlossomIt |
|
3161 int blossomNum() const { |
|
3162 return _blossom_potential.size(); |
|
3163 } |
|
3164 |
|
3165 /// \brief Return the number of the nodes in the given blossom. |
|
3166 /// |
|
3167 /// This function returns the number of the nodes in the given blossom. |
|
3168 /// |
|
3169 /// \pre Either run() or start() must be called before using this function. |
|
3170 /// \see BlossomIt |
|
3171 int blossomSize(int k) const { |
|
3172 return _blossom_potential[k].end - _blossom_potential[k].begin; |
|
3173 } |
|
3174 |
|
3175 /// \brief Return the dual value (ptential) of the given blossom. |
|
3176 /// |
|
3177 /// This function returns the dual value (ptential) of the given blossom. |
|
3178 /// |
|
3179 /// \pre Either run() or start() must be called before using this function. |
|
3180 Value blossomValue(int k) const { |
|
3181 return _blossom_potential[k].value; |
|
3182 } |
|
3183 |
|
3184 /// \brief Iterator for obtaining the nodes of a blossom. |
|
3185 /// |
|
3186 /// This class provides an iterator for obtaining the nodes of the |
|
3187 /// given blossom. It lists a subset of the nodes. |
|
3188 /// Before using this iterator, you must allocate a |
|
3189 /// MaxWeightedPerfectMatching class and execute it. |
|
3190 class BlossomIt { |
|
3191 public: |
|
3192 |
|
3193 /// \brief Constructor. |
|
3194 /// |
|
3195 /// Constructor to get the nodes of the given variable. |
|
3196 /// |
|
3197 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" |
|
3198 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" |
|
3199 /// must be called before initializing this iterator. |
|
3200 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable) |
|
3201 : _algorithm(&algorithm) |
|
3202 { |
|
3203 _index = _algorithm->_blossom_potential[variable].begin; |
|
3204 _last = _algorithm->_blossom_potential[variable].end; |
|
3205 } |
|
3206 |
|
3207 /// \brief Conversion to \c Node. |
|
3208 /// |
|
3209 /// Conversion to \c Node. |
|
3210 operator Node() const { |
|
3211 return _algorithm->_blossom_node_list[_index]; |
|
3212 } |
|
3213 |
|
3214 /// \brief Increment operator. |
|
3215 /// |
|
3216 /// Increment operator. |
|
3217 BlossomIt& operator++() { |
|
3218 ++_index; |
|
3219 return *this; |
|
3220 } |
|
3221 |
|
3222 /// \brief Validity checking |
|
3223 /// |
|
3224 /// This function checks whether the iterator is invalid. |
|
3225 bool operator==(Invalid) const { return _index == _last; } |
|
3226 |
|
3227 /// \brief Validity checking |
|
3228 /// |
|
3229 /// This function checks whether the iterator is valid. |
|
3230 bool operator!=(Invalid) const { return _index != _last; } |
|
3231 |
|
3232 private: |
|
3233 const MaxWeightedPerfectMatching* _algorithm; |
|
3234 int _last; |
|
3235 int _index; |
|
3236 }; |
|
3237 |
|
3238 /// @} |
|
3239 |
|
3240 }; |
|
3241 |
|
3242 } //END OF NAMESPACE LEMON |
|
3243 |
|
3244 #endif //LEMON_MAX_MATCHING_H |
|