1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2013
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #ifndef LEMON_MATCHING_H
20 #define LEMON_MATCHING_H
27 #include <lemon/core.h>
28 #include <lemon/unionfind.h>
29 #include <lemon/bin_heap.h>
30 #include <lemon/maps.h>
31 #include <lemon/fractional_matching.h>
35 ///\brief Maximum matching algorithms in general graphs.
41 /// \brief Maximum cardinality matching in general graphs
43 /// This class implements Edmonds' alternating forest matching algorithm
44 /// for finding a maximum cardinality matching in a general undirected graph.
45 /// It can be started from an arbitrary initial matching
46 /// (the default is the empty one).
48 /// The dual solution of the problem is a map of the nodes to
49 /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
50 /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
51 /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
52 /// with factor-critical components, the nodes in \c ODD/A form the
53 /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
54 /// a perfect matching. The number of the factor-critical components
55 /// minus the number of barrier nodes is a lower bound on the
56 /// unmatched nodes, and the matching is optimal if and only if this bound is
57 /// tight. This decomposition can be obtained using \ref status() or
58 /// \ref statusMap() after running the algorithm.
60 /// \tparam GR The undirected graph type the algorithm runs on.
61 template <typename GR>
65 /// The graph type of the algorithm
67 /// The type of the matching map
68 typedef typename Graph::template NodeMap<typename Graph::Arc>
71 ///\brief Status constants for Gallai-Edmonds decomposition.
73 ///These constants are used for indicating the Gallai-Edmonds
74 ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
75 ///induce a subgraph with factor-critical components, the nodes with
76 ///status \c ODD (or \c A) form the canonical barrier, and the nodes
77 ///with status \c MATCHED (or \c C) induce a subgraph having a
80 EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
82 MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.)
84 ODD = -1, ///< = -1. (\c A is an alias for \c ODD.)
86 UNMATCHED = -2 ///< = -2.
89 /// The type of the status map
90 typedef typename Graph::template NodeMap<Status> StatusMap;
94 TEMPLATE_GRAPH_TYPEDEFS(Graph);
96 typedef UnionFindEnum<IntNodeMap> BlossomSet;
97 typedef ExtendFindEnum<IntNodeMap> TreeSet;
98 typedef RangeMap<Node> NodeIntMap;
99 typedef MatchingMap EarMap;
100 typedef std::vector<Node> NodeQueue;
103 MatchingMap* _matching;
108 IntNodeMap* _blossom_set_index;
109 BlossomSet* _blossom_set;
110 NodeIntMap* _blossom_rep;
112 IntNodeMap* _tree_set_index;
115 NodeQueue _node_queue;
116 int _process, _postpone, _last;
118 int _node_num, _unmatched;
122 void createStructures() {
123 _node_num = countNodes(_graph);
125 _matching = new MatchingMap(_graph);
128 _status = new StatusMap(_graph);
131 _ear = new EarMap(_graph);
134 _blossom_set_index = new IntNodeMap(_graph);
135 _blossom_set = new BlossomSet(*_blossom_set_index);
138 _blossom_rep = new NodeIntMap(_node_num);
141 _tree_set_index = new IntNodeMap(_graph);
142 _tree_set = new TreeSet(*_tree_set_index);
144 _node_queue.resize(_node_num);
147 void destroyStructures() {
159 delete _blossom_set_index;
165 delete _tree_set_index;
170 void processDense(const Node& n) {
171 _process = _postpone = _last = 0;
172 _node_queue[_last++] = n;
174 while (_process != _last) {
175 Node u = _node_queue[_process++];
176 for (OutArcIt a(_graph, u); a != INVALID; ++a) {
177 Node v = _graph.target(a);
178 if ((*_status)[v] == MATCHED) {
180 } else if ((*_status)[v] == UNMATCHED) {
188 while (_postpone != _last) {
189 Node u = _node_queue[_postpone++];
191 for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
192 Node v = _graph.target(a);
194 if ((*_status)[v] == EVEN) {
195 if (_blossom_set->find(u) != _blossom_set->find(v)) {
200 while (_process != _last) {
201 Node w = _node_queue[_process++];
202 for (OutArcIt b(_graph, w); b != INVALID; ++b) {
203 Node x = _graph.target(b);
204 if ((*_status)[x] == MATCHED) {
206 } else if ((*_status)[x] == UNMATCHED) {
217 void processSparse(const Node& n) {
218 _process = _last = 0;
219 _node_queue[_last++] = n;
220 while (_process != _last) {
221 Node u = _node_queue[_process++];
222 for (OutArcIt a(_graph, u); a != INVALID; ++a) {
223 Node v = _graph.target(a);
225 if ((*_status)[v] == EVEN) {
226 if (_blossom_set->find(u) != _blossom_set->find(v)) {
229 } else if ((*_status)[v] == MATCHED) {
231 } else if ((*_status)[v] == UNMATCHED) {
240 void shrinkOnEdge(const Edge& e) {
244 std::set<Node> left_set, right_set;
246 Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
247 left_set.insert(left);
249 Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
250 right_set.insert(right);
253 if ((*_matching)[left] == INVALID) break;
254 left = _graph.target((*_matching)[left]);
255 left = (*_blossom_rep)[_blossom_set->
256 find(_graph.target((*_ear)[left]))];
257 if (right_set.find(left) != right_set.end()) {
261 left_set.insert(left);
263 if ((*_matching)[right] == INVALID) break;
264 right = _graph.target((*_matching)[right]);
265 right = (*_blossom_rep)[_blossom_set->
266 find(_graph.target((*_ear)[right]))];
267 if (left_set.find(right) != left_set.end()) {
271 right_set.insert(right);
274 if (nca == INVALID) {
275 if ((*_matching)[left] == INVALID) {
277 while (left_set.find(nca) == left_set.end()) {
278 nca = _graph.target((*_matching)[nca]);
279 nca =(*_blossom_rep)[_blossom_set->
280 find(_graph.target((*_ear)[nca]))];
284 while (right_set.find(nca) == right_set.end()) {
285 nca = _graph.target((*_matching)[nca]);
286 nca = (*_blossom_rep)[_blossom_set->
287 find(_graph.target((*_ear)[nca]))];
295 Node node = _graph.u(e);
296 Arc arc = _graph.direct(e, true);
297 Node base = (*_blossom_rep)[_blossom_set->find(node)];
299 while (base != nca) {
304 n = _graph.target((*_matching)[n]);
306 n = _graph.target(a);
307 (*_ear)[n] = _graph.oppositeArc(a);
309 node = _graph.target((*_matching)[base]);
310 _tree_set->erase(base);
311 _tree_set->erase(node);
312 _blossom_set->insert(node, _blossom_set->find(base));
313 (*_status)[node] = EVEN;
314 _node_queue[_last++] = node;
315 arc = _graph.oppositeArc((*_ear)[node]);
316 node = _graph.target((*_ear)[node]);
317 base = (*_blossom_rep)[_blossom_set->find(node)];
318 _blossom_set->join(_graph.target(arc), base);
322 (*_blossom_rep)[_blossom_set->find(nca)] = nca;
326 Node node = _graph.v(e);
327 Arc arc = _graph.direct(e, false);
328 Node base = (*_blossom_rep)[_blossom_set->find(node)];
330 while (base != nca) {
335 n = _graph.target((*_matching)[n]);
337 n = _graph.target(a);
338 (*_ear)[n] = _graph.oppositeArc(a);
340 node = _graph.target((*_matching)[base]);
341 _tree_set->erase(base);
342 _tree_set->erase(node);
343 _blossom_set->insert(node, _blossom_set->find(base));
344 (*_status)[node] = EVEN;
345 _node_queue[_last++] = node;
346 arc = _graph.oppositeArc((*_ear)[node]);
347 node = _graph.target((*_ear)[node]);
348 base = (*_blossom_rep)[_blossom_set->find(node)];
349 _blossom_set->join(_graph.target(arc), base);
353 (*_blossom_rep)[_blossom_set->find(nca)] = nca;
356 void extendOnArc(const Arc& a) {
357 Node base = _graph.source(a);
358 Node odd = _graph.target(a);
360 (*_ear)[odd] = _graph.oppositeArc(a);
361 Node even = _graph.target((*_matching)[odd]);
362 (*_blossom_rep)[_blossom_set->insert(even)] = even;
363 (*_status)[odd] = ODD;
364 (*_status)[even] = EVEN;
365 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
366 _tree_set->insert(odd, tree);
367 _tree_set->insert(even, tree);
368 _node_queue[_last++] = even;
372 void augmentOnArc(const Arc& a) {
373 Node even = _graph.source(a);
374 Node odd = _graph.target(a);
376 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
378 (*_matching)[odd] = _graph.oppositeArc(a);
379 (*_status)[odd] = MATCHED;
381 Arc arc = (*_matching)[even];
382 (*_matching)[even] = a;
384 while (arc != INVALID) {
385 odd = _graph.target(arc);
387 even = _graph.target(arc);
388 (*_matching)[odd] = arc;
389 arc = (*_matching)[even];
390 (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
393 for (typename TreeSet::ItemIt it(*_tree_set, tree);
394 it != INVALID; ++it) {
395 if ((*_status)[it] == ODD) {
396 (*_status)[it] = MATCHED;
398 int blossom = _blossom_set->find(it);
399 for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
400 jt != INVALID; ++jt) {
401 (*_status)[jt] = MATCHED;
403 _blossom_set->eraseClass(blossom);
406 _tree_set->eraseClass(tree);
412 /// \brief Constructor
415 MaxMatching(const Graph& graph)
416 : _graph(graph), _matching(0), _status(0), _ear(0),
417 _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
418 _tree_set_index(0), _tree_set(0) {}
424 /// \name Execution Control
425 /// The simplest way to execute the algorithm is to use the
426 /// \c run() member function.\n
427 /// If you need better control on the execution, you have to call
428 /// one of the functions \ref init(), \ref greedyInit() or
429 /// \ref matchingInit() first, then you can start the algorithm with
430 /// \ref startSparse() or \ref startDense().
434 /// \brief Set the initial matching to the empty matching.
436 /// This function sets the initial matching to the empty matching.
439 for(NodeIt n(_graph); n != INVALID; ++n) {
440 (*_matching)[n] = INVALID;
441 (*_status)[n] = UNMATCHED;
443 _unmatched = _node_num;
446 /// \brief Find an initial matching in a greedy way.
448 /// This function finds an initial matching in a greedy way.
451 for (NodeIt n(_graph); n != INVALID; ++n) {
452 (*_matching)[n] = INVALID;
453 (*_status)[n] = UNMATCHED;
455 _unmatched = _node_num;
456 for (NodeIt n(_graph); n != INVALID; ++n) {
457 if ((*_matching)[n] == INVALID) {
458 for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
459 Node v = _graph.target(a);
460 if ((*_matching)[v] == INVALID && v != n) {
462 (*_status)[n] = MATCHED;
463 (*_matching)[v] = _graph.oppositeArc(a);
464 (*_status)[v] = MATCHED;
474 /// \brief Initialize the matching from a map.
476 /// This function initializes the matching from a \c bool valued edge
477 /// map. This map should have the property that there are no two incident
478 /// edges with \c true value, i.e. it really contains a matching.
479 /// \return \c true if the map contains a matching.
480 template <typename MatchingMap>
481 bool matchingInit(const MatchingMap& matching) {
484 for (NodeIt n(_graph); n != INVALID; ++n) {
485 (*_matching)[n] = INVALID;
486 (*_status)[n] = UNMATCHED;
488 _unmatched = _node_num;
489 for(EdgeIt e(_graph); e!=INVALID; ++e) {
492 Node u = _graph.u(e);
493 if ((*_matching)[u] != INVALID) return false;
494 (*_matching)[u] = _graph.direct(e, true);
495 (*_status)[u] = MATCHED;
497 Node v = _graph.v(e);
498 if ((*_matching)[v] != INVALID) return false;
499 (*_matching)[v] = _graph.direct(e, false);
500 (*_status)[v] = MATCHED;
508 /// \brief Start Edmonds' algorithm
510 /// This function runs the original Edmonds' algorithm. If the
511 /// \c decomposition parameter is set to false, then the Gallai-Edmonds
512 /// decomposition is not computed.
514 /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
515 /// called before using this function.
516 void startSparse(bool decomposition = true) {
517 int _unmatched_limit = decomposition ? 0 : 1;
518 for(NodeIt n(_graph); _unmatched > _unmatched_limit; ++n) {
519 if ((*_status)[n] == UNMATCHED) {
520 (*_blossom_rep)[_blossom_set->insert(n)] = n;
521 _tree_set->insert(n);
522 (*_status)[n] = EVEN;
529 /// \brief Start Edmonds' algorithm with a heuristic improvement
532 /// This function runs Edmonds' algorithm with a heuristic of postponing
533 /// shrinks, therefore resulting in a faster algorithm for dense graphs. If
534 /// the \c decomposition parameter is set to false, then the Gallai-Edmonds
535 /// decomposition is not computed.
537 /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
538 /// called before using this function.
539 void startDense(bool decomposition = true) {
540 int _unmatched_limit = decomposition ? 0 : 1;
541 for(NodeIt n(_graph); _unmatched > _unmatched_limit; ++n) {
542 if ((*_status)[n] == UNMATCHED) {
543 (*_blossom_rep)[_blossom_set->insert(n)] = n;
544 _tree_set->insert(n);
545 (*_status)[n] = EVEN;
553 /// \brief Run Edmonds' algorithm
555 /// This function runs Edmonds' algorithm. An additional heuristic of
556 /// postponing shrinks is used for relatively dense graphs (for which
557 /// <tt>m>=2*n</tt> holds). If the \c decomposition parameter is set to
558 /// false, then the Gallai-Edmonds decomposition is not computed. In some
559 /// cases, this can speed up the algorithm significantly, especially when a
560 /// maximum matching is computed in a dense graph with odd number of nodes.
561 void run(bool decomposition = true) {
562 if (countEdges(_graph) < 2 * countNodes(_graph)) {
564 startSparse(decomposition);
567 startDense(decomposition);
573 /// \name Primal Solution
574 /// Functions to get the primal solution, i.e. the maximum matching.
578 /// \brief Return the size (cardinality) of the matching.
580 /// This function returns the size (cardinality) of the current matching.
581 /// After run() it returns the size of the maximum matching in the graph.
582 int matchingSize() const {
584 for (NodeIt n(_graph); n != INVALID; ++n) {
585 if ((*_matching)[n] != INVALID) {
592 /// \brief Return \c true if the given edge is in the matching.
594 /// This function returns \c true if the given edge is in the current
596 bool matching(const Edge& edge) const {
597 return edge == (*_matching)[_graph.u(edge)];
600 /// \brief Return the matching arc (or edge) incident to the given node.
602 /// This function returns the matching arc (or edge) incident to the
603 /// given node in the current matching or \c INVALID if the node is
604 /// not covered by the matching.
605 Arc matching(const Node& n) const {
606 return (*_matching)[n];
609 /// \brief Return a const reference to the matching map.
611 /// This function returns a const reference to a node map that stores
612 /// the matching arc (or edge) incident to each node.
613 const MatchingMap& matchingMap() const {
617 /// \brief Return the mate of the given node.
619 /// This function returns the mate of the given node in the current
620 /// matching or \c INVALID if the node is not covered by the matching.
621 Node mate(const Node& n) const {
622 return (*_matching)[n] != INVALID ?
623 _graph.target((*_matching)[n]) : INVALID;
628 /// \name Dual Solution
629 /// Functions to get the dual solution, i.e. the Gallai-Edmonds
634 /// \brief Return the status of the given node in the Edmonds-Gallai
637 /// This function returns the \ref Status "status" of the given node
638 /// in the Edmonds-Gallai decomposition.
639 Status status(const Node& n) const {
640 return (*_status)[n];
643 /// \brief Return a const reference to the status map, which stores
644 /// the Edmonds-Gallai decomposition.
646 /// This function returns a const reference to a node map that stores the
647 /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
648 const StatusMap& statusMap() const {
652 /// \brief Return \c true if the given node is in the barrier.
654 /// This function returns \c true if the given node is in the barrier.
655 bool barrier(const Node& n) const {
656 return (*_status)[n] == ODD;
663 /// \ingroup matching
665 /// \brief Weighted matching in general graphs
667 /// This class provides an efficient implementation of Edmond's
668 /// maximum weighted matching algorithm. The implementation is based
669 /// on extensive use of priority queues and provides
670 /// \f$O(nm\log n)\f$ time complexity.
672 /// The maximum weighted matching problem is to find a subset of the
673 /// edges in an undirected graph with maximum overall weight for which
674 /// each node has at most one incident edge.
675 /// It can be formulated with the following linear program.
676 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
677 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
678 \quad \forall B\in\mathcal{O}\f] */
679 /// \f[x_e \ge 0\quad \forall e\in E\f]
680 /// \f[\max \sum_{e\in E}x_ew_e\f]
681 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
682 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
683 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
684 /// subsets of the nodes.
686 /// The algorithm calculates an optimal matching and a proof of the
687 /// optimality. The solution of the dual problem can be used to check
688 /// the result of the algorithm. The dual linear problem is the
690 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
691 z_B \ge w_{uv} \quad \forall uv\in E\f] */
692 /// \f[y_u \ge 0 \quad \forall u \in V\f]
693 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
694 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
695 \frac{\vert B \vert - 1}{2}z_B\f] */
697 /// The algorithm can be executed with the run() function.
698 /// After it the matching (the primal solution) and the dual solution
699 /// can be obtained using the query functions and the
700 /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
701 /// which is able to iterate on the nodes of a blossom.
702 /// If the value type is integer, then the dual solution is multiplied
703 /// by \ref MaxWeightedMatching::dualScale "4".
705 /// \tparam GR The undirected graph type the algorithm runs on.
706 /// \tparam WM The type edge weight map. The default type is
707 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
709 template <typename GR, typename WM>
711 template <typename GR,
712 typename WM = typename GR::template EdgeMap<int> >
714 class MaxWeightedMatching {
717 /// The graph type of the algorithm
719 /// The type of the edge weight map
720 typedef WM WeightMap;
721 /// The value type of the edge weights
722 typedef typename WeightMap::Value Value;
724 /// The type of the matching map
725 typedef typename Graph::template NodeMap<typename Graph::Arc>
728 /// \brief Scaling factor for dual solution
730 /// Scaling factor for dual solution. It is equal to 4 or 1
731 /// according to the value type.
732 static const int dualScale =
733 std::numeric_limits<Value>::is_integer ? 4 : 1;
737 TEMPLATE_GRAPH_TYPEDEFS(Graph);
739 typedef typename Graph::template NodeMap<Value> NodePotential;
740 typedef std::vector<Node> BlossomNodeList;
742 struct BlossomVariable {
746 BlossomVariable(int _begin, int _end, Value _value)
747 : begin(_begin), end(_end), value(_value) {}
751 typedef std::vector<BlossomVariable> BlossomPotential;
754 const WeightMap& _weight;
756 MatchingMap* _matching;
758 NodePotential* _node_potential;
760 BlossomPotential _blossom_potential;
761 BlossomNodeList _blossom_node_list;
766 typedef RangeMap<int> IntIntMap;
769 EVEN = -1, MATCHED = 0, ODD = 1
772 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
781 IntNodeMap *_blossom_index;
782 BlossomSet *_blossom_set;
783 RangeMap<BlossomData>* _blossom_data;
785 IntNodeMap *_node_index;
786 IntArcMap *_node_heap_index;
790 NodeData(IntArcMap& node_heap_index)
791 : heap(node_heap_index) {}
795 BinHeap<Value, IntArcMap> heap;
796 std::map<int, Arc> heap_index;
801 RangeMap<NodeData>* _node_data;
803 typedef ExtendFindEnum<IntIntMap> TreeSet;
805 IntIntMap *_tree_set_index;
808 IntNodeMap *_delta1_index;
809 BinHeap<Value, IntNodeMap> *_delta1;
811 IntIntMap *_delta2_index;
812 BinHeap<Value, IntIntMap> *_delta2;
814 IntEdgeMap *_delta3_index;
815 BinHeap<Value, IntEdgeMap> *_delta3;
817 IntIntMap *_delta4_index;
818 BinHeap<Value, IntIntMap> *_delta4;
823 typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
824 FractionalMatching *_fractional;
826 void createStructures() {
827 _node_num = countNodes(_graph);
828 _blossom_num = _node_num * 3 / 2;
831 _matching = new MatchingMap(_graph);
834 if (!_node_potential) {
835 _node_potential = new NodePotential(_graph);
839 _blossom_index = new IntNodeMap(_graph);
840 _blossom_set = new BlossomSet(*_blossom_index);
841 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
842 } else if (_blossom_data->size() != _blossom_num) {
843 delete _blossom_data;
844 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
848 _node_index = new IntNodeMap(_graph);
849 _node_heap_index = new IntArcMap(_graph);
850 _node_data = new RangeMap<NodeData>(_node_num,
851 NodeData(*_node_heap_index));
854 _node_data = new RangeMap<NodeData>(_node_num,
855 NodeData(*_node_heap_index));
859 _tree_set_index = new IntIntMap(_blossom_num);
860 _tree_set = new TreeSet(*_tree_set_index);
862 _tree_set_index->resize(_blossom_num);
866 _delta1_index = new IntNodeMap(_graph);
867 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
871 _delta2_index = new IntIntMap(_blossom_num);
872 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
874 _delta2_index->resize(_blossom_num);
878 _delta3_index = new IntEdgeMap(_graph);
879 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
883 _delta4_index = new IntIntMap(_blossom_num);
884 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
886 _delta4_index->resize(_blossom_num);
890 void destroyStructures() {
894 if (_node_potential) {
895 delete _node_potential;
898 delete _blossom_index;
900 delete _blossom_data;
905 delete _node_heap_index;
910 delete _tree_set_index;
914 delete _delta1_index;
918 delete _delta2_index;
922 delete _delta3_index;
926 delete _delta4_index;
931 void matchedToEven(int blossom, int tree) {
932 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
933 _delta2->erase(blossom);
936 if (!_blossom_set->trivial(blossom)) {
937 (*_blossom_data)[blossom].pot -=
938 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
941 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
944 _blossom_set->increase(n, std::numeric_limits<Value>::max());
945 int ni = (*_node_index)[n];
947 (*_node_data)[ni].heap.clear();
948 (*_node_data)[ni].heap_index.clear();
950 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
952 _delta1->push(n, (*_node_data)[ni].pot);
954 for (InArcIt e(_graph, n); e != INVALID; ++e) {
955 Node v = _graph.source(e);
956 int vb = _blossom_set->find(v);
957 int vi = (*_node_index)[v];
959 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
960 dualScale * _weight[e];
962 if ((*_blossom_data)[vb].status == EVEN) {
963 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
964 _delta3->push(e, rw / 2);
967 typename std::map<int, Arc>::iterator it =
968 (*_node_data)[vi].heap_index.find(tree);
970 if (it != (*_node_data)[vi].heap_index.end()) {
971 if ((*_node_data)[vi].heap[it->second] > rw) {
972 (*_node_data)[vi].heap.replace(it->second, e);
973 (*_node_data)[vi].heap.decrease(e, rw);
977 (*_node_data)[vi].heap.push(e, rw);
978 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
981 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
982 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
984 if ((*_blossom_data)[vb].status == MATCHED) {
985 if (_delta2->state(vb) != _delta2->IN_HEAP) {
986 _delta2->push(vb, _blossom_set->classPrio(vb) -
987 (*_blossom_data)[vb].offset);
988 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
989 (*_blossom_data)[vb].offset) {
990 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
991 (*_blossom_data)[vb].offset);
998 (*_blossom_data)[blossom].offset = 0;
1001 void matchedToOdd(int blossom) {
1002 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1003 _delta2->erase(blossom);
1005 (*_blossom_data)[blossom].offset += _delta_sum;
1006 if (!_blossom_set->trivial(blossom)) {
1007 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
1008 (*_blossom_data)[blossom].offset);
1012 void evenToMatched(int blossom, int tree) {
1013 if (!_blossom_set->trivial(blossom)) {
1014 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
1017 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1018 n != INVALID; ++n) {
1019 int ni = (*_node_index)[n];
1020 (*_node_data)[ni].pot -= _delta_sum;
1024 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1025 Node v = _graph.source(e);
1026 int vb = _blossom_set->find(v);
1027 int vi = (*_node_index)[v];
1029 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1030 dualScale * _weight[e];
1032 if (vb == blossom) {
1033 if (_delta3->state(e) == _delta3->IN_HEAP) {
1036 } else if ((*_blossom_data)[vb].status == EVEN) {
1038 if (_delta3->state(e) == _delta3->IN_HEAP) {
1042 int vt = _tree_set->find(vb);
1046 Arc r = _graph.oppositeArc(e);
1048 typename std::map<int, Arc>::iterator it =
1049 (*_node_data)[ni].heap_index.find(vt);
1051 if (it != (*_node_data)[ni].heap_index.end()) {
1052 if ((*_node_data)[ni].heap[it->second] > rw) {
1053 (*_node_data)[ni].heap.replace(it->second, r);
1054 (*_node_data)[ni].heap.decrease(r, rw);
1058 (*_node_data)[ni].heap.push(r, rw);
1059 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1062 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1063 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1065 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1066 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1067 (*_blossom_data)[blossom].offset);
1068 } else if ((*_delta2)[blossom] >
1069 _blossom_set->classPrio(blossom) -
1070 (*_blossom_data)[blossom].offset){
1071 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1072 (*_blossom_data)[blossom].offset);
1078 typename std::map<int, Arc>::iterator it =
1079 (*_node_data)[vi].heap_index.find(tree);
1081 if (it != (*_node_data)[vi].heap_index.end()) {
1082 (*_node_data)[vi].heap.erase(it->second);
1083 (*_node_data)[vi].heap_index.erase(it);
1084 if ((*_node_data)[vi].heap.empty()) {
1085 _blossom_set->increase(v, std::numeric_limits<Value>::max());
1086 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1087 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1090 if ((*_blossom_data)[vb].status == MATCHED) {
1091 if (_blossom_set->classPrio(vb) ==
1092 std::numeric_limits<Value>::max()) {
1094 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1095 (*_blossom_data)[vb].offset) {
1096 _delta2->increase(vb, _blossom_set->classPrio(vb) -
1097 (*_blossom_data)[vb].offset);
1106 void oddToMatched(int blossom) {
1107 (*_blossom_data)[blossom].offset -= _delta_sum;
1109 if (_blossom_set->classPrio(blossom) !=
1110 std::numeric_limits<Value>::max()) {
1111 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1112 (*_blossom_data)[blossom].offset);
1115 if (!_blossom_set->trivial(blossom)) {
1116 _delta4->erase(blossom);
1120 void oddToEven(int blossom, int tree) {
1121 if (!_blossom_set->trivial(blossom)) {
1122 _delta4->erase(blossom);
1123 (*_blossom_data)[blossom].pot -=
1124 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1127 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1128 n != INVALID; ++n) {
1129 int ni = (*_node_index)[n];
1131 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1133 (*_node_data)[ni].heap.clear();
1134 (*_node_data)[ni].heap_index.clear();
1135 (*_node_data)[ni].pot +=
1136 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1138 _delta1->push(n, (*_node_data)[ni].pot);
1140 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1141 Node v = _graph.source(e);
1142 int vb = _blossom_set->find(v);
1143 int vi = (*_node_index)[v];
1145 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1146 dualScale * _weight[e];
1148 if ((*_blossom_data)[vb].status == EVEN) {
1149 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1150 _delta3->push(e, rw / 2);
1154 typename std::map<int, Arc>::iterator it =
1155 (*_node_data)[vi].heap_index.find(tree);
1157 if (it != (*_node_data)[vi].heap_index.end()) {
1158 if ((*_node_data)[vi].heap[it->second] > rw) {
1159 (*_node_data)[vi].heap.replace(it->second, e);
1160 (*_node_data)[vi].heap.decrease(e, rw);
1164 (*_node_data)[vi].heap.push(e, rw);
1165 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1168 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1169 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1171 if ((*_blossom_data)[vb].status == MATCHED) {
1172 if (_delta2->state(vb) != _delta2->IN_HEAP) {
1173 _delta2->push(vb, _blossom_set->classPrio(vb) -
1174 (*_blossom_data)[vb].offset);
1175 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1176 (*_blossom_data)[vb].offset) {
1177 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1178 (*_blossom_data)[vb].offset);
1185 (*_blossom_data)[blossom].offset = 0;
1188 void alternatePath(int even, int tree) {
1191 evenToMatched(even, tree);
1192 (*_blossom_data)[even].status = MATCHED;
1194 while ((*_blossom_data)[even].pred != INVALID) {
1195 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1196 (*_blossom_data)[odd].status = MATCHED;
1198 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1200 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1201 (*_blossom_data)[even].status = MATCHED;
1202 evenToMatched(even, tree);
1203 (*_blossom_data)[even].next =
1204 _graph.oppositeArc((*_blossom_data)[odd].pred);
1209 void destroyTree(int tree) {
1210 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1211 if ((*_blossom_data)[b].status == EVEN) {
1212 (*_blossom_data)[b].status = MATCHED;
1213 evenToMatched(b, tree);
1214 } else if ((*_blossom_data)[b].status == ODD) {
1215 (*_blossom_data)[b].status = MATCHED;
1219 _tree_set->eraseClass(tree);
1223 void unmatchNode(const Node& node) {
1224 int blossom = _blossom_set->find(node);
1225 int tree = _tree_set->find(blossom);
1227 alternatePath(blossom, tree);
1230 (*_blossom_data)[blossom].base = node;
1231 (*_blossom_data)[blossom].next = INVALID;
1234 void augmentOnEdge(const Edge& edge) {
1236 int left = _blossom_set->find(_graph.u(edge));
1237 int right = _blossom_set->find(_graph.v(edge));
1239 int left_tree = _tree_set->find(left);
1240 alternatePath(left, left_tree);
1241 destroyTree(left_tree);
1243 int right_tree = _tree_set->find(right);
1244 alternatePath(right, right_tree);
1245 destroyTree(right_tree);
1247 (*_blossom_data)[left].next = _graph.direct(edge, true);
1248 (*_blossom_data)[right].next = _graph.direct(edge, false);
1251 void augmentOnArc(const Arc& arc) {
1253 int left = _blossom_set->find(_graph.source(arc));
1254 int right = _blossom_set->find(_graph.target(arc));
1256 (*_blossom_data)[left].status = MATCHED;
1258 int right_tree = _tree_set->find(right);
1259 alternatePath(right, right_tree);
1260 destroyTree(right_tree);
1262 (*_blossom_data)[left].next = arc;
1263 (*_blossom_data)[right].next = _graph.oppositeArc(arc);
1266 void extendOnArc(const Arc& arc) {
1267 int base = _blossom_set->find(_graph.target(arc));
1268 int tree = _tree_set->find(base);
1270 int odd = _blossom_set->find(_graph.source(arc));
1271 _tree_set->insert(odd, tree);
1272 (*_blossom_data)[odd].status = ODD;
1274 (*_blossom_data)[odd].pred = arc;
1276 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1277 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1278 _tree_set->insert(even, tree);
1279 (*_blossom_data)[even].status = EVEN;
1280 matchedToEven(even, tree);
1283 void shrinkOnEdge(const Edge& edge, int tree) {
1285 std::vector<int> left_path, right_path;
1288 std::set<int> left_set, right_set;
1289 int left = _blossom_set->find(_graph.u(edge));
1290 left_path.push_back(left);
1291 left_set.insert(left);
1293 int right = _blossom_set->find(_graph.v(edge));
1294 right_path.push_back(right);
1295 right_set.insert(right);
1299 if ((*_blossom_data)[left].pred == INVALID) break;
1302 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1303 left_path.push_back(left);
1305 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1306 left_path.push_back(left);
1308 left_set.insert(left);
1310 if (right_set.find(left) != right_set.end()) {
1315 if ((*_blossom_data)[right].pred == INVALID) break;
1318 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1319 right_path.push_back(right);
1321 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1322 right_path.push_back(right);
1324 right_set.insert(right);
1326 if (left_set.find(right) != left_set.end()) {
1334 if ((*_blossom_data)[left].pred == INVALID) {
1336 while (left_set.find(nca) == left_set.end()) {
1338 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1339 right_path.push_back(nca);
1341 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1342 right_path.push_back(nca);
1346 while (right_set.find(nca) == right_set.end()) {
1348 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1349 left_path.push_back(nca);
1351 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1352 left_path.push_back(nca);
1358 std::vector<int> subblossoms;
1361 prev = _graph.direct(edge, true);
1362 for (int i = 0; left_path[i] != nca; i += 2) {
1363 subblossoms.push_back(left_path[i]);
1364 (*_blossom_data)[left_path[i]].next = prev;
1365 _tree_set->erase(left_path[i]);
1367 subblossoms.push_back(left_path[i + 1]);
1368 (*_blossom_data)[left_path[i + 1]].status = EVEN;
1369 oddToEven(left_path[i + 1], tree);
1370 _tree_set->erase(left_path[i + 1]);
1371 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1375 while (right_path[k] != nca) ++k;
1377 subblossoms.push_back(nca);
1378 (*_blossom_data)[nca].next = prev;
1380 for (int i = k - 2; i >= 0; i -= 2) {
1381 subblossoms.push_back(right_path[i + 1]);
1382 (*_blossom_data)[right_path[i + 1]].status = EVEN;
1383 oddToEven(right_path[i + 1], tree);
1384 _tree_set->erase(right_path[i + 1]);
1386 (*_blossom_data)[right_path[i + 1]].next =
1387 (*_blossom_data)[right_path[i + 1]].pred;
1389 subblossoms.push_back(right_path[i]);
1390 _tree_set->erase(right_path[i]);
1394 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1396 for (int i = 0; i < int(subblossoms.size()); ++i) {
1397 if (!_blossom_set->trivial(subblossoms[i])) {
1398 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1400 (*_blossom_data)[subblossoms[i]].status = MATCHED;
1403 (*_blossom_data)[surface].pot = -2 * _delta_sum;
1404 (*_blossom_data)[surface].offset = 0;
1405 (*_blossom_data)[surface].status = EVEN;
1406 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1407 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1409 _tree_set->insert(surface, tree);
1410 _tree_set->erase(nca);
1413 void splitBlossom(int blossom) {
1414 Arc next = (*_blossom_data)[blossom].next;
1415 Arc pred = (*_blossom_data)[blossom].pred;
1417 int tree = _tree_set->find(blossom);
1419 (*_blossom_data)[blossom].status = MATCHED;
1420 oddToMatched(blossom);
1421 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1422 _delta2->erase(blossom);
1425 std::vector<int> subblossoms;
1426 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1428 Value offset = (*_blossom_data)[blossom].offset;
1429 int b = _blossom_set->find(_graph.source(pred));
1430 int d = _blossom_set->find(_graph.source(next));
1432 int ib = -1, id = -1;
1433 for (int i = 0; i < int(subblossoms.size()); ++i) {
1434 if (subblossoms[i] == b) ib = i;
1435 if (subblossoms[i] == d) id = i;
1437 (*_blossom_data)[subblossoms[i]].offset = offset;
1438 if (!_blossom_set->trivial(subblossoms[i])) {
1439 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1441 if (_blossom_set->classPrio(subblossoms[i]) !=
1442 std::numeric_limits<Value>::max()) {
1443 _delta2->push(subblossoms[i],
1444 _blossom_set->classPrio(subblossoms[i]) -
1445 (*_blossom_data)[subblossoms[i]].offset);
1449 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1450 for (int i = (id + 1) % subblossoms.size();
1451 i != ib; i = (i + 2) % subblossoms.size()) {
1452 int sb = subblossoms[i];
1453 int tb = subblossoms[(i + 1) % subblossoms.size()];
1454 (*_blossom_data)[sb].next =
1455 _graph.oppositeArc((*_blossom_data)[tb].next);
1458 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1459 int sb = subblossoms[i];
1460 int tb = subblossoms[(i + 1) % subblossoms.size()];
1461 int ub = subblossoms[(i + 2) % subblossoms.size()];
1463 (*_blossom_data)[sb].status = ODD;
1465 _tree_set->insert(sb, tree);
1466 (*_blossom_data)[sb].pred = pred;
1467 (*_blossom_data)[sb].next =
1468 _graph.oppositeArc((*_blossom_data)[tb].next);
1470 pred = (*_blossom_data)[ub].next;
1472 (*_blossom_data)[tb].status = EVEN;
1473 matchedToEven(tb, tree);
1474 _tree_set->insert(tb, tree);
1475 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1478 (*_blossom_data)[subblossoms[id]].status = ODD;
1479 matchedToOdd(subblossoms[id]);
1480 _tree_set->insert(subblossoms[id], tree);
1481 (*_blossom_data)[subblossoms[id]].next = next;
1482 (*_blossom_data)[subblossoms[id]].pred = pred;
1486 for (int i = (ib + 1) % subblossoms.size();
1487 i != id; i = (i + 2) % subblossoms.size()) {
1488 int sb = subblossoms[i];
1489 int tb = subblossoms[(i + 1) % subblossoms.size()];
1490 (*_blossom_data)[sb].next =
1491 _graph.oppositeArc((*_blossom_data)[tb].next);
1494 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1495 int sb = subblossoms[i];
1496 int tb = subblossoms[(i + 1) % subblossoms.size()];
1497 int ub = subblossoms[(i + 2) % subblossoms.size()];
1499 (*_blossom_data)[sb].status = ODD;
1501 _tree_set->insert(sb, tree);
1502 (*_blossom_data)[sb].next = next;
1503 (*_blossom_data)[sb].pred =
1504 _graph.oppositeArc((*_blossom_data)[tb].next);
1506 (*_blossom_data)[tb].status = EVEN;
1507 matchedToEven(tb, tree);
1508 _tree_set->insert(tb, tree);
1509 (*_blossom_data)[tb].pred =
1510 (*_blossom_data)[tb].next =
1511 _graph.oppositeArc((*_blossom_data)[ub].next);
1512 next = (*_blossom_data)[ub].next;
1515 (*_blossom_data)[subblossoms[ib]].status = ODD;
1516 matchedToOdd(subblossoms[ib]);
1517 _tree_set->insert(subblossoms[ib], tree);
1518 (*_blossom_data)[subblossoms[ib]].next = next;
1519 (*_blossom_data)[subblossoms[ib]].pred = pred;
1521 _tree_set->erase(blossom);
1524 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1525 if (_blossom_set->trivial(blossom)) {
1526 int bi = (*_node_index)[base];
1527 Value pot = (*_node_data)[bi].pot;
1529 (*_matching)[base] = matching;
1530 _blossom_node_list.push_back(base);
1531 (*_node_potential)[base] = pot;
1534 Value pot = (*_blossom_data)[blossom].pot;
1535 int bn = _blossom_node_list.size();
1537 std::vector<int> subblossoms;
1538 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1539 int b = _blossom_set->find(base);
1541 for (int i = 0; i < int(subblossoms.size()); ++i) {
1542 if (subblossoms[i] == b) { ib = i; break; }
1545 for (int i = 1; i < int(subblossoms.size()); i += 2) {
1546 int sb = subblossoms[(ib + i) % subblossoms.size()];
1547 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1549 Arc m = (*_blossom_data)[tb].next;
1550 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1551 extractBlossom(tb, _graph.source(m), m);
1553 extractBlossom(subblossoms[ib], base, matching);
1555 int en = _blossom_node_list.size();
1557 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1561 void extractMatching() {
1562 std::vector<int> blossoms;
1563 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1564 blossoms.push_back(c);
1567 for (int i = 0; i < int(blossoms.size()); ++i) {
1568 if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1570 Value offset = (*_blossom_data)[blossoms[i]].offset;
1571 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1572 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1573 n != INVALID; ++n) {
1574 (*_node_data)[(*_node_index)[n]].pot -= offset;
1577 Arc matching = (*_blossom_data)[blossoms[i]].next;
1578 Node base = _graph.source(matching);
1579 extractBlossom(blossoms[i], base, matching);
1581 Node base = (*_blossom_data)[blossoms[i]].base;
1582 extractBlossom(blossoms[i], base, INVALID);
1589 /// \brief Constructor
1592 MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1593 : _graph(graph), _weight(weight), _matching(0),
1594 _node_potential(0), _blossom_potential(), _blossom_node_list(),
1595 _node_num(0), _blossom_num(0),
1597 _blossom_index(0), _blossom_set(0), _blossom_data(0),
1598 _node_index(0), _node_heap_index(0), _node_data(0),
1599 _tree_set_index(0), _tree_set(0),
1601 _delta1_index(0), _delta1(0),
1602 _delta2_index(0), _delta2(0),
1603 _delta3_index(0), _delta3(0),
1604 _delta4_index(0), _delta4(0),
1606 _delta_sum(), _unmatched(0),
1611 ~MaxWeightedMatching() {
1612 destroyStructures();
1618 /// \name Execution Control
1619 /// The simplest way to execute the algorithm is to use the
1620 /// \ref run() member function.
1624 /// \brief Initialize the algorithm
1626 /// This function initializes the algorithm.
1630 _blossom_node_list.clear();
1631 _blossom_potential.clear();
1633 for (ArcIt e(_graph); e != INVALID; ++e) {
1634 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1636 for (NodeIt n(_graph); n != INVALID; ++n) {
1637 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1639 for (EdgeIt e(_graph); e != INVALID; ++e) {
1640 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1642 for (int i = 0; i < _blossom_num; ++i) {
1643 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1644 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1647 _unmatched = _node_num;
1653 _blossom_set->clear();
1657 for (NodeIt n(_graph); n != INVALID; ++n) {
1659 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1660 if (_graph.target(e) == n) continue;
1661 if ((dualScale * _weight[e]) / 2 > max) {
1662 max = (dualScale * _weight[e]) / 2;
1665 (*_node_index)[n] = index;
1666 (*_node_data)[index].heap_index.clear();
1667 (*_node_data)[index].heap.clear();
1668 (*_node_data)[index].pot = max;
1669 _delta1->push(n, max);
1671 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1673 _tree_set->insert(blossom);
1675 (*_blossom_data)[blossom].status = EVEN;
1676 (*_blossom_data)[blossom].pred = INVALID;
1677 (*_blossom_data)[blossom].next = INVALID;
1678 (*_blossom_data)[blossom].pot = 0;
1679 (*_blossom_data)[blossom].offset = 0;
1682 for (EdgeIt e(_graph); e != INVALID; ++e) {
1683 int si = (*_node_index)[_graph.u(e)];
1684 int ti = (*_node_index)[_graph.v(e)];
1685 if (_graph.u(e) != _graph.v(e)) {
1686 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1687 dualScale * _weight[e]) / 2);
1692 /// \brief Initialize the algorithm with fractional matching
1694 /// This function initializes the algorithm with a fractional
1695 /// matching. This initialization is also called jumpstart heuristic.
1696 void fractionalInit() {
1699 _blossom_node_list.clear();
1700 _blossom_potential.clear();
1702 if (_fractional == 0) {
1703 _fractional = new FractionalMatching(_graph, _weight, false);
1707 for (ArcIt e(_graph); e != INVALID; ++e) {
1708 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1710 for (NodeIt n(_graph); n != INVALID; ++n) {
1711 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1713 for (EdgeIt e(_graph); e != INVALID; ++e) {
1714 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1716 for (int i = 0; i < _blossom_num; ++i) {
1717 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1718 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1727 _blossom_set->clear();
1731 for (NodeIt n(_graph); n != INVALID; ++n) {
1732 Value pot = _fractional->nodeValue(n);
1733 (*_node_index)[n] = index;
1734 (*_node_data)[index].pot = pot;
1735 (*_node_data)[index].heap_index.clear();
1736 (*_node_data)[index].heap.clear();
1738 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1740 (*_blossom_data)[blossom].status = MATCHED;
1741 (*_blossom_data)[blossom].pred = INVALID;
1742 (*_blossom_data)[blossom].next = _fractional->matching(n);
1743 if (_fractional->matching(n) == INVALID) {
1744 (*_blossom_data)[blossom].base = n;
1746 (*_blossom_data)[blossom].pot = 0;
1747 (*_blossom_data)[blossom].offset = 0;
1751 typename Graph::template NodeMap<bool> processed(_graph, false);
1752 for (NodeIt n(_graph); n != INVALID; ++n) {
1753 if (processed[n]) continue;
1754 processed[n] = true;
1755 if (_fractional->matching(n) == INVALID) continue;
1757 Node v = _graph.target(_fractional->matching(n));
1759 processed[v] = true;
1760 v = _graph.target(_fractional->matching(v));
1765 std::vector<int> subblossoms(num);
1767 subblossoms[--num] = _blossom_set->find(n);
1768 _delta1->push(n, _fractional->nodeValue(n));
1769 v = _graph.target(_fractional->matching(n));
1771 subblossoms[--num] = _blossom_set->find(v);
1772 _delta1->push(v, _fractional->nodeValue(v));
1773 v = _graph.target(_fractional->matching(v));
1777 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1778 (*_blossom_data)[surface].status = EVEN;
1779 (*_blossom_data)[surface].pred = INVALID;
1780 (*_blossom_data)[surface].next = INVALID;
1781 (*_blossom_data)[surface].pot = 0;
1782 (*_blossom_data)[surface].offset = 0;
1784 _tree_set->insert(surface);
1789 for (EdgeIt e(_graph); e != INVALID; ++e) {
1790 int si = (*_node_index)[_graph.u(e)];
1791 int sb = _blossom_set->find(_graph.u(e));
1792 int ti = (*_node_index)[_graph.v(e)];
1793 int tb = _blossom_set->find(_graph.v(e));
1794 if ((*_blossom_data)[sb].status == EVEN &&
1795 (*_blossom_data)[tb].status == EVEN && sb != tb) {
1796 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1797 dualScale * _weight[e]) / 2);
1801 for (NodeIt n(_graph); n != INVALID; ++n) {
1802 int nb = _blossom_set->find(n);
1803 if ((*_blossom_data)[nb].status != MATCHED) continue;
1804 int ni = (*_node_index)[n];
1806 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1807 Node v = _graph.target(e);
1808 int vb = _blossom_set->find(v);
1809 int vi = (*_node_index)[v];
1811 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1812 dualScale * _weight[e];
1814 if ((*_blossom_data)[vb].status == EVEN) {
1816 int vt = _tree_set->find(vb);
1818 typename std::map<int, Arc>::iterator it =
1819 (*_node_data)[ni].heap_index.find(vt);
1821 if (it != (*_node_data)[ni].heap_index.end()) {
1822 if ((*_node_data)[ni].heap[it->second] > rw) {
1823 (*_node_data)[ni].heap.replace(it->second, e);
1824 (*_node_data)[ni].heap.decrease(e, rw);
1828 (*_node_data)[ni].heap.push(e, rw);
1829 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
1834 if (!(*_node_data)[ni].heap.empty()) {
1835 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1836 _delta2->push(nb, _blossom_set->classPrio(nb));
1841 /// \brief Start the algorithm
1843 /// This function starts the algorithm.
1845 /// \pre \ref init() or \ref fractionalInit() must be called
1846 /// before using this function.
1852 while (_unmatched > 0) {
1853 Value d1 = !_delta1->empty() ?
1854 _delta1->prio() : std::numeric_limits<Value>::max();
1856 Value d2 = !_delta2->empty() ?
1857 _delta2->prio() : std::numeric_limits<Value>::max();
1859 Value d3 = !_delta3->empty() ?
1860 _delta3->prio() : std::numeric_limits<Value>::max();
1862 Value d4 = !_delta4->empty() ?
1863 _delta4->prio() : std::numeric_limits<Value>::max();
1865 _delta_sum = d3; OpType ot = D3;
1866 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1867 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1868 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1873 Node n = _delta1->top();
1880 int blossom = _delta2->top();
1881 Node n = _blossom_set->classTop(blossom);
1882 Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1883 if ((*_blossom_data)[blossom].next == INVALID) {
1893 Edge e = _delta3->top();
1895 int left_blossom = _blossom_set->find(_graph.u(e));
1896 int right_blossom = _blossom_set->find(_graph.v(e));
1898 if (left_blossom == right_blossom) {
1901 int left_tree = _tree_set->find(left_blossom);
1902 int right_tree = _tree_set->find(right_blossom);
1904 if (left_tree == right_tree) {
1905 shrinkOnEdge(e, left_tree);
1913 splitBlossom(_delta4->top());
1920 /// \brief Run the algorithm.
1922 /// This method runs the \c %MaxWeightedMatching algorithm.
1924 /// \note mwm.run() is just a shortcut of the following code.
1926 /// mwm.fractionalInit();
1936 /// \name Primal Solution
1937 /// Functions to get the primal solution, i.e. the maximum weighted
1939 /// Either \ref run() or \ref start() function should be called before
1944 /// \brief Return the weight of the matching.
1946 /// This function returns the weight of the found matching.
1948 /// \pre Either run() or start() must be called before using this function.
1949 Value matchingWeight() const {
1951 for (NodeIt n(_graph); n != INVALID; ++n) {
1952 if ((*_matching)[n] != INVALID) {
1953 sum += _weight[(*_matching)[n]];
1959 /// \brief Return the size (cardinality) of the matching.
1961 /// This function returns the size (cardinality) of the found matching.
1963 /// \pre Either run() or start() must be called before using this function.
1964 int matchingSize() const {
1966 for (NodeIt n(_graph); n != INVALID; ++n) {
1967 if ((*_matching)[n] != INVALID) {
1974 /// \brief Return \c true if the given edge is in the matching.
1976 /// This function returns \c true if the given edge is in the found
1979 /// \pre Either run() or start() must be called before using this function.
1980 bool matching(const Edge& edge) const {
1981 return edge == (*_matching)[_graph.u(edge)];
1984 /// \brief Return the matching arc (or edge) incident to the given node.
1986 /// This function returns the matching arc (or edge) incident to the
1987 /// given node in the found matching or \c INVALID if the node is
1988 /// not covered by the matching.
1990 /// \pre Either run() or start() must be called before using this function.
1991 Arc matching(const Node& node) const {
1992 return (*_matching)[node];
1995 /// \brief Return a const reference to the matching map.
1997 /// This function returns a const reference to a node map that stores
1998 /// the matching arc (or edge) incident to each node.
1999 const MatchingMap& matchingMap() const {
2003 /// \brief Return the mate of the given node.
2005 /// This function returns the mate of the given node in the found
2006 /// matching or \c INVALID if the node is not covered by the matching.
2008 /// \pre Either run() or start() must be called before using this function.
2009 Node mate(const Node& node) const {
2010 return (*_matching)[node] != INVALID ?
2011 _graph.target((*_matching)[node]) : INVALID;
2016 /// \name Dual Solution
2017 /// Functions to get the dual solution.\n
2018 /// Either \ref run() or \ref start() function should be called before
2023 /// \brief Return the value of the dual solution.
2025 /// This function returns the value of the dual solution.
2026 /// It should be equal to the primal value scaled by \ref dualScale
2029 /// \pre Either run() or start() must be called before using this function.
2030 Value dualValue() const {
2032 for (NodeIt n(_graph); n != INVALID; ++n) {
2033 sum += nodeValue(n);
2035 for (int i = 0; i < blossomNum(); ++i) {
2036 sum += blossomValue(i) * (blossomSize(i) / 2);
2041 /// \brief Return the dual value (potential) of the given node.
2043 /// This function returns the dual value (potential) of the given node.
2045 /// \pre Either run() or start() must be called before using this function.
2046 Value nodeValue(const Node& n) const {
2047 return (*_node_potential)[n];
2050 /// \brief Return the number of the blossoms in the basis.
2052 /// This function returns the number of the blossoms in the basis.
2054 /// \pre Either run() or start() must be called before using this function.
2056 int blossomNum() const {
2057 return _blossom_potential.size();
2060 /// \brief Return the number of the nodes in the given blossom.
2062 /// This function returns the number of the nodes in the given blossom.
2064 /// \pre Either run() or start() must be called before using this function.
2066 int blossomSize(int k) const {
2067 return _blossom_potential[k].end - _blossom_potential[k].begin;
2070 /// \brief Return the dual value (ptential) of the given blossom.
2072 /// This function returns the dual value (ptential) of the given blossom.
2074 /// \pre Either run() or start() must be called before using this function.
2075 Value blossomValue(int k) const {
2076 return _blossom_potential[k].value;
2079 /// \brief Iterator for obtaining the nodes of a blossom.
2081 /// This class provides an iterator for obtaining the nodes of the
2082 /// given blossom. It lists a subset of the nodes.
2083 /// Before using this iterator, you must allocate a
2084 /// MaxWeightedMatching class and execute it.
2088 /// \brief Constructor.
2090 /// Constructor to get the nodes of the given variable.
2092 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2093 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
2094 /// called before initializing this iterator.
2095 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
2096 : _algorithm(&algorithm)
2098 _index = _algorithm->_blossom_potential[variable].begin;
2099 _last = _algorithm->_blossom_potential[variable].end;
2102 /// \brief Conversion to \c Node.
2104 /// Conversion to \c Node.
2105 operator Node() const {
2106 return _algorithm->_blossom_node_list[_index];
2109 /// \brief Increment operator.
2111 /// Increment operator.
2112 BlossomIt& operator++() {
2117 /// \brief Validity checking
2119 /// Checks whether the iterator is invalid.
2120 bool operator==(Invalid) const { return _index == _last; }
2122 /// \brief Validity checking
2124 /// Checks whether the iterator is valid.
2125 bool operator!=(Invalid) const { return _index != _last; }
2128 const MaxWeightedMatching* _algorithm;
2137 /// \ingroup matching
2139 /// \brief Weighted perfect matching in general graphs
2141 /// This class provides an efficient implementation of Edmond's
2142 /// maximum weighted perfect matching algorithm. The implementation
2143 /// is based on extensive use of priority queues and provides
2144 /// \f$O(nm\log n)\f$ time complexity.
2146 /// The maximum weighted perfect matching problem is to find a subset of
2147 /// the edges in an undirected graph with maximum overall weight for which
2148 /// each node has exactly one incident edge.
2149 /// It can be formulated with the following linear program.
2150 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2151 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2152 \quad \forall B\in\mathcal{O}\f] */
2153 /// \f[x_e \ge 0\quad \forall e\in E\f]
2154 /// \f[\max \sum_{e\in E}x_ew_e\f]
2155 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2156 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2157 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2158 /// subsets of the nodes.
2160 /// The algorithm calculates an optimal matching and a proof of the
2161 /// optimality. The solution of the dual problem can be used to check
2162 /// the result of the algorithm. The dual linear problem is the
2164 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2165 w_{uv} \quad \forall uv\in E\f] */
2166 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2167 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2168 \frac{\vert B \vert - 1}{2}z_B\f] */
2170 /// The algorithm can be executed with the run() function.
2171 /// After it the matching (the primal solution) and the dual solution
2172 /// can be obtained using the query functions and the
2173 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2174 /// which is able to iterate on the nodes of a blossom.
2175 /// If the value type is integer, then the dual solution is multiplied
2176 /// by \ref MaxWeightedMatching::dualScale "4".
2178 /// \tparam GR The undirected graph type the algorithm runs on.
2179 /// \tparam WM The type edge weight map. The default type is
2180 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2182 template <typename GR, typename WM>
2184 template <typename GR,
2185 typename WM = typename GR::template EdgeMap<int> >
2187 class MaxWeightedPerfectMatching {
2190 /// The graph type of the algorithm
2192 /// The type of the edge weight map
2193 typedef WM WeightMap;
2194 /// The value type of the edge weights
2195 typedef typename WeightMap::Value Value;
2197 /// \brief Scaling factor for dual solution
2199 /// Scaling factor for dual solution, it is equal to 4 or 1
2200 /// according to the value type.
2201 static const int dualScale =
2202 std::numeric_limits<Value>::is_integer ? 4 : 1;
2204 /// The type of the matching map
2205 typedef typename Graph::template NodeMap<typename Graph::Arc>
2210 TEMPLATE_GRAPH_TYPEDEFS(Graph);
2212 typedef typename Graph::template NodeMap<Value> NodePotential;
2213 typedef std::vector<Node> BlossomNodeList;
2215 struct BlossomVariable {
2219 BlossomVariable(int _begin, int _end, Value _value)
2220 : begin(_begin), end(_end), value(_value) {}
2224 typedef std::vector<BlossomVariable> BlossomPotential;
2226 const Graph& _graph;
2227 const WeightMap& _weight;
2229 MatchingMap* _matching;
2231 NodePotential* _node_potential;
2233 BlossomPotential _blossom_potential;
2234 BlossomNodeList _blossom_node_list;
2239 typedef RangeMap<int> IntIntMap;
2242 EVEN = -1, MATCHED = 0, ODD = 1
2245 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2246 struct BlossomData {
2253 IntNodeMap *_blossom_index;
2254 BlossomSet *_blossom_set;
2255 RangeMap<BlossomData>* _blossom_data;
2257 IntNodeMap *_node_index;
2258 IntArcMap *_node_heap_index;
2262 NodeData(IntArcMap& node_heap_index)
2263 : heap(node_heap_index) {}
2267 BinHeap<Value, IntArcMap> heap;
2268 std::map<int, Arc> heap_index;
2273 RangeMap<NodeData>* _node_data;
2275 typedef ExtendFindEnum<IntIntMap> TreeSet;
2277 IntIntMap *_tree_set_index;
2280 IntIntMap *_delta2_index;
2281 BinHeap<Value, IntIntMap> *_delta2;
2283 IntEdgeMap *_delta3_index;
2284 BinHeap<Value, IntEdgeMap> *_delta3;
2286 IntIntMap *_delta4_index;
2287 BinHeap<Value, IntIntMap> *_delta4;
2292 typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>
2294 FractionalMatching *_fractional;
2296 void createStructures() {
2297 _node_num = countNodes(_graph);
2298 _blossom_num = _node_num * 3 / 2;
2301 _matching = new MatchingMap(_graph);
2304 if (!_node_potential) {
2305 _node_potential = new NodePotential(_graph);
2308 if (!_blossom_set) {
2309 _blossom_index = new IntNodeMap(_graph);
2310 _blossom_set = new BlossomSet(*_blossom_index);
2311 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2312 } else if (_blossom_data->size() != _blossom_num) {
2313 delete _blossom_data;
2314 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2318 _node_index = new IntNodeMap(_graph);
2319 _node_heap_index = new IntArcMap(_graph);
2320 _node_data = new RangeMap<NodeData>(_node_num,
2321 NodeData(*_node_heap_index));
2322 } else if (_node_data->size() != _node_num) {
2324 _node_data = new RangeMap<NodeData>(_node_num,
2325 NodeData(*_node_heap_index));
2329 _tree_set_index = new IntIntMap(_blossom_num);
2330 _tree_set = new TreeSet(*_tree_set_index);
2332 _tree_set_index->resize(_blossom_num);
2336 _delta2_index = new IntIntMap(_blossom_num);
2337 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2339 _delta2_index->resize(_blossom_num);
2343 _delta3_index = new IntEdgeMap(_graph);
2344 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2348 _delta4_index = new IntIntMap(_blossom_num);
2349 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2351 _delta4_index->resize(_blossom_num);
2355 void destroyStructures() {
2359 if (_node_potential) {
2360 delete _node_potential;
2363 delete _blossom_index;
2364 delete _blossom_set;
2365 delete _blossom_data;
2370 delete _node_heap_index;
2375 delete _tree_set_index;
2379 delete _delta2_index;
2383 delete _delta3_index;
2387 delete _delta4_index;
2392 void matchedToEven(int blossom, int tree) {
2393 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2394 _delta2->erase(blossom);
2397 if (!_blossom_set->trivial(blossom)) {
2398 (*_blossom_data)[blossom].pot -=
2399 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2402 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2403 n != INVALID; ++n) {
2405 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2406 int ni = (*_node_index)[n];
2408 (*_node_data)[ni].heap.clear();
2409 (*_node_data)[ni].heap_index.clear();
2411 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2413 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2414 Node v = _graph.source(e);
2415 int vb = _blossom_set->find(v);
2416 int vi = (*_node_index)[v];
2418 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2419 dualScale * _weight[e];
2421 if ((*_blossom_data)[vb].status == EVEN) {
2422 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2423 _delta3->push(e, rw / 2);
2426 typename std::map<int, Arc>::iterator it =
2427 (*_node_data)[vi].heap_index.find(tree);
2429 if (it != (*_node_data)[vi].heap_index.end()) {
2430 if ((*_node_data)[vi].heap[it->second] > rw) {
2431 (*_node_data)[vi].heap.replace(it->second, e);
2432 (*_node_data)[vi].heap.decrease(e, rw);
2436 (*_node_data)[vi].heap.push(e, rw);
2437 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2440 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2441 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2443 if ((*_blossom_data)[vb].status == MATCHED) {
2444 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2445 _delta2->push(vb, _blossom_set->classPrio(vb) -
2446 (*_blossom_data)[vb].offset);
2447 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2448 (*_blossom_data)[vb].offset){
2449 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2450 (*_blossom_data)[vb].offset);
2457 (*_blossom_data)[blossom].offset = 0;
2460 void matchedToOdd(int blossom) {
2461 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2462 _delta2->erase(blossom);
2464 (*_blossom_data)[blossom].offset += _delta_sum;
2465 if (!_blossom_set->trivial(blossom)) {
2466 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2467 (*_blossom_data)[blossom].offset);
2471 void evenToMatched(int blossom, int tree) {
2472 if (!_blossom_set->trivial(blossom)) {
2473 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2476 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2477 n != INVALID; ++n) {
2478 int ni = (*_node_index)[n];
2479 (*_node_data)[ni].pot -= _delta_sum;
2481 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2482 Node v = _graph.source(e);
2483 int vb = _blossom_set->find(v);
2484 int vi = (*_node_index)[v];
2486 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2487 dualScale * _weight[e];
2489 if (vb == blossom) {
2490 if (_delta3->state(e) == _delta3->IN_HEAP) {
2493 } else if ((*_blossom_data)[vb].status == EVEN) {
2495 if (_delta3->state(e) == _delta3->IN_HEAP) {
2499 int vt = _tree_set->find(vb);
2503 Arc r = _graph.oppositeArc(e);
2505 typename std::map<int, Arc>::iterator it =
2506 (*_node_data)[ni].heap_index.find(vt);
2508 if (it != (*_node_data)[ni].heap_index.end()) {
2509 if ((*_node_data)[ni].heap[it->second] > rw) {
2510 (*_node_data)[ni].heap.replace(it->second, r);
2511 (*_node_data)[ni].heap.decrease(r, rw);
2515 (*_node_data)[ni].heap.push(r, rw);
2516 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2519 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2520 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2522 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2523 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2524 (*_blossom_data)[blossom].offset);
2525 } else if ((*_delta2)[blossom] >
2526 _blossom_set->classPrio(blossom) -
2527 (*_blossom_data)[blossom].offset){
2528 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2529 (*_blossom_data)[blossom].offset);
2535 typename std::map<int, Arc>::iterator it =
2536 (*_node_data)[vi].heap_index.find(tree);
2538 if (it != (*_node_data)[vi].heap_index.end()) {
2539 (*_node_data)[vi].heap.erase(it->second);
2540 (*_node_data)[vi].heap_index.erase(it);
2541 if ((*_node_data)[vi].heap.empty()) {
2542 _blossom_set->increase(v, std::numeric_limits<Value>::max());
2543 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2544 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2547 if ((*_blossom_data)[vb].status == MATCHED) {
2548 if (_blossom_set->classPrio(vb) ==
2549 std::numeric_limits<Value>::max()) {
2551 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2552 (*_blossom_data)[vb].offset) {
2553 _delta2->increase(vb, _blossom_set->classPrio(vb) -
2554 (*_blossom_data)[vb].offset);
2563 void oddToMatched(int blossom) {
2564 (*_blossom_data)[blossom].offset -= _delta_sum;
2566 if (_blossom_set->classPrio(blossom) !=
2567 std::numeric_limits<Value>::max()) {
2568 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2569 (*_blossom_data)[blossom].offset);
2572 if (!_blossom_set->trivial(blossom)) {
2573 _delta4->erase(blossom);
2577 void oddToEven(int blossom, int tree) {
2578 if (!_blossom_set->trivial(blossom)) {
2579 _delta4->erase(blossom);
2580 (*_blossom_data)[blossom].pot -=
2581 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2584 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2585 n != INVALID; ++n) {
2586 int ni = (*_node_index)[n];
2588 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2590 (*_node_data)[ni].heap.clear();
2591 (*_node_data)[ni].heap_index.clear();
2592 (*_node_data)[ni].pot +=
2593 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2595 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2596 Node v = _graph.source(e);
2597 int vb = _blossom_set->find(v);
2598 int vi = (*_node_index)[v];
2600 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2601 dualScale * _weight[e];
2603 if ((*_blossom_data)[vb].status == EVEN) {
2604 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2605 _delta3->push(e, rw / 2);
2609 typename std::map<int, Arc>::iterator it =
2610 (*_node_data)[vi].heap_index.find(tree);
2612 if (it != (*_node_data)[vi].heap_index.end()) {
2613 if ((*_node_data)[vi].heap[it->second] > rw) {
2614 (*_node_data)[vi].heap.replace(it->second, e);
2615 (*_node_data)[vi].heap.decrease(e, rw);
2619 (*_node_data)[vi].heap.push(e, rw);
2620 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2623 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2624 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2626 if ((*_blossom_data)[vb].status == MATCHED) {
2627 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2628 _delta2->push(vb, _blossom_set->classPrio(vb) -
2629 (*_blossom_data)[vb].offset);
2630 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2631 (*_blossom_data)[vb].offset) {
2632 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2633 (*_blossom_data)[vb].offset);
2640 (*_blossom_data)[blossom].offset = 0;
2643 void alternatePath(int even, int tree) {
2646 evenToMatched(even, tree);
2647 (*_blossom_data)[even].status = MATCHED;
2649 while ((*_blossom_data)[even].pred != INVALID) {
2650 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2651 (*_blossom_data)[odd].status = MATCHED;
2653 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2655 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2656 (*_blossom_data)[even].status = MATCHED;
2657 evenToMatched(even, tree);
2658 (*_blossom_data)[even].next =
2659 _graph.oppositeArc((*_blossom_data)[odd].pred);
2664 void destroyTree(int tree) {
2665 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2666 if ((*_blossom_data)[b].status == EVEN) {
2667 (*_blossom_data)[b].status = MATCHED;
2668 evenToMatched(b, tree);
2669 } else if ((*_blossom_data)[b].status == ODD) {
2670 (*_blossom_data)[b].status = MATCHED;
2674 _tree_set->eraseClass(tree);
2677 void augmentOnEdge(const Edge& edge) {
2679 int left = _blossom_set->find(_graph.u(edge));
2680 int right = _blossom_set->find(_graph.v(edge));
2682 int left_tree = _tree_set->find(left);
2683 alternatePath(left, left_tree);
2684 destroyTree(left_tree);
2686 int right_tree = _tree_set->find(right);
2687 alternatePath(right, right_tree);
2688 destroyTree(right_tree);
2690 (*_blossom_data)[left].next = _graph.direct(edge, true);
2691 (*_blossom_data)[right].next = _graph.direct(edge, false);
2694 void extendOnArc(const Arc& arc) {
2695 int base = _blossom_set->find(_graph.target(arc));
2696 int tree = _tree_set->find(base);
2698 int odd = _blossom_set->find(_graph.source(arc));
2699 _tree_set->insert(odd, tree);
2700 (*_blossom_data)[odd].status = ODD;
2702 (*_blossom_data)[odd].pred = arc;
2704 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2705 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2706 _tree_set->insert(even, tree);
2707 (*_blossom_data)[even].status = EVEN;
2708 matchedToEven(even, tree);
2711 void shrinkOnEdge(const Edge& edge, int tree) {
2713 std::vector<int> left_path, right_path;
2716 std::set<int> left_set, right_set;
2717 int left = _blossom_set->find(_graph.u(edge));
2718 left_path.push_back(left);
2719 left_set.insert(left);
2721 int right = _blossom_set->find(_graph.v(edge));
2722 right_path.push_back(right);
2723 right_set.insert(right);
2727 if ((*_blossom_data)[left].pred == INVALID) break;
2730 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2731 left_path.push_back(left);
2733 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2734 left_path.push_back(left);
2736 left_set.insert(left);
2738 if (right_set.find(left) != right_set.end()) {
2743 if ((*_blossom_data)[right].pred == INVALID) break;
2746 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2747 right_path.push_back(right);
2749 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2750 right_path.push_back(right);
2752 right_set.insert(right);
2754 if (left_set.find(right) != left_set.end()) {
2762 if ((*_blossom_data)[left].pred == INVALID) {
2764 while (left_set.find(nca) == left_set.end()) {
2766 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2767 right_path.push_back(nca);
2769 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2770 right_path.push_back(nca);
2774 while (right_set.find(nca) == right_set.end()) {
2776 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2777 left_path.push_back(nca);
2779 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2780 left_path.push_back(nca);
2786 std::vector<int> subblossoms;
2789 prev = _graph.direct(edge, true);
2790 for (int i = 0; left_path[i] != nca; i += 2) {
2791 subblossoms.push_back(left_path[i]);
2792 (*_blossom_data)[left_path[i]].next = prev;
2793 _tree_set->erase(left_path[i]);
2795 subblossoms.push_back(left_path[i + 1]);
2796 (*_blossom_data)[left_path[i + 1]].status = EVEN;
2797 oddToEven(left_path[i + 1], tree);
2798 _tree_set->erase(left_path[i + 1]);
2799 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2803 while (right_path[k] != nca) ++k;
2805 subblossoms.push_back(nca);
2806 (*_blossom_data)[nca].next = prev;
2808 for (int i = k - 2; i >= 0; i -= 2) {
2809 subblossoms.push_back(right_path[i + 1]);
2810 (*_blossom_data)[right_path[i + 1]].status = EVEN;
2811 oddToEven(right_path[i + 1], tree);
2812 _tree_set->erase(right_path[i + 1]);
2814 (*_blossom_data)[right_path[i + 1]].next =
2815 (*_blossom_data)[right_path[i + 1]].pred;
2817 subblossoms.push_back(right_path[i]);
2818 _tree_set->erase(right_path[i]);
2822 _blossom_set->join(subblossoms.begin(), subblossoms.end());
2824 for (int i = 0; i < int(subblossoms.size()); ++i) {
2825 if (!_blossom_set->trivial(subblossoms[i])) {
2826 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2828 (*_blossom_data)[subblossoms[i]].status = MATCHED;
2831 (*_blossom_data)[surface].pot = -2 * _delta_sum;
2832 (*_blossom_data)[surface].offset = 0;
2833 (*_blossom_data)[surface].status = EVEN;
2834 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2835 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2837 _tree_set->insert(surface, tree);
2838 _tree_set->erase(nca);
2841 void splitBlossom(int blossom) {
2842 Arc next = (*_blossom_data)[blossom].next;
2843 Arc pred = (*_blossom_data)[blossom].pred;
2845 int tree = _tree_set->find(blossom);
2847 (*_blossom_data)[blossom].status = MATCHED;
2848 oddToMatched(blossom);
2849 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2850 _delta2->erase(blossom);
2853 std::vector<int> subblossoms;
2854 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2856 Value offset = (*_blossom_data)[blossom].offset;
2857 int b = _blossom_set->find(_graph.source(pred));
2858 int d = _blossom_set->find(_graph.source(next));
2860 int ib = -1, id = -1;
2861 for (int i = 0; i < int(subblossoms.size()); ++i) {
2862 if (subblossoms[i] == b) ib = i;
2863 if (subblossoms[i] == d) id = i;
2865 (*_blossom_data)[subblossoms[i]].offset = offset;
2866 if (!_blossom_set->trivial(subblossoms[i])) {
2867 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2869 if (_blossom_set->classPrio(subblossoms[i]) !=
2870 std::numeric_limits<Value>::max()) {
2871 _delta2->push(subblossoms[i],
2872 _blossom_set->classPrio(subblossoms[i]) -
2873 (*_blossom_data)[subblossoms[i]].offset);
2877 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2878 for (int i = (id + 1) % subblossoms.size();
2879 i != ib; i = (i + 2) % subblossoms.size()) {
2880 int sb = subblossoms[i];
2881 int tb = subblossoms[(i + 1) % subblossoms.size()];
2882 (*_blossom_data)[sb].next =
2883 _graph.oppositeArc((*_blossom_data)[tb].next);
2886 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2887 int sb = subblossoms[i];
2888 int tb = subblossoms[(i + 1) % subblossoms.size()];
2889 int ub = subblossoms[(i + 2) % subblossoms.size()];
2891 (*_blossom_data)[sb].status = ODD;
2893 _tree_set->insert(sb, tree);
2894 (*_blossom_data)[sb].pred = pred;
2895 (*_blossom_data)[sb].next =
2896 _graph.oppositeArc((*_blossom_data)[tb].next);
2898 pred = (*_blossom_data)[ub].next;
2900 (*_blossom_data)[tb].status = EVEN;
2901 matchedToEven(tb, tree);
2902 _tree_set->insert(tb, tree);
2903 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2906 (*_blossom_data)[subblossoms[id]].status = ODD;
2907 matchedToOdd(subblossoms[id]);
2908 _tree_set->insert(subblossoms[id], tree);
2909 (*_blossom_data)[subblossoms[id]].next = next;
2910 (*_blossom_data)[subblossoms[id]].pred = pred;
2914 for (int i = (ib + 1) % subblossoms.size();
2915 i != id; i = (i + 2) % subblossoms.size()) {
2916 int sb = subblossoms[i];
2917 int tb = subblossoms[(i + 1) % subblossoms.size()];
2918 (*_blossom_data)[sb].next =
2919 _graph.oppositeArc((*_blossom_data)[tb].next);
2922 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2923 int sb = subblossoms[i];
2924 int tb = subblossoms[(i + 1) % subblossoms.size()];
2925 int ub = subblossoms[(i + 2) % subblossoms.size()];
2927 (*_blossom_data)[sb].status = ODD;
2929 _tree_set->insert(sb, tree);
2930 (*_blossom_data)[sb].next = next;
2931 (*_blossom_data)[sb].pred =
2932 _graph.oppositeArc((*_blossom_data)[tb].next);
2934 (*_blossom_data)[tb].status = EVEN;
2935 matchedToEven(tb, tree);
2936 _tree_set->insert(tb, tree);
2937 (*_blossom_data)[tb].pred =
2938 (*_blossom_data)[tb].next =
2939 _graph.oppositeArc((*_blossom_data)[ub].next);
2940 next = (*_blossom_data)[ub].next;
2943 (*_blossom_data)[subblossoms[ib]].status = ODD;
2944 matchedToOdd(subblossoms[ib]);
2945 _tree_set->insert(subblossoms[ib], tree);
2946 (*_blossom_data)[subblossoms[ib]].next = next;
2947 (*_blossom_data)[subblossoms[ib]].pred = pred;
2949 _tree_set->erase(blossom);
2952 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2953 if (_blossom_set->trivial(blossom)) {
2954 int bi = (*_node_index)[base];
2955 Value pot = (*_node_data)[bi].pot;
2957 (*_matching)[base] = matching;
2958 _blossom_node_list.push_back(base);
2959 (*_node_potential)[base] = pot;
2962 Value pot = (*_blossom_data)[blossom].pot;
2963 int bn = _blossom_node_list.size();
2965 std::vector<int> subblossoms;
2966 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2967 int b = _blossom_set->find(base);
2969 for (int i = 0; i < int(subblossoms.size()); ++i) {
2970 if (subblossoms[i] == b) { ib = i; break; }
2973 for (int i = 1; i < int(subblossoms.size()); i += 2) {
2974 int sb = subblossoms[(ib + i) % subblossoms.size()];
2975 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2977 Arc m = (*_blossom_data)[tb].next;
2978 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2979 extractBlossom(tb, _graph.source(m), m);
2981 extractBlossom(subblossoms[ib], base, matching);
2983 int en = _blossom_node_list.size();
2985 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2989 void extractMatching() {
2990 std::vector<int> blossoms;
2991 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2992 blossoms.push_back(c);
2995 for (int i = 0; i < int(blossoms.size()); ++i) {
2997 Value offset = (*_blossom_data)[blossoms[i]].offset;
2998 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2999 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
3000 n != INVALID; ++n) {
3001 (*_node_data)[(*_node_index)[n]].pot -= offset;
3004 Arc matching = (*_blossom_data)[blossoms[i]].next;
3005 Node base = _graph.source(matching);
3006 extractBlossom(blossoms[i], base, matching);
3012 /// \brief Constructor
3015 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
3016 : _graph(graph), _weight(weight), _matching(0),
3017 _node_potential(0), _blossom_potential(), _blossom_node_list(),
3018 _node_num(0), _blossom_num(0),
3020 _blossom_index(0), _blossom_set(0), _blossom_data(0),
3021 _node_index(0), _node_heap_index(0), _node_data(0),
3022 _tree_set_index(0), _tree_set(0),
3024 _delta2_index(0), _delta2(0),
3025 _delta3_index(0), _delta3(0),
3026 _delta4_index(0), _delta4(0),
3028 _delta_sum(), _unmatched(0),
3033 ~MaxWeightedPerfectMatching() {
3034 destroyStructures();
3040 /// \name Execution Control
3041 /// The simplest way to execute the algorithm is to use the
3042 /// \ref run() member function.
3046 /// \brief Initialize the algorithm
3048 /// This function initializes the algorithm.
3052 _blossom_node_list.clear();
3053 _blossom_potential.clear();
3055 for (ArcIt e(_graph); e != INVALID; ++e) {
3056 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3058 for (EdgeIt e(_graph); e != INVALID; ++e) {
3059 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3061 for (int i = 0; i < _blossom_num; ++i) {
3062 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3063 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3066 _unmatched = _node_num;
3071 _blossom_set->clear();
3075 for (NodeIt n(_graph); n != INVALID; ++n) {
3076 Value max = - std::numeric_limits<Value>::max();
3077 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3078 if (_graph.target(e) == n) continue;
3079 if ((dualScale * _weight[e]) / 2 > max) {
3080 max = (dualScale * _weight[e]) / 2;
3083 (*_node_index)[n] = index;
3084 (*_node_data)[index].heap_index.clear();
3085 (*_node_data)[index].heap.clear();
3086 (*_node_data)[index].pot = max;
3088 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3090 _tree_set->insert(blossom);
3092 (*_blossom_data)[blossom].status = EVEN;
3093 (*_blossom_data)[blossom].pred = INVALID;
3094 (*_blossom_data)[blossom].next = INVALID;
3095 (*_blossom_data)[blossom].pot = 0;
3096 (*_blossom_data)[blossom].offset = 0;
3099 for (EdgeIt e(_graph); e != INVALID; ++e) {
3100 int si = (*_node_index)[_graph.u(e)];
3101 int ti = (*_node_index)[_graph.v(e)];
3102 if (_graph.u(e) != _graph.v(e)) {
3103 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3104 dualScale * _weight[e]) / 2);
3109 /// \brief Initialize the algorithm with fractional matching
3111 /// This function initializes the algorithm with a fractional
3112 /// matching. This initialization is also called jumpstart heuristic.
3113 void fractionalInit() {
3116 _blossom_node_list.clear();
3117 _blossom_potential.clear();
3119 if (_fractional == 0) {
3120 _fractional = new FractionalMatching(_graph, _weight, false);
3122 if (!_fractional->run()) {
3127 for (ArcIt e(_graph); e != INVALID; ++e) {
3128 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3130 for (EdgeIt e(_graph); e != INVALID; ++e) {
3131 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3133 for (int i = 0; i < _blossom_num; ++i) {
3134 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3135 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3143 _blossom_set->clear();
3147 for (NodeIt n(_graph); n != INVALID; ++n) {
3148 Value pot = _fractional->nodeValue(n);
3149 (*_node_index)[n] = index;
3150 (*_node_data)[index].pot = pot;
3151 (*_node_data)[index].heap_index.clear();
3152 (*_node_data)[index].heap.clear();
3154 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3156 (*_blossom_data)[blossom].status = MATCHED;
3157 (*_blossom_data)[blossom].pred = INVALID;
3158 (*_blossom_data)[blossom].next = _fractional->matching(n);
3159 (*_blossom_data)[blossom].pot = 0;
3160 (*_blossom_data)[blossom].offset = 0;
3164 typename Graph::template NodeMap<bool> processed(_graph, false);
3165 for (NodeIt n(_graph); n != INVALID; ++n) {
3166 if (processed[n]) continue;
3167 processed[n] = true;
3168 if (_fractional->matching(n) == INVALID) continue;
3170 Node v = _graph.target(_fractional->matching(n));
3172 processed[v] = true;
3173 v = _graph.target(_fractional->matching(v));
3178 std::vector<int> subblossoms(num);
3180 subblossoms[--num] = _blossom_set->find(n);
3181 v = _graph.target(_fractional->matching(n));
3183 subblossoms[--num] = _blossom_set->find(v);
3184 v = _graph.target(_fractional->matching(v));
3188 _blossom_set->join(subblossoms.begin(), subblossoms.end());
3189 (*_blossom_data)[surface].status = EVEN;
3190 (*_blossom_data)[surface].pred = INVALID;
3191 (*_blossom_data)[surface].next = INVALID;
3192 (*_blossom_data)[surface].pot = 0;
3193 (*_blossom_data)[surface].offset = 0;
3195 _tree_set->insert(surface);
3200 for (EdgeIt e(_graph); e != INVALID; ++e) {
3201 int si = (*_node_index)[_graph.u(e)];
3202 int sb = _blossom_set->find(_graph.u(e));
3203 int ti = (*_node_index)[_graph.v(e)];
3204 int tb = _blossom_set->find(_graph.v(e));
3205 if ((*_blossom_data)[sb].status == EVEN &&
3206 (*_blossom_data)[tb].status == EVEN && sb != tb) {
3207 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3208 dualScale * _weight[e]) / 2);
3212 for (NodeIt n(_graph); n != INVALID; ++n) {
3213 int nb = _blossom_set->find(n);
3214 if ((*_blossom_data)[nb].status != MATCHED) continue;
3215 int ni = (*_node_index)[n];
3217 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3218 Node v = _graph.target(e);
3219 int vb = _blossom_set->find(v);
3220 int vi = (*_node_index)[v];
3222 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3223 dualScale * _weight[e];
3225 if ((*_blossom_data)[vb].status == EVEN) {
3227 int vt = _tree_set->find(vb);
3229 typename std::map<int, Arc>::iterator it =
3230 (*_node_data)[ni].heap_index.find(vt);
3232 if (it != (*_node_data)[ni].heap_index.end()) {
3233 if ((*_node_data)[ni].heap[it->second] > rw) {
3234 (*_node_data)[ni].heap.replace(it->second, e);
3235 (*_node_data)[ni].heap.decrease(e, rw);
3239 (*_node_data)[ni].heap.push(e, rw);
3240 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
3245 if (!(*_node_data)[ni].heap.empty()) {
3246 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3247 _delta2->push(nb, _blossom_set->classPrio(nb));
3252 /// \brief Start the algorithm
3254 /// This function starts the algorithm.
3256 /// \pre \ref init() or \ref fractionalInit() must be called before
3257 /// using this function.
3263 if (_unmatched == -1) return false;
3265 while (_unmatched > 0) {
3266 Value d2 = !_delta2->empty() ?
3267 _delta2->prio() : std::numeric_limits<Value>::max();
3269 Value d3 = !_delta3->empty() ?
3270 _delta3->prio() : std::numeric_limits<Value>::max();
3272 Value d4 = !_delta4->empty() ?
3273 _delta4->prio() : std::numeric_limits<Value>::max();
3275 _delta_sum = d3; OpType ot = D3;
3276 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
3277 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3279 if (_delta_sum == std::numeric_limits<Value>::max()) {
3286 int blossom = _delta2->top();
3287 Node n = _blossom_set->classTop(blossom);
3288 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3294 Edge e = _delta3->top();
3296 int left_blossom = _blossom_set->find(_graph.u(e));
3297 int right_blossom = _blossom_set->find(_graph.v(e));
3299 if (left_blossom == right_blossom) {
3302 int left_tree = _tree_set->find(left_blossom);
3303 int right_tree = _tree_set->find(right_blossom);
3305 if (left_tree == right_tree) {
3306 shrinkOnEdge(e, left_tree);
3314 splitBlossom(_delta4->top());
3322 /// \brief Run the algorithm.
3324 /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3326 /// \note mwpm.run() is just a shortcut of the following code.
3328 /// mwpm.fractionalInit();
3338 /// \name Primal Solution
3339 /// Functions to get the primal solution, i.e. the maximum weighted
3340 /// perfect matching.\n
3341 /// Either \ref run() or \ref start() function should be called before
3346 /// \brief Return the weight of the matching.
3348 /// This function returns the weight of the found matching.
3350 /// \pre Either run() or start() must be called before using this function.
3351 Value matchingWeight() const {
3353 for (NodeIt n(_graph); n != INVALID; ++n) {
3354 if ((*_matching)[n] != INVALID) {
3355 sum += _weight[(*_matching)[n]];
3361 /// \brief Return \c true if the given edge is in the matching.
3363 /// This function returns \c true if the given edge is in the found
3366 /// \pre Either run() or start() must be called before using this function.
3367 bool matching(const Edge& edge) const {
3368 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3371 /// \brief Return the matching arc (or edge) incident to the given node.
3373 /// This function returns the matching arc (or edge) incident to the
3374 /// given node in the found matching or \c INVALID if the node is
3375 /// not covered by the matching.
3377 /// \pre Either run() or start() must be called before using this function.
3378 Arc matching(const Node& node) const {
3379 return (*_matching)[node];
3382 /// \brief Return a const reference to the matching map.
3384 /// This function returns a const reference to a node map that stores
3385 /// the matching arc (or edge) incident to each node.
3386 const MatchingMap& matchingMap() const {
3390 /// \brief Return the mate of the given node.
3392 /// This function returns the mate of the given node in the found
3393 /// matching or \c INVALID if the node is not covered by the matching.
3395 /// \pre Either run() or start() must be called before using this function.
3396 Node mate(const Node& node) const {
3397 return _graph.target((*_matching)[node]);
3402 /// \name Dual Solution
3403 /// Functions to get the dual solution.\n
3404 /// Either \ref run() or \ref start() function should be called before
3409 /// \brief Return the value of the dual solution.
3411 /// This function returns the value of the dual solution.
3412 /// It should be equal to the primal value scaled by \ref dualScale
3415 /// \pre Either run() or start() must be called before using this function.
3416 Value dualValue() const {
3418 for (NodeIt n(_graph); n != INVALID; ++n) {
3419 sum += nodeValue(n);
3421 for (int i = 0; i < blossomNum(); ++i) {
3422 sum += blossomValue(i) * (blossomSize(i) / 2);
3427 /// \brief Return the dual value (potential) of the given node.
3429 /// This function returns the dual value (potential) of the given node.
3431 /// \pre Either run() or start() must be called before using this function.
3432 Value nodeValue(const Node& n) const {
3433 return (*_node_potential)[n];
3436 /// \brief Return the number of the blossoms in the basis.
3438 /// This function returns the number of the blossoms in the basis.
3440 /// \pre Either run() or start() must be called before using this function.
3442 int blossomNum() const {
3443 return _blossom_potential.size();
3446 /// \brief Return the number of the nodes in the given blossom.
3448 /// This function returns the number of the nodes in the given blossom.
3450 /// \pre Either run() or start() must be called before using this function.
3452 int blossomSize(int k) const {
3453 return _blossom_potential[k].end - _blossom_potential[k].begin;
3456 /// \brief Return the dual value (ptential) of the given blossom.
3458 /// This function returns the dual value (ptential) of the given blossom.
3460 /// \pre Either run() or start() must be called before using this function.
3461 Value blossomValue(int k) const {
3462 return _blossom_potential[k].value;
3465 /// \brief Iterator for obtaining the nodes of a blossom.
3467 /// This class provides an iterator for obtaining the nodes of the
3468 /// given blossom. It lists a subset of the nodes.
3469 /// Before using this iterator, you must allocate a
3470 /// MaxWeightedPerfectMatching class and execute it.
3474 /// \brief Constructor.
3476 /// Constructor to get the nodes of the given variable.
3478 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3479 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3480 /// must be called before initializing this iterator.
3481 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3482 : _algorithm(&algorithm)
3484 _index = _algorithm->_blossom_potential[variable].begin;
3485 _last = _algorithm->_blossom_potential[variable].end;
3488 /// \brief Conversion to \c Node.
3490 /// Conversion to \c Node.
3491 operator Node() const {
3492 return _algorithm->_blossom_node_list[_index];
3495 /// \brief Increment operator.
3497 /// Increment operator.
3498 BlossomIt& operator++() {
3503 /// \brief Validity checking
3505 /// This function checks whether the iterator is invalid.
3506 bool operator==(Invalid) const { return _index == _last; }
3508 /// \brief Validity checking
3510 /// This function checks whether the iterator is valid.
3511 bool operator!=(Invalid) const { return _index != _last; }
3514 const MaxWeightedPerfectMatching* _algorithm;
3523 } //END OF NAMESPACE LEMON
3525 #endif //LEMON_MATCHING_H