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, Value _value)
747 : begin(_begin), end(-1), 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 struct ExtractBlossomItem {
1529 ExtractBlossomItem(int _blossom, Node _base,
1530 Arc _matching, int _close_index)
1531 : blossom(_blossom), base(_base), matching(_matching),
1532 close_index(_close_index) {}
1535 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1536 std::vector<ExtractBlossomItem> stack;
1537 std::vector<int> close_stack;
1538 stack.push_back(ExtractBlossomItem(blossom, base, matching, 0));
1539 while (!stack.empty()) {
1540 if (_blossom_set->trivial(stack.back().blossom)) {
1541 int bi = (*_node_index)[stack.back().base];
1542 Value pot = (*_node_data)[bi].pot;
1544 (*_matching)[stack.back().base] = stack.back().matching;
1545 (*_node_potential)[stack.back().base] = pot;
1546 _blossom_node_list.push_back(stack.back().base);
1547 while (int(close_stack.size()) > stack.back().close_index) {
1548 _blossom_potential[close_stack.back()].end = _blossom_node_list.size();
1549 close_stack.pop_back();
1553 Value pot = (*_blossom_data)[stack.back().blossom].pot;
1554 int bn = _blossom_node_list.size();
1555 close_stack.push_back(_blossom_potential.size());
1556 _blossom_potential.push_back(BlossomVariable(bn, pot));
1558 std::vector<int> subblossoms;
1559 _blossom_set->split(stack.back().blossom, std::back_inserter(subblossoms));
1560 int b = _blossom_set->find(stack.back().base);
1562 for (int i = 0; i < int(subblossoms.size()); ++i) {
1563 if (subblossoms[i] == b) { ib = i; break; }
1566 stack.back().blossom = subblossoms[ib];
1567 for (int i = 1; i < int(subblossoms.size()); i += 2) {
1568 int sb = subblossoms[(ib + i) % subblossoms.size()];
1569 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1571 Arc m = (*_blossom_data)[tb].next;
1572 stack.push_back(ExtractBlossomItem(
1573 sb, _graph.target(m), _graph.oppositeArc(m), close_stack.size()));
1574 stack.push_back(ExtractBlossomItem(
1575 tb, _graph.source(m), m, close_stack.size()));
1581 void extractMatching() {
1582 std::vector<int> blossoms;
1583 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1584 blossoms.push_back(c);
1587 for (int i = 0; i < int(blossoms.size()); ++i) {
1588 if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1590 Value offset = (*_blossom_data)[blossoms[i]].offset;
1591 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1592 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1593 n != INVALID; ++n) {
1594 (*_node_data)[(*_node_index)[n]].pot -= offset;
1597 Arc matching = (*_blossom_data)[blossoms[i]].next;
1598 Node base = _graph.source(matching);
1599 extractBlossom(blossoms[i], base, matching);
1601 Node base = (*_blossom_data)[blossoms[i]].base;
1602 extractBlossom(blossoms[i], base, INVALID);
1609 /// \brief Constructor
1612 MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1613 : _graph(graph), _weight(weight), _matching(0),
1614 _node_potential(0), _blossom_potential(), _blossom_node_list(),
1615 _node_num(0), _blossom_num(0),
1617 _blossom_index(0), _blossom_set(0), _blossom_data(0),
1618 _node_index(0), _node_heap_index(0), _node_data(0),
1619 _tree_set_index(0), _tree_set(0),
1621 _delta1_index(0), _delta1(0),
1622 _delta2_index(0), _delta2(0),
1623 _delta3_index(0), _delta3(0),
1624 _delta4_index(0), _delta4(0),
1626 _delta_sum(), _unmatched(0),
1631 ~MaxWeightedMatching() {
1632 destroyStructures();
1638 /// \name Execution Control
1639 /// The simplest way to execute the algorithm is to use the
1640 /// \ref run() member function.
1644 /// \brief Initialize the algorithm
1646 /// This function initializes the algorithm.
1650 _blossom_node_list.clear();
1651 _blossom_potential.clear();
1653 for (ArcIt e(_graph); e != INVALID; ++e) {
1654 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1656 for (NodeIt n(_graph); n != INVALID; ++n) {
1657 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1659 for (EdgeIt e(_graph); e != INVALID; ++e) {
1660 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1662 for (int i = 0; i < _blossom_num; ++i) {
1663 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1664 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1667 _unmatched = _node_num;
1673 _blossom_set->clear();
1677 for (NodeIt n(_graph); n != INVALID; ++n) {
1679 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1680 if (_graph.target(e) == n) continue;
1681 if ((dualScale * _weight[e]) / 2 > max) {
1682 max = (dualScale * _weight[e]) / 2;
1685 (*_node_index)[n] = index;
1686 (*_node_data)[index].heap_index.clear();
1687 (*_node_data)[index].heap.clear();
1688 (*_node_data)[index].pot = max;
1689 _delta1->push(n, max);
1691 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1693 _tree_set->insert(blossom);
1695 (*_blossom_data)[blossom].status = EVEN;
1696 (*_blossom_data)[blossom].pred = INVALID;
1697 (*_blossom_data)[blossom].next = INVALID;
1698 (*_blossom_data)[blossom].pot = 0;
1699 (*_blossom_data)[blossom].offset = 0;
1702 for (EdgeIt e(_graph); e != INVALID; ++e) {
1703 int si = (*_node_index)[_graph.u(e)];
1704 int ti = (*_node_index)[_graph.v(e)];
1705 if (_graph.u(e) != _graph.v(e)) {
1706 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1707 dualScale * _weight[e]) / 2);
1712 /// \brief Initialize the algorithm with fractional matching
1714 /// This function initializes the algorithm with a fractional
1715 /// matching. This initialization is also called jumpstart heuristic.
1716 void fractionalInit() {
1719 _blossom_node_list.clear();
1720 _blossom_potential.clear();
1722 if (_fractional == 0) {
1723 _fractional = new FractionalMatching(_graph, _weight, false);
1727 for (ArcIt e(_graph); e != INVALID; ++e) {
1728 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1730 for (NodeIt n(_graph); n != INVALID; ++n) {
1731 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1733 for (EdgeIt e(_graph); e != INVALID; ++e) {
1734 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1736 for (int i = 0; i < _blossom_num; ++i) {
1737 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1738 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1747 _blossom_set->clear();
1751 for (NodeIt n(_graph); n != INVALID; ++n) {
1752 Value pot = _fractional->nodeValue(n);
1753 (*_node_index)[n] = index;
1754 (*_node_data)[index].pot = pot;
1755 (*_node_data)[index].heap_index.clear();
1756 (*_node_data)[index].heap.clear();
1758 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1760 (*_blossom_data)[blossom].status = MATCHED;
1761 (*_blossom_data)[blossom].pred = INVALID;
1762 (*_blossom_data)[blossom].next = _fractional->matching(n);
1763 if (_fractional->matching(n) == INVALID) {
1764 (*_blossom_data)[blossom].base = n;
1766 (*_blossom_data)[blossom].pot = 0;
1767 (*_blossom_data)[blossom].offset = 0;
1771 typename Graph::template NodeMap<bool> processed(_graph, false);
1772 for (NodeIt n(_graph); n != INVALID; ++n) {
1773 if (processed[n]) continue;
1774 processed[n] = true;
1775 if (_fractional->matching(n) == INVALID) continue;
1777 Node v = _graph.target(_fractional->matching(n));
1779 processed[v] = true;
1780 v = _graph.target(_fractional->matching(v));
1785 std::vector<int> subblossoms(num);
1787 subblossoms[--num] = _blossom_set->find(n);
1788 _delta1->push(n, _fractional->nodeValue(n));
1789 v = _graph.target(_fractional->matching(n));
1791 subblossoms[--num] = _blossom_set->find(v);
1792 _delta1->push(v, _fractional->nodeValue(v));
1793 v = _graph.target(_fractional->matching(v));
1797 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1798 (*_blossom_data)[surface].status = EVEN;
1799 (*_blossom_data)[surface].pred = INVALID;
1800 (*_blossom_data)[surface].next = INVALID;
1801 (*_blossom_data)[surface].pot = 0;
1802 (*_blossom_data)[surface].offset = 0;
1804 _tree_set->insert(surface);
1809 for (EdgeIt e(_graph); e != INVALID; ++e) {
1810 int si = (*_node_index)[_graph.u(e)];
1811 int sb = _blossom_set->find(_graph.u(e));
1812 int ti = (*_node_index)[_graph.v(e)];
1813 int tb = _blossom_set->find(_graph.v(e));
1814 if ((*_blossom_data)[sb].status == EVEN &&
1815 (*_blossom_data)[tb].status == EVEN && sb != tb) {
1816 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1817 dualScale * _weight[e]) / 2);
1821 for (NodeIt n(_graph); n != INVALID; ++n) {
1822 int nb = _blossom_set->find(n);
1823 if ((*_blossom_data)[nb].status != MATCHED) continue;
1824 int ni = (*_node_index)[n];
1826 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1827 Node v = _graph.target(e);
1828 int vb = _blossom_set->find(v);
1829 int vi = (*_node_index)[v];
1831 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1832 dualScale * _weight[e];
1834 if ((*_blossom_data)[vb].status == EVEN) {
1836 int vt = _tree_set->find(vb);
1838 typename std::map<int, Arc>::iterator it =
1839 (*_node_data)[ni].heap_index.find(vt);
1841 if (it != (*_node_data)[ni].heap_index.end()) {
1842 if ((*_node_data)[ni].heap[it->second] > rw) {
1843 (*_node_data)[ni].heap.replace(it->second, e);
1844 (*_node_data)[ni].heap.decrease(e, rw);
1848 (*_node_data)[ni].heap.push(e, rw);
1849 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
1854 if (!(*_node_data)[ni].heap.empty()) {
1855 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1856 _delta2->push(nb, _blossom_set->classPrio(nb));
1861 /// \brief Start the algorithm
1863 /// This function starts the algorithm.
1865 /// \pre \ref init() or \ref fractionalInit() must be called
1866 /// before using this function.
1872 while (_unmatched > 0) {
1873 Value d1 = !_delta1->empty() ?
1874 _delta1->prio() : std::numeric_limits<Value>::max();
1876 Value d2 = !_delta2->empty() ?
1877 _delta2->prio() : std::numeric_limits<Value>::max();
1879 Value d3 = !_delta3->empty() ?
1880 _delta3->prio() : std::numeric_limits<Value>::max();
1882 Value d4 = !_delta4->empty() ?
1883 _delta4->prio() : std::numeric_limits<Value>::max();
1885 _delta_sum = d3; OpType ot = D3;
1886 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1887 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1888 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1893 Node n = _delta1->top();
1900 int blossom = _delta2->top();
1901 Node n = _blossom_set->classTop(blossom);
1902 Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1903 if ((*_blossom_data)[blossom].next == INVALID) {
1913 Edge e = _delta3->top();
1915 int left_blossom = _blossom_set->find(_graph.u(e));
1916 int right_blossom = _blossom_set->find(_graph.v(e));
1918 if (left_blossom == right_blossom) {
1921 int left_tree = _tree_set->find(left_blossom);
1922 int right_tree = _tree_set->find(right_blossom);
1924 if (left_tree == right_tree) {
1925 shrinkOnEdge(e, left_tree);
1933 splitBlossom(_delta4->top());
1940 /// \brief Run the algorithm.
1942 /// This method runs the \c %MaxWeightedMatching algorithm.
1944 /// \note mwm.run() is just a shortcut of the following code.
1946 /// mwm.fractionalInit();
1956 /// \name Primal Solution
1957 /// Functions to get the primal solution, i.e. the maximum weighted
1959 /// Either \ref run() or \ref start() function should be called before
1964 /// \brief Return the weight of the matching.
1966 /// This function returns the weight of the found matching.
1968 /// \pre Either run() or start() must be called before using this function.
1969 Value matchingWeight() const {
1971 for (NodeIt n(_graph); n != INVALID; ++n) {
1972 if ((*_matching)[n] != INVALID) {
1973 sum += _weight[(*_matching)[n]];
1979 /// \brief Return the size (cardinality) of the matching.
1981 /// This function returns the size (cardinality) of the found matching.
1983 /// \pre Either run() or start() must be called before using this function.
1984 int matchingSize() const {
1986 for (NodeIt n(_graph); n != INVALID; ++n) {
1987 if ((*_matching)[n] != INVALID) {
1994 /// \brief Return \c true if the given edge is in the matching.
1996 /// This function returns \c true if the given edge is in the found
1999 /// \pre Either run() or start() must be called before using this function.
2000 bool matching(const Edge& edge) const {
2001 return edge == (*_matching)[_graph.u(edge)];
2004 /// \brief Return the matching arc (or edge) incident to the given node.
2006 /// This function returns the matching arc (or edge) incident to the
2007 /// given node in the found matching or \c INVALID if the node is
2008 /// not covered by the matching.
2010 /// \pre Either run() or start() must be called before using this function.
2011 Arc matching(const Node& node) const {
2012 return (*_matching)[node];
2015 /// \brief Return a const reference to the matching map.
2017 /// This function returns a const reference to a node map that stores
2018 /// the matching arc (or edge) incident to each node.
2019 const MatchingMap& matchingMap() const {
2023 /// \brief Return the mate of the given node.
2025 /// This function returns the mate of the given node in the found
2026 /// matching or \c INVALID if the node is not covered by the matching.
2028 /// \pre Either run() or start() must be called before using this function.
2029 Node mate(const Node& node) const {
2030 return (*_matching)[node] != INVALID ?
2031 _graph.target((*_matching)[node]) : INVALID;
2036 /// \name Dual Solution
2037 /// Functions to get the dual solution.\n
2038 /// Either \ref run() or \ref start() function should be called before
2043 /// \brief Return the value of the dual solution.
2045 /// This function returns the value of the dual solution.
2046 /// It should be equal to the primal value scaled by \ref dualScale
2049 /// \pre Either run() or start() must be called before using this function.
2050 Value dualValue() const {
2052 for (NodeIt n(_graph); n != INVALID; ++n) {
2053 sum += nodeValue(n);
2055 for (int i = 0; i < blossomNum(); ++i) {
2056 sum += blossomValue(i) * (blossomSize(i) / 2);
2061 /// \brief Return the dual value (potential) of the given node.
2063 /// This function returns the dual value (potential) of the given node.
2065 /// \pre Either run() or start() must be called before using this function.
2066 Value nodeValue(const Node& n) const {
2067 return (*_node_potential)[n];
2070 /// \brief Return the number of the blossoms in the basis.
2072 /// This function returns the number of the blossoms in the basis.
2074 /// \pre Either run() or start() must be called before using this function.
2076 int blossomNum() const {
2077 return _blossom_potential.size();
2080 /// \brief Return the number of the nodes in the given blossom.
2082 /// This function returns the number of the nodes in the given blossom.
2084 /// \pre Either run() or start() must be called before using this function.
2086 int blossomSize(int k) const {
2087 return _blossom_potential[k].end - _blossom_potential[k].begin;
2090 /// \brief Return the dual value (ptential) of the given blossom.
2092 /// This function returns the dual value (ptential) of the given blossom.
2094 /// \pre Either run() or start() must be called before using this function.
2095 Value blossomValue(int k) const {
2096 return _blossom_potential[k].value;
2099 /// \brief Iterator for obtaining the nodes of a blossom.
2101 /// This class provides an iterator for obtaining the nodes of the
2102 /// given blossom. It lists a subset of the nodes.
2103 /// Before using this iterator, you must allocate a
2104 /// MaxWeightedMatching class and execute it.
2108 /// \brief Constructor.
2110 /// Constructor to get the nodes of the given variable.
2112 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2113 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
2114 /// called before initializing this iterator.
2115 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
2116 : _algorithm(&algorithm)
2118 _index = _algorithm->_blossom_potential[variable].begin;
2119 _last = _algorithm->_blossom_potential[variable].end;
2122 /// \brief Conversion to \c Node.
2124 /// Conversion to \c Node.
2125 operator Node() const {
2126 return _algorithm->_blossom_node_list[_index];
2129 /// \brief Increment operator.
2131 /// Increment operator.
2132 BlossomIt& operator++() {
2137 /// \brief Validity checking
2139 /// Checks whether the iterator is invalid.
2140 bool operator==(Invalid) const { return _index == _last; }
2142 /// \brief Validity checking
2144 /// Checks whether the iterator is valid.
2145 bool operator!=(Invalid) const { return _index != _last; }
2148 const MaxWeightedMatching* _algorithm;
2157 /// \ingroup matching
2159 /// \brief Weighted perfect matching in general graphs
2161 /// This class provides an efficient implementation of Edmond's
2162 /// maximum weighted perfect matching algorithm. The implementation
2163 /// is based on extensive use of priority queues and provides
2164 /// \f$O(nm\log n)\f$ time complexity.
2166 /// The maximum weighted perfect matching problem is to find a subset of
2167 /// the edges in an undirected graph with maximum overall weight for which
2168 /// each node has exactly one incident edge.
2169 /// It can be formulated with the following linear program.
2170 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2171 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2172 \quad \forall B\in\mathcal{O}\f] */
2173 /// \f[x_e \ge 0\quad \forall e\in E\f]
2174 /// \f[\max \sum_{e\in E}x_ew_e\f]
2175 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2176 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2177 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2178 /// subsets of the nodes.
2180 /// The algorithm calculates an optimal matching and a proof of the
2181 /// optimality. The solution of the dual problem can be used to check
2182 /// the result of the algorithm. The dual linear problem is the
2184 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2185 w_{uv} \quad \forall uv\in E\f] */
2186 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2187 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2188 \frac{\vert B \vert - 1}{2}z_B\f] */
2190 /// The algorithm can be executed with the run() function.
2191 /// After it the matching (the primal solution) and the dual solution
2192 /// can be obtained using the query functions and the
2193 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2194 /// which is able to iterate on the nodes of a blossom.
2195 /// If the value type is integer, then the dual solution is multiplied
2196 /// by \ref MaxWeightedMatching::dualScale "4".
2198 /// \tparam GR The undirected graph type the algorithm runs on.
2199 /// \tparam WM The type edge weight map. The default type is
2200 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2202 template <typename GR, typename WM>
2204 template <typename GR,
2205 typename WM = typename GR::template EdgeMap<int> >
2207 class MaxWeightedPerfectMatching {
2210 /// The graph type of the algorithm
2212 /// The type of the edge weight map
2213 typedef WM WeightMap;
2214 /// The value type of the edge weights
2215 typedef typename WeightMap::Value Value;
2217 /// \brief Scaling factor for dual solution
2219 /// Scaling factor for dual solution, it is equal to 4 or 1
2220 /// according to the value type.
2221 static const int dualScale =
2222 std::numeric_limits<Value>::is_integer ? 4 : 1;
2224 /// The type of the matching map
2225 typedef typename Graph::template NodeMap<typename Graph::Arc>
2230 TEMPLATE_GRAPH_TYPEDEFS(Graph);
2232 typedef typename Graph::template NodeMap<Value> NodePotential;
2233 typedef std::vector<Node> BlossomNodeList;
2235 struct BlossomVariable {
2239 BlossomVariable(int _begin, Value _value)
2240 : begin(_begin), value(_value) {}
2244 typedef std::vector<BlossomVariable> BlossomPotential;
2246 const Graph& _graph;
2247 const WeightMap& _weight;
2249 MatchingMap* _matching;
2251 NodePotential* _node_potential;
2253 BlossomPotential _blossom_potential;
2254 BlossomNodeList _blossom_node_list;
2259 typedef RangeMap<int> IntIntMap;
2262 EVEN = -1, MATCHED = 0, ODD = 1
2265 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2266 struct BlossomData {
2273 IntNodeMap *_blossom_index;
2274 BlossomSet *_blossom_set;
2275 RangeMap<BlossomData>* _blossom_data;
2277 IntNodeMap *_node_index;
2278 IntArcMap *_node_heap_index;
2282 NodeData(IntArcMap& node_heap_index)
2283 : heap(node_heap_index) {}
2287 BinHeap<Value, IntArcMap> heap;
2288 std::map<int, Arc> heap_index;
2293 RangeMap<NodeData>* _node_data;
2295 typedef ExtendFindEnum<IntIntMap> TreeSet;
2297 IntIntMap *_tree_set_index;
2300 IntIntMap *_delta2_index;
2301 BinHeap<Value, IntIntMap> *_delta2;
2303 IntEdgeMap *_delta3_index;
2304 BinHeap<Value, IntEdgeMap> *_delta3;
2306 IntIntMap *_delta4_index;
2307 BinHeap<Value, IntIntMap> *_delta4;
2312 typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>
2314 FractionalMatching *_fractional;
2316 void createStructures() {
2317 _node_num = countNodes(_graph);
2318 _blossom_num = _node_num * 3 / 2;
2321 _matching = new MatchingMap(_graph);
2324 if (!_node_potential) {
2325 _node_potential = new NodePotential(_graph);
2328 if (!_blossom_set) {
2329 _blossom_index = new IntNodeMap(_graph);
2330 _blossom_set = new BlossomSet(*_blossom_index);
2331 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2332 } else if (_blossom_data->size() != _blossom_num) {
2333 delete _blossom_data;
2334 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2338 _node_index = new IntNodeMap(_graph);
2339 _node_heap_index = new IntArcMap(_graph);
2340 _node_data = new RangeMap<NodeData>(_node_num,
2341 NodeData(*_node_heap_index));
2342 } else if (_node_data->size() != _node_num) {
2344 _node_data = new RangeMap<NodeData>(_node_num,
2345 NodeData(*_node_heap_index));
2349 _tree_set_index = new IntIntMap(_blossom_num);
2350 _tree_set = new TreeSet(*_tree_set_index);
2352 _tree_set_index->resize(_blossom_num);
2356 _delta2_index = new IntIntMap(_blossom_num);
2357 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2359 _delta2_index->resize(_blossom_num);
2363 _delta3_index = new IntEdgeMap(_graph);
2364 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2368 _delta4_index = new IntIntMap(_blossom_num);
2369 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2371 _delta4_index->resize(_blossom_num);
2375 void destroyStructures() {
2379 if (_node_potential) {
2380 delete _node_potential;
2383 delete _blossom_index;
2384 delete _blossom_set;
2385 delete _blossom_data;
2390 delete _node_heap_index;
2395 delete _tree_set_index;
2399 delete _delta2_index;
2403 delete _delta3_index;
2407 delete _delta4_index;
2412 void matchedToEven(int blossom, int tree) {
2413 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2414 _delta2->erase(blossom);
2417 if (!_blossom_set->trivial(blossom)) {
2418 (*_blossom_data)[blossom].pot -=
2419 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2422 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2423 n != INVALID; ++n) {
2425 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2426 int ni = (*_node_index)[n];
2428 (*_node_data)[ni].heap.clear();
2429 (*_node_data)[ni].heap_index.clear();
2431 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2433 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2434 Node v = _graph.source(e);
2435 int vb = _blossom_set->find(v);
2436 int vi = (*_node_index)[v];
2438 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2439 dualScale * _weight[e];
2441 if ((*_blossom_data)[vb].status == EVEN) {
2442 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2443 _delta3->push(e, rw / 2);
2446 typename std::map<int, Arc>::iterator it =
2447 (*_node_data)[vi].heap_index.find(tree);
2449 if (it != (*_node_data)[vi].heap_index.end()) {
2450 if ((*_node_data)[vi].heap[it->second] > rw) {
2451 (*_node_data)[vi].heap.replace(it->second, e);
2452 (*_node_data)[vi].heap.decrease(e, rw);
2456 (*_node_data)[vi].heap.push(e, rw);
2457 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2460 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2461 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2463 if ((*_blossom_data)[vb].status == MATCHED) {
2464 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2465 _delta2->push(vb, _blossom_set->classPrio(vb) -
2466 (*_blossom_data)[vb].offset);
2467 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2468 (*_blossom_data)[vb].offset){
2469 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2470 (*_blossom_data)[vb].offset);
2477 (*_blossom_data)[blossom].offset = 0;
2480 void matchedToOdd(int blossom) {
2481 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2482 _delta2->erase(blossom);
2484 (*_blossom_data)[blossom].offset += _delta_sum;
2485 if (!_blossom_set->trivial(blossom)) {
2486 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2487 (*_blossom_data)[blossom].offset);
2491 void evenToMatched(int blossom, int tree) {
2492 if (!_blossom_set->trivial(blossom)) {
2493 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2496 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2497 n != INVALID; ++n) {
2498 int ni = (*_node_index)[n];
2499 (*_node_data)[ni].pot -= _delta_sum;
2501 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2502 Node v = _graph.source(e);
2503 int vb = _blossom_set->find(v);
2504 int vi = (*_node_index)[v];
2506 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2507 dualScale * _weight[e];
2509 if (vb == blossom) {
2510 if (_delta3->state(e) == _delta3->IN_HEAP) {
2513 } else if ((*_blossom_data)[vb].status == EVEN) {
2515 if (_delta3->state(e) == _delta3->IN_HEAP) {
2519 int vt = _tree_set->find(vb);
2523 Arc r = _graph.oppositeArc(e);
2525 typename std::map<int, Arc>::iterator it =
2526 (*_node_data)[ni].heap_index.find(vt);
2528 if (it != (*_node_data)[ni].heap_index.end()) {
2529 if ((*_node_data)[ni].heap[it->second] > rw) {
2530 (*_node_data)[ni].heap.replace(it->second, r);
2531 (*_node_data)[ni].heap.decrease(r, rw);
2535 (*_node_data)[ni].heap.push(r, rw);
2536 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2539 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2540 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2542 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2543 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2544 (*_blossom_data)[blossom].offset);
2545 } else if ((*_delta2)[blossom] >
2546 _blossom_set->classPrio(blossom) -
2547 (*_blossom_data)[blossom].offset){
2548 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2549 (*_blossom_data)[blossom].offset);
2555 typename std::map<int, Arc>::iterator it =
2556 (*_node_data)[vi].heap_index.find(tree);
2558 if (it != (*_node_data)[vi].heap_index.end()) {
2559 (*_node_data)[vi].heap.erase(it->second);
2560 (*_node_data)[vi].heap_index.erase(it);
2561 if ((*_node_data)[vi].heap.empty()) {
2562 _blossom_set->increase(v, std::numeric_limits<Value>::max());
2563 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2564 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2567 if ((*_blossom_data)[vb].status == MATCHED) {
2568 if (_blossom_set->classPrio(vb) ==
2569 std::numeric_limits<Value>::max()) {
2571 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2572 (*_blossom_data)[vb].offset) {
2573 _delta2->increase(vb, _blossom_set->classPrio(vb) -
2574 (*_blossom_data)[vb].offset);
2583 void oddToMatched(int blossom) {
2584 (*_blossom_data)[blossom].offset -= _delta_sum;
2586 if (_blossom_set->classPrio(blossom) !=
2587 std::numeric_limits<Value>::max()) {
2588 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2589 (*_blossom_data)[blossom].offset);
2592 if (!_blossom_set->trivial(blossom)) {
2593 _delta4->erase(blossom);
2597 void oddToEven(int blossom, int tree) {
2598 if (!_blossom_set->trivial(blossom)) {
2599 _delta4->erase(blossom);
2600 (*_blossom_data)[blossom].pot -=
2601 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2604 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2605 n != INVALID; ++n) {
2606 int ni = (*_node_index)[n];
2608 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2610 (*_node_data)[ni].heap.clear();
2611 (*_node_data)[ni].heap_index.clear();
2612 (*_node_data)[ni].pot +=
2613 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2615 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2616 Node v = _graph.source(e);
2617 int vb = _blossom_set->find(v);
2618 int vi = (*_node_index)[v];
2620 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2621 dualScale * _weight[e];
2623 if ((*_blossom_data)[vb].status == EVEN) {
2624 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2625 _delta3->push(e, rw / 2);
2629 typename std::map<int, Arc>::iterator it =
2630 (*_node_data)[vi].heap_index.find(tree);
2632 if (it != (*_node_data)[vi].heap_index.end()) {
2633 if ((*_node_data)[vi].heap[it->second] > rw) {
2634 (*_node_data)[vi].heap.replace(it->second, e);
2635 (*_node_data)[vi].heap.decrease(e, rw);
2639 (*_node_data)[vi].heap.push(e, rw);
2640 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2643 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2644 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2646 if ((*_blossom_data)[vb].status == MATCHED) {
2647 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2648 _delta2->push(vb, _blossom_set->classPrio(vb) -
2649 (*_blossom_data)[vb].offset);
2650 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2651 (*_blossom_data)[vb].offset) {
2652 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2653 (*_blossom_data)[vb].offset);
2660 (*_blossom_data)[blossom].offset = 0;
2663 void alternatePath(int even, int tree) {
2666 evenToMatched(even, tree);
2667 (*_blossom_data)[even].status = MATCHED;
2669 while ((*_blossom_data)[even].pred != INVALID) {
2670 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2671 (*_blossom_data)[odd].status = MATCHED;
2673 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2675 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2676 (*_blossom_data)[even].status = MATCHED;
2677 evenToMatched(even, tree);
2678 (*_blossom_data)[even].next =
2679 _graph.oppositeArc((*_blossom_data)[odd].pred);
2684 void destroyTree(int tree) {
2685 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2686 if ((*_blossom_data)[b].status == EVEN) {
2687 (*_blossom_data)[b].status = MATCHED;
2688 evenToMatched(b, tree);
2689 } else if ((*_blossom_data)[b].status == ODD) {
2690 (*_blossom_data)[b].status = MATCHED;
2694 _tree_set->eraseClass(tree);
2697 void augmentOnEdge(const Edge& edge) {
2699 int left = _blossom_set->find(_graph.u(edge));
2700 int right = _blossom_set->find(_graph.v(edge));
2702 int left_tree = _tree_set->find(left);
2703 alternatePath(left, left_tree);
2704 destroyTree(left_tree);
2706 int right_tree = _tree_set->find(right);
2707 alternatePath(right, right_tree);
2708 destroyTree(right_tree);
2710 (*_blossom_data)[left].next = _graph.direct(edge, true);
2711 (*_blossom_data)[right].next = _graph.direct(edge, false);
2714 void extendOnArc(const Arc& arc) {
2715 int base = _blossom_set->find(_graph.target(arc));
2716 int tree = _tree_set->find(base);
2718 int odd = _blossom_set->find(_graph.source(arc));
2719 _tree_set->insert(odd, tree);
2720 (*_blossom_data)[odd].status = ODD;
2722 (*_blossom_data)[odd].pred = arc;
2724 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2725 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2726 _tree_set->insert(even, tree);
2727 (*_blossom_data)[even].status = EVEN;
2728 matchedToEven(even, tree);
2731 void shrinkOnEdge(const Edge& edge, int tree) {
2733 std::vector<int> left_path, right_path;
2736 std::set<int> left_set, right_set;
2737 int left = _blossom_set->find(_graph.u(edge));
2738 left_path.push_back(left);
2739 left_set.insert(left);
2741 int right = _blossom_set->find(_graph.v(edge));
2742 right_path.push_back(right);
2743 right_set.insert(right);
2747 if ((*_blossom_data)[left].pred == INVALID) break;
2750 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2751 left_path.push_back(left);
2753 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2754 left_path.push_back(left);
2756 left_set.insert(left);
2758 if (right_set.find(left) != right_set.end()) {
2763 if ((*_blossom_data)[right].pred == INVALID) break;
2766 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2767 right_path.push_back(right);
2769 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2770 right_path.push_back(right);
2772 right_set.insert(right);
2774 if (left_set.find(right) != left_set.end()) {
2782 if ((*_blossom_data)[left].pred == INVALID) {
2784 while (left_set.find(nca) == left_set.end()) {
2786 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2787 right_path.push_back(nca);
2789 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2790 right_path.push_back(nca);
2794 while (right_set.find(nca) == right_set.end()) {
2796 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2797 left_path.push_back(nca);
2799 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2800 left_path.push_back(nca);
2806 std::vector<int> subblossoms;
2809 prev = _graph.direct(edge, true);
2810 for (int i = 0; left_path[i] != nca; i += 2) {
2811 subblossoms.push_back(left_path[i]);
2812 (*_blossom_data)[left_path[i]].next = prev;
2813 _tree_set->erase(left_path[i]);
2815 subblossoms.push_back(left_path[i + 1]);
2816 (*_blossom_data)[left_path[i + 1]].status = EVEN;
2817 oddToEven(left_path[i + 1], tree);
2818 _tree_set->erase(left_path[i + 1]);
2819 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2823 while (right_path[k] != nca) ++k;
2825 subblossoms.push_back(nca);
2826 (*_blossom_data)[nca].next = prev;
2828 for (int i = k - 2; i >= 0; i -= 2) {
2829 subblossoms.push_back(right_path[i + 1]);
2830 (*_blossom_data)[right_path[i + 1]].status = EVEN;
2831 oddToEven(right_path[i + 1], tree);
2832 _tree_set->erase(right_path[i + 1]);
2834 (*_blossom_data)[right_path[i + 1]].next =
2835 (*_blossom_data)[right_path[i + 1]].pred;
2837 subblossoms.push_back(right_path[i]);
2838 _tree_set->erase(right_path[i]);
2842 _blossom_set->join(subblossoms.begin(), subblossoms.end());
2844 for (int i = 0; i < int(subblossoms.size()); ++i) {
2845 if (!_blossom_set->trivial(subblossoms[i])) {
2846 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2848 (*_blossom_data)[subblossoms[i]].status = MATCHED;
2851 (*_blossom_data)[surface].pot = -2 * _delta_sum;
2852 (*_blossom_data)[surface].offset = 0;
2853 (*_blossom_data)[surface].status = EVEN;
2854 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2855 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2857 _tree_set->insert(surface, tree);
2858 _tree_set->erase(nca);
2861 void splitBlossom(int blossom) {
2862 Arc next = (*_blossom_data)[blossom].next;
2863 Arc pred = (*_blossom_data)[blossom].pred;
2865 int tree = _tree_set->find(blossom);
2867 (*_blossom_data)[blossom].status = MATCHED;
2868 oddToMatched(blossom);
2869 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2870 _delta2->erase(blossom);
2873 std::vector<int> subblossoms;
2874 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2876 Value offset = (*_blossom_data)[blossom].offset;
2877 int b = _blossom_set->find(_graph.source(pred));
2878 int d = _blossom_set->find(_graph.source(next));
2880 int ib = -1, id = -1;
2881 for (int i = 0; i < int(subblossoms.size()); ++i) {
2882 if (subblossoms[i] == b) ib = i;
2883 if (subblossoms[i] == d) id = i;
2885 (*_blossom_data)[subblossoms[i]].offset = offset;
2886 if (!_blossom_set->trivial(subblossoms[i])) {
2887 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2889 if (_blossom_set->classPrio(subblossoms[i]) !=
2890 std::numeric_limits<Value>::max()) {
2891 _delta2->push(subblossoms[i],
2892 _blossom_set->classPrio(subblossoms[i]) -
2893 (*_blossom_data)[subblossoms[i]].offset);
2897 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2898 for (int i = (id + 1) % subblossoms.size();
2899 i != ib; i = (i + 2) % subblossoms.size()) {
2900 int sb = subblossoms[i];
2901 int tb = subblossoms[(i + 1) % subblossoms.size()];
2902 (*_blossom_data)[sb].next =
2903 _graph.oppositeArc((*_blossom_data)[tb].next);
2906 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2907 int sb = subblossoms[i];
2908 int tb = subblossoms[(i + 1) % subblossoms.size()];
2909 int ub = subblossoms[(i + 2) % subblossoms.size()];
2911 (*_blossom_data)[sb].status = ODD;
2913 _tree_set->insert(sb, tree);
2914 (*_blossom_data)[sb].pred = pred;
2915 (*_blossom_data)[sb].next =
2916 _graph.oppositeArc((*_blossom_data)[tb].next);
2918 pred = (*_blossom_data)[ub].next;
2920 (*_blossom_data)[tb].status = EVEN;
2921 matchedToEven(tb, tree);
2922 _tree_set->insert(tb, tree);
2923 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2926 (*_blossom_data)[subblossoms[id]].status = ODD;
2927 matchedToOdd(subblossoms[id]);
2928 _tree_set->insert(subblossoms[id], tree);
2929 (*_blossom_data)[subblossoms[id]].next = next;
2930 (*_blossom_data)[subblossoms[id]].pred = pred;
2934 for (int i = (ib + 1) % subblossoms.size();
2935 i != id; i = (i + 2) % subblossoms.size()) {
2936 int sb = subblossoms[i];
2937 int tb = subblossoms[(i + 1) % subblossoms.size()];
2938 (*_blossom_data)[sb].next =
2939 _graph.oppositeArc((*_blossom_data)[tb].next);
2942 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2943 int sb = subblossoms[i];
2944 int tb = subblossoms[(i + 1) % subblossoms.size()];
2945 int ub = subblossoms[(i + 2) % subblossoms.size()];
2947 (*_blossom_data)[sb].status = ODD;
2949 _tree_set->insert(sb, tree);
2950 (*_blossom_data)[sb].next = next;
2951 (*_blossom_data)[sb].pred =
2952 _graph.oppositeArc((*_blossom_data)[tb].next);
2954 (*_blossom_data)[tb].status = EVEN;
2955 matchedToEven(tb, tree);
2956 _tree_set->insert(tb, tree);
2957 (*_blossom_data)[tb].pred =
2958 (*_blossom_data)[tb].next =
2959 _graph.oppositeArc((*_blossom_data)[ub].next);
2960 next = (*_blossom_data)[ub].next;
2963 (*_blossom_data)[subblossoms[ib]].status = ODD;
2964 matchedToOdd(subblossoms[ib]);
2965 _tree_set->insert(subblossoms[ib], tree);
2966 (*_blossom_data)[subblossoms[ib]].next = next;
2967 (*_blossom_data)[subblossoms[ib]].pred = pred;
2969 _tree_set->erase(blossom);
2972 struct ExtractBlossomItem {
2977 ExtractBlossomItem(int _blossom, Node _base,
2978 Arc _matching, int _close_index)
2979 : blossom(_blossom), base(_base), matching(_matching),
2980 close_index(_close_index) {}
2983 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2984 std::vector<ExtractBlossomItem> stack;
2985 std::vector<int> close_stack;
2986 stack.push_back(ExtractBlossomItem(blossom, base, matching, 0));
2987 while (!stack.empty()) {
2988 if (_blossom_set->trivial(stack.back().blossom)) {
2989 int bi = (*_node_index)[stack.back().base];
2990 Value pot = (*_node_data)[bi].pot;
2992 (*_matching)[stack.back().base] = stack.back().matching;
2993 (*_node_potential)[stack.back().base] = pot;
2994 _blossom_node_list.push_back(stack.back().base);
2995 while (int(close_stack.size()) > stack.back().close_index) {
2996 _blossom_potential[close_stack.back()].end = _blossom_node_list.size();
2997 close_stack.pop_back();
3001 Value pot = (*_blossom_data)[stack.back().blossom].pot;
3002 int bn = _blossom_node_list.size();
3003 close_stack.push_back(_blossom_potential.size());
3004 _blossom_potential.push_back(BlossomVariable(bn, pot));
3006 std::vector<int> subblossoms;
3007 _blossom_set->split(stack.back().blossom, std::back_inserter(subblossoms));
3008 int b = _blossom_set->find(stack.back().base);
3010 for (int i = 0; i < int(subblossoms.size()); ++i) {
3011 if (subblossoms[i] == b) { ib = i; break; }
3014 stack.back().blossom = subblossoms[ib];
3015 for (int i = 1; i < int(subblossoms.size()); i += 2) {
3016 int sb = subblossoms[(ib + i) % subblossoms.size()];
3017 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
3019 Arc m = (*_blossom_data)[tb].next;
3020 stack.push_back(ExtractBlossomItem(
3021 sb, _graph.target(m), _graph.oppositeArc(m), close_stack.size()));
3022 stack.push_back(ExtractBlossomItem(
3023 tb, _graph.source(m), m, close_stack.size()));
3029 void extractMatching() {
3030 std::vector<int> blossoms;
3031 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
3032 blossoms.push_back(c);
3035 for (int i = 0; i < int(blossoms.size()); ++i) {
3037 Value offset = (*_blossom_data)[blossoms[i]].offset;
3038 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
3039 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
3040 n != INVALID; ++n) {
3041 (*_node_data)[(*_node_index)[n]].pot -= offset;
3044 Arc matching = (*_blossom_data)[blossoms[i]].next;
3045 Node base = _graph.source(matching);
3046 extractBlossom(blossoms[i], base, matching);
3052 /// \brief Constructor
3055 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
3056 : _graph(graph), _weight(weight), _matching(0),
3057 _node_potential(0), _blossom_potential(), _blossom_node_list(),
3058 _node_num(0), _blossom_num(0),
3060 _blossom_index(0), _blossom_set(0), _blossom_data(0),
3061 _node_index(0), _node_heap_index(0), _node_data(0),
3062 _tree_set_index(0), _tree_set(0),
3064 _delta2_index(0), _delta2(0),
3065 _delta3_index(0), _delta3(0),
3066 _delta4_index(0), _delta4(0),
3068 _delta_sum(), _unmatched(0),
3073 ~MaxWeightedPerfectMatching() {
3074 destroyStructures();
3080 /// \name Execution Control
3081 /// The simplest way to execute the algorithm is to use the
3082 /// \ref run() member function.
3086 /// \brief Initialize the algorithm
3088 /// This function initializes the algorithm.
3092 _blossom_node_list.clear();
3093 _blossom_potential.clear();
3095 for (ArcIt e(_graph); e != INVALID; ++e) {
3096 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3098 for (EdgeIt e(_graph); e != INVALID; ++e) {
3099 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3101 for (int i = 0; i < _blossom_num; ++i) {
3102 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3103 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3106 _unmatched = _node_num;
3111 _blossom_set->clear();
3115 for (NodeIt n(_graph); n != INVALID; ++n) {
3116 Value max = - std::numeric_limits<Value>::max();
3117 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3118 if (_graph.target(e) == n) continue;
3119 if ((dualScale * _weight[e]) / 2 > max) {
3120 max = (dualScale * _weight[e]) / 2;
3123 (*_node_index)[n] = index;
3124 (*_node_data)[index].heap_index.clear();
3125 (*_node_data)[index].heap.clear();
3126 (*_node_data)[index].pot = max;
3128 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3130 _tree_set->insert(blossom);
3132 (*_blossom_data)[blossom].status = EVEN;
3133 (*_blossom_data)[blossom].pred = INVALID;
3134 (*_blossom_data)[blossom].next = INVALID;
3135 (*_blossom_data)[blossom].pot = 0;
3136 (*_blossom_data)[blossom].offset = 0;
3139 for (EdgeIt e(_graph); e != INVALID; ++e) {
3140 int si = (*_node_index)[_graph.u(e)];
3141 int ti = (*_node_index)[_graph.v(e)];
3142 if (_graph.u(e) != _graph.v(e)) {
3143 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3144 dualScale * _weight[e]) / 2);
3149 /// \brief Initialize the algorithm with fractional matching
3151 /// This function initializes the algorithm with a fractional
3152 /// matching. This initialization is also called jumpstart heuristic.
3153 void fractionalInit() {
3156 _blossom_node_list.clear();
3157 _blossom_potential.clear();
3159 if (_fractional == 0) {
3160 _fractional = new FractionalMatching(_graph, _weight, false);
3162 if (!_fractional->run()) {
3167 for (ArcIt e(_graph); e != INVALID; ++e) {
3168 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3170 for (EdgeIt e(_graph); e != INVALID; ++e) {
3171 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3173 for (int i = 0; i < _blossom_num; ++i) {
3174 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3175 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3183 _blossom_set->clear();
3187 for (NodeIt n(_graph); n != INVALID; ++n) {
3188 Value pot = _fractional->nodeValue(n);
3189 (*_node_index)[n] = index;
3190 (*_node_data)[index].pot = pot;
3191 (*_node_data)[index].heap_index.clear();
3192 (*_node_data)[index].heap.clear();
3194 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3196 (*_blossom_data)[blossom].status = MATCHED;
3197 (*_blossom_data)[blossom].pred = INVALID;
3198 (*_blossom_data)[blossom].next = _fractional->matching(n);
3199 (*_blossom_data)[blossom].pot = 0;
3200 (*_blossom_data)[blossom].offset = 0;
3204 typename Graph::template NodeMap<bool> processed(_graph, false);
3205 for (NodeIt n(_graph); n != INVALID; ++n) {
3206 if (processed[n]) continue;
3207 processed[n] = true;
3208 if (_fractional->matching(n) == INVALID) continue;
3210 Node v = _graph.target(_fractional->matching(n));
3212 processed[v] = true;
3213 v = _graph.target(_fractional->matching(v));
3218 std::vector<int> subblossoms(num);
3220 subblossoms[--num] = _blossom_set->find(n);
3221 v = _graph.target(_fractional->matching(n));
3223 subblossoms[--num] = _blossom_set->find(v);
3224 v = _graph.target(_fractional->matching(v));
3228 _blossom_set->join(subblossoms.begin(), subblossoms.end());
3229 (*_blossom_data)[surface].status = EVEN;
3230 (*_blossom_data)[surface].pred = INVALID;
3231 (*_blossom_data)[surface].next = INVALID;
3232 (*_blossom_data)[surface].pot = 0;
3233 (*_blossom_data)[surface].offset = 0;
3235 _tree_set->insert(surface);
3240 for (EdgeIt e(_graph); e != INVALID; ++e) {
3241 int si = (*_node_index)[_graph.u(e)];
3242 int sb = _blossom_set->find(_graph.u(e));
3243 int ti = (*_node_index)[_graph.v(e)];
3244 int tb = _blossom_set->find(_graph.v(e));
3245 if ((*_blossom_data)[sb].status == EVEN &&
3246 (*_blossom_data)[tb].status == EVEN && sb != tb) {
3247 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3248 dualScale * _weight[e]) / 2);
3252 for (NodeIt n(_graph); n != INVALID; ++n) {
3253 int nb = _blossom_set->find(n);
3254 if ((*_blossom_data)[nb].status != MATCHED) continue;
3255 int ni = (*_node_index)[n];
3257 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3258 Node v = _graph.target(e);
3259 int vb = _blossom_set->find(v);
3260 int vi = (*_node_index)[v];
3262 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3263 dualScale * _weight[e];
3265 if ((*_blossom_data)[vb].status == EVEN) {
3267 int vt = _tree_set->find(vb);
3269 typename std::map<int, Arc>::iterator it =
3270 (*_node_data)[ni].heap_index.find(vt);
3272 if (it != (*_node_data)[ni].heap_index.end()) {
3273 if ((*_node_data)[ni].heap[it->second] > rw) {
3274 (*_node_data)[ni].heap.replace(it->second, e);
3275 (*_node_data)[ni].heap.decrease(e, rw);
3279 (*_node_data)[ni].heap.push(e, rw);
3280 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
3285 if (!(*_node_data)[ni].heap.empty()) {
3286 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3287 _delta2->push(nb, _blossom_set->classPrio(nb));
3292 /// \brief Start the algorithm
3294 /// This function starts the algorithm.
3296 /// \pre \ref init() or \ref fractionalInit() must be called before
3297 /// using this function.
3303 if (_unmatched == -1) return false;
3305 while (_unmatched > 0) {
3306 Value d2 = !_delta2->empty() ?
3307 _delta2->prio() : std::numeric_limits<Value>::max();
3309 Value d3 = !_delta3->empty() ?
3310 _delta3->prio() : std::numeric_limits<Value>::max();
3312 Value d4 = !_delta4->empty() ?
3313 _delta4->prio() : std::numeric_limits<Value>::max();
3315 _delta_sum = d3; OpType ot = D3;
3316 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
3317 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3319 if (_delta_sum == std::numeric_limits<Value>::max()) {
3326 int blossom = _delta2->top();
3327 Node n = _blossom_set->classTop(blossom);
3328 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3334 Edge e = _delta3->top();
3336 int left_blossom = _blossom_set->find(_graph.u(e));
3337 int right_blossom = _blossom_set->find(_graph.v(e));
3339 if (left_blossom == right_blossom) {
3342 int left_tree = _tree_set->find(left_blossom);
3343 int right_tree = _tree_set->find(right_blossom);
3345 if (left_tree == right_tree) {
3346 shrinkOnEdge(e, left_tree);
3354 splitBlossom(_delta4->top());
3362 /// \brief Run the algorithm.
3364 /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3366 /// \note mwpm.run() is just a shortcut of the following code.
3368 /// mwpm.fractionalInit();
3378 /// \name Primal Solution
3379 /// Functions to get the primal solution, i.e. the maximum weighted
3380 /// perfect matching.\n
3381 /// Either \ref run() or \ref start() function should be called before
3386 /// \brief Return the weight of the matching.
3388 /// This function returns the weight of the found matching.
3390 /// \pre Either run() or start() must be called before using this function.
3391 Value matchingWeight() const {
3393 for (NodeIt n(_graph); n != INVALID; ++n) {
3394 if ((*_matching)[n] != INVALID) {
3395 sum += _weight[(*_matching)[n]];
3401 /// \brief Return \c true if the given edge is in the matching.
3403 /// This function returns \c true if the given edge is in the found
3406 /// \pre Either run() or start() must be called before using this function.
3407 bool matching(const Edge& edge) const {
3408 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3411 /// \brief Return the matching arc (or edge) incident to the given node.
3413 /// This function returns the matching arc (or edge) incident to the
3414 /// given node in the found matching or \c INVALID if the node is
3415 /// not covered by the matching.
3417 /// \pre Either run() or start() must be called before using this function.
3418 Arc matching(const Node& node) const {
3419 return (*_matching)[node];
3422 /// \brief Return a const reference to the matching map.
3424 /// This function returns a const reference to a node map that stores
3425 /// the matching arc (or edge) incident to each node.
3426 const MatchingMap& matchingMap() const {
3430 /// \brief Return the mate of the given node.
3432 /// This function returns the mate of the given node in the found
3433 /// matching or \c INVALID if the node is not covered by the matching.
3435 /// \pre Either run() or start() must be called before using this function.
3436 Node mate(const Node& node) const {
3437 return _graph.target((*_matching)[node]);
3442 /// \name Dual Solution
3443 /// Functions to get the dual solution.\n
3444 /// Either \ref run() or \ref start() function should be called before
3449 /// \brief Return the value of the dual solution.
3451 /// This function returns the value of the dual solution.
3452 /// It should be equal to the primal value scaled by \ref dualScale
3455 /// \pre Either run() or start() must be called before using this function.
3456 Value dualValue() const {
3458 for (NodeIt n(_graph); n != INVALID; ++n) {
3459 sum += nodeValue(n);
3461 for (int i = 0; i < blossomNum(); ++i) {
3462 sum += blossomValue(i) * (blossomSize(i) / 2);
3467 /// \brief Return the dual value (potential) of the given node.
3469 /// This function returns the dual value (potential) of the given node.
3471 /// \pre Either run() or start() must be called before using this function.
3472 Value nodeValue(const Node& n) const {
3473 return (*_node_potential)[n];
3476 /// \brief Return the number of the blossoms in the basis.
3478 /// This function returns the number of the blossoms in the basis.
3480 /// \pre Either run() or start() must be called before using this function.
3482 int blossomNum() const {
3483 return _blossom_potential.size();
3486 /// \brief Return the number of the nodes in the given blossom.
3488 /// This function returns the number of the nodes in the given blossom.
3490 /// \pre Either run() or start() must be called before using this function.
3492 int blossomSize(int k) const {
3493 return _blossom_potential[k].end - _blossom_potential[k].begin;
3496 /// \brief Return the dual value (ptential) of the given blossom.
3498 /// This function returns the dual value (ptential) of the given blossom.
3500 /// \pre Either run() or start() must be called before using this function.
3501 Value blossomValue(int k) const {
3502 return _blossom_potential[k].value;
3505 /// \brief Iterator for obtaining the nodes of a blossom.
3507 /// This class provides an iterator for obtaining the nodes of the
3508 /// given blossom. It lists a subset of the nodes.
3509 /// Before using this iterator, you must allocate a
3510 /// MaxWeightedPerfectMatching class and execute it.
3514 /// \brief Constructor.
3516 /// Constructor to get the nodes of the given variable.
3518 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3519 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3520 /// must be called before initializing this iterator.
3521 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3522 : _algorithm(&algorithm)
3524 _index = _algorithm->_blossom_potential[variable].begin;
3525 _last = _algorithm->_blossom_potential[variable].end;
3528 /// \brief Conversion to \c Node.
3530 /// Conversion to \c Node.
3531 operator Node() const {
3532 return _algorithm->_blossom_node_list[_index];
3535 /// \brief Increment operator.
3537 /// Increment operator.
3538 BlossomIt& operator++() {
3543 /// \brief Validity checking
3545 /// This function checks whether the iterator is invalid.
3546 bool operator==(Invalid) const { return _index == _last; }
3548 /// \brief Validity checking
3550 /// This function checks whether the iterator is valid.
3551 bool operator!=(Invalid) const { return _index != _last; }
3554 const MaxWeightedPerfectMatching* _algorithm;
3563 } //END OF NAMESPACE LEMON
3565 #endif //LEMON_MATCHING_H