1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2010
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);
814 if (!_node_potential) {
815 _node_potential = new NodePotential(_graph);
819 _blossom_index = new IntNodeMap(_graph);
820 _blossom_set = new BlossomSet(*_blossom_index);
821 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
822 } else if (_blossom_data->size() != _blossom_num) {
823 delete _blossom_data;
824 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
828 _node_index = new IntNodeMap(_graph);
829 _node_heap_index = new IntArcMap(_graph);
830 _node_data = new RangeMap<NodeData>(_node_num,
831 NodeData(*_node_heap_index));
834 _node_data = new RangeMap<NodeData>(_node_num,
835 NodeData(*_node_heap_index));
839 _tree_set_index = new IntIntMap(_blossom_num);
840 _tree_set = new TreeSet(*_tree_set_index);
842 _tree_set_index->resize(_blossom_num);
846 _delta1_index = new IntNodeMap(_graph);
847 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
851 _delta2_index = new IntIntMap(_blossom_num);
852 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
854 _delta2_index->resize(_blossom_num);
858 _delta3_index = new IntEdgeMap(_graph);
859 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
863 _delta4_index = new IntIntMap(_blossom_num);
864 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
866 _delta4_index->resize(_blossom_num);
870 void destroyStructures() {
874 if (_node_potential) {
875 delete _node_potential;
878 delete _blossom_index;
880 delete _blossom_data;
885 delete _node_heap_index;
890 delete _tree_set_index;
894 delete _delta1_index;
898 delete _delta2_index;
902 delete _delta3_index;
906 delete _delta4_index;
911 void matchedToEven(int blossom, int tree) {
912 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
913 _delta2->erase(blossom);
916 if (!_blossom_set->trivial(blossom)) {
917 (*_blossom_data)[blossom].pot -=
918 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
921 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
924 _blossom_set->increase(n, std::numeric_limits<Value>::max());
925 int ni = (*_node_index)[n];
927 (*_node_data)[ni].heap.clear();
928 (*_node_data)[ni].heap_index.clear();
930 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
932 _delta1->push(n, (*_node_data)[ni].pot);
934 for (InArcIt e(_graph, n); e != INVALID; ++e) {
935 Node v = _graph.source(e);
936 int vb = _blossom_set->find(v);
937 int vi = (*_node_index)[v];
939 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
940 dualScale * _weight[e];
942 if ((*_blossom_data)[vb].status == EVEN) {
943 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
944 _delta3->push(e, rw / 2);
947 typename std::map<int, Arc>::iterator it =
948 (*_node_data)[vi].heap_index.find(tree);
950 if (it != (*_node_data)[vi].heap_index.end()) {
951 if ((*_node_data)[vi].heap[it->second] > rw) {
952 (*_node_data)[vi].heap.replace(it->second, e);
953 (*_node_data)[vi].heap.decrease(e, rw);
957 (*_node_data)[vi].heap.push(e, rw);
958 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
961 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
962 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
964 if ((*_blossom_data)[vb].status == MATCHED) {
965 if (_delta2->state(vb) != _delta2->IN_HEAP) {
966 _delta2->push(vb, _blossom_set->classPrio(vb) -
967 (*_blossom_data)[vb].offset);
968 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
969 (*_blossom_data)[vb].offset) {
970 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
971 (*_blossom_data)[vb].offset);
978 (*_blossom_data)[blossom].offset = 0;
981 void matchedToOdd(int blossom) {
982 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
983 _delta2->erase(blossom);
985 (*_blossom_data)[blossom].offset += _delta_sum;
986 if (!_blossom_set->trivial(blossom)) {
987 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
988 (*_blossom_data)[blossom].offset);
992 void evenToMatched(int blossom, int tree) {
993 if (!_blossom_set->trivial(blossom)) {
994 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
997 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
999 int ni = (*_node_index)[n];
1000 (*_node_data)[ni].pot -= _delta_sum;
1004 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1005 Node v = _graph.source(e);
1006 int vb = _blossom_set->find(v);
1007 int vi = (*_node_index)[v];
1009 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1010 dualScale * _weight[e];
1012 if (vb == blossom) {
1013 if (_delta3->state(e) == _delta3->IN_HEAP) {
1016 } else if ((*_blossom_data)[vb].status == EVEN) {
1018 if (_delta3->state(e) == _delta3->IN_HEAP) {
1022 int vt = _tree_set->find(vb);
1026 Arc r = _graph.oppositeArc(e);
1028 typename std::map<int, Arc>::iterator it =
1029 (*_node_data)[ni].heap_index.find(vt);
1031 if (it != (*_node_data)[ni].heap_index.end()) {
1032 if ((*_node_data)[ni].heap[it->second] > rw) {
1033 (*_node_data)[ni].heap.replace(it->second, r);
1034 (*_node_data)[ni].heap.decrease(r, rw);
1038 (*_node_data)[ni].heap.push(r, rw);
1039 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1042 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1043 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1045 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1046 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1047 (*_blossom_data)[blossom].offset);
1048 } else if ((*_delta2)[blossom] >
1049 _blossom_set->classPrio(blossom) -
1050 (*_blossom_data)[blossom].offset){
1051 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1052 (*_blossom_data)[blossom].offset);
1058 typename std::map<int, Arc>::iterator it =
1059 (*_node_data)[vi].heap_index.find(tree);
1061 if (it != (*_node_data)[vi].heap_index.end()) {
1062 (*_node_data)[vi].heap.erase(it->second);
1063 (*_node_data)[vi].heap_index.erase(it);
1064 if ((*_node_data)[vi].heap.empty()) {
1065 _blossom_set->increase(v, std::numeric_limits<Value>::max());
1066 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1067 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1070 if ((*_blossom_data)[vb].status == MATCHED) {
1071 if (_blossom_set->classPrio(vb) ==
1072 std::numeric_limits<Value>::max()) {
1074 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1075 (*_blossom_data)[vb].offset) {
1076 _delta2->increase(vb, _blossom_set->classPrio(vb) -
1077 (*_blossom_data)[vb].offset);
1086 void oddToMatched(int blossom) {
1087 (*_blossom_data)[blossom].offset -= _delta_sum;
1089 if (_blossom_set->classPrio(blossom) !=
1090 std::numeric_limits<Value>::max()) {
1091 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1092 (*_blossom_data)[blossom].offset);
1095 if (!_blossom_set->trivial(blossom)) {
1096 _delta4->erase(blossom);
1100 void oddToEven(int blossom, int tree) {
1101 if (!_blossom_set->trivial(blossom)) {
1102 _delta4->erase(blossom);
1103 (*_blossom_data)[blossom].pot -=
1104 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1107 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1108 n != INVALID; ++n) {
1109 int ni = (*_node_index)[n];
1111 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1113 (*_node_data)[ni].heap.clear();
1114 (*_node_data)[ni].heap_index.clear();
1115 (*_node_data)[ni].pot +=
1116 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1118 _delta1->push(n, (*_node_data)[ni].pot);
1120 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1121 Node v = _graph.source(e);
1122 int vb = _blossom_set->find(v);
1123 int vi = (*_node_index)[v];
1125 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1126 dualScale * _weight[e];
1128 if ((*_blossom_data)[vb].status == EVEN) {
1129 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1130 _delta3->push(e, rw / 2);
1134 typename std::map<int, Arc>::iterator it =
1135 (*_node_data)[vi].heap_index.find(tree);
1137 if (it != (*_node_data)[vi].heap_index.end()) {
1138 if ((*_node_data)[vi].heap[it->second] > rw) {
1139 (*_node_data)[vi].heap.replace(it->second, e);
1140 (*_node_data)[vi].heap.decrease(e, rw);
1144 (*_node_data)[vi].heap.push(e, rw);
1145 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1148 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1149 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1151 if ((*_blossom_data)[vb].status == MATCHED) {
1152 if (_delta2->state(vb) != _delta2->IN_HEAP) {
1153 _delta2->push(vb, _blossom_set->classPrio(vb) -
1154 (*_blossom_data)[vb].offset);
1155 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1156 (*_blossom_data)[vb].offset) {
1157 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1158 (*_blossom_data)[vb].offset);
1165 (*_blossom_data)[blossom].offset = 0;
1168 void alternatePath(int even, int tree) {
1171 evenToMatched(even, tree);
1172 (*_blossom_data)[even].status = MATCHED;
1174 while ((*_blossom_data)[even].pred != INVALID) {
1175 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1176 (*_blossom_data)[odd].status = MATCHED;
1178 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1180 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1181 (*_blossom_data)[even].status = MATCHED;
1182 evenToMatched(even, tree);
1183 (*_blossom_data)[even].next =
1184 _graph.oppositeArc((*_blossom_data)[odd].pred);
1189 void destroyTree(int tree) {
1190 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1191 if ((*_blossom_data)[b].status == EVEN) {
1192 (*_blossom_data)[b].status = MATCHED;
1193 evenToMatched(b, tree);
1194 } else if ((*_blossom_data)[b].status == ODD) {
1195 (*_blossom_data)[b].status = MATCHED;
1199 _tree_set->eraseClass(tree);
1203 void unmatchNode(const Node& node) {
1204 int blossom = _blossom_set->find(node);
1205 int tree = _tree_set->find(blossom);
1207 alternatePath(blossom, tree);
1210 (*_blossom_data)[blossom].base = node;
1211 (*_blossom_data)[blossom].next = INVALID;
1214 void augmentOnEdge(const Edge& edge) {
1216 int left = _blossom_set->find(_graph.u(edge));
1217 int right = _blossom_set->find(_graph.v(edge));
1219 int left_tree = _tree_set->find(left);
1220 alternatePath(left, left_tree);
1221 destroyTree(left_tree);
1223 int right_tree = _tree_set->find(right);
1224 alternatePath(right, right_tree);
1225 destroyTree(right_tree);
1227 (*_blossom_data)[left].next = _graph.direct(edge, true);
1228 (*_blossom_data)[right].next = _graph.direct(edge, false);
1231 void augmentOnArc(const Arc& arc) {
1233 int left = _blossom_set->find(_graph.source(arc));
1234 int right = _blossom_set->find(_graph.target(arc));
1236 (*_blossom_data)[left].status = MATCHED;
1238 int right_tree = _tree_set->find(right);
1239 alternatePath(right, right_tree);
1240 destroyTree(right_tree);
1242 (*_blossom_data)[left].next = arc;
1243 (*_blossom_data)[right].next = _graph.oppositeArc(arc);
1246 void extendOnArc(const Arc& arc) {
1247 int base = _blossom_set->find(_graph.target(arc));
1248 int tree = _tree_set->find(base);
1250 int odd = _blossom_set->find(_graph.source(arc));
1251 _tree_set->insert(odd, tree);
1252 (*_blossom_data)[odd].status = ODD;
1254 (*_blossom_data)[odd].pred = arc;
1256 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1257 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1258 _tree_set->insert(even, tree);
1259 (*_blossom_data)[even].status = EVEN;
1260 matchedToEven(even, tree);
1263 void shrinkOnEdge(const Edge& edge, int tree) {
1265 std::vector<int> left_path, right_path;
1268 std::set<int> left_set, right_set;
1269 int left = _blossom_set->find(_graph.u(edge));
1270 left_path.push_back(left);
1271 left_set.insert(left);
1273 int right = _blossom_set->find(_graph.v(edge));
1274 right_path.push_back(right);
1275 right_set.insert(right);
1279 if ((*_blossom_data)[left].pred == INVALID) break;
1282 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1283 left_path.push_back(left);
1285 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1286 left_path.push_back(left);
1288 left_set.insert(left);
1290 if (right_set.find(left) != right_set.end()) {
1295 if ((*_blossom_data)[right].pred == INVALID) break;
1298 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1299 right_path.push_back(right);
1301 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1302 right_path.push_back(right);
1304 right_set.insert(right);
1306 if (left_set.find(right) != left_set.end()) {
1314 if ((*_blossom_data)[left].pred == INVALID) {
1316 while (left_set.find(nca) == left_set.end()) {
1318 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1319 right_path.push_back(nca);
1321 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1322 right_path.push_back(nca);
1326 while (right_set.find(nca) == right_set.end()) {
1328 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1329 left_path.push_back(nca);
1331 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1332 left_path.push_back(nca);
1338 std::vector<int> subblossoms;
1341 prev = _graph.direct(edge, true);
1342 for (int i = 0; left_path[i] != nca; i += 2) {
1343 subblossoms.push_back(left_path[i]);
1344 (*_blossom_data)[left_path[i]].next = prev;
1345 _tree_set->erase(left_path[i]);
1347 subblossoms.push_back(left_path[i + 1]);
1348 (*_blossom_data)[left_path[i + 1]].status = EVEN;
1349 oddToEven(left_path[i + 1], tree);
1350 _tree_set->erase(left_path[i + 1]);
1351 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1355 while (right_path[k] != nca) ++k;
1357 subblossoms.push_back(nca);
1358 (*_blossom_data)[nca].next = prev;
1360 for (int i = k - 2; i >= 0; i -= 2) {
1361 subblossoms.push_back(right_path[i + 1]);
1362 (*_blossom_data)[right_path[i + 1]].status = EVEN;
1363 oddToEven(right_path[i + 1], tree);
1364 _tree_set->erase(right_path[i + 1]);
1366 (*_blossom_data)[right_path[i + 1]].next =
1367 (*_blossom_data)[right_path[i + 1]].pred;
1369 subblossoms.push_back(right_path[i]);
1370 _tree_set->erase(right_path[i]);
1374 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1376 for (int i = 0; i < int(subblossoms.size()); ++i) {
1377 if (!_blossom_set->trivial(subblossoms[i])) {
1378 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1380 (*_blossom_data)[subblossoms[i]].status = MATCHED;
1383 (*_blossom_data)[surface].pot = -2 * _delta_sum;
1384 (*_blossom_data)[surface].offset = 0;
1385 (*_blossom_data)[surface].status = EVEN;
1386 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1387 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1389 _tree_set->insert(surface, tree);
1390 _tree_set->erase(nca);
1393 void splitBlossom(int blossom) {
1394 Arc next = (*_blossom_data)[blossom].next;
1395 Arc pred = (*_blossom_data)[blossom].pred;
1397 int tree = _tree_set->find(blossom);
1399 (*_blossom_data)[blossom].status = MATCHED;
1400 oddToMatched(blossom);
1401 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1402 _delta2->erase(blossom);
1405 std::vector<int> subblossoms;
1406 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1408 Value offset = (*_blossom_data)[blossom].offset;
1409 int b = _blossom_set->find(_graph.source(pred));
1410 int d = _blossom_set->find(_graph.source(next));
1412 int ib = -1, id = -1;
1413 for (int i = 0; i < int(subblossoms.size()); ++i) {
1414 if (subblossoms[i] == b) ib = i;
1415 if (subblossoms[i] == d) id = i;
1417 (*_blossom_data)[subblossoms[i]].offset = offset;
1418 if (!_blossom_set->trivial(subblossoms[i])) {
1419 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1421 if (_blossom_set->classPrio(subblossoms[i]) !=
1422 std::numeric_limits<Value>::max()) {
1423 _delta2->push(subblossoms[i],
1424 _blossom_set->classPrio(subblossoms[i]) -
1425 (*_blossom_data)[subblossoms[i]].offset);
1429 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1430 for (int i = (id + 1) % subblossoms.size();
1431 i != ib; i = (i + 2) % subblossoms.size()) {
1432 int sb = subblossoms[i];
1433 int tb = subblossoms[(i + 1) % subblossoms.size()];
1434 (*_blossom_data)[sb].next =
1435 _graph.oppositeArc((*_blossom_data)[tb].next);
1438 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1439 int sb = subblossoms[i];
1440 int tb = subblossoms[(i + 1) % subblossoms.size()];
1441 int ub = subblossoms[(i + 2) % subblossoms.size()];
1443 (*_blossom_data)[sb].status = ODD;
1445 _tree_set->insert(sb, tree);
1446 (*_blossom_data)[sb].pred = pred;
1447 (*_blossom_data)[sb].next =
1448 _graph.oppositeArc((*_blossom_data)[tb].next);
1450 pred = (*_blossom_data)[ub].next;
1452 (*_blossom_data)[tb].status = EVEN;
1453 matchedToEven(tb, tree);
1454 _tree_set->insert(tb, tree);
1455 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1458 (*_blossom_data)[subblossoms[id]].status = ODD;
1459 matchedToOdd(subblossoms[id]);
1460 _tree_set->insert(subblossoms[id], tree);
1461 (*_blossom_data)[subblossoms[id]].next = next;
1462 (*_blossom_data)[subblossoms[id]].pred = pred;
1466 for (int i = (ib + 1) % subblossoms.size();
1467 i != id; i = (i + 2) % subblossoms.size()) {
1468 int sb = subblossoms[i];
1469 int tb = subblossoms[(i + 1) % subblossoms.size()];
1470 (*_blossom_data)[sb].next =
1471 _graph.oppositeArc((*_blossom_data)[tb].next);
1474 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1475 int sb = subblossoms[i];
1476 int tb = subblossoms[(i + 1) % subblossoms.size()];
1477 int ub = subblossoms[(i + 2) % subblossoms.size()];
1479 (*_blossom_data)[sb].status = ODD;
1481 _tree_set->insert(sb, tree);
1482 (*_blossom_data)[sb].next = next;
1483 (*_blossom_data)[sb].pred =
1484 _graph.oppositeArc((*_blossom_data)[tb].next);
1486 (*_blossom_data)[tb].status = EVEN;
1487 matchedToEven(tb, tree);
1488 _tree_set->insert(tb, tree);
1489 (*_blossom_data)[tb].pred =
1490 (*_blossom_data)[tb].next =
1491 _graph.oppositeArc((*_blossom_data)[ub].next);
1492 next = (*_blossom_data)[ub].next;
1495 (*_blossom_data)[subblossoms[ib]].status = ODD;
1496 matchedToOdd(subblossoms[ib]);
1497 _tree_set->insert(subblossoms[ib], tree);
1498 (*_blossom_data)[subblossoms[ib]].next = next;
1499 (*_blossom_data)[subblossoms[ib]].pred = pred;
1501 _tree_set->erase(blossom);
1504 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1505 if (_blossom_set->trivial(blossom)) {
1506 int bi = (*_node_index)[base];
1507 Value pot = (*_node_data)[bi].pot;
1509 (*_matching)[base] = matching;
1510 _blossom_node_list.push_back(base);
1511 (*_node_potential)[base] = pot;
1514 Value pot = (*_blossom_data)[blossom].pot;
1515 int bn = _blossom_node_list.size();
1517 std::vector<int> subblossoms;
1518 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1519 int b = _blossom_set->find(base);
1521 for (int i = 0; i < int(subblossoms.size()); ++i) {
1522 if (subblossoms[i] == b) { ib = i; break; }
1525 for (int i = 1; i < int(subblossoms.size()); i += 2) {
1526 int sb = subblossoms[(ib + i) % subblossoms.size()];
1527 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1529 Arc m = (*_blossom_data)[tb].next;
1530 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1531 extractBlossom(tb, _graph.source(m), m);
1533 extractBlossom(subblossoms[ib], base, matching);
1535 int en = _blossom_node_list.size();
1537 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1541 void extractMatching() {
1542 std::vector<int> blossoms;
1543 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1544 blossoms.push_back(c);
1547 for (int i = 0; i < int(blossoms.size()); ++i) {
1548 if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1550 Value offset = (*_blossom_data)[blossoms[i]].offset;
1551 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1552 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1553 n != INVALID; ++n) {
1554 (*_node_data)[(*_node_index)[n]].pot -= offset;
1557 Arc matching = (*_blossom_data)[blossoms[i]].next;
1558 Node base = _graph.source(matching);
1559 extractBlossom(blossoms[i], base, matching);
1561 Node base = (*_blossom_data)[blossoms[i]].base;
1562 extractBlossom(blossoms[i], base, INVALID);
1569 /// \brief Constructor
1572 MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1573 : _graph(graph), _weight(weight), _matching(0),
1574 _node_potential(0), _blossom_potential(), _blossom_node_list(),
1575 _node_num(0), _blossom_num(0),
1577 _blossom_index(0), _blossom_set(0), _blossom_data(0),
1578 _node_index(0), _node_heap_index(0), _node_data(0),
1579 _tree_set_index(0), _tree_set(0),
1581 _delta1_index(0), _delta1(0),
1582 _delta2_index(0), _delta2(0),
1583 _delta3_index(0), _delta3(0),
1584 _delta4_index(0), _delta4(0),
1586 _delta_sum(), _unmatched(0),
1591 ~MaxWeightedMatching() {
1592 destroyStructures();
1598 /// \name Execution Control
1599 /// The simplest way to execute the algorithm is to use the
1600 /// \ref run() member function.
1604 /// \brief Initialize the algorithm
1606 /// This function initializes the algorithm.
1610 _blossom_node_list.clear();
1611 _blossom_potential.clear();
1613 for (ArcIt e(_graph); e != INVALID; ++e) {
1614 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1616 for (NodeIt n(_graph); n != INVALID; ++n) {
1617 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1619 for (EdgeIt e(_graph); e != INVALID; ++e) {
1620 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1622 for (int i = 0; i < _blossom_num; ++i) {
1623 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1624 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1627 _unmatched = _node_num;
1633 _blossom_set->clear();
1637 for (NodeIt n(_graph); n != INVALID; ++n) {
1639 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1640 if (_graph.target(e) == n) continue;
1641 if ((dualScale * _weight[e]) / 2 > max) {
1642 max = (dualScale * _weight[e]) / 2;
1645 (*_node_index)[n] = index;
1646 (*_node_data)[index].heap_index.clear();
1647 (*_node_data)[index].heap.clear();
1648 (*_node_data)[index].pot = max;
1649 _delta1->push(n, max);
1651 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1653 _tree_set->insert(blossom);
1655 (*_blossom_data)[blossom].status = EVEN;
1656 (*_blossom_data)[blossom].pred = INVALID;
1657 (*_blossom_data)[blossom].next = INVALID;
1658 (*_blossom_data)[blossom].pot = 0;
1659 (*_blossom_data)[blossom].offset = 0;
1662 for (EdgeIt e(_graph); e != INVALID; ++e) {
1663 int si = (*_node_index)[_graph.u(e)];
1664 int ti = (*_node_index)[_graph.v(e)];
1665 if (_graph.u(e) != _graph.v(e)) {
1666 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1667 dualScale * _weight[e]) / 2);
1672 /// \brief Initialize the algorithm with fractional matching
1674 /// This function initializes the algorithm with a fractional
1675 /// matching. This initialization is also called jumpstart heuristic.
1676 void fractionalInit() {
1679 _blossom_node_list.clear();
1680 _blossom_potential.clear();
1682 if (_fractional == 0) {
1683 _fractional = new FractionalMatching(_graph, _weight, false);
1687 for (ArcIt e(_graph); e != INVALID; ++e) {
1688 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1690 for (NodeIt n(_graph); n != INVALID; ++n) {
1691 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1693 for (EdgeIt e(_graph); e != INVALID; ++e) {
1694 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1696 for (int i = 0; i < _blossom_num; ++i) {
1697 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1698 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1707 _blossom_set->clear();
1711 for (NodeIt n(_graph); n != INVALID; ++n) {
1712 Value pot = _fractional->nodeValue(n);
1713 (*_node_index)[n] = index;
1714 (*_node_data)[index].pot = pot;
1715 (*_node_data)[index].heap_index.clear();
1716 (*_node_data)[index].heap.clear();
1718 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1720 (*_blossom_data)[blossom].status = MATCHED;
1721 (*_blossom_data)[blossom].pred = INVALID;
1722 (*_blossom_data)[blossom].next = _fractional->matching(n);
1723 if (_fractional->matching(n) == INVALID) {
1724 (*_blossom_data)[blossom].base = n;
1726 (*_blossom_data)[blossom].pot = 0;
1727 (*_blossom_data)[blossom].offset = 0;
1731 typename Graph::template NodeMap<bool> processed(_graph, false);
1732 for (NodeIt n(_graph); n != INVALID; ++n) {
1733 if (processed[n]) continue;
1734 processed[n] = true;
1735 if (_fractional->matching(n) == INVALID) continue;
1737 Node v = _graph.target(_fractional->matching(n));
1739 processed[v] = true;
1740 v = _graph.target(_fractional->matching(v));
1745 std::vector<int> subblossoms(num);
1747 subblossoms[--num] = _blossom_set->find(n);
1748 _delta1->push(n, _fractional->nodeValue(n));
1749 v = _graph.target(_fractional->matching(n));
1751 subblossoms[--num] = _blossom_set->find(v);
1752 _delta1->push(v, _fractional->nodeValue(v));
1753 v = _graph.target(_fractional->matching(v));
1757 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1758 (*_blossom_data)[surface].status = EVEN;
1759 (*_blossom_data)[surface].pred = INVALID;
1760 (*_blossom_data)[surface].next = INVALID;
1761 (*_blossom_data)[surface].pot = 0;
1762 (*_blossom_data)[surface].offset = 0;
1764 _tree_set->insert(surface);
1769 for (EdgeIt e(_graph); e != INVALID; ++e) {
1770 int si = (*_node_index)[_graph.u(e)];
1771 int sb = _blossom_set->find(_graph.u(e));
1772 int ti = (*_node_index)[_graph.v(e)];
1773 int tb = _blossom_set->find(_graph.v(e));
1774 if ((*_blossom_data)[sb].status == EVEN &&
1775 (*_blossom_data)[tb].status == EVEN && sb != tb) {
1776 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1777 dualScale * _weight[e]) / 2);
1781 for (NodeIt n(_graph); n != INVALID; ++n) {
1782 int nb = _blossom_set->find(n);
1783 if ((*_blossom_data)[nb].status != MATCHED) continue;
1784 int ni = (*_node_index)[n];
1786 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1787 Node v = _graph.target(e);
1788 int vb = _blossom_set->find(v);
1789 int vi = (*_node_index)[v];
1791 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1792 dualScale * _weight[e];
1794 if ((*_blossom_data)[vb].status == EVEN) {
1796 int vt = _tree_set->find(vb);
1798 typename std::map<int, Arc>::iterator it =
1799 (*_node_data)[ni].heap_index.find(vt);
1801 if (it != (*_node_data)[ni].heap_index.end()) {
1802 if ((*_node_data)[ni].heap[it->second] > rw) {
1803 (*_node_data)[ni].heap.replace(it->second, e);
1804 (*_node_data)[ni].heap.decrease(e, rw);
1808 (*_node_data)[ni].heap.push(e, rw);
1809 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
1814 if (!(*_node_data)[ni].heap.empty()) {
1815 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1816 _delta2->push(nb, _blossom_set->classPrio(nb));
1821 /// \brief Start the algorithm
1823 /// This function starts the algorithm.
1825 /// \pre \ref init() or \ref fractionalInit() must be called
1826 /// before using this function.
1832 while (_unmatched > 0) {
1833 Value d1 = !_delta1->empty() ?
1834 _delta1->prio() : std::numeric_limits<Value>::max();
1836 Value d2 = !_delta2->empty() ?
1837 _delta2->prio() : std::numeric_limits<Value>::max();
1839 Value d3 = !_delta3->empty() ?
1840 _delta3->prio() : std::numeric_limits<Value>::max();
1842 Value d4 = !_delta4->empty() ?
1843 _delta4->prio() : std::numeric_limits<Value>::max();
1845 _delta_sum = d3; OpType ot = D3;
1846 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1847 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1848 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1853 Node n = _delta1->top();
1860 int blossom = _delta2->top();
1861 Node n = _blossom_set->classTop(blossom);
1862 Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1863 if ((*_blossom_data)[blossom].next == INVALID) {
1873 Edge e = _delta3->top();
1875 int left_blossom = _blossom_set->find(_graph.u(e));
1876 int right_blossom = _blossom_set->find(_graph.v(e));
1878 if (left_blossom == right_blossom) {
1881 int left_tree = _tree_set->find(left_blossom);
1882 int right_tree = _tree_set->find(right_blossom);
1884 if (left_tree == right_tree) {
1885 shrinkOnEdge(e, left_tree);
1893 splitBlossom(_delta4->top());
1900 /// \brief Run the algorithm.
1902 /// This method runs the \c %MaxWeightedMatching algorithm.
1904 /// \note mwm.run() is just a shortcut of the following code.
1906 /// mwm.fractionalInit();
1916 /// \name Primal Solution
1917 /// Functions to get the primal solution, i.e. the maximum weighted
1919 /// Either \ref run() or \ref start() function should be called before
1924 /// \brief Return the weight of the matching.
1926 /// This function returns the weight of the found matching.
1928 /// \pre Either run() or start() must be called before using this function.
1929 Value matchingWeight() const {
1931 for (NodeIt n(_graph); n != INVALID; ++n) {
1932 if ((*_matching)[n] != INVALID) {
1933 sum += _weight[(*_matching)[n]];
1939 /// \brief Return the size (cardinality) of the matching.
1941 /// This function returns the size (cardinality) of the found matching.
1943 /// \pre Either run() or start() must be called before using this function.
1944 int matchingSize() const {
1946 for (NodeIt n(_graph); n != INVALID; ++n) {
1947 if ((*_matching)[n] != INVALID) {
1954 /// \brief Return \c true if the given edge is in the matching.
1956 /// This function returns \c true if the given edge is in the found
1959 /// \pre Either run() or start() must be called before using this function.
1960 bool matching(const Edge& edge) const {
1961 return edge == (*_matching)[_graph.u(edge)];
1964 /// \brief Return the matching arc (or edge) incident to the given node.
1966 /// This function returns the matching arc (or edge) incident to the
1967 /// given node in the found matching or \c INVALID if the node is
1968 /// not covered by the matching.
1970 /// \pre Either run() or start() must be called before using this function.
1971 Arc matching(const Node& node) const {
1972 return (*_matching)[node];
1975 /// \brief Return a const reference to the matching map.
1977 /// This function returns a const reference to a node map that stores
1978 /// the matching arc (or edge) incident to each node.
1979 const MatchingMap& matchingMap() const {
1983 /// \brief Return the mate of the given node.
1985 /// This function returns the mate of the given node in the found
1986 /// matching or \c INVALID if the node is not covered by the matching.
1988 /// \pre Either run() or start() must be called before using this function.
1989 Node mate(const Node& node) const {
1990 return (*_matching)[node] != INVALID ?
1991 _graph.target((*_matching)[node]) : INVALID;
1996 /// \name Dual Solution
1997 /// Functions to get the dual solution.\n
1998 /// Either \ref run() or \ref start() function should be called before
2003 /// \brief Return the value of the dual solution.
2005 /// This function returns the value of the dual solution.
2006 /// It should be equal to the primal value scaled by \ref dualScale
2009 /// \pre Either run() or start() must be called before using this function.
2010 Value dualValue() const {
2012 for (NodeIt n(_graph); n != INVALID; ++n) {
2013 sum += nodeValue(n);
2015 for (int i = 0; i < blossomNum(); ++i) {
2016 sum += blossomValue(i) * (blossomSize(i) / 2);
2021 /// \brief Return the dual value (potential) of the given node.
2023 /// This function returns the dual value (potential) of the given node.
2025 /// \pre Either run() or start() must be called before using this function.
2026 Value nodeValue(const Node& n) const {
2027 return (*_node_potential)[n];
2030 /// \brief Return the number of the blossoms in the basis.
2032 /// This function returns the number of the blossoms in the basis.
2034 /// \pre Either run() or start() must be called before using this function.
2036 int blossomNum() const {
2037 return _blossom_potential.size();
2040 /// \brief Return the number of the nodes in the given blossom.
2042 /// This function returns the number of the nodes in the given blossom.
2044 /// \pre Either run() or start() must be called before using this function.
2046 int blossomSize(int k) const {
2047 return _blossom_potential[k].end - _blossom_potential[k].begin;
2050 /// \brief Return the dual value (ptential) of the given blossom.
2052 /// This function returns the dual value (ptential) of the given blossom.
2054 /// \pre Either run() or start() must be called before using this function.
2055 Value blossomValue(int k) const {
2056 return _blossom_potential[k].value;
2059 /// \brief Iterator for obtaining the nodes of a blossom.
2061 /// This class provides an iterator for obtaining the nodes of the
2062 /// given blossom. It lists a subset of the nodes.
2063 /// Before using this iterator, you must allocate a
2064 /// MaxWeightedMatching class and execute it.
2068 /// \brief Constructor.
2070 /// Constructor to get the nodes of the given variable.
2072 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2073 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
2074 /// called before initializing this iterator.
2075 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
2076 : _algorithm(&algorithm)
2078 _index = _algorithm->_blossom_potential[variable].begin;
2079 _last = _algorithm->_blossom_potential[variable].end;
2082 /// \brief Conversion to \c Node.
2084 /// Conversion to \c Node.
2085 operator Node() const {
2086 return _algorithm->_blossom_node_list[_index];
2089 /// \brief Increment operator.
2091 /// Increment operator.
2092 BlossomIt& operator++() {
2097 /// \brief Validity checking
2099 /// Checks whether the iterator is invalid.
2100 bool operator==(Invalid) const { return _index == _last; }
2102 /// \brief Validity checking
2104 /// Checks whether the iterator is valid.
2105 bool operator!=(Invalid) const { return _index != _last; }
2108 const MaxWeightedMatching* _algorithm;
2117 /// \ingroup matching
2119 /// \brief Weighted perfect matching in general graphs
2121 /// This class provides an efficient implementation of Edmond's
2122 /// maximum weighted perfect matching algorithm. The implementation
2123 /// is based on extensive use of priority queues and provides
2124 /// \f$O(nm\log n)\f$ time complexity.
2126 /// The maximum weighted perfect matching problem is to find a subset of
2127 /// the edges in an undirected graph with maximum overall weight for which
2128 /// each node has exactly one incident edge.
2129 /// It can be formulated with the following linear program.
2130 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2131 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2132 \quad \forall B\in\mathcal{O}\f] */
2133 /// \f[x_e \ge 0\quad \forall e\in E\f]
2134 /// \f[\max \sum_{e\in E}x_ew_e\f]
2135 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2136 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2137 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2138 /// subsets of the nodes.
2140 /// The algorithm calculates an optimal matching and a proof of the
2141 /// optimality. The solution of the dual problem can be used to check
2142 /// the result of the algorithm. The dual linear problem is the
2144 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2145 w_{uv} \quad \forall uv\in E\f] */
2146 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2147 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2148 \frac{\vert B \vert - 1}{2}z_B\f] */
2150 /// The algorithm can be executed with the run() function.
2151 /// After it the matching (the primal solution) and the dual solution
2152 /// can be obtained using the query functions and the
2153 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2154 /// which is able to iterate on the nodes of a blossom.
2155 /// If the value type is integer, then the dual solution is multiplied
2156 /// by \ref MaxWeightedMatching::dualScale "4".
2158 /// \tparam GR The undirected graph type the algorithm runs on.
2159 /// \tparam WM The type edge weight map. The default type is
2160 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2162 template <typename GR, typename WM>
2164 template <typename GR,
2165 typename WM = typename GR::template EdgeMap<int> >
2167 class MaxWeightedPerfectMatching {
2170 /// The graph type of the algorithm
2172 /// The type of the edge weight map
2173 typedef WM WeightMap;
2174 /// The value type of the edge weights
2175 typedef typename WeightMap::Value Value;
2177 /// \brief Scaling factor for dual solution
2179 /// Scaling factor for dual solution, it is equal to 4 or 1
2180 /// according to the value type.
2181 static const int dualScale =
2182 std::numeric_limits<Value>::is_integer ? 4 : 1;
2184 /// The type of the matching map
2185 typedef typename Graph::template NodeMap<typename Graph::Arc>
2190 TEMPLATE_GRAPH_TYPEDEFS(Graph);
2192 typedef typename Graph::template NodeMap<Value> NodePotential;
2193 typedef std::vector<Node> BlossomNodeList;
2195 struct BlossomVariable {
2199 BlossomVariable(int _begin, int _end, Value _value)
2200 : begin(_begin), end(_end), value(_value) {}
2204 typedef std::vector<BlossomVariable> BlossomPotential;
2206 const Graph& _graph;
2207 const WeightMap& _weight;
2209 MatchingMap* _matching;
2211 NodePotential* _node_potential;
2213 BlossomPotential _blossom_potential;
2214 BlossomNodeList _blossom_node_list;
2219 typedef RangeMap<int> IntIntMap;
2222 EVEN = -1, MATCHED = 0, ODD = 1
2225 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2226 struct BlossomData {
2233 IntNodeMap *_blossom_index;
2234 BlossomSet *_blossom_set;
2235 RangeMap<BlossomData>* _blossom_data;
2237 IntNodeMap *_node_index;
2238 IntArcMap *_node_heap_index;
2242 NodeData(IntArcMap& node_heap_index)
2243 : heap(node_heap_index) {}
2247 BinHeap<Value, IntArcMap> heap;
2248 std::map<int, Arc> heap_index;
2253 RangeMap<NodeData>* _node_data;
2255 typedef ExtendFindEnum<IntIntMap> TreeSet;
2257 IntIntMap *_tree_set_index;
2260 IntIntMap *_delta2_index;
2261 BinHeap<Value, IntIntMap> *_delta2;
2263 IntEdgeMap *_delta3_index;
2264 BinHeap<Value, IntEdgeMap> *_delta3;
2266 IntIntMap *_delta4_index;
2267 BinHeap<Value, IntIntMap> *_delta4;
2272 typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>
2274 FractionalMatching *_fractional;
2276 void createStructures() {
2277 _node_num = countNodes(_graph);
2278 _blossom_num = _node_num * 3 / 2;
2281 _matching = new MatchingMap(_graph);
2284 if (!_node_potential) {
2285 _node_potential = new NodePotential(_graph);
2288 if (!_blossom_set) {
2289 _blossom_index = new IntNodeMap(_graph);
2290 _blossom_set = new BlossomSet(*_blossom_index);
2291 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2292 } else if (_blossom_data->size() != _blossom_num) {
2293 delete _blossom_data;
2294 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2298 _node_index = new IntNodeMap(_graph);
2299 _node_heap_index = new IntArcMap(_graph);
2300 _node_data = new RangeMap<NodeData>(_node_num,
2301 NodeData(*_node_heap_index));
2302 } else if (_node_data->size() != _node_num) {
2304 _node_data = new RangeMap<NodeData>(_node_num,
2305 NodeData(*_node_heap_index));
2309 _tree_set_index = new IntIntMap(_blossom_num);
2310 _tree_set = new TreeSet(*_tree_set_index);
2312 _tree_set_index->resize(_blossom_num);
2316 _delta2_index = new IntIntMap(_blossom_num);
2317 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2319 _delta2_index->resize(_blossom_num);
2323 _delta3_index = new IntEdgeMap(_graph);
2324 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2328 _delta4_index = new IntIntMap(_blossom_num);
2329 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2331 _delta4_index->resize(_blossom_num);
2335 void destroyStructures() {
2339 if (_node_potential) {
2340 delete _node_potential;
2343 delete _blossom_index;
2344 delete _blossom_set;
2345 delete _blossom_data;
2350 delete _node_heap_index;
2355 delete _tree_set_index;
2359 delete _delta2_index;
2363 delete _delta3_index;
2367 delete _delta4_index;
2372 void matchedToEven(int blossom, int tree) {
2373 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2374 _delta2->erase(blossom);
2377 if (!_blossom_set->trivial(blossom)) {
2378 (*_blossom_data)[blossom].pot -=
2379 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2382 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2383 n != INVALID; ++n) {
2385 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2386 int ni = (*_node_index)[n];
2388 (*_node_data)[ni].heap.clear();
2389 (*_node_data)[ni].heap_index.clear();
2391 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2393 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2394 Node v = _graph.source(e);
2395 int vb = _blossom_set->find(v);
2396 int vi = (*_node_index)[v];
2398 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2399 dualScale * _weight[e];
2401 if ((*_blossom_data)[vb].status == EVEN) {
2402 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2403 _delta3->push(e, rw / 2);
2406 typename std::map<int, Arc>::iterator it =
2407 (*_node_data)[vi].heap_index.find(tree);
2409 if (it != (*_node_data)[vi].heap_index.end()) {
2410 if ((*_node_data)[vi].heap[it->second] > rw) {
2411 (*_node_data)[vi].heap.replace(it->second, e);
2412 (*_node_data)[vi].heap.decrease(e, rw);
2416 (*_node_data)[vi].heap.push(e, rw);
2417 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2420 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2421 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2423 if ((*_blossom_data)[vb].status == MATCHED) {
2424 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2425 _delta2->push(vb, _blossom_set->classPrio(vb) -
2426 (*_blossom_data)[vb].offset);
2427 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2428 (*_blossom_data)[vb].offset){
2429 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2430 (*_blossom_data)[vb].offset);
2437 (*_blossom_data)[blossom].offset = 0;
2440 void matchedToOdd(int blossom) {
2441 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2442 _delta2->erase(blossom);
2444 (*_blossom_data)[blossom].offset += _delta_sum;
2445 if (!_blossom_set->trivial(blossom)) {
2446 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2447 (*_blossom_data)[blossom].offset);
2451 void evenToMatched(int blossom, int tree) {
2452 if (!_blossom_set->trivial(blossom)) {
2453 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2456 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2457 n != INVALID; ++n) {
2458 int ni = (*_node_index)[n];
2459 (*_node_data)[ni].pot -= _delta_sum;
2461 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2462 Node v = _graph.source(e);
2463 int vb = _blossom_set->find(v);
2464 int vi = (*_node_index)[v];
2466 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2467 dualScale * _weight[e];
2469 if (vb == blossom) {
2470 if (_delta3->state(e) == _delta3->IN_HEAP) {
2473 } else if ((*_blossom_data)[vb].status == EVEN) {
2475 if (_delta3->state(e) == _delta3->IN_HEAP) {
2479 int vt = _tree_set->find(vb);
2483 Arc r = _graph.oppositeArc(e);
2485 typename std::map<int, Arc>::iterator it =
2486 (*_node_data)[ni].heap_index.find(vt);
2488 if (it != (*_node_data)[ni].heap_index.end()) {
2489 if ((*_node_data)[ni].heap[it->second] > rw) {
2490 (*_node_data)[ni].heap.replace(it->second, r);
2491 (*_node_data)[ni].heap.decrease(r, rw);
2495 (*_node_data)[ni].heap.push(r, rw);
2496 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2499 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2500 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2502 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2503 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2504 (*_blossom_data)[blossom].offset);
2505 } else if ((*_delta2)[blossom] >
2506 _blossom_set->classPrio(blossom) -
2507 (*_blossom_data)[blossom].offset){
2508 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2509 (*_blossom_data)[blossom].offset);
2515 typename std::map<int, Arc>::iterator it =
2516 (*_node_data)[vi].heap_index.find(tree);
2518 if (it != (*_node_data)[vi].heap_index.end()) {
2519 (*_node_data)[vi].heap.erase(it->second);
2520 (*_node_data)[vi].heap_index.erase(it);
2521 if ((*_node_data)[vi].heap.empty()) {
2522 _blossom_set->increase(v, std::numeric_limits<Value>::max());
2523 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2524 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2527 if ((*_blossom_data)[vb].status == MATCHED) {
2528 if (_blossom_set->classPrio(vb) ==
2529 std::numeric_limits<Value>::max()) {
2531 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2532 (*_blossom_data)[vb].offset) {
2533 _delta2->increase(vb, _blossom_set->classPrio(vb) -
2534 (*_blossom_data)[vb].offset);
2543 void oddToMatched(int blossom) {
2544 (*_blossom_data)[blossom].offset -= _delta_sum;
2546 if (_blossom_set->classPrio(blossom) !=
2547 std::numeric_limits<Value>::max()) {
2548 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2549 (*_blossom_data)[blossom].offset);
2552 if (!_blossom_set->trivial(blossom)) {
2553 _delta4->erase(blossom);
2557 void oddToEven(int blossom, int tree) {
2558 if (!_blossom_set->trivial(blossom)) {
2559 _delta4->erase(blossom);
2560 (*_blossom_data)[blossom].pot -=
2561 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2564 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2565 n != INVALID; ++n) {
2566 int ni = (*_node_index)[n];
2568 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2570 (*_node_data)[ni].heap.clear();
2571 (*_node_data)[ni].heap_index.clear();
2572 (*_node_data)[ni].pot +=
2573 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2575 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2576 Node v = _graph.source(e);
2577 int vb = _blossom_set->find(v);
2578 int vi = (*_node_index)[v];
2580 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2581 dualScale * _weight[e];
2583 if ((*_blossom_data)[vb].status == EVEN) {
2584 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2585 _delta3->push(e, rw / 2);
2589 typename std::map<int, Arc>::iterator it =
2590 (*_node_data)[vi].heap_index.find(tree);
2592 if (it != (*_node_data)[vi].heap_index.end()) {
2593 if ((*_node_data)[vi].heap[it->second] > rw) {
2594 (*_node_data)[vi].heap.replace(it->second, e);
2595 (*_node_data)[vi].heap.decrease(e, rw);
2599 (*_node_data)[vi].heap.push(e, rw);
2600 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2603 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2604 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2606 if ((*_blossom_data)[vb].status == MATCHED) {
2607 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2608 _delta2->push(vb, _blossom_set->classPrio(vb) -
2609 (*_blossom_data)[vb].offset);
2610 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2611 (*_blossom_data)[vb].offset) {
2612 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2613 (*_blossom_data)[vb].offset);
2620 (*_blossom_data)[blossom].offset = 0;
2623 void alternatePath(int even, int tree) {
2626 evenToMatched(even, tree);
2627 (*_blossom_data)[even].status = MATCHED;
2629 while ((*_blossom_data)[even].pred != INVALID) {
2630 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2631 (*_blossom_data)[odd].status = MATCHED;
2633 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2635 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2636 (*_blossom_data)[even].status = MATCHED;
2637 evenToMatched(even, tree);
2638 (*_blossom_data)[even].next =
2639 _graph.oppositeArc((*_blossom_data)[odd].pred);
2644 void destroyTree(int tree) {
2645 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2646 if ((*_blossom_data)[b].status == EVEN) {
2647 (*_blossom_data)[b].status = MATCHED;
2648 evenToMatched(b, tree);
2649 } else if ((*_blossom_data)[b].status == ODD) {
2650 (*_blossom_data)[b].status = MATCHED;
2654 _tree_set->eraseClass(tree);
2657 void augmentOnEdge(const Edge& edge) {
2659 int left = _blossom_set->find(_graph.u(edge));
2660 int right = _blossom_set->find(_graph.v(edge));
2662 int left_tree = _tree_set->find(left);
2663 alternatePath(left, left_tree);
2664 destroyTree(left_tree);
2666 int right_tree = _tree_set->find(right);
2667 alternatePath(right, right_tree);
2668 destroyTree(right_tree);
2670 (*_blossom_data)[left].next = _graph.direct(edge, true);
2671 (*_blossom_data)[right].next = _graph.direct(edge, false);
2674 void extendOnArc(const Arc& arc) {
2675 int base = _blossom_set->find(_graph.target(arc));
2676 int tree = _tree_set->find(base);
2678 int odd = _blossom_set->find(_graph.source(arc));
2679 _tree_set->insert(odd, tree);
2680 (*_blossom_data)[odd].status = ODD;
2682 (*_blossom_data)[odd].pred = arc;
2684 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2685 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2686 _tree_set->insert(even, tree);
2687 (*_blossom_data)[even].status = EVEN;
2688 matchedToEven(even, tree);
2691 void shrinkOnEdge(const Edge& edge, int tree) {
2693 std::vector<int> left_path, right_path;
2696 std::set<int> left_set, right_set;
2697 int left = _blossom_set->find(_graph.u(edge));
2698 left_path.push_back(left);
2699 left_set.insert(left);
2701 int right = _blossom_set->find(_graph.v(edge));
2702 right_path.push_back(right);
2703 right_set.insert(right);
2707 if ((*_blossom_data)[left].pred == INVALID) break;
2710 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2711 left_path.push_back(left);
2713 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2714 left_path.push_back(left);
2716 left_set.insert(left);
2718 if (right_set.find(left) != right_set.end()) {
2723 if ((*_blossom_data)[right].pred == INVALID) break;
2726 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2727 right_path.push_back(right);
2729 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2730 right_path.push_back(right);
2732 right_set.insert(right);
2734 if (left_set.find(right) != left_set.end()) {
2742 if ((*_blossom_data)[left].pred == INVALID) {
2744 while (left_set.find(nca) == left_set.end()) {
2746 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2747 right_path.push_back(nca);
2749 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2750 right_path.push_back(nca);
2754 while (right_set.find(nca) == right_set.end()) {
2756 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2757 left_path.push_back(nca);
2759 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2760 left_path.push_back(nca);
2766 std::vector<int> subblossoms;
2769 prev = _graph.direct(edge, true);
2770 for (int i = 0; left_path[i] != nca; i += 2) {
2771 subblossoms.push_back(left_path[i]);
2772 (*_blossom_data)[left_path[i]].next = prev;
2773 _tree_set->erase(left_path[i]);
2775 subblossoms.push_back(left_path[i + 1]);
2776 (*_blossom_data)[left_path[i + 1]].status = EVEN;
2777 oddToEven(left_path[i + 1], tree);
2778 _tree_set->erase(left_path[i + 1]);
2779 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2783 while (right_path[k] != nca) ++k;
2785 subblossoms.push_back(nca);
2786 (*_blossom_data)[nca].next = prev;
2788 for (int i = k - 2; i >= 0; i -= 2) {
2789 subblossoms.push_back(right_path[i + 1]);
2790 (*_blossom_data)[right_path[i + 1]].status = EVEN;
2791 oddToEven(right_path[i + 1], tree);
2792 _tree_set->erase(right_path[i + 1]);
2794 (*_blossom_data)[right_path[i + 1]].next =
2795 (*_blossom_data)[right_path[i + 1]].pred;
2797 subblossoms.push_back(right_path[i]);
2798 _tree_set->erase(right_path[i]);
2802 _blossom_set->join(subblossoms.begin(), subblossoms.end());
2804 for (int i = 0; i < int(subblossoms.size()); ++i) {
2805 if (!_blossom_set->trivial(subblossoms[i])) {
2806 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2808 (*_blossom_data)[subblossoms[i]].status = MATCHED;
2811 (*_blossom_data)[surface].pot = -2 * _delta_sum;
2812 (*_blossom_data)[surface].offset = 0;
2813 (*_blossom_data)[surface].status = EVEN;
2814 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2815 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2817 _tree_set->insert(surface, tree);
2818 _tree_set->erase(nca);
2821 void splitBlossom(int blossom) {
2822 Arc next = (*_blossom_data)[blossom].next;
2823 Arc pred = (*_blossom_data)[blossom].pred;
2825 int tree = _tree_set->find(blossom);
2827 (*_blossom_data)[blossom].status = MATCHED;
2828 oddToMatched(blossom);
2829 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2830 _delta2->erase(blossom);
2833 std::vector<int> subblossoms;
2834 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2836 Value offset = (*_blossom_data)[blossom].offset;
2837 int b = _blossom_set->find(_graph.source(pred));
2838 int d = _blossom_set->find(_graph.source(next));
2840 int ib = -1, id = -1;
2841 for (int i = 0; i < int(subblossoms.size()); ++i) {
2842 if (subblossoms[i] == b) ib = i;
2843 if (subblossoms[i] == d) id = i;
2845 (*_blossom_data)[subblossoms[i]].offset = offset;
2846 if (!_blossom_set->trivial(subblossoms[i])) {
2847 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2849 if (_blossom_set->classPrio(subblossoms[i]) !=
2850 std::numeric_limits<Value>::max()) {
2851 _delta2->push(subblossoms[i],
2852 _blossom_set->classPrio(subblossoms[i]) -
2853 (*_blossom_data)[subblossoms[i]].offset);
2857 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2858 for (int i = (id + 1) % subblossoms.size();
2859 i != ib; i = (i + 2) % subblossoms.size()) {
2860 int sb = subblossoms[i];
2861 int tb = subblossoms[(i + 1) % subblossoms.size()];
2862 (*_blossom_data)[sb].next =
2863 _graph.oppositeArc((*_blossom_data)[tb].next);
2866 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2867 int sb = subblossoms[i];
2868 int tb = subblossoms[(i + 1) % subblossoms.size()];
2869 int ub = subblossoms[(i + 2) % subblossoms.size()];
2871 (*_blossom_data)[sb].status = ODD;
2873 _tree_set->insert(sb, tree);
2874 (*_blossom_data)[sb].pred = pred;
2875 (*_blossom_data)[sb].next =
2876 _graph.oppositeArc((*_blossom_data)[tb].next);
2878 pred = (*_blossom_data)[ub].next;
2880 (*_blossom_data)[tb].status = EVEN;
2881 matchedToEven(tb, tree);
2882 _tree_set->insert(tb, tree);
2883 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2886 (*_blossom_data)[subblossoms[id]].status = ODD;
2887 matchedToOdd(subblossoms[id]);
2888 _tree_set->insert(subblossoms[id], tree);
2889 (*_blossom_data)[subblossoms[id]].next = next;
2890 (*_blossom_data)[subblossoms[id]].pred = pred;
2894 for (int i = (ib + 1) % subblossoms.size();
2895 i != id; i = (i + 2) % subblossoms.size()) {
2896 int sb = subblossoms[i];
2897 int tb = subblossoms[(i + 1) % subblossoms.size()];
2898 (*_blossom_data)[sb].next =
2899 _graph.oppositeArc((*_blossom_data)[tb].next);
2902 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2903 int sb = subblossoms[i];
2904 int tb = subblossoms[(i + 1) % subblossoms.size()];
2905 int ub = subblossoms[(i + 2) % subblossoms.size()];
2907 (*_blossom_data)[sb].status = ODD;
2909 _tree_set->insert(sb, tree);
2910 (*_blossom_data)[sb].next = next;
2911 (*_blossom_data)[sb].pred =
2912 _graph.oppositeArc((*_blossom_data)[tb].next);
2914 (*_blossom_data)[tb].status = EVEN;
2915 matchedToEven(tb, tree);
2916 _tree_set->insert(tb, tree);
2917 (*_blossom_data)[tb].pred =
2918 (*_blossom_data)[tb].next =
2919 _graph.oppositeArc((*_blossom_data)[ub].next);
2920 next = (*_blossom_data)[ub].next;
2923 (*_blossom_data)[subblossoms[ib]].status = ODD;
2924 matchedToOdd(subblossoms[ib]);
2925 _tree_set->insert(subblossoms[ib], tree);
2926 (*_blossom_data)[subblossoms[ib]].next = next;
2927 (*_blossom_data)[subblossoms[ib]].pred = pred;
2929 _tree_set->erase(blossom);
2932 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2933 if (_blossom_set->trivial(blossom)) {
2934 int bi = (*_node_index)[base];
2935 Value pot = (*_node_data)[bi].pot;
2937 (*_matching)[base] = matching;
2938 _blossom_node_list.push_back(base);
2939 (*_node_potential)[base] = pot;
2942 Value pot = (*_blossom_data)[blossom].pot;
2943 int bn = _blossom_node_list.size();
2945 std::vector<int> subblossoms;
2946 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2947 int b = _blossom_set->find(base);
2949 for (int i = 0; i < int(subblossoms.size()); ++i) {
2950 if (subblossoms[i] == b) { ib = i; break; }
2953 for (int i = 1; i < int(subblossoms.size()); i += 2) {
2954 int sb = subblossoms[(ib + i) % subblossoms.size()];
2955 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2957 Arc m = (*_blossom_data)[tb].next;
2958 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2959 extractBlossom(tb, _graph.source(m), m);
2961 extractBlossom(subblossoms[ib], base, matching);
2963 int en = _blossom_node_list.size();
2965 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2969 void extractMatching() {
2970 std::vector<int> blossoms;
2971 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2972 blossoms.push_back(c);
2975 for (int i = 0; i < int(blossoms.size()); ++i) {
2977 Value offset = (*_blossom_data)[blossoms[i]].offset;
2978 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2979 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2980 n != INVALID; ++n) {
2981 (*_node_data)[(*_node_index)[n]].pot -= offset;
2984 Arc matching = (*_blossom_data)[blossoms[i]].next;
2985 Node base = _graph.source(matching);
2986 extractBlossom(blossoms[i], base, matching);
2992 /// \brief Constructor
2995 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2996 : _graph(graph), _weight(weight), _matching(0),
2997 _node_potential(0), _blossom_potential(), _blossom_node_list(),
2998 _node_num(0), _blossom_num(0),
3000 _blossom_index(0), _blossom_set(0), _blossom_data(0),
3001 _node_index(0), _node_heap_index(0), _node_data(0),
3002 _tree_set_index(0), _tree_set(0),
3004 _delta2_index(0), _delta2(0),
3005 _delta3_index(0), _delta3(0),
3006 _delta4_index(0), _delta4(0),
3008 _delta_sum(), _unmatched(0),
3013 ~MaxWeightedPerfectMatching() {
3014 destroyStructures();
3020 /// \name Execution Control
3021 /// The simplest way to execute the algorithm is to use the
3022 /// \ref run() member function.
3026 /// \brief Initialize the algorithm
3028 /// This function initializes the algorithm.
3032 _blossom_node_list.clear();
3033 _blossom_potential.clear();
3035 for (ArcIt e(_graph); e != INVALID; ++e) {
3036 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3038 for (EdgeIt e(_graph); e != INVALID; ++e) {
3039 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3041 for (int i = 0; i < _blossom_num; ++i) {
3042 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3043 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3046 _unmatched = _node_num;
3051 _blossom_set->clear();
3055 for (NodeIt n(_graph); n != INVALID; ++n) {
3056 Value max = - std::numeric_limits<Value>::max();
3057 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3058 if (_graph.target(e) == n) continue;
3059 if ((dualScale * _weight[e]) / 2 > max) {
3060 max = (dualScale * _weight[e]) / 2;
3063 (*_node_index)[n] = index;
3064 (*_node_data)[index].heap_index.clear();
3065 (*_node_data)[index].heap.clear();
3066 (*_node_data)[index].pot = max;
3068 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3070 _tree_set->insert(blossom);
3072 (*_blossom_data)[blossom].status = EVEN;
3073 (*_blossom_data)[blossom].pred = INVALID;
3074 (*_blossom_data)[blossom].next = INVALID;
3075 (*_blossom_data)[blossom].pot = 0;
3076 (*_blossom_data)[blossom].offset = 0;
3079 for (EdgeIt e(_graph); e != INVALID; ++e) {
3080 int si = (*_node_index)[_graph.u(e)];
3081 int ti = (*_node_index)[_graph.v(e)];
3082 if (_graph.u(e) != _graph.v(e)) {
3083 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3084 dualScale * _weight[e]) / 2);
3089 /// \brief Initialize the algorithm with fractional matching
3091 /// This function initializes the algorithm with a fractional
3092 /// matching. This initialization is also called jumpstart heuristic.
3093 void fractionalInit() {
3096 _blossom_node_list.clear();
3097 _blossom_potential.clear();
3099 if (_fractional == 0) {
3100 _fractional = new FractionalMatching(_graph, _weight, false);
3102 if (!_fractional->run()) {
3107 for (ArcIt e(_graph); e != INVALID; ++e) {
3108 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
3110 for (EdgeIt e(_graph); e != INVALID; ++e) {
3111 (*_delta3_index)[e] = _delta3->PRE_HEAP;
3113 for (int i = 0; i < _blossom_num; ++i) {
3114 (*_delta2_index)[i] = _delta2->PRE_HEAP;
3115 (*_delta4_index)[i] = _delta4->PRE_HEAP;
3123 _blossom_set->clear();
3127 for (NodeIt n(_graph); n != INVALID; ++n) {
3128 Value pot = _fractional->nodeValue(n);
3129 (*_node_index)[n] = index;
3130 (*_node_data)[index].pot = pot;
3131 (*_node_data)[index].heap_index.clear();
3132 (*_node_data)[index].heap.clear();
3134 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3136 (*_blossom_data)[blossom].status = MATCHED;
3137 (*_blossom_data)[blossom].pred = INVALID;
3138 (*_blossom_data)[blossom].next = _fractional->matching(n);
3139 (*_blossom_data)[blossom].pot = 0;
3140 (*_blossom_data)[blossom].offset = 0;
3144 typename Graph::template NodeMap<bool> processed(_graph, false);
3145 for (NodeIt n(_graph); n != INVALID; ++n) {
3146 if (processed[n]) continue;
3147 processed[n] = true;
3148 if (_fractional->matching(n) == INVALID) continue;
3150 Node v = _graph.target(_fractional->matching(n));
3152 processed[v] = true;
3153 v = _graph.target(_fractional->matching(v));
3158 std::vector<int> subblossoms(num);
3160 subblossoms[--num] = _blossom_set->find(n);
3161 v = _graph.target(_fractional->matching(n));
3163 subblossoms[--num] = _blossom_set->find(v);
3164 v = _graph.target(_fractional->matching(v));
3168 _blossom_set->join(subblossoms.begin(), subblossoms.end());
3169 (*_blossom_data)[surface].status = EVEN;
3170 (*_blossom_data)[surface].pred = INVALID;
3171 (*_blossom_data)[surface].next = INVALID;
3172 (*_blossom_data)[surface].pot = 0;
3173 (*_blossom_data)[surface].offset = 0;
3175 _tree_set->insert(surface);
3180 for (EdgeIt e(_graph); e != INVALID; ++e) {
3181 int si = (*_node_index)[_graph.u(e)];
3182 int sb = _blossom_set->find(_graph.u(e));
3183 int ti = (*_node_index)[_graph.v(e)];
3184 int tb = _blossom_set->find(_graph.v(e));
3185 if ((*_blossom_data)[sb].status == EVEN &&
3186 (*_blossom_data)[tb].status == EVEN && sb != tb) {
3187 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3188 dualScale * _weight[e]) / 2);
3192 for (NodeIt n(_graph); n != INVALID; ++n) {
3193 int nb = _blossom_set->find(n);
3194 if ((*_blossom_data)[nb].status != MATCHED) continue;
3195 int ni = (*_node_index)[n];
3197 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3198 Node v = _graph.target(e);
3199 int vb = _blossom_set->find(v);
3200 int vi = (*_node_index)[v];
3202 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
3203 dualScale * _weight[e];
3205 if ((*_blossom_data)[vb].status == EVEN) {
3207 int vt = _tree_set->find(vb);
3209 typename std::map<int, Arc>::iterator it =
3210 (*_node_data)[ni].heap_index.find(vt);
3212 if (it != (*_node_data)[ni].heap_index.end()) {
3213 if ((*_node_data)[ni].heap[it->second] > rw) {
3214 (*_node_data)[ni].heap.replace(it->second, e);
3215 (*_node_data)[ni].heap.decrease(e, rw);
3219 (*_node_data)[ni].heap.push(e, rw);
3220 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
3225 if (!(*_node_data)[ni].heap.empty()) {
3226 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
3227 _delta2->push(nb, _blossom_set->classPrio(nb));
3232 /// \brief Start the algorithm
3234 /// This function starts the algorithm.
3236 /// \pre \ref init() or \ref fractionalInit() must be called before
3237 /// using this function.
3243 if (_unmatched == -1) return false;
3245 while (_unmatched > 0) {
3246 Value d2 = !_delta2->empty() ?
3247 _delta2->prio() : std::numeric_limits<Value>::max();
3249 Value d3 = !_delta3->empty() ?
3250 _delta3->prio() : std::numeric_limits<Value>::max();
3252 Value d4 = !_delta4->empty() ?
3253 _delta4->prio() : std::numeric_limits<Value>::max();
3255 _delta_sum = d3; OpType ot = D3;
3256 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
3257 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3259 if (_delta_sum == std::numeric_limits<Value>::max()) {
3266 int blossom = _delta2->top();
3267 Node n = _blossom_set->classTop(blossom);
3268 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3274 Edge e = _delta3->top();
3276 int left_blossom = _blossom_set->find(_graph.u(e));
3277 int right_blossom = _blossom_set->find(_graph.v(e));
3279 if (left_blossom == right_blossom) {
3282 int left_tree = _tree_set->find(left_blossom);
3283 int right_tree = _tree_set->find(right_blossom);
3285 if (left_tree == right_tree) {
3286 shrinkOnEdge(e, left_tree);
3294 splitBlossom(_delta4->top());
3302 /// \brief Run the algorithm.
3304 /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3306 /// \note mwpm.run() is just a shortcut of the following code.
3308 /// mwpm.fractionalInit();
3318 /// \name Primal Solution
3319 /// Functions to get the primal solution, i.e. the maximum weighted
3320 /// perfect matching.\n
3321 /// Either \ref run() or \ref start() function should be called before
3326 /// \brief Return the weight of the matching.
3328 /// This function returns the weight of the found matching.
3330 /// \pre Either run() or start() must be called before using this function.
3331 Value matchingWeight() const {
3333 for (NodeIt n(_graph); n != INVALID; ++n) {
3334 if ((*_matching)[n] != INVALID) {
3335 sum += _weight[(*_matching)[n]];
3341 /// \brief Return \c true if the given edge is in the matching.
3343 /// This function returns \c true if the given edge is in the found
3346 /// \pre Either run() or start() must be called before using this function.
3347 bool matching(const Edge& edge) const {
3348 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3351 /// \brief Return the matching arc (or edge) incident to the given node.
3353 /// This function returns the matching arc (or edge) incident to the
3354 /// given node in the found matching or \c INVALID if the node is
3355 /// not covered by the matching.
3357 /// \pre Either run() or start() must be called before using this function.
3358 Arc matching(const Node& node) const {
3359 return (*_matching)[node];
3362 /// \brief Return a const reference to the matching map.
3364 /// This function returns a const reference to a node map that stores
3365 /// the matching arc (or edge) incident to each node.
3366 const MatchingMap& matchingMap() const {
3370 /// \brief Return the mate of the given node.
3372 /// This function returns the mate of the given node in the found
3373 /// matching or \c INVALID if the node is not covered by the matching.
3375 /// \pre Either run() or start() must be called before using this function.
3376 Node mate(const Node& node) const {
3377 return _graph.target((*_matching)[node]);
3382 /// \name Dual Solution
3383 /// Functions to get the dual solution.\n
3384 /// Either \ref run() or \ref start() function should be called before
3389 /// \brief Return the value of the dual solution.
3391 /// This function returns the value of the dual solution.
3392 /// It should be equal to the primal value scaled by \ref dualScale
3395 /// \pre Either run() or start() must be called before using this function.
3396 Value dualValue() const {
3398 for (NodeIt n(_graph); n != INVALID; ++n) {
3399 sum += nodeValue(n);
3401 for (int i = 0; i < blossomNum(); ++i) {
3402 sum += blossomValue(i) * (blossomSize(i) / 2);
3407 /// \brief Return the dual value (potential) of the given node.
3409 /// This function returns the dual value (potential) of the given node.
3411 /// \pre Either run() or start() must be called before using this function.
3412 Value nodeValue(const Node& n) const {
3413 return (*_node_potential)[n];
3416 /// \brief Return the number of the blossoms in the basis.
3418 /// This function returns the number of the blossoms in the basis.
3420 /// \pre Either run() or start() must be called before using this function.
3422 int blossomNum() const {
3423 return _blossom_potential.size();
3426 /// \brief Return the number of the nodes in the given blossom.
3428 /// This function returns the number of the nodes in the given blossom.
3430 /// \pre Either run() or start() must be called before using this function.
3432 int blossomSize(int k) const {
3433 return _blossom_potential[k].end - _blossom_potential[k].begin;
3436 /// \brief Return the dual value (ptential) of the given blossom.
3438 /// This function returns the dual value (ptential) of the given blossom.
3440 /// \pre Either run() or start() must be called before using this function.
3441 Value blossomValue(int k) const {
3442 return _blossom_potential[k].value;
3445 /// \brief Iterator for obtaining the nodes of a blossom.
3447 /// This class provides an iterator for obtaining the nodes of the
3448 /// given blossom. It lists a subset of the nodes.
3449 /// Before using this iterator, you must allocate a
3450 /// MaxWeightedPerfectMatching class and execute it.
3454 /// \brief Constructor.
3456 /// Constructor to get the nodes of the given variable.
3458 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3459 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3460 /// must be called before initializing this iterator.
3461 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3462 : _algorithm(&algorithm)
3464 _index = _algorithm->_blossom_potential[variable].begin;
3465 _last = _algorithm->_blossom_potential[variable].end;
3468 /// \brief Conversion to \c Node.
3470 /// Conversion to \c Node.
3471 operator Node() const {
3472 return _algorithm->_blossom_node_list[_index];
3475 /// \brief Increment operator.
3477 /// Increment operator.
3478 BlossomIt& operator++() {
3483 /// \brief Validity checking
3485 /// This function checks whether the iterator is invalid.
3486 bool operator==(Invalid) const { return _index == _last; }
3488 /// \brief Validity checking
3490 /// This function checks whether the iterator is valid.
3491 bool operator!=(Invalid) const { return _index != _last; }
3494 const MaxWeightedPerfectMatching* _algorithm;
3503 } //END OF NAMESPACE LEMON
3505 #endif //LEMON_MATCHING_H