COIN-OR::LEMON - Graph Library

source: lemon-main/lemon/matching.h @ 1203:8c567e298d7f

Last change on this file since 1203:8c567e298d7f was 1203:8c567e298d7f, checked in by Balazs Dezso <deba@…>, 5 years ago

Paremeter to stop matching calculation when only single node is unmatched

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