1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
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;
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) {
187 while (_postpone != _last) {
188 Node u = _node_queue[_postpone++];
190 for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
191 Node v = _graph.target(a);
193 if ((*_status)[v] == EVEN) {
194 if (_blossom_set->find(u) != _blossom_set->find(v)) {
199 while (_process != _last) {
200 Node w = _node_queue[_process++];
201 for (OutArcIt b(_graph, w); b != INVALID; ++b) {
202 Node x = _graph.target(b);
203 if ((*_status)[x] == MATCHED) {
205 } else if ((*_status)[x] == UNMATCHED) {
215 void processSparse(const Node& n) {
216 _process = _last = 0;
217 _node_queue[_last++] = n;
218 while (_process != _last) {
219 Node u = _node_queue[_process++];
220 for (OutArcIt a(_graph, u); a != INVALID; ++a) {
221 Node v = _graph.target(a);
223 if ((*_status)[v] == EVEN) {
224 if (_blossom_set->find(u) != _blossom_set->find(v)) {
227 } else if ((*_status)[v] == MATCHED) {
229 } else if ((*_status)[v] == UNMATCHED) {
237 void shrinkOnEdge(const Edge& e) {
241 std::set<Node> left_set, right_set;
243 Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
244 left_set.insert(left);
246 Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
247 right_set.insert(right);
250 if ((*_matching)[left] == INVALID) break;
251 left = _graph.target((*_matching)[left]);
252 left = (*_blossom_rep)[_blossom_set->
253 find(_graph.target((*_ear)[left]))];
254 if (right_set.find(left) != right_set.end()) {
258 left_set.insert(left);
260 if ((*_matching)[right] == INVALID) break;
261 right = _graph.target((*_matching)[right]);
262 right = (*_blossom_rep)[_blossom_set->
263 find(_graph.target((*_ear)[right]))];
264 if (left_set.find(right) != left_set.end()) {
268 right_set.insert(right);
271 if (nca == INVALID) {
272 if ((*_matching)[left] == INVALID) {
274 while (left_set.find(nca) == left_set.end()) {
275 nca = _graph.target((*_matching)[nca]);
276 nca =(*_blossom_rep)[_blossom_set->
277 find(_graph.target((*_ear)[nca]))];
281 while (right_set.find(nca) == right_set.end()) {
282 nca = _graph.target((*_matching)[nca]);
283 nca = (*_blossom_rep)[_blossom_set->
284 find(_graph.target((*_ear)[nca]))];
292 Node node = _graph.u(e);
293 Arc arc = _graph.direct(e, true);
294 Node base = (*_blossom_rep)[_blossom_set->find(node)];
296 while (base != nca) {
301 n = _graph.target((*_matching)[n]);
303 n = _graph.target(a);
304 (*_ear)[n] = _graph.oppositeArc(a);
306 node = _graph.target((*_matching)[base]);
307 _tree_set->erase(base);
308 _tree_set->erase(node);
309 _blossom_set->insert(node, _blossom_set->find(base));
310 (*_status)[node] = EVEN;
311 _node_queue[_last++] = node;
312 arc = _graph.oppositeArc((*_ear)[node]);
313 node = _graph.target((*_ear)[node]);
314 base = (*_blossom_rep)[_blossom_set->find(node)];
315 _blossom_set->join(_graph.target(arc), base);
319 (*_blossom_rep)[_blossom_set->find(nca)] = nca;
323 Node node = _graph.v(e);
324 Arc arc = _graph.direct(e, false);
325 Node base = (*_blossom_rep)[_blossom_set->find(node)];
327 while (base != nca) {
332 n = _graph.target((*_matching)[n]);
334 n = _graph.target(a);
335 (*_ear)[n] = _graph.oppositeArc(a);
337 node = _graph.target((*_matching)[base]);
338 _tree_set->erase(base);
339 _tree_set->erase(node);
340 _blossom_set->insert(node, _blossom_set->find(base));
341 (*_status)[node] = EVEN;
342 _node_queue[_last++] = node;
343 arc = _graph.oppositeArc((*_ear)[node]);
344 node = _graph.target((*_ear)[node]);
345 base = (*_blossom_rep)[_blossom_set->find(node)];
346 _blossom_set->join(_graph.target(arc), base);
350 (*_blossom_rep)[_blossom_set->find(nca)] = nca;
353 void extendOnArc(const Arc& a) {
354 Node base = _graph.source(a);
355 Node odd = _graph.target(a);
357 (*_ear)[odd] = _graph.oppositeArc(a);
358 Node even = _graph.target((*_matching)[odd]);
359 (*_blossom_rep)[_blossom_set->insert(even)] = even;
360 (*_status)[odd] = ODD;
361 (*_status)[even] = EVEN;
362 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
363 _tree_set->insert(odd, tree);
364 _tree_set->insert(even, tree);
365 _node_queue[_last++] = even;
369 void augmentOnArc(const Arc& a) {
370 Node even = _graph.source(a);
371 Node odd = _graph.target(a);
373 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
375 (*_matching)[odd] = _graph.oppositeArc(a);
376 (*_status)[odd] = MATCHED;
378 Arc arc = (*_matching)[even];
379 (*_matching)[even] = a;
381 while (arc != INVALID) {
382 odd = _graph.target(arc);
384 even = _graph.target(arc);
385 (*_matching)[odd] = arc;
386 arc = (*_matching)[even];
387 (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
390 for (typename TreeSet::ItemIt it(*_tree_set, tree);
391 it != INVALID; ++it) {
392 if ((*_status)[it] == ODD) {
393 (*_status)[it] = MATCHED;
395 int blossom = _blossom_set->find(it);
396 for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
397 jt != INVALID; ++jt) {
398 (*_status)[jt] = MATCHED;
400 _blossom_set->eraseClass(blossom);
403 _tree_set->eraseClass(tree);
409 /// \brief Constructor
412 MaxMatching(const Graph& graph)
413 : _graph(graph), _matching(0), _status(0), _ear(0),
414 _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
415 _tree_set_index(0), _tree_set(0) {}
421 /// \name Execution Control
422 /// The simplest way to execute the algorithm is to use the
423 /// \c run() member function.\n
424 /// If you need better control on the execution, you have to call
425 /// one of the functions \ref init(), \ref greedyInit() or
426 /// \ref matchingInit() first, then you can start the algorithm with
427 /// \ref startSparse() or \ref startDense().
431 /// \brief Set the initial matching to the empty matching.
433 /// This function sets the initial matching to the empty matching.
436 for(NodeIt n(_graph); n != INVALID; ++n) {
437 (*_matching)[n] = INVALID;
438 (*_status)[n] = UNMATCHED;
442 /// \brief Find an initial matching in a greedy way.
444 /// This function finds an initial matching in a greedy way.
447 for (NodeIt n(_graph); n != INVALID; ++n) {
448 (*_matching)[n] = INVALID;
449 (*_status)[n] = UNMATCHED;
451 for (NodeIt n(_graph); n != INVALID; ++n) {
452 if ((*_matching)[n] == INVALID) {
453 for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
454 Node v = _graph.target(a);
455 if ((*_matching)[v] == INVALID && v != n) {
457 (*_status)[n] = MATCHED;
458 (*_matching)[v] = _graph.oppositeArc(a);
459 (*_status)[v] = MATCHED;
468 /// \brief Initialize the matching from a map.
470 /// This function initializes the matching from a \c bool valued edge
471 /// map. This map should have the property that there are no two incident
472 /// edges with \c true value, i.e. it really contains a matching.
473 /// \return \c true if the map contains a matching.
474 template <typename MatchingMap>
475 bool matchingInit(const MatchingMap& matching) {
478 for (NodeIt n(_graph); n != INVALID; ++n) {
479 (*_matching)[n] = INVALID;
480 (*_status)[n] = UNMATCHED;
482 for(EdgeIt e(_graph); e!=INVALID; ++e) {
485 Node u = _graph.u(e);
486 if ((*_matching)[u] != INVALID) return false;
487 (*_matching)[u] = _graph.direct(e, true);
488 (*_status)[u] = MATCHED;
490 Node v = _graph.v(e);
491 if ((*_matching)[v] != INVALID) return false;
492 (*_matching)[v] = _graph.direct(e, false);
493 (*_status)[v] = MATCHED;
499 /// \brief Start Edmonds' algorithm
501 /// This function runs the original Edmonds' algorithm.
503 /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
504 /// called before using this function.
506 for(NodeIt n(_graph); n != INVALID; ++n) {
507 if ((*_status)[n] == UNMATCHED) {
508 (*_blossom_rep)[_blossom_set->insert(n)] = n;
509 _tree_set->insert(n);
510 (*_status)[n] = EVEN;
516 /// \brief Start Edmonds' algorithm with a heuristic improvement
519 /// This function runs Edmonds' algorithm with a heuristic of postponing
520 /// shrinks, therefore resulting in a faster algorithm for dense graphs.
522 /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
523 /// called before using this function.
525 for(NodeIt n(_graph); n != INVALID; ++n) {
526 if ((*_status)[n] == UNMATCHED) {
527 (*_blossom_rep)[_blossom_set->insert(n)] = n;
528 _tree_set->insert(n);
529 (*_status)[n] = EVEN;
536 /// \brief Run Edmonds' algorithm
538 /// This function runs Edmonds' algorithm. An additional heuristic of
539 /// postponing shrinks is used for relatively dense graphs
540 /// (for which <tt>m>=2*n</tt> holds).
542 if (countEdges(_graph) < 2 * countNodes(_graph)) {
553 /// \name Primal Solution
554 /// Functions to get the primal solution, i.e. the maximum matching.
558 /// \brief Return the size (cardinality) of the matching.
560 /// This function returns the size (cardinality) of the current matching.
561 /// After run() it returns the size of the maximum matching in the graph.
562 int matchingSize() const {
564 for (NodeIt n(_graph); n != INVALID; ++n) {
565 if ((*_matching)[n] != INVALID) {
572 /// \brief Return \c true if the given edge is in the matching.
574 /// This function returns \c true if the given edge is in the current
576 bool matching(const Edge& edge) const {
577 return edge == (*_matching)[_graph.u(edge)];
580 /// \brief Return the matching arc (or edge) incident to the given node.
582 /// This function returns the matching arc (or edge) incident to the
583 /// given node in the current matching or \c INVALID if the node is
584 /// not covered by the matching.
585 Arc matching(const Node& n) const {
586 return (*_matching)[n];
589 /// \brief Return a const reference to the matching map.
591 /// This function returns a const reference to a node map that stores
592 /// the matching arc (or edge) incident to each node.
593 const MatchingMap& matchingMap() const {
597 /// \brief Return the mate of the given node.
599 /// This function returns the mate of the given node in the current
600 /// matching or \c INVALID if the node is not covered by the matching.
601 Node mate(const Node& n) const {
602 return (*_matching)[n] != INVALID ?
603 _graph.target((*_matching)[n]) : INVALID;
608 /// \name Dual Solution
609 /// Functions to get the dual solution, i.e. the Gallai-Edmonds
614 /// \brief Return the status of the given node in the Edmonds-Gallai
617 /// This function returns the \ref Status "status" of the given node
618 /// in the Edmonds-Gallai decomposition.
619 Status status(const Node& n) const {
620 return (*_status)[n];
623 /// \brief Return a const reference to the status map, which stores
624 /// the Edmonds-Gallai decomposition.
626 /// This function returns a const reference to a node map that stores the
627 /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
628 const StatusMap& statusMap() const {
632 /// \brief Return \c true if the given node is in the barrier.
634 /// This function returns \c true if the given node is in the barrier.
635 bool barrier(const Node& n) const {
636 return (*_status)[n] == ODD;
643 /// \ingroup matching
645 /// \brief Weighted matching in general graphs
647 /// This class provides an efficient implementation of Edmond's
648 /// maximum weighted matching algorithm. The implementation is based
649 /// on extensive use of priority queues and provides
650 /// \f$O(nm\log n)\f$ time complexity.
652 /// The maximum weighted matching problem is to find a subset of the
653 /// edges in an undirected graph with maximum overall weight for which
654 /// each node has at most one incident edge.
655 /// It can be formulated with the following linear program.
656 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
657 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
658 \quad \forall B\in\mathcal{O}\f] */
659 /// \f[x_e \ge 0\quad \forall e\in E\f]
660 /// \f[\max \sum_{e\in E}x_ew_e\f]
661 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
662 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
663 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
664 /// subsets of the nodes.
666 /// The algorithm calculates an optimal matching and a proof of the
667 /// optimality. The solution of the dual problem can be used to check
668 /// the result of the algorithm. The dual linear problem is the
670 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
671 z_B \ge w_{uv} \quad \forall uv\in E\f] */
672 /// \f[y_u \ge 0 \quad \forall u \in V\f]
673 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
674 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
675 \frac{\vert B \vert - 1}{2}z_B\f] */
677 /// The algorithm can be executed with the run() function.
678 /// After it the matching (the primal solution) and the dual solution
679 /// can be obtained using the query functions and the
680 /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
681 /// which is able to iterate on the nodes of a blossom.
682 /// If the value type is integer, then the dual solution is multiplied
683 /// by \ref MaxWeightedMatching::dualScale "4".
685 /// \tparam GR The undirected graph type the algorithm runs on.
686 /// \tparam WM The type edge weight map. The default type is
687 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
689 template <typename GR, typename WM>
691 template <typename GR,
692 typename WM = typename GR::template EdgeMap<int> >
694 class MaxWeightedMatching {
697 /// The graph type of the algorithm
699 /// The type of the edge weight map
700 typedef WM WeightMap;
701 /// The value type of the edge weights
702 typedef typename WeightMap::Value Value;
704 /// The type of the matching map
705 typedef typename Graph::template NodeMap<typename Graph::Arc>
708 /// \brief Scaling factor for dual solution
710 /// Scaling factor for dual solution. It is equal to 4 or 1
711 /// according to the value type.
712 static const int dualScale =
713 std::numeric_limits<Value>::is_integer ? 4 : 1;
717 TEMPLATE_GRAPH_TYPEDEFS(Graph);
719 typedef typename Graph::template NodeMap<Value> NodePotential;
720 typedef std::vector<Node> BlossomNodeList;
722 struct BlossomVariable {
726 BlossomVariable(int _begin, int _end, Value _value)
727 : begin(_begin), end(_end), value(_value) {}
731 typedef std::vector<BlossomVariable> BlossomPotential;
734 const WeightMap& _weight;
736 MatchingMap* _matching;
738 NodePotential* _node_potential;
740 BlossomPotential _blossom_potential;
741 BlossomNodeList _blossom_node_list;
746 typedef RangeMap<int> IntIntMap;
749 EVEN = -1, MATCHED = 0, ODD = 1
752 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
761 IntNodeMap *_blossom_index;
762 BlossomSet *_blossom_set;
763 RangeMap<BlossomData>* _blossom_data;
765 IntNodeMap *_node_index;
766 IntArcMap *_node_heap_index;
770 NodeData(IntArcMap& node_heap_index)
771 : heap(node_heap_index) {}
775 BinHeap<Value, IntArcMap> heap;
776 std::map<int, Arc> heap_index;
781 RangeMap<NodeData>* _node_data;
783 typedef ExtendFindEnum<IntIntMap> TreeSet;
785 IntIntMap *_tree_set_index;
788 IntNodeMap *_delta1_index;
789 BinHeap<Value, IntNodeMap> *_delta1;
791 IntIntMap *_delta2_index;
792 BinHeap<Value, IntIntMap> *_delta2;
794 IntEdgeMap *_delta3_index;
795 BinHeap<Value, IntEdgeMap> *_delta3;
797 IntIntMap *_delta4_index;
798 BinHeap<Value, IntIntMap> *_delta4;
803 typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
804 FractionalMatching *_fractional;
806 void createStructures() {
807 _node_num = countNodes(_graph);
808 _blossom_num = _node_num * 3 / 2;
811 _matching = new MatchingMap(_graph);
813 if (!_node_potential) {
814 _node_potential = new NodePotential(_graph);
817 _blossom_index = new IntNodeMap(_graph);
818 _blossom_set = new BlossomSet(*_blossom_index);
819 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
823 _node_index = new IntNodeMap(_graph);
824 _node_heap_index = new IntArcMap(_graph);
825 _node_data = new RangeMap<NodeData>(_node_num,
826 NodeData(*_node_heap_index));
830 _tree_set_index = new IntIntMap(_blossom_num);
831 _tree_set = new TreeSet(*_tree_set_index);
834 _delta1_index = new IntNodeMap(_graph);
835 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
838 _delta2_index = new IntIntMap(_blossom_num);
839 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
842 _delta3_index = new IntEdgeMap(_graph);
843 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
846 _delta4_index = new IntIntMap(_blossom_num);
847 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
851 void destroyStructures() {
855 if (_node_potential) {
856 delete _node_potential;
859 delete _blossom_index;
861 delete _blossom_data;
866 delete _node_heap_index;
871 delete _tree_set_index;
875 delete _delta1_index;
879 delete _delta2_index;
883 delete _delta3_index;
887 delete _delta4_index;
892 void matchedToEven(int blossom, int tree) {
893 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
894 _delta2->erase(blossom);
897 if (!_blossom_set->trivial(blossom)) {
898 (*_blossom_data)[blossom].pot -=
899 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
902 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
905 _blossom_set->increase(n, std::numeric_limits<Value>::max());
906 int ni = (*_node_index)[n];
908 (*_node_data)[ni].heap.clear();
909 (*_node_data)[ni].heap_index.clear();
911 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
913 _delta1->push(n, (*_node_data)[ni].pot);
915 for (InArcIt e(_graph, n); e != INVALID; ++e) {
916 Node v = _graph.source(e);
917 int vb = _blossom_set->find(v);
918 int vi = (*_node_index)[v];
920 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
921 dualScale * _weight[e];
923 if ((*_blossom_data)[vb].status == EVEN) {
924 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
925 _delta3->push(e, rw / 2);
928 typename std::map<int, Arc>::iterator it =
929 (*_node_data)[vi].heap_index.find(tree);
931 if (it != (*_node_data)[vi].heap_index.end()) {
932 if ((*_node_data)[vi].heap[it->second] > rw) {
933 (*_node_data)[vi].heap.replace(it->second, e);
934 (*_node_data)[vi].heap.decrease(e, rw);
938 (*_node_data)[vi].heap.push(e, rw);
939 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
942 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
943 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
945 if ((*_blossom_data)[vb].status == MATCHED) {
946 if (_delta2->state(vb) != _delta2->IN_HEAP) {
947 _delta2->push(vb, _blossom_set->classPrio(vb) -
948 (*_blossom_data)[vb].offset);
949 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
950 (*_blossom_data)[vb].offset) {
951 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
952 (*_blossom_data)[vb].offset);
959 (*_blossom_data)[blossom].offset = 0;
962 void matchedToOdd(int blossom) {
963 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
964 _delta2->erase(blossom);
966 (*_blossom_data)[blossom].offset += _delta_sum;
967 if (!_blossom_set->trivial(blossom)) {
968 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
969 (*_blossom_data)[blossom].offset);
973 void evenToMatched(int blossom, int tree) {
974 if (!_blossom_set->trivial(blossom)) {
975 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
978 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
980 int ni = (*_node_index)[n];
981 (*_node_data)[ni].pot -= _delta_sum;
985 for (InArcIt e(_graph, n); e != INVALID; ++e) {
986 Node v = _graph.source(e);
987 int vb = _blossom_set->find(v);
988 int vi = (*_node_index)[v];
990 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
991 dualScale * _weight[e];
994 if (_delta3->state(e) == _delta3->IN_HEAP) {
997 } else if ((*_blossom_data)[vb].status == EVEN) {
999 if (_delta3->state(e) == _delta3->IN_HEAP) {
1003 int vt = _tree_set->find(vb);
1007 Arc r = _graph.oppositeArc(e);
1009 typename std::map<int, Arc>::iterator it =
1010 (*_node_data)[ni].heap_index.find(vt);
1012 if (it != (*_node_data)[ni].heap_index.end()) {
1013 if ((*_node_data)[ni].heap[it->second] > rw) {
1014 (*_node_data)[ni].heap.replace(it->second, r);
1015 (*_node_data)[ni].heap.decrease(r, rw);
1019 (*_node_data)[ni].heap.push(r, rw);
1020 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1023 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1024 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1026 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1027 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1028 (*_blossom_data)[blossom].offset);
1029 } else if ((*_delta2)[blossom] >
1030 _blossom_set->classPrio(blossom) -
1031 (*_blossom_data)[blossom].offset){
1032 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1033 (*_blossom_data)[blossom].offset);
1039 typename std::map<int, Arc>::iterator it =
1040 (*_node_data)[vi].heap_index.find(tree);
1042 if (it != (*_node_data)[vi].heap_index.end()) {
1043 (*_node_data)[vi].heap.erase(it->second);
1044 (*_node_data)[vi].heap_index.erase(it);
1045 if ((*_node_data)[vi].heap.empty()) {
1046 _blossom_set->increase(v, std::numeric_limits<Value>::max());
1047 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1048 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1051 if ((*_blossom_data)[vb].status == MATCHED) {
1052 if (_blossom_set->classPrio(vb) ==
1053 std::numeric_limits<Value>::max()) {
1055 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1056 (*_blossom_data)[vb].offset) {
1057 _delta2->increase(vb, _blossom_set->classPrio(vb) -
1058 (*_blossom_data)[vb].offset);
1067 void oddToMatched(int blossom) {
1068 (*_blossom_data)[blossom].offset -= _delta_sum;
1070 if (_blossom_set->classPrio(blossom) !=
1071 std::numeric_limits<Value>::max()) {
1072 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1073 (*_blossom_data)[blossom].offset);
1076 if (!_blossom_set->trivial(blossom)) {
1077 _delta4->erase(blossom);
1081 void oddToEven(int blossom, int tree) {
1082 if (!_blossom_set->trivial(blossom)) {
1083 _delta4->erase(blossom);
1084 (*_blossom_data)[blossom].pot -=
1085 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1088 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1089 n != INVALID; ++n) {
1090 int ni = (*_node_index)[n];
1092 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1094 (*_node_data)[ni].heap.clear();
1095 (*_node_data)[ni].heap_index.clear();
1096 (*_node_data)[ni].pot +=
1097 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1099 _delta1->push(n, (*_node_data)[ni].pot);
1101 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1102 Node v = _graph.source(e);
1103 int vb = _blossom_set->find(v);
1104 int vi = (*_node_index)[v];
1106 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1107 dualScale * _weight[e];
1109 if ((*_blossom_data)[vb].status == EVEN) {
1110 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1111 _delta3->push(e, rw / 2);
1115 typename std::map<int, Arc>::iterator it =
1116 (*_node_data)[vi].heap_index.find(tree);
1118 if (it != (*_node_data)[vi].heap_index.end()) {
1119 if ((*_node_data)[vi].heap[it->second] > rw) {
1120 (*_node_data)[vi].heap.replace(it->second, e);
1121 (*_node_data)[vi].heap.decrease(e, rw);
1125 (*_node_data)[vi].heap.push(e, rw);
1126 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1129 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1130 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1132 if ((*_blossom_data)[vb].status == MATCHED) {
1133 if (_delta2->state(vb) != _delta2->IN_HEAP) {
1134 _delta2->push(vb, _blossom_set->classPrio(vb) -
1135 (*_blossom_data)[vb].offset);
1136 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1137 (*_blossom_data)[vb].offset) {
1138 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1139 (*_blossom_data)[vb].offset);
1146 (*_blossom_data)[blossom].offset = 0;
1149 void alternatePath(int even, int tree) {
1152 evenToMatched(even, tree);
1153 (*_blossom_data)[even].status = MATCHED;
1155 while ((*_blossom_data)[even].pred != INVALID) {
1156 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1157 (*_blossom_data)[odd].status = MATCHED;
1159 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1161 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1162 (*_blossom_data)[even].status = MATCHED;
1163 evenToMatched(even, tree);
1164 (*_blossom_data)[even].next =
1165 _graph.oppositeArc((*_blossom_data)[odd].pred);
1170 void destroyTree(int tree) {
1171 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1172 if ((*_blossom_data)[b].status == EVEN) {
1173 (*_blossom_data)[b].status = MATCHED;
1174 evenToMatched(b, tree);
1175 } else if ((*_blossom_data)[b].status == ODD) {
1176 (*_blossom_data)[b].status = MATCHED;
1180 _tree_set->eraseClass(tree);
1184 void unmatchNode(const Node& node) {
1185 int blossom = _blossom_set->find(node);
1186 int tree = _tree_set->find(blossom);
1188 alternatePath(blossom, tree);
1191 (*_blossom_data)[blossom].base = node;
1192 (*_blossom_data)[blossom].next = INVALID;
1195 void augmentOnEdge(const Edge& edge) {
1197 int left = _blossom_set->find(_graph.u(edge));
1198 int right = _blossom_set->find(_graph.v(edge));
1200 int left_tree = _tree_set->find(left);
1201 alternatePath(left, left_tree);
1202 destroyTree(left_tree);
1204 int right_tree = _tree_set->find(right);
1205 alternatePath(right, right_tree);
1206 destroyTree(right_tree);
1208 (*_blossom_data)[left].next = _graph.direct(edge, true);
1209 (*_blossom_data)[right].next = _graph.direct(edge, false);
1212 void augmentOnArc(const Arc& arc) {
1214 int left = _blossom_set->find(_graph.source(arc));
1215 int right = _blossom_set->find(_graph.target(arc));
1217 (*_blossom_data)[left].status = MATCHED;
1219 int right_tree = _tree_set->find(right);
1220 alternatePath(right, right_tree);
1221 destroyTree(right_tree);
1223 (*_blossom_data)[left].next = arc;
1224 (*_blossom_data)[right].next = _graph.oppositeArc(arc);
1227 void extendOnArc(const Arc& arc) {
1228 int base = _blossom_set->find(_graph.target(arc));
1229 int tree = _tree_set->find(base);
1231 int odd = _blossom_set->find(_graph.source(arc));
1232 _tree_set->insert(odd, tree);
1233 (*_blossom_data)[odd].status = ODD;
1235 (*_blossom_data)[odd].pred = arc;
1237 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1238 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1239 _tree_set->insert(even, tree);
1240 (*_blossom_data)[even].status = EVEN;
1241 matchedToEven(even, tree);
1244 void shrinkOnEdge(const Edge& edge, int tree) {
1246 std::vector<int> left_path, right_path;
1249 std::set<int> left_set, right_set;
1250 int left = _blossom_set->find(_graph.u(edge));
1251 left_path.push_back(left);
1252 left_set.insert(left);
1254 int right = _blossom_set->find(_graph.v(edge));
1255 right_path.push_back(right);
1256 right_set.insert(right);
1260 if ((*_blossom_data)[left].pred == INVALID) break;
1263 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1264 left_path.push_back(left);
1266 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1267 left_path.push_back(left);
1269 left_set.insert(left);
1271 if (right_set.find(left) != right_set.end()) {
1276 if ((*_blossom_data)[right].pred == INVALID) break;
1279 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1280 right_path.push_back(right);
1282 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1283 right_path.push_back(right);
1285 right_set.insert(right);
1287 if (left_set.find(right) != left_set.end()) {
1295 if ((*_blossom_data)[left].pred == INVALID) {
1297 while (left_set.find(nca) == left_set.end()) {
1299 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1300 right_path.push_back(nca);
1302 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1303 right_path.push_back(nca);
1307 while (right_set.find(nca) == right_set.end()) {
1309 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1310 left_path.push_back(nca);
1312 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1313 left_path.push_back(nca);
1319 std::vector<int> subblossoms;
1322 prev = _graph.direct(edge, true);
1323 for (int i = 0; left_path[i] != nca; i += 2) {
1324 subblossoms.push_back(left_path[i]);
1325 (*_blossom_data)[left_path[i]].next = prev;
1326 _tree_set->erase(left_path[i]);
1328 subblossoms.push_back(left_path[i + 1]);
1329 (*_blossom_data)[left_path[i + 1]].status = EVEN;
1330 oddToEven(left_path[i + 1], tree);
1331 _tree_set->erase(left_path[i + 1]);
1332 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1336 while (right_path[k] != nca) ++k;
1338 subblossoms.push_back(nca);
1339 (*_blossom_data)[nca].next = prev;
1341 for (int i = k - 2; i >= 0; i -= 2) {
1342 subblossoms.push_back(right_path[i + 1]);
1343 (*_blossom_data)[right_path[i + 1]].status = EVEN;
1344 oddToEven(right_path[i + 1], tree);
1345 _tree_set->erase(right_path[i + 1]);
1347 (*_blossom_data)[right_path[i + 1]].next =
1348 (*_blossom_data)[right_path[i + 1]].pred;
1350 subblossoms.push_back(right_path[i]);
1351 _tree_set->erase(right_path[i]);
1355 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1357 for (int i = 0; i < int(subblossoms.size()); ++i) {
1358 if (!_blossom_set->trivial(subblossoms[i])) {
1359 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1361 (*_blossom_data)[subblossoms[i]].status = MATCHED;
1364 (*_blossom_data)[surface].pot = -2 * _delta_sum;
1365 (*_blossom_data)[surface].offset = 0;
1366 (*_blossom_data)[surface].status = EVEN;
1367 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1368 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1370 _tree_set->insert(surface, tree);
1371 _tree_set->erase(nca);
1374 void splitBlossom(int blossom) {
1375 Arc next = (*_blossom_data)[blossom].next;
1376 Arc pred = (*_blossom_data)[blossom].pred;
1378 int tree = _tree_set->find(blossom);
1380 (*_blossom_data)[blossom].status = MATCHED;
1381 oddToMatched(blossom);
1382 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1383 _delta2->erase(blossom);
1386 std::vector<int> subblossoms;
1387 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1389 Value offset = (*_blossom_data)[blossom].offset;
1390 int b = _blossom_set->find(_graph.source(pred));
1391 int d = _blossom_set->find(_graph.source(next));
1393 int ib = -1, id = -1;
1394 for (int i = 0; i < int(subblossoms.size()); ++i) {
1395 if (subblossoms[i] == b) ib = i;
1396 if (subblossoms[i] == d) id = i;
1398 (*_blossom_data)[subblossoms[i]].offset = offset;
1399 if (!_blossom_set->trivial(subblossoms[i])) {
1400 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1402 if (_blossom_set->classPrio(subblossoms[i]) !=
1403 std::numeric_limits<Value>::max()) {
1404 _delta2->push(subblossoms[i],
1405 _blossom_set->classPrio(subblossoms[i]) -
1406 (*_blossom_data)[subblossoms[i]].offset);
1410 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1411 for (int i = (id + 1) % subblossoms.size();
1412 i != ib; i = (i + 2) % subblossoms.size()) {
1413 int sb = subblossoms[i];
1414 int tb = subblossoms[(i + 1) % subblossoms.size()];
1415 (*_blossom_data)[sb].next =
1416 _graph.oppositeArc((*_blossom_data)[tb].next);
1419 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1420 int sb = subblossoms[i];
1421 int tb = subblossoms[(i + 1) % subblossoms.size()];
1422 int ub = subblossoms[(i + 2) % subblossoms.size()];
1424 (*_blossom_data)[sb].status = ODD;
1426 _tree_set->insert(sb, tree);
1427 (*_blossom_data)[sb].pred = pred;
1428 (*_blossom_data)[sb].next =
1429 _graph.oppositeArc((*_blossom_data)[tb].next);
1431 pred = (*_blossom_data)[ub].next;
1433 (*_blossom_data)[tb].status = EVEN;
1434 matchedToEven(tb, tree);
1435 _tree_set->insert(tb, tree);
1436 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1439 (*_blossom_data)[subblossoms[id]].status = ODD;
1440 matchedToOdd(subblossoms[id]);
1441 _tree_set->insert(subblossoms[id], tree);
1442 (*_blossom_data)[subblossoms[id]].next = next;
1443 (*_blossom_data)[subblossoms[id]].pred = pred;
1447 for (int i = (ib + 1) % subblossoms.size();
1448 i != id; i = (i + 2) % subblossoms.size()) {
1449 int sb = subblossoms[i];
1450 int tb = subblossoms[(i + 1) % subblossoms.size()];
1451 (*_blossom_data)[sb].next =
1452 _graph.oppositeArc((*_blossom_data)[tb].next);
1455 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1456 int sb = subblossoms[i];
1457 int tb = subblossoms[(i + 1) % subblossoms.size()];
1458 int ub = subblossoms[(i + 2) % subblossoms.size()];
1460 (*_blossom_data)[sb].status = ODD;
1462 _tree_set->insert(sb, tree);
1463 (*_blossom_data)[sb].next = next;
1464 (*_blossom_data)[sb].pred =
1465 _graph.oppositeArc((*_blossom_data)[tb].next);
1467 (*_blossom_data)[tb].status = EVEN;
1468 matchedToEven(tb, tree);
1469 _tree_set->insert(tb, tree);
1470 (*_blossom_data)[tb].pred =
1471 (*_blossom_data)[tb].next =
1472 _graph.oppositeArc((*_blossom_data)[ub].next);
1473 next = (*_blossom_data)[ub].next;
1476 (*_blossom_data)[subblossoms[ib]].status = ODD;
1477 matchedToOdd(subblossoms[ib]);
1478 _tree_set->insert(subblossoms[ib], tree);
1479 (*_blossom_data)[subblossoms[ib]].next = next;
1480 (*_blossom_data)[subblossoms[ib]].pred = pred;
1482 _tree_set->erase(blossom);
1485 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1486 if (_blossom_set->trivial(blossom)) {
1487 int bi = (*_node_index)[base];
1488 Value pot = (*_node_data)[bi].pot;
1490 (*_matching)[base] = matching;
1491 _blossom_node_list.push_back(base);
1492 (*_node_potential)[base] = pot;
1495 Value pot = (*_blossom_data)[blossom].pot;
1496 int bn = _blossom_node_list.size();
1498 std::vector<int> subblossoms;
1499 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1500 int b = _blossom_set->find(base);
1502 for (int i = 0; i < int(subblossoms.size()); ++i) {
1503 if (subblossoms[i] == b) { ib = i; break; }
1506 for (int i = 1; i < int(subblossoms.size()); i += 2) {
1507 int sb = subblossoms[(ib + i) % subblossoms.size()];
1508 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1510 Arc m = (*_blossom_data)[tb].next;
1511 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1512 extractBlossom(tb, _graph.source(m), m);
1514 extractBlossom(subblossoms[ib], base, matching);
1516 int en = _blossom_node_list.size();
1518 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1522 void extractMatching() {
1523 std::vector<int> blossoms;
1524 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1525 blossoms.push_back(c);
1528 for (int i = 0; i < int(blossoms.size()); ++i) {
1529 if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1531 Value offset = (*_blossom_data)[blossoms[i]].offset;
1532 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1533 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1534 n != INVALID; ++n) {
1535 (*_node_data)[(*_node_index)[n]].pot -= offset;
1538 Arc matching = (*_blossom_data)[blossoms[i]].next;
1539 Node base = _graph.source(matching);
1540 extractBlossom(blossoms[i], base, matching);
1542 Node base = (*_blossom_data)[blossoms[i]].base;
1543 extractBlossom(blossoms[i], base, INVALID);
1550 /// \brief Constructor
1553 MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1554 : _graph(graph), _weight(weight), _matching(0),
1555 _node_potential(0), _blossom_potential(), _blossom_node_list(),
1556 _node_num(0), _blossom_num(0),
1558 _blossom_index(0), _blossom_set(0), _blossom_data(0),
1559 _node_index(0), _node_heap_index(0), _node_data(0),
1560 _tree_set_index(0), _tree_set(0),
1562 _delta1_index(0), _delta1(0),
1563 _delta2_index(0), _delta2(0),
1564 _delta3_index(0), _delta3(0),
1565 _delta4_index(0), _delta4(0),
1567 _delta_sum(), _unmatched(0),
1572 ~MaxWeightedMatching() {
1573 destroyStructures();
1579 /// \name Execution Control
1580 /// The simplest way to execute the algorithm is to use the
1581 /// \ref run() member function.
1585 /// \brief Initialize the algorithm
1587 /// This function initializes the algorithm.
1591 for (ArcIt e(_graph); e != INVALID; ++e) {
1592 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1594 for (NodeIt n(_graph); n != INVALID; ++n) {
1595 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1597 for (EdgeIt e(_graph); e != INVALID; ++e) {
1598 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1600 for (int i = 0; i < _blossom_num; ++i) {
1601 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1602 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1605 _unmatched = _node_num;
1608 for (NodeIt n(_graph); n != INVALID; ++n) {
1610 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1611 if (_graph.target(e) == n) continue;
1612 if ((dualScale * _weight[e]) / 2 > max) {
1613 max = (dualScale * _weight[e]) / 2;
1616 (*_node_index)[n] = index;
1617 (*_node_data)[index].pot = max;
1618 _delta1->push(n, max);
1620 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1622 _tree_set->insert(blossom);
1624 (*_blossom_data)[blossom].status = EVEN;
1625 (*_blossom_data)[blossom].pred = INVALID;
1626 (*_blossom_data)[blossom].next = INVALID;
1627 (*_blossom_data)[blossom].pot = 0;
1628 (*_blossom_data)[blossom].offset = 0;
1631 for (EdgeIt e(_graph); e != INVALID; ++e) {
1632 int si = (*_node_index)[_graph.u(e)];
1633 int ti = (*_node_index)[_graph.v(e)];
1634 if (_graph.u(e) != _graph.v(e)) {
1635 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1636 dualScale * _weight[e]) / 2);
1641 /// \brief Initialize the algorithm with fractional matching
1643 /// This function initializes the algorithm with a fractional
1644 /// matching. This initialization is also called jumpstart heuristic.
1645 void fractionalInit() {
1648 if (_fractional == 0) {
1649 _fractional = new FractionalMatching(_graph, _weight, false);
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;
1670 for (NodeIt n(_graph); n != INVALID; ++n) {
1671 Value pot = _fractional->nodeValue(n);
1672 (*_node_index)[n] = index;
1673 (*_node_data)[index].pot = pot;
1675 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1677 (*_blossom_data)[blossom].status = MATCHED;
1678 (*_blossom_data)[blossom].pred = INVALID;
1679 (*_blossom_data)[blossom].next = _fractional->matching(n);
1680 if (_fractional->matching(n) == INVALID) {
1681 (*_blossom_data)[blossom].base = n;
1683 (*_blossom_data)[blossom].pot = 0;
1684 (*_blossom_data)[blossom].offset = 0;
1688 typename Graph::template NodeMap<bool> processed(_graph, false);
1689 for (NodeIt n(_graph); n != INVALID; ++n) {
1690 if (processed[n]) continue;
1691 processed[n] = true;
1692 if (_fractional->matching(n) == INVALID) continue;
1694 Node v = _graph.target(_fractional->matching(n));
1696 processed[v] = true;
1697 v = _graph.target(_fractional->matching(v));
1702 std::vector<int> subblossoms(num);
1704 subblossoms[--num] = _blossom_set->find(n);
1705 _delta1->push(n, _fractional->nodeValue(n));
1706 v = _graph.target(_fractional->matching(n));
1708 subblossoms[--num] = _blossom_set->find(v);
1709 _delta1->push(v, _fractional->nodeValue(v));
1710 v = _graph.target(_fractional->matching(v));
1714 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1715 (*_blossom_data)[surface].status = EVEN;
1716 (*_blossom_data)[surface].pred = INVALID;
1717 (*_blossom_data)[surface].next = INVALID;
1718 (*_blossom_data)[surface].pot = 0;
1719 (*_blossom_data)[surface].offset = 0;
1721 _tree_set->insert(surface);
1726 for (EdgeIt e(_graph); e != INVALID; ++e) {
1727 int si = (*_node_index)[_graph.u(e)];
1728 int sb = _blossom_set->find(_graph.u(e));
1729 int ti = (*_node_index)[_graph.v(e)];
1730 int tb = _blossom_set->find(_graph.v(e));
1731 if ((*_blossom_data)[sb].status == EVEN &&
1732 (*_blossom_data)[tb].status == EVEN && sb != tb) {
1733 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1734 dualScale * _weight[e]) / 2);
1738 for (NodeIt n(_graph); n != INVALID; ++n) {
1739 int nb = _blossom_set->find(n);
1740 if ((*_blossom_data)[nb].status != MATCHED) continue;
1741 int ni = (*_node_index)[n];
1743 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1744 Node v = _graph.target(e);
1745 int vb = _blossom_set->find(v);
1746 int vi = (*_node_index)[v];
1748 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1749 dualScale * _weight[e];
1751 if ((*_blossom_data)[vb].status == EVEN) {
1753 int vt = _tree_set->find(vb);
1755 typename std::map<int, Arc>::iterator it =
1756 (*_node_data)[ni].heap_index.find(vt);
1758 if (it != (*_node_data)[ni].heap_index.end()) {
1759 if ((*_node_data)[ni].heap[it->second] > rw) {
1760 (*_node_data)[ni].heap.replace(it->second, e);
1761 (*_node_data)[ni].heap.decrease(e, rw);
1765 (*_node_data)[ni].heap.push(e, rw);
1766 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
1771 if (!(*_node_data)[ni].heap.empty()) {
1772 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1773 _delta2->push(nb, _blossom_set->classPrio(nb));
1778 /// \brief Start the algorithm
1780 /// This function starts the algorithm.
1782 /// \pre \ref init() or \ref fractionalInit() must be called
1783 /// before using this function.
1789 while (_unmatched > 0) {
1790 Value d1 = !_delta1->empty() ?
1791 _delta1->prio() : std::numeric_limits<Value>::max();
1793 Value d2 = !_delta2->empty() ?
1794 _delta2->prio() : std::numeric_limits<Value>::max();
1796 Value d3 = !_delta3->empty() ?
1797 _delta3->prio() : std::numeric_limits<Value>::max();
1799 Value d4 = !_delta4->empty() ?
1800 _delta4->prio() : std::numeric_limits<Value>::max();
1802 _delta_sum = d3; OpType ot = D3;
1803 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1804 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1805 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1810 Node n = _delta1->top();
1817 int blossom = _delta2->top();
1818 Node n = _blossom_set->classTop(blossom);
1819 Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1820 if ((*_blossom_data)[blossom].next == INVALID) {
1830 Edge e = _delta3->top();
1832 int left_blossom = _blossom_set->find(_graph.u(e));
1833 int right_blossom = _blossom_set->find(_graph.v(e));
1835 if (left_blossom == right_blossom) {
1838 int left_tree = _tree_set->find(left_blossom);
1839 int right_tree = _tree_set->find(right_blossom);
1841 if (left_tree == right_tree) {
1842 shrinkOnEdge(e, left_tree);
1850 splitBlossom(_delta4->top());
1857 /// \brief Run the algorithm.
1859 /// This method runs the \c %MaxWeightedMatching algorithm.
1861 /// \note mwm.run() is just a shortcut of the following code.
1863 /// mwm.fractionalInit();
1873 /// \name Primal Solution
1874 /// Functions to get the primal solution, i.e. the maximum weighted
1876 /// Either \ref run() or \ref start() function should be called before
1881 /// \brief Return the weight of the matching.
1883 /// This function returns the weight of the found matching.
1885 /// \pre Either run() or start() must be called before using this function.
1886 Value matchingWeight() const {
1888 for (NodeIt n(_graph); n != INVALID; ++n) {
1889 if ((*_matching)[n] != INVALID) {
1890 sum += _weight[(*_matching)[n]];
1896 /// \brief Return the size (cardinality) of the matching.
1898 /// This function returns the size (cardinality) of the found matching.
1900 /// \pre Either run() or start() must be called before using this function.
1901 int matchingSize() const {
1903 for (NodeIt n(_graph); n != INVALID; ++n) {
1904 if ((*_matching)[n] != INVALID) {
1911 /// \brief Return \c true if the given edge is in the matching.
1913 /// This function returns \c true if the given edge is in the found
1916 /// \pre Either run() or start() must be called before using this function.
1917 bool matching(const Edge& edge) const {
1918 return edge == (*_matching)[_graph.u(edge)];
1921 /// \brief Return the matching arc (or edge) incident to the given node.
1923 /// This function returns the matching arc (or edge) incident to the
1924 /// given node in the found matching or \c INVALID if the node is
1925 /// not covered by the matching.
1927 /// \pre Either run() or start() must be called before using this function.
1928 Arc matching(const Node& node) const {
1929 return (*_matching)[node];
1932 /// \brief Return a const reference to the matching map.
1934 /// This function returns a const reference to a node map that stores
1935 /// the matching arc (or edge) incident to each node.
1936 const MatchingMap& matchingMap() const {
1940 /// \brief Return the mate of the given node.
1942 /// This function returns the mate of the given node in the found
1943 /// matching or \c INVALID if the node is not covered by the matching.
1945 /// \pre Either run() or start() must be called before using this function.
1946 Node mate(const Node& node) const {
1947 return (*_matching)[node] != INVALID ?
1948 _graph.target((*_matching)[node]) : INVALID;
1953 /// \name Dual Solution
1954 /// Functions to get the dual solution.\n
1955 /// Either \ref run() or \ref start() function should be called before
1960 /// \brief Return the value of the dual solution.
1962 /// This function returns the value of the dual solution.
1963 /// It should be equal to the primal value scaled by \ref dualScale
1966 /// \pre Either run() or start() must be called before using this function.
1967 Value dualValue() const {
1969 for (NodeIt n(_graph); n != INVALID; ++n) {
1970 sum += nodeValue(n);
1972 for (int i = 0; i < blossomNum(); ++i) {
1973 sum += blossomValue(i) * (blossomSize(i) / 2);
1978 /// \brief Return the dual value (potential) of the given node.
1980 /// This function returns the dual value (potential) of the given node.
1982 /// \pre Either run() or start() must be called before using this function.
1983 Value nodeValue(const Node& n) const {
1984 return (*_node_potential)[n];
1987 /// \brief Return the number of the blossoms in the basis.
1989 /// This function returns the number of the blossoms in the basis.
1991 /// \pre Either run() or start() must be called before using this function.
1993 int blossomNum() const {
1994 return _blossom_potential.size();
1997 /// \brief Return the number of the nodes in the given blossom.
1999 /// This function returns the number of the nodes in the given blossom.
2001 /// \pre Either run() or start() must be called before using this function.
2003 int blossomSize(int k) const {
2004 return _blossom_potential[k].end - _blossom_potential[k].begin;
2007 /// \brief Return the dual value (ptential) of the given blossom.
2009 /// This function returns the dual value (ptential) of the given blossom.
2011 /// \pre Either run() or start() must be called before using this function.
2012 Value blossomValue(int k) const {
2013 return _blossom_potential[k].value;
2016 /// \brief Iterator for obtaining the nodes of a blossom.
2018 /// This class provides an iterator for obtaining the nodes of the
2019 /// given blossom. It lists a subset of the nodes.
2020 /// Before using this iterator, you must allocate a
2021 /// MaxWeightedMatching class and execute it.
2025 /// \brief Constructor.
2027 /// Constructor to get the nodes of the given variable.
2029 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2030 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
2031 /// called before initializing this iterator.
2032 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
2033 : _algorithm(&algorithm)
2035 _index = _algorithm->_blossom_potential[variable].begin;
2036 _last = _algorithm->_blossom_potential[variable].end;
2039 /// \brief Conversion to \c Node.
2041 /// Conversion to \c Node.
2042 operator Node() const {
2043 return _algorithm->_blossom_node_list[_index];
2046 /// \brief Increment operator.
2048 /// Increment operator.
2049 BlossomIt& operator++() {
2054 /// \brief Validity checking
2056 /// Checks whether the iterator is invalid.
2057 bool operator==(Invalid) const { return _index == _last; }
2059 /// \brief Validity checking
2061 /// Checks whether the iterator is valid.
2062 bool operator!=(Invalid) const { return _index != _last; }
2065 const MaxWeightedMatching* _algorithm;
2074 /// \ingroup matching
2076 /// \brief Weighted perfect matching in general graphs
2078 /// This class provides an efficient implementation of Edmond's
2079 /// maximum weighted perfect matching algorithm. The implementation
2080 /// is based on extensive use of priority queues and provides
2081 /// \f$O(nm\log n)\f$ time complexity.
2083 /// The maximum weighted perfect matching problem is to find a subset of
2084 /// the edges in an undirected graph with maximum overall weight for which
2085 /// each node has exactly one incident edge.
2086 /// It can be formulated with the following linear program.
2087 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2088 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2089 \quad \forall B\in\mathcal{O}\f] */
2090 /// \f[x_e \ge 0\quad \forall e\in E\f]
2091 /// \f[\max \sum_{e\in E}x_ew_e\f]
2092 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2093 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2094 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2095 /// subsets of the nodes.
2097 /// The algorithm calculates an optimal matching and a proof of the
2098 /// optimality. The solution of the dual problem can be used to check
2099 /// the result of the algorithm. The dual linear problem is the
2101 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2102 w_{uv} \quad \forall uv\in E\f] */
2103 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2104 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2105 \frac{\vert B \vert - 1}{2}z_B\f] */
2107 /// The algorithm can be executed with the run() function.
2108 /// After it the matching (the primal solution) and the dual solution
2109 /// can be obtained using the query functions and the
2110 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2111 /// which is able to iterate on the nodes of a blossom.
2112 /// If the value type is integer, then the dual solution is multiplied
2113 /// by \ref MaxWeightedMatching::dualScale "4".
2115 /// \tparam GR The undirected graph type the algorithm runs on.
2116 /// \tparam WM The type edge weight map. The default type is
2117 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2119 template <typename GR, typename WM>
2121 template <typename GR,
2122 typename WM = typename GR::template EdgeMap<int> >
2124 class MaxWeightedPerfectMatching {
2127 /// The graph type of the algorithm
2129 /// The type of the edge weight map
2130 typedef WM WeightMap;
2131 /// The value type of the edge weights
2132 typedef typename WeightMap::Value Value;
2134 /// \brief Scaling factor for dual solution
2136 /// Scaling factor for dual solution, it is equal to 4 or 1
2137 /// according to the value type.
2138 static const int dualScale =
2139 std::numeric_limits<Value>::is_integer ? 4 : 1;
2141 /// The type of the matching map
2142 typedef typename Graph::template NodeMap<typename Graph::Arc>
2147 TEMPLATE_GRAPH_TYPEDEFS(Graph);
2149 typedef typename Graph::template NodeMap<Value> NodePotential;
2150 typedef std::vector<Node> BlossomNodeList;
2152 struct BlossomVariable {
2156 BlossomVariable(int _begin, int _end, Value _value)
2157 : begin(_begin), end(_end), value(_value) {}
2161 typedef std::vector<BlossomVariable> BlossomPotential;
2163 const Graph& _graph;
2164 const WeightMap& _weight;
2166 MatchingMap* _matching;
2168 NodePotential* _node_potential;
2170 BlossomPotential _blossom_potential;
2171 BlossomNodeList _blossom_node_list;
2176 typedef RangeMap<int> IntIntMap;
2179 EVEN = -1, MATCHED = 0, ODD = 1
2182 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2183 struct BlossomData {
2190 IntNodeMap *_blossom_index;
2191 BlossomSet *_blossom_set;
2192 RangeMap<BlossomData>* _blossom_data;
2194 IntNodeMap *_node_index;
2195 IntArcMap *_node_heap_index;
2199 NodeData(IntArcMap& node_heap_index)
2200 : heap(node_heap_index) {}
2204 BinHeap<Value, IntArcMap> heap;
2205 std::map<int, Arc> heap_index;
2210 RangeMap<NodeData>* _node_data;
2212 typedef ExtendFindEnum<IntIntMap> TreeSet;
2214 IntIntMap *_tree_set_index;
2217 IntIntMap *_delta2_index;
2218 BinHeap<Value, IntIntMap> *_delta2;
2220 IntEdgeMap *_delta3_index;
2221 BinHeap<Value, IntEdgeMap> *_delta3;
2223 IntIntMap *_delta4_index;
2224 BinHeap<Value, IntIntMap> *_delta4;
2229 typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>
2231 FractionalMatching *_fractional;
2233 void createStructures() {
2234 _node_num = countNodes(_graph);
2235 _blossom_num = _node_num * 3 / 2;
2238 _matching = new MatchingMap(_graph);
2240 if (!_node_potential) {
2241 _node_potential = new NodePotential(_graph);
2243 if (!_blossom_set) {
2244 _blossom_index = new IntNodeMap(_graph);
2245 _blossom_set = new BlossomSet(*_blossom_index);
2246 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2250 _node_index = new IntNodeMap(_graph);
2251 _node_heap_index = new IntArcMap(_graph);
2252 _node_data = new RangeMap<NodeData>(_node_num,
2253 NodeData(*_node_heap_index));
2257 _tree_set_index = new IntIntMap(_blossom_num);
2258 _tree_set = new TreeSet(*_tree_set_index);
2261 _delta2_index = new IntIntMap(_blossom_num);
2262 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2265 _delta3_index = new IntEdgeMap(_graph);
2266 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2269 _delta4_index = new IntIntMap(_blossom_num);
2270 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2274 void destroyStructures() {
2278 if (_node_potential) {
2279 delete _node_potential;
2282 delete _blossom_index;
2283 delete _blossom_set;
2284 delete _blossom_data;
2289 delete _node_heap_index;
2294 delete _tree_set_index;
2298 delete _delta2_index;
2302 delete _delta3_index;
2306 delete _delta4_index;
2311 void matchedToEven(int blossom, int tree) {
2312 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2313 _delta2->erase(blossom);
2316 if (!_blossom_set->trivial(blossom)) {
2317 (*_blossom_data)[blossom].pot -=
2318 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2321 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2322 n != INVALID; ++n) {
2324 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2325 int ni = (*_node_index)[n];
2327 (*_node_data)[ni].heap.clear();
2328 (*_node_data)[ni].heap_index.clear();
2330 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2332 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2333 Node v = _graph.source(e);
2334 int vb = _blossom_set->find(v);
2335 int vi = (*_node_index)[v];
2337 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2338 dualScale * _weight[e];
2340 if ((*_blossom_data)[vb].status == EVEN) {
2341 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2342 _delta3->push(e, rw / 2);
2345 typename std::map<int, Arc>::iterator it =
2346 (*_node_data)[vi].heap_index.find(tree);
2348 if (it != (*_node_data)[vi].heap_index.end()) {
2349 if ((*_node_data)[vi].heap[it->second] > rw) {
2350 (*_node_data)[vi].heap.replace(it->second, e);
2351 (*_node_data)[vi].heap.decrease(e, rw);
2355 (*_node_data)[vi].heap.push(e, rw);
2356 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2359 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2360 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2362 if ((*_blossom_data)[vb].status == MATCHED) {
2363 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2364 _delta2->push(vb, _blossom_set->classPrio(vb) -
2365 (*_blossom_data)[vb].offset);
2366 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2367 (*_blossom_data)[vb].offset){
2368 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2369 (*_blossom_data)[vb].offset);
2376 (*_blossom_data)[blossom].offset = 0;
2379 void matchedToOdd(int blossom) {
2380 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2381 _delta2->erase(blossom);
2383 (*_blossom_data)[blossom].offset += _delta_sum;
2384 if (!_blossom_set->trivial(blossom)) {
2385 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2386 (*_blossom_data)[blossom].offset);
2390 void evenToMatched(int blossom, int tree) {
2391 if (!_blossom_set->trivial(blossom)) {
2392 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2395 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2396 n != INVALID; ++n) {
2397 int ni = (*_node_index)[n];
2398 (*_node_data)[ni].pot -= _delta_sum;
2400 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2401 Node v = _graph.source(e);
2402 int vb = _blossom_set->find(v);
2403 int vi = (*_node_index)[v];
2405 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2406 dualScale * _weight[e];
2408 if (vb == blossom) {
2409 if (_delta3->state(e) == _delta3->IN_HEAP) {
2412 } else if ((*_blossom_data)[vb].status == EVEN) {
2414 if (_delta3->state(e) == _delta3->IN_HEAP) {
2418 int vt = _tree_set->find(vb);
2422 Arc r = _graph.oppositeArc(e);
2424 typename std::map<int, Arc>::iterator it =
2425 (*_node_data)[ni].heap_index.find(vt);
2427 if (it != (*_node_data)[ni].heap_index.end()) {
2428 if ((*_node_data)[ni].heap[it->second] > rw) {
2429 (*_node_data)[ni].heap.replace(it->second, r);
2430 (*_node_data)[ni].heap.decrease(r, rw);
2434 (*_node_data)[ni].heap.push(r, rw);
2435 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2438 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2439 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2441 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2442 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2443 (*_blossom_data)[blossom].offset);
2444 } else if ((*_delta2)[blossom] >
2445 _blossom_set->classPrio(blossom) -
2446 (*_blossom_data)[blossom].offset){
2447 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2448 (*_blossom_data)[blossom].offset);
2454 typename std::map<int, Arc>::iterator it =
2455 (*_node_data)[vi].heap_index.find(tree);
2457 if (it != (*_node_data)[vi].heap_index.end()) {
2458 (*_node_data)[vi].heap.erase(it->second);
2459 (*_node_data)[vi].heap_index.erase(it);
2460 if ((*_node_data)[vi].heap.empty()) {
2461 _blossom_set->increase(v, std::numeric_limits<Value>::max());
2462 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2463 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2466 if ((*_blossom_data)[vb].status == MATCHED) {
2467 if (_blossom_set->classPrio(vb) ==
2468 std::numeric_limits<Value>::max()) {
2470 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2471 (*_blossom_data)[vb].offset) {
2472 _delta2->increase(vb, _blossom_set->classPrio(vb) -
2473 (*_blossom_data)[vb].offset);
2482 void oddToMatched(int blossom) {
2483 (*_blossom_data)[blossom].offset -= _delta_sum;
2485 if (_blossom_set->classPrio(blossom) !=
2486 std::numeric_limits<Value>::max()) {
2487 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2488 (*_blossom_data)[blossom].offset);
2491 if (!_blossom_set->trivial(blossom)) {
2492 _delta4->erase(blossom);
2496 void oddToEven(int blossom, int tree) {
2497 if (!_blossom_set->trivial(blossom)) {
2498 _delta4->erase(blossom);
2499 (*_blossom_data)[blossom].pot -=
2500 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2503 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2504 n != INVALID; ++n) {
2505 int ni = (*_node_index)[n];
2507 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2509 (*_node_data)[ni].heap.clear();
2510 (*_node_data)[ni].heap_index.clear();
2511 (*_node_data)[ni].pot +=
2512 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2514 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2515 Node v = _graph.source(e);
2516 int vb = _blossom_set->find(v);
2517 int vi = (*_node_index)[v];
2519 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2520 dualScale * _weight[e];
2522 if ((*_blossom_data)[vb].status == EVEN) {
2523 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2524 _delta3->push(e, rw / 2);
2528 typename std::map<int, Arc>::iterator it =
2529 (*_node_data)[vi].heap_index.find(tree);
2531 if (it != (*_node_data)[vi].heap_index.end()) {
2532 if ((*_node_data)[vi].heap[it->second] > rw) {
2533 (*_node_data)[vi].heap.replace(it->second, e);
2534 (*_node_data)[vi].heap.decrease(e, rw);
2538 (*_node_data)[vi].heap.push(e, rw);
2539 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2542 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2543 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2545 if ((*_blossom_data)[vb].status == MATCHED) {
2546 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2547 _delta2->push(vb, _blossom_set->classPrio(vb) -
2548 (*_blossom_data)[vb].offset);
2549 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2550 (*_blossom_data)[vb].offset) {
2551 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2552 (*_blossom_data)[vb].offset);
2559 (*_blossom_data)[blossom].offset = 0;
2562 void alternatePath(int even, int tree) {
2565 evenToMatched(even, tree);
2566 (*_blossom_data)[even].status = MATCHED;
2568 while ((*_blossom_data)[even].pred != INVALID) {
2569 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2570 (*_blossom_data)[odd].status = MATCHED;
2572 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2574 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2575 (*_blossom_data)[even].status = MATCHED;
2576 evenToMatched(even, tree);
2577 (*_blossom_data)[even].next =
2578 _graph.oppositeArc((*_blossom_data)[odd].pred);
2583 void destroyTree(int tree) {
2584 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2585 if ((*_blossom_data)[b].status == EVEN) {
2586 (*_blossom_data)[b].status = MATCHED;
2587 evenToMatched(b, tree);
2588 } else if ((*_blossom_data)[b].status == ODD) {
2589 (*_blossom_data)[b].status = MATCHED;
2593 _tree_set->eraseClass(tree);
2596 void augmentOnEdge(const Edge& edge) {
2598 int left = _blossom_set->find(_graph.u(edge));
2599 int right = _blossom_set->find(_graph.v(edge));
2601 int left_tree = _tree_set->find(left);
2602 alternatePath(left, left_tree);
2603 destroyTree(left_tree);
2605 int right_tree = _tree_set->find(right);
2606 alternatePath(right, right_tree);
2607 destroyTree(right_tree);
2609 (*_blossom_data)[left].next = _graph.direct(edge, true);
2610 (*_blossom_data)[right].next = _graph.direct(edge, false);
2613 void extendOnArc(const Arc& arc) {
2614 int base = _blossom_set->find(_graph.target(arc));
2615 int tree = _tree_set->find(base);
2617 int odd = _blossom_set->find(_graph.source(arc));
2618 _tree_set->insert(odd, tree);
2619 (*_blossom_data)[odd].status = ODD;
2621 (*_blossom_data)[odd].pred = arc;
2623 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2624 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2625 _tree_set->insert(even, tree);
2626 (*_blossom_data)[even].status = EVEN;
2627 matchedToEven(even, tree);
2630 void shrinkOnEdge(const Edge& edge, int tree) {
2632 std::vector<int> left_path, right_path;
2635 std::set<int> left_set, right_set;
2636 int left = _blossom_set->find(_graph.u(edge));
2637 left_path.push_back(left);
2638 left_set.insert(left);
2640 int right = _blossom_set->find(_graph.v(edge));
2641 right_path.push_back(right);
2642 right_set.insert(right);
2646 if ((*_blossom_data)[left].pred == INVALID) break;
2649 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2650 left_path.push_back(left);
2652 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2653 left_path.push_back(left);
2655 left_set.insert(left);
2657 if (right_set.find(left) != right_set.end()) {
2662 if ((*_blossom_data)[right].pred == INVALID) break;
2665 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2666 right_path.push_back(right);
2668 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2669 right_path.push_back(right);
2671 right_set.insert(right);
2673 if (left_set.find(right) != left_set.end()) {
2681 if ((*_blossom_data)[left].pred == INVALID) {
2683 while (left_set.find(nca) == left_set.end()) {
2685 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2686 right_path.push_back(nca);
2688 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2689 right_path.push_back(nca);
2693 while (right_set.find(nca) == right_set.end()) {
2695 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2696 left_path.push_back(nca);
2698 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2699 left_path.push_back(nca);
2705 std::vector<int> subblossoms;
2708 prev = _graph.direct(edge, true);
2709 for (int i = 0; left_path[i] != nca; i += 2) {
2710 subblossoms.push_back(left_path[i]);
2711 (*_blossom_data)[left_path[i]].next = prev;
2712 _tree_set->erase(left_path[i]);
2714 subblossoms.push_back(left_path[i + 1]);
2715 (*_blossom_data)[left_path[i + 1]].status = EVEN;
2716 oddToEven(left_path[i + 1], tree);
2717 _tree_set->erase(left_path[i + 1]);
2718 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2722 while (right_path[k] != nca) ++k;
2724 subblossoms.push_back(nca);
2725 (*_blossom_data)[nca].next = prev;
2727 for (int i = k - 2; i >= 0; i -= 2) {
2728 subblossoms.push_back(right_path[i + 1]);
2729 (*_blossom_data)[right_path[i + 1]].status = EVEN;
2730 oddToEven(right_path[i + 1], tree);
2731 _tree_set->erase(right_path[i + 1]);
2733 (*_blossom_data)[right_path[i + 1]].next =
2734 (*_blossom_data)[right_path[i + 1]].pred;
2736 subblossoms.push_back(right_path[i]);
2737 _tree_set->erase(right_path[i]);
2741 _blossom_set->join(subblossoms.begin(), subblossoms.end());
2743 for (int i = 0; i < int(subblossoms.size()); ++i) {
2744 if (!_blossom_set->trivial(subblossoms[i])) {
2745 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2747 (*_blossom_data)[subblossoms[i]].status = MATCHED;
2750 (*_blossom_data)[surface].pot = -2 * _delta_sum;
2751 (*_blossom_data)[surface].offset = 0;
2752 (*_blossom_data)[surface].status = EVEN;
2753 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2754 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2756 _tree_set->insert(surface, tree);
2757 _tree_set->erase(nca);
2760 void splitBlossom(int blossom) {
2761 Arc next = (*_blossom_data)[blossom].next;
2762 Arc pred = (*_blossom_data)[blossom].pred;
2764 int tree = _tree_set->find(blossom);
2766 (*_blossom_data)[blossom].status = MATCHED;
2767 oddToMatched(blossom);
2768 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2769 _delta2->erase(blossom);
2772 std::vector<int> subblossoms;
2773 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2775 Value offset = (*_blossom_data)[blossom].offset;
2776 int b = _blossom_set->find(_graph.source(pred));
2777 int d = _blossom_set->find(_graph.source(next));
2779 int ib = -1, id = -1;
2780 for (int i = 0; i < int(subblossoms.size()); ++i) {
2781 if (subblossoms[i] == b) ib = i;
2782 if (subblossoms[i] == d) id = i;
2784 (*_blossom_data)[subblossoms[i]].offset = offset;
2785 if (!_blossom_set->trivial(subblossoms[i])) {
2786 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2788 if (_blossom_set->classPrio(subblossoms[i]) !=
2789 std::numeric_limits<Value>::max()) {
2790 _delta2->push(subblossoms[i],
2791 _blossom_set->classPrio(subblossoms[i]) -
2792 (*_blossom_data)[subblossoms[i]].offset);
2796 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2797 for (int i = (id + 1) % subblossoms.size();
2798 i != ib; i = (i + 2) % subblossoms.size()) {
2799 int sb = subblossoms[i];
2800 int tb = subblossoms[(i + 1) % subblossoms.size()];
2801 (*_blossom_data)[sb].next =
2802 _graph.oppositeArc((*_blossom_data)[tb].next);
2805 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2806 int sb = subblossoms[i];
2807 int tb = subblossoms[(i + 1) % subblossoms.size()];
2808 int ub = subblossoms[(i + 2) % subblossoms.size()];
2810 (*_blossom_data)[sb].status = ODD;
2812 _tree_set->insert(sb, tree);
2813 (*_blossom_data)[sb].pred = pred;
2814 (*_blossom_data)[sb].next =
2815 _graph.oppositeArc((*_blossom_data)[tb].next);
2817 pred = (*_blossom_data)[ub].next;
2819 (*_blossom_data)[tb].status = EVEN;
2820 matchedToEven(tb, tree);
2821 _tree_set->insert(tb, tree);
2822 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2825 (*_blossom_data)[subblossoms[id]].status = ODD;
2826 matchedToOdd(subblossoms[id]);
2827 _tree_set->insert(subblossoms[id], tree);
2828 (*_blossom_data)[subblossoms[id]].next = next;
2829 (*_blossom_data)[subblossoms[id]].pred = pred;
2833 for (int i = (ib + 1) % subblossoms.size();
2834 i != id; i = (i + 2) % subblossoms.size()) {
2835 int sb = subblossoms[i];
2836 int tb = subblossoms[(i + 1) % subblossoms.size()];
2837 (*_blossom_data)[sb].next =
2838 _graph.oppositeArc((*_blossom_data)[tb].next);
2841 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2842 int sb = subblossoms[i];
2843 int tb = subblossoms[(i + 1) % subblossoms.size()];
2844 int ub = subblossoms[(i + 2) % subblossoms.size()];
2846 (*_blossom_data)[sb].status = ODD;
2848 _tree_set->insert(sb, tree);
2849 (*_blossom_data)[sb].next = next;
2850 (*_blossom_data)[sb].pred =
2851 _graph.oppositeArc((*_blossom_data)[tb].next);
2853 (*_blossom_data)[tb].status = EVEN;
2854 matchedToEven(tb, tree);
2855 _tree_set->insert(tb, tree);
2856 (*_blossom_data)[tb].pred =
2857 (*_blossom_data)[tb].next =
2858 _graph.oppositeArc((*_blossom_data)[ub].next);
2859 next = (*_blossom_data)[ub].next;
2862 (*_blossom_data)[subblossoms[ib]].status = ODD;
2863 matchedToOdd(subblossoms[ib]);
2864 _tree_set->insert(subblossoms[ib], tree);
2865 (*_blossom_data)[subblossoms[ib]].next = next;
2866 (*_blossom_data)[subblossoms[ib]].pred = pred;
2868 _tree_set->erase(blossom);
2871 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2872 if (_blossom_set->trivial(blossom)) {
2873 int bi = (*_node_index)[base];
2874 Value pot = (*_node_data)[bi].pot;
2876 (*_matching)[base] = matching;
2877 _blossom_node_list.push_back(base);
2878 (*_node_potential)[base] = pot;
2881 Value pot = (*_blossom_data)[blossom].pot;
2882 int bn = _blossom_node_list.size();
2884 std::vector<int> subblossoms;
2885 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2886 int b = _blossom_set->find(base);
2888 for (int i = 0; i < int(subblossoms.size()); ++i) {
2889 if (subblossoms[i] == b) { ib = i; break; }
2892 for (int i = 1; i < int(subblossoms.size()); i += 2) {
2893 int sb = subblossoms[(ib + i) % subblossoms.size()];
2894 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2896 Arc m = (*_blossom_data)[tb].next;
2897 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2898 extractBlossom(tb, _graph.source(m), m);
2900 extractBlossom(subblossoms[ib], base, matching);
2902 int en = _blossom_node_list.size();
2904 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2908 void extractMatching() {
2909 std::vector<int> blossoms;
2910 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2911 blossoms.push_back(c);
2914 for (int i = 0; i < int(blossoms.size()); ++i) {
2916 Value offset = (*_blossom_data)[blossoms[i]].offset;
2917 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2918 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2919 n != INVALID; ++n) {
2920 (*_node_data)[(*_node_index)[n]].pot -= offset;
2923 Arc matching = (*_blossom_data)[blossoms[i]].next;
2924 Node base = _graph.source(matching);
2925 extractBlossom(blossoms[i], base, matching);
2931 /// \brief Constructor
2934 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2935 : _graph(graph), _weight(weight), _matching(0),
2936 _node_potential(0), _blossom_potential(), _blossom_node_list(),
2937 _node_num(0), _blossom_num(0),
2939 _blossom_index(0), _blossom_set(0), _blossom_data(0),
2940 _node_index(0), _node_heap_index(0), _node_data(0),
2941 _tree_set_index(0), _tree_set(0),
2943 _delta2_index(0), _delta2(0),
2944 _delta3_index(0), _delta3(0),
2945 _delta4_index(0), _delta4(0),
2947 _delta_sum(), _unmatched(0),
2952 ~MaxWeightedPerfectMatching() {
2953 destroyStructures();
2959 /// \name Execution Control
2960 /// The simplest way to execute the algorithm is to use the
2961 /// \ref run() member function.
2965 /// \brief Initialize the algorithm
2967 /// This function initializes the algorithm.
2971 for (ArcIt e(_graph); e != INVALID; ++e) {
2972 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2974 for (EdgeIt e(_graph); e != INVALID; ++e) {
2975 (*_delta3_index)[e] = _delta3->PRE_HEAP;
2977 for (int i = 0; i < _blossom_num; ++i) {
2978 (*_delta2_index)[i] = _delta2->PRE_HEAP;
2979 (*_delta4_index)[i] = _delta4->PRE_HEAP;
2982 _unmatched = _node_num;
2985 for (NodeIt n(_graph); n != INVALID; ++n) {
2986 Value max = - std::numeric_limits<Value>::max();
2987 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2988 if (_graph.target(e) == n) continue;
2989 if ((dualScale * _weight[e]) / 2 > max) {
2990 max = (dualScale * _weight[e]) / 2;
2993 (*_node_index)[n] = index;
2994 (*_node_data)[index].pot = max;
2996 _blossom_set->insert(n, std::numeric_limits<Value>::max());
2998 _tree_set->insert(blossom);
3000 (*_blossom_data)[blossom].status = EVEN;
3001 (*_blossom_data)[blossom].pred = INVALID;
3002 (*_blossom_data)[blossom].next = INVALID;
3003 (*_blossom_data)[blossom].pot = 0;
3004 (*_blossom_data)[blossom].offset = 0;
3007 for (EdgeIt e(_graph); e != INVALID; ++e) {
3008 int si = (*_node_index)[_graph.u(e)];
3009 int ti = (*_node_index)[_graph.v(e)];
3010 if (_graph.u(e) != _graph.v(e)) {
3011 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3012 dualScale * _weight[e]) / 2);
3017 /// \brief Initialize the algorithm with fractional matching
3019 /// This function initializes the algorithm with a fractional
3020 /// matching. This initialization is also called jumpstart heuristic.
3021 void fractionalInit() {
3024 if (_fractional == 0) {
3025 _fractional = new FractionalMatching(_graph, _weight, false);
3027 if (!_fractional->run()) {
3032 for (ArcIt e(_graph); e != INVALID; ++e) {
3033 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3035 for (EdgeIt e(_graph); e != INVALID; ++e) {
3036 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3038 for (int i = 0; i < _blossom_num; ++i) {
3039 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3040 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3046 for (NodeIt n(_graph); n != INVALID; ++n) {
3047 Value pot = _fractional->nodeValue(n);
3048 (*_node_index)[n] = index;
3049 (*_node_data)[index].pot = pot;
3051 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3053 (*_blossom_data)[blossom].status = MATCHED;
3054 (*_blossom_data)[blossom].pred = INVALID;
3055 (*_blossom_data)[blossom].next = _fractional->matching(n);
3056 (*_blossom_data)[blossom].pot = 0;
3057 (*_blossom_data)[blossom].offset = 0;
3061 typename Graph::template NodeMap<bool> processed(_graph, false);
3062 for (NodeIt n(_graph); n != INVALID; ++n) {
3063 if (processed[n]) continue;
3064 processed[n] = true;
3065 if (_fractional->matching(n) == INVALID) continue;
3067 Node v = _graph.target(_fractional->matching(n));
3069 processed[v] = true;
3070 v = _graph.target(_fractional->matching(v));
3075 std::vector<int> subblossoms(num);
3077 subblossoms[--num] = _blossom_set->find(n);
3078 v = _graph.target(_fractional->matching(n));
3080 subblossoms[--num] = _blossom_set->find(v);
3081 v = _graph.target(_fractional->matching(v));
3085 _blossom_set->join(subblossoms.begin(), subblossoms.end());
3086 (*_blossom_data)[surface].status = EVEN;
3087 (*_blossom_data)[surface].pred = INVALID;
3088 (*_blossom_data)[surface].next = INVALID;
3089 (*_blossom_data)[surface].pot = 0;
3090 (*_blossom_data)[surface].offset = 0;
3092 _tree_set->insert(surface);
3097 for (EdgeIt e(_graph); e != INVALID; ++e) {
3098 int si = (*_node_index)[_graph.u(e)];
3099 int sb = _blossom_set->find(_graph.u(e));
3100 int ti = (*_node_index)[_graph.v(e)];
3101 int tb = _blossom_set->find(_graph.v(e));
3102 if ((*_blossom_data)[sb].status == EVEN &&
3103 (*_blossom_data)[tb].status == EVEN && sb != tb) {
3104 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3105 dualScale * _weight[e]) / 2);
3109 for (NodeIt n(_graph); n != INVALID; ++n) {
3110 int nb = _blossom_set->find(n);
3111 if ((*_blossom_data)[nb].status != MATCHED) continue;
3112 int ni = (*_node_index)[n];
3114 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3115 Node v = _graph.target(e);
3116 int vb = _blossom_set->find(v);
3117 int vi = (*_node_index)[v];
3119 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3120 dualScale * _weight[e];
3122 if ((*_blossom_data)[vb].status == EVEN) {
3124 int vt = _tree_set->find(vb);
3126 typename std::map<int, Arc>::iterator it =
3127 (*_node_data)[ni].heap_index.find(vt);
3129 if (it != (*_node_data)[ni].heap_index.end()) {
3130 if ((*_node_data)[ni].heap[it->second] > rw) {
3131 (*_node_data)[ni].heap.replace(it->second, e);
3132 (*_node_data)[ni].heap.decrease(e, rw);
3136 (*_node_data)[ni].heap.push(e, rw);
3137 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
3142 if (!(*_node_data)[ni].heap.empty()) {
3143 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3144 _delta2->push(nb, _blossom_set->classPrio(nb));
3149 /// \brief Start the algorithm
3151 /// This function starts the algorithm.
3153 /// \pre \ref init() or \ref fractionalInit() must be called before
3154 /// using this function.
3160 if (_unmatched == -1) return false;
3162 while (_unmatched > 0) {
3163 Value d2 = !_delta2->empty() ?
3164 _delta2->prio() : std::numeric_limits<Value>::max();
3166 Value d3 = !_delta3->empty() ?
3167 _delta3->prio() : std::numeric_limits<Value>::max();
3169 Value d4 = !_delta4->empty() ?
3170 _delta4->prio() : std::numeric_limits<Value>::max();
3172 _delta_sum = d3; OpType ot = D3;
3173 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
3174 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3176 if (_delta_sum == std::numeric_limits<Value>::max()) {
3183 int blossom = _delta2->top();
3184 Node n = _blossom_set->classTop(blossom);
3185 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3191 Edge e = _delta3->top();
3193 int left_blossom = _blossom_set->find(_graph.u(e));
3194 int right_blossom = _blossom_set->find(_graph.v(e));
3196 if (left_blossom == right_blossom) {
3199 int left_tree = _tree_set->find(left_blossom);
3200 int right_tree = _tree_set->find(right_blossom);
3202 if (left_tree == right_tree) {
3203 shrinkOnEdge(e, left_tree);
3211 splitBlossom(_delta4->top());
3219 /// \brief Run the algorithm.
3221 /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3223 /// \note mwpm.run() is just a shortcut of the following code.
3225 /// mwpm.fractionalInit();
3235 /// \name Primal Solution
3236 /// Functions to get the primal solution, i.e. the maximum weighted
3237 /// perfect matching.\n
3238 /// Either \ref run() or \ref start() function should be called before
3243 /// \brief Return the weight of the matching.
3245 /// This function returns the weight of the found matching.
3247 /// \pre Either run() or start() must be called before using this function.
3248 Value matchingWeight() const {
3250 for (NodeIt n(_graph); n != INVALID; ++n) {
3251 if ((*_matching)[n] != INVALID) {
3252 sum += _weight[(*_matching)[n]];
3258 /// \brief Return \c true if the given edge is in the matching.
3260 /// This function returns \c true if the given edge is in the found
3263 /// \pre Either run() or start() must be called before using this function.
3264 bool matching(const Edge& edge) const {
3265 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3268 /// \brief Return the matching arc (or edge) incident to the given node.
3270 /// This function returns the matching arc (or edge) incident to the
3271 /// given node in the found matching or \c INVALID if the node is
3272 /// not covered by the matching.
3274 /// \pre Either run() or start() must be called before using this function.
3275 Arc matching(const Node& node) const {
3276 return (*_matching)[node];
3279 /// \brief Return a const reference to the matching map.
3281 /// This function returns a const reference to a node map that stores
3282 /// the matching arc (or edge) incident to each node.
3283 const MatchingMap& matchingMap() const {
3287 /// \brief Return the mate of the given node.
3289 /// This function returns the mate of the given node in the found
3290 /// matching or \c INVALID if the node is not covered by the matching.
3292 /// \pre Either run() or start() must be called before using this function.
3293 Node mate(const Node& node) const {
3294 return _graph.target((*_matching)[node]);
3299 /// \name Dual Solution
3300 /// Functions to get the dual solution.\n
3301 /// Either \ref run() or \ref start() function should be called before
3306 /// \brief Return the value of the dual solution.
3308 /// This function returns the value of the dual solution.
3309 /// It should be equal to the primal value scaled by \ref dualScale
3312 /// \pre Either run() or start() must be called before using this function.
3313 Value dualValue() const {
3315 for (NodeIt n(_graph); n != INVALID; ++n) {
3316 sum += nodeValue(n);
3318 for (int i = 0; i < blossomNum(); ++i) {
3319 sum += blossomValue(i) * (blossomSize(i) / 2);
3324 /// \brief Return the dual value (potential) of the given node.
3326 /// This function returns the dual value (potential) of the given node.
3328 /// \pre Either run() or start() must be called before using this function.
3329 Value nodeValue(const Node& n) const {
3330 return (*_node_potential)[n];
3333 /// \brief Return the number of the blossoms in the basis.
3335 /// This function returns the number of the blossoms in the basis.
3337 /// \pre Either run() or start() must be called before using this function.
3339 int blossomNum() const {
3340 return _blossom_potential.size();
3343 /// \brief Return the number of the nodes in the given blossom.
3345 /// This function returns the number of the nodes in the given blossom.
3347 /// \pre Either run() or start() must be called before using this function.
3349 int blossomSize(int k) const {
3350 return _blossom_potential[k].end - _blossom_potential[k].begin;
3353 /// \brief Return the dual value (ptential) of the given blossom.
3355 /// This function returns the dual value (ptential) of the given blossom.
3357 /// \pre Either run() or start() must be called before using this function.
3358 Value blossomValue(int k) const {
3359 return _blossom_potential[k].value;
3362 /// \brief Iterator for obtaining the nodes of a blossom.
3364 /// This class provides an iterator for obtaining the nodes of the
3365 /// given blossom. It lists a subset of the nodes.
3366 /// Before using this iterator, you must allocate a
3367 /// MaxWeightedPerfectMatching class and execute it.
3371 /// \brief Constructor.
3373 /// Constructor to get the nodes of the given variable.
3375 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3376 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3377 /// must be called before initializing this iterator.
3378 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3379 : _algorithm(&algorithm)
3381 _index = _algorithm->_blossom_potential[variable].begin;
3382 _last = _algorithm->_blossom_potential[variable].end;
3385 /// \brief Conversion to \c Node.
3387 /// Conversion to \c Node.
3388 operator Node() const {
3389 return _algorithm->_blossom_node_list[_index];
3392 /// \brief Increment operator.
3394 /// Increment operator.
3395 BlossomIt& operator++() {
3400 /// \brief Validity checking
3402 /// This function checks whether the iterator is invalid.
3403 bool operator==(Invalid) const { return _index == _last; }
3405 /// \brief Validity checking
3407 /// This function checks whether the iterator is valid.
3408 bool operator!=(Invalid) const { return _index != _last; }
3411 const MaxWeightedPerfectMatching* _algorithm;
3420 } //END OF NAMESPACE LEMON
3422 #endif //LEMON_MATCHING_H