lemon/matching.h
changeset 874 d8ea85825e02
parent 868 0513ccfea967
child 875 07ec2b52e53d
equal deleted inserted replaced
3:4fa2e7cacf26 4:b397b2f8308e
    26 
    26 
    27 #include <lemon/core.h>
    27 #include <lemon/core.h>
    28 #include <lemon/unionfind.h>
    28 #include <lemon/unionfind.h>
    29 #include <lemon/bin_heap.h>
    29 #include <lemon/bin_heap.h>
    30 #include <lemon/maps.h>
    30 #include <lemon/maps.h>
       
    31 #include <lemon/fractional_matching.h>
    31 
    32 
    32 ///\ingroup matching
    33 ///\ingroup matching
    33 ///\file
    34 ///\file
    34 ///\brief Maximum matching algorithms in general graphs.
    35 ///\brief Maximum matching algorithms in general graphs.
    35 
    36 
   795 
   796 
   796     IntIntMap *_delta4_index;
   797     IntIntMap *_delta4_index;
   797     BinHeap<Value, IntIntMap> *_delta4;
   798     BinHeap<Value, IntIntMap> *_delta4;
   798 
   799 
   799     Value _delta_sum;
   800     Value _delta_sum;
       
   801     int _unmatched;
       
   802 
       
   803     typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
       
   804     FractionalMatching *_fractional;
   800 
   805 
   801     void createStructures() {
   806     void createStructures() {
   802       _node_num = countNodes(_graph);
   807       _node_num = countNodes(_graph);
   803       _blossom_num = _node_num * 3 / 2;
   808       _blossom_num = _node_num * 3 / 2;
   804 
   809 
  1557         _delta1_index(0), _delta1(0),
  1562         _delta1_index(0), _delta1(0),
  1558         _delta2_index(0), _delta2(0),
  1563         _delta2_index(0), _delta2(0),
  1559         _delta3_index(0), _delta3(0),
  1564         _delta3_index(0), _delta3(0),
  1560         _delta4_index(0), _delta4(0),
  1565         _delta4_index(0), _delta4(0),
  1561 
  1566 
  1562         _delta_sum() {}
  1567         _delta_sum(), _unmatched(0),
       
  1568 
       
  1569         _fractional(0)
       
  1570     {}
  1563 
  1571 
  1564     ~MaxWeightedMatching() {
  1572     ~MaxWeightedMatching() {
  1565       destroyStructures();
  1573       destroyStructures();
       
  1574       if (_fractional) {
       
  1575         delete _fractional;
       
  1576       }
  1566     }
  1577     }
  1567 
  1578 
  1568     /// \name Execution Control
  1579     /// \name Execution Control
  1569     /// The simplest way to execute the algorithm is to use the
  1580     /// The simplest way to execute the algorithm is to use the
  1570     /// \ref run() member function.
  1581     /// \ref run() member function.
  1588       }
  1599       }
  1589       for (int i = 0; i < _blossom_num; ++i) {
  1600       for (int i = 0; i < _blossom_num; ++i) {
  1590         (*_delta2_index)[i] = _delta2->PRE_HEAP;
  1601         (*_delta2_index)[i] = _delta2->PRE_HEAP;
  1591         (*_delta4_index)[i] = _delta4->PRE_HEAP;
  1602         (*_delta4_index)[i] = _delta4->PRE_HEAP;
  1592       }
  1603       }
       
  1604 
       
  1605       _unmatched = _node_num;
  1593 
  1606 
  1594       int index = 0;
  1607       int index = 0;
  1595       for (NodeIt n(_graph); n != INVALID; ++n) {
  1608       for (NodeIt n(_graph); n != INVALID; ++n) {
  1596         Value max = 0;
  1609         Value max = 0;
  1597         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  1610         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  1623                             dualScale * _weight[e]) / 2);
  1636                             dualScale * _weight[e]) / 2);
  1624         }
  1637         }
  1625       }
  1638       }
  1626     }
  1639     }
  1627 
  1640 
       
  1641     /// \brief Initialize the algorithm with fractional matching
       
  1642     ///
       
  1643     /// This function initializes the algorithm with a fractional
       
  1644     /// matching. This initialization is also called jumpstart heuristic.
       
  1645     void fractionalInit() {
       
  1646       createStructures();
       
  1647       
       
  1648       if (_fractional == 0) {
       
  1649         _fractional = new FractionalMatching(_graph, _weight, false);
       
  1650       }
       
  1651       _fractional->run();
       
  1652 
       
  1653       for (ArcIt e(_graph); e != INVALID; ++e) {
       
  1654         (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
       
  1655       }
       
  1656       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1657         (*_delta1_index)[n] = _delta1->PRE_HEAP;
       
  1658       }
       
  1659       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  1660         (*_delta3_index)[e] = _delta3->PRE_HEAP;
       
  1661       }
       
  1662       for (int i = 0; i < _blossom_num; ++i) {
       
  1663         (*_delta2_index)[i] = _delta2->PRE_HEAP;
       
  1664         (*_delta4_index)[i] = _delta4->PRE_HEAP;
       
  1665       }
       
  1666 
       
  1667       _unmatched = 0;
       
  1668 
       
  1669       int index = 0;
       
  1670       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1671         Value pot = _fractional->nodeValue(n);
       
  1672         (*_node_index)[n] = index;
       
  1673         (*_node_data)[index].pot = pot;
       
  1674         int blossom =
       
  1675           _blossom_set->insert(n, std::numeric_limits<Value>::max());
       
  1676 
       
  1677         (*_blossom_data)[blossom].status = MATCHED;
       
  1678         (*_blossom_data)[blossom].pred = INVALID;
       
  1679         (*_blossom_data)[blossom].next = _fractional->matching(n);
       
  1680         if (_fractional->matching(n) == INVALID) {
       
  1681           (*_blossom_data)[blossom].base = n;
       
  1682         }
       
  1683         (*_blossom_data)[blossom].pot = 0;
       
  1684         (*_blossom_data)[blossom].offset = 0;
       
  1685         ++index;
       
  1686       }
       
  1687 
       
  1688       typename Graph::template NodeMap<bool> processed(_graph, false);
       
  1689       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1690         if (processed[n]) continue;
       
  1691         processed[n] = true;
       
  1692         if (_fractional->matching(n) == INVALID) continue;
       
  1693         int num = 1;
       
  1694         Node v = _graph.target(_fractional->matching(n));
       
  1695         while (n != v) {
       
  1696           processed[v] = true;
       
  1697           v = _graph.target(_fractional->matching(v));
       
  1698           ++num;
       
  1699         }
       
  1700 
       
  1701         if (num % 2 == 1) {
       
  1702           std::vector<int> subblossoms(num);
       
  1703 
       
  1704           subblossoms[--num] = _blossom_set->find(n);
       
  1705           _delta1->push(n, _fractional->nodeValue(n));
       
  1706           v = _graph.target(_fractional->matching(n));
       
  1707           while (n != v) {
       
  1708             subblossoms[--num] = _blossom_set->find(v);
       
  1709             _delta1->push(v, _fractional->nodeValue(v));
       
  1710             v = _graph.target(_fractional->matching(v));            
       
  1711           }
       
  1712           
       
  1713           int surface = 
       
  1714             _blossom_set->join(subblossoms.begin(), subblossoms.end());
       
  1715           (*_blossom_data)[surface].status = EVEN;
       
  1716           (*_blossom_data)[surface].pred = INVALID;
       
  1717           (*_blossom_data)[surface].next = INVALID;
       
  1718           (*_blossom_data)[surface].pot = 0;
       
  1719           (*_blossom_data)[surface].offset = 0;
       
  1720           
       
  1721           _tree_set->insert(surface);
       
  1722           ++_unmatched;
       
  1723         }
       
  1724       }
       
  1725 
       
  1726       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  1727         int si = (*_node_index)[_graph.u(e)];
       
  1728         int sb = _blossom_set->find(_graph.u(e));
       
  1729         int ti = (*_node_index)[_graph.v(e)];
       
  1730         int tb = _blossom_set->find(_graph.v(e));
       
  1731         if ((*_blossom_data)[sb].status == EVEN &&
       
  1732             (*_blossom_data)[tb].status == EVEN && sb != tb) {
       
  1733           _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
       
  1734                             dualScale * _weight[e]) / 2);
       
  1735         }
       
  1736       }
       
  1737 
       
  1738       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  1739         int nb = _blossom_set->find(n);
       
  1740         if ((*_blossom_data)[nb].status != MATCHED) continue;
       
  1741         int ni = (*_node_index)[n];
       
  1742 
       
  1743         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
       
  1744           Node v = _graph.target(e);
       
  1745           int vb = _blossom_set->find(v);
       
  1746           int vi = (*_node_index)[v];
       
  1747 
       
  1748           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
       
  1749             dualScale * _weight[e];
       
  1750 
       
  1751           if ((*_blossom_data)[vb].status == EVEN) {
       
  1752 
       
  1753             int vt = _tree_set->find(vb);
       
  1754 
       
  1755             typename std::map<int, Arc>::iterator it =
       
  1756               (*_node_data)[ni].heap_index.find(vt);
       
  1757 
       
  1758             if (it != (*_node_data)[ni].heap_index.end()) {
       
  1759               if ((*_node_data)[ni].heap[it->second] > rw) {
       
  1760                 (*_node_data)[ni].heap.replace(it->second, e);
       
  1761                 (*_node_data)[ni].heap.decrease(e, rw);
       
  1762                 it->second = e;
       
  1763               }
       
  1764             } else {
       
  1765               (*_node_data)[ni].heap.push(e, rw);
       
  1766               (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
       
  1767             }
       
  1768           }
       
  1769         }
       
  1770             
       
  1771         if (!(*_node_data)[ni].heap.empty()) {
       
  1772           _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
       
  1773           _delta2->push(nb, _blossom_set->classPrio(nb));
       
  1774         }
       
  1775       }
       
  1776     }
       
  1777 
  1628     /// \brief Start the algorithm
  1778     /// \brief Start the algorithm
  1629     ///
  1779     ///
  1630     /// This function starts the algorithm.
  1780     /// This function starts the algorithm.
  1631     ///
  1781     ///
  1632     /// \pre \ref init() must be called before using this function.
  1782     /// \pre \ref init() or \ref fractionalInit() must be called
       
  1783     /// before using this function.
  1633     void start() {
  1784     void start() {
  1634       enum OpType {
  1785       enum OpType {
  1635         D1, D2, D3, D4
  1786         D1, D2, D3, D4
  1636       };
  1787       };
  1637 
  1788 
  1638       int unmatched = _node_num;
  1789       while (_unmatched > 0) {
  1639       while (unmatched > 0) {
       
  1640         Value d1 = !_delta1->empty() ?
  1790         Value d1 = !_delta1->empty() ?
  1641           _delta1->prio() : std::numeric_limits<Value>::max();
  1791           _delta1->prio() : std::numeric_limits<Value>::max();
  1642 
  1792 
  1643         Value d2 = !_delta2->empty() ?
  1793         Value d2 = !_delta2->empty() ?
  1644           _delta2->prio() : std::numeric_limits<Value>::max();
  1794           _delta2->prio() : std::numeric_limits<Value>::max();
  1657         switch (ot) {
  1807         switch (ot) {
  1658         case D1:
  1808         case D1:
  1659           {
  1809           {
  1660             Node n = _delta1->top();
  1810             Node n = _delta1->top();
  1661             unmatchNode(n);
  1811             unmatchNode(n);
  1662             --unmatched;
  1812             --_unmatched;
  1663           }
  1813           }
  1664           break;
  1814           break;
  1665         case D2:
  1815         case D2:
  1666           {
  1816           {
  1667             int blossom = _delta2->top();
  1817             int blossom = _delta2->top();
  1668             Node n = _blossom_set->classTop(blossom);
  1818             Node n = _blossom_set->classTop(blossom);
  1669             Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
  1819             Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
  1670             if ((*_blossom_data)[blossom].next == INVALID) {
  1820             if ((*_blossom_data)[blossom].next == INVALID) {
  1671               augmentOnArc(a);
  1821               augmentOnArc(a);
  1672               --unmatched;
  1822               --_unmatched;
  1673             } else {
  1823             } else {
  1674               extendOnArc(a);
  1824               extendOnArc(a);
  1675             }
  1825             }
  1676           }
  1826           }
  1677           break;
  1827           break;
  1690 
  1840 
  1691               if (left_tree == right_tree) {
  1841               if (left_tree == right_tree) {
  1692                 shrinkOnEdge(e, left_tree);
  1842                 shrinkOnEdge(e, left_tree);
  1693               } else {
  1843               } else {
  1694                 augmentOnEdge(e);
  1844                 augmentOnEdge(e);
  1695                 unmatched -= 2;
  1845                 _unmatched -= 2;
  1696               }
  1846               }
  1697             }
  1847             }
  1698           } break;
  1848           } break;
  1699         case D4:
  1849         case D4:
  1700           splitBlossom(_delta4->top());
  1850           splitBlossom(_delta4->top());
  1708     ///
  1858     ///
  1709     /// This method runs the \c %MaxWeightedMatching algorithm.
  1859     /// This method runs the \c %MaxWeightedMatching algorithm.
  1710     ///
  1860     ///
  1711     /// \note mwm.run() is just a shortcut of the following code.
  1861     /// \note mwm.run() is just a shortcut of the following code.
  1712     /// \code
  1862     /// \code
  1713     ///   mwm.init();
  1863     ///   mwm.fractionalInit();
  1714     ///   mwm.start();
  1864     ///   mwm.start();
  1715     /// \endcode
  1865     /// \endcode
  1716     void run() {
  1866     void run() {
  1717       init();
  1867       fractionalInit();
  1718       start();
  1868       start();
  1719     }
  1869     }
  1720 
  1870 
  1721     /// @}
  1871     /// @}
  1722 
  1872 
  2072 
  2222 
  2073     IntIntMap *_delta4_index;
  2223     IntIntMap *_delta4_index;
  2074     BinHeap<Value, IntIntMap> *_delta4;
  2224     BinHeap<Value, IntIntMap> *_delta4;
  2075 
  2225 
  2076     Value _delta_sum;
  2226     Value _delta_sum;
       
  2227     int _unmatched;
       
  2228 
       
  2229     typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap> 
       
  2230     FractionalMatching;
       
  2231     FractionalMatching *_fractional;
  2077 
  2232 
  2078     void createStructures() {
  2233     void createStructures() {
  2079       _node_num = countNodes(_graph);
  2234       _node_num = countNodes(_graph);
  2080       _blossom_num = _node_num * 3 / 2;
  2235       _blossom_num = _node_num * 3 / 2;
  2081 
  2236 
  2787 
  2942 
  2788         _delta2_index(0), _delta2(0),
  2943         _delta2_index(0), _delta2(0),
  2789         _delta3_index(0), _delta3(0),
  2944         _delta3_index(0), _delta3(0),
  2790         _delta4_index(0), _delta4(0),
  2945         _delta4_index(0), _delta4(0),
  2791 
  2946 
  2792         _delta_sum() {}
  2947         _delta_sum(), _unmatched(0),
       
  2948 
       
  2949         _fractional(0)
       
  2950     {}
  2793 
  2951 
  2794     ~MaxWeightedPerfectMatching() {
  2952     ~MaxWeightedPerfectMatching() {
  2795       destroyStructures();
  2953       destroyStructures();
       
  2954       if (_fractional) {
       
  2955         delete _fractional;
       
  2956       }
  2796     }
  2957     }
  2797 
  2958 
  2798     /// \name Execution Control
  2959     /// \name Execution Control
  2799     /// The simplest way to execute the algorithm is to use the
  2960     /// The simplest way to execute the algorithm is to use the
  2800     /// \ref run() member function.
  2961     /// \ref run() member function.
  2815       }
  2976       }
  2816       for (int i = 0; i < _blossom_num; ++i) {
  2977       for (int i = 0; i < _blossom_num; ++i) {
  2817         (*_delta2_index)[i] = _delta2->PRE_HEAP;
  2978         (*_delta2_index)[i] = _delta2->PRE_HEAP;
  2818         (*_delta4_index)[i] = _delta4->PRE_HEAP;
  2979         (*_delta4_index)[i] = _delta4->PRE_HEAP;
  2819       }
  2980       }
       
  2981 
       
  2982       _unmatched = _node_num;
  2820 
  2983 
  2821       int index = 0;
  2984       int index = 0;
  2822       for (NodeIt n(_graph); n != INVALID; ++n) {
  2985       for (NodeIt n(_graph); n != INVALID; ++n) {
  2823         Value max = - std::numeric_limits<Value>::max();
  2986         Value max = - std::numeric_limits<Value>::max();
  2824         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  2987         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  2849                             dualScale * _weight[e]) / 2);
  3012                             dualScale * _weight[e]) / 2);
  2850         }
  3013         }
  2851       }
  3014       }
  2852     }
  3015     }
  2853 
  3016 
       
  3017     /// \brief Initialize the algorithm with fractional matching
       
  3018     ///
       
  3019     /// This function initializes the algorithm with a fractional
       
  3020     /// matching. This initialization is also called jumpstart heuristic.
       
  3021     void fractionalInit() {
       
  3022       createStructures();
       
  3023       
       
  3024       if (_fractional == 0) {
       
  3025         _fractional = new FractionalMatching(_graph, _weight, false);
       
  3026       }
       
  3027       if (!_fractional->run()) {
       
  3028         _unmatched = -1;
       
  3029         return;
       
  3030       }
       
  3031 
       
  3032       for (ArcIt e(_graph); e != INVALID; ++e) {
       
  3033         (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
       
  3034       }
       
  3035       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  3036         (*_delta3_index)[e] = _delta3->PRE_HEAP;
       
  3037       }
       
  3038       for (int i = 0; i < _blossom_num; ++i) {
       
  3039         (*_delta2_index)[i] = _delta2->PRE_HEAP;
       
  3040         (*_delta4_index)[i] = _delta4->PRE_HEAP;
       
  3041       }
       
  3042 
       
  3043       _unmatched = 0;
       
  3044 
       
  3045       int index = 0;
       
  3046       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  3047         Value pot = _fractional->nodeValue(n);
       
  3048         (*_node_index)[n] = index;
       
  3049         (*_node_data)[index].pot = pot;
       
  3050         int blossom =
       
  3051           _blossom_set->insert(n, std::numeric_limits<Value>::max());
       
  3052 
       
  3053         (*_blossom_data)[blossom].status = MATCHED;
       
  3054         (*_blossom_data)[blossom].pred = INVALID;
       
  3055         (*_blossom_data)[blossom].next = _fractional->matching(n);
       
  3056         (*_blossom_data)[blossom].pot = 0;
       
  3057         (*_blossom_data)[blossom].offset = 0;
       
  3058         ++index;
       
  3059       }
       
  3060 
       
  3061       typename Graph::template NodeMap<bool> processed(_graph, false);
       
  3062       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  3063         if (processed[n]) continue;
       
  3064         processed[n] = true;
       
  3065         if (_fractional->matching(n) == INVALID) continue;
       
  3066         int num = 1;
       
  3067         Node v = _graph.target(_fractional->matching(n));
       
  3068         while (n != v) {
       
  3069           processed[v] = true;
       
  3070           v = _graph.target(_fractional->matching(v));
       
  3071           ++num;
       
  3072         }
       
  3073 
       
  3074         if (num % 2 == 1) {
       
  3075           std::vector<int> subblossoms(num);
       
  3076 
       
  3077           subblossoms[--num] = _blossom_set->find(n);
       
  3078           v = _graph.target(_fractional->matching(n));
       
  3079           while (n != v) {
       
  3080             subblossoms[--num] = _blossom_set->find(v);
       
  3081             v = _graph.target(_fractional->matching(v));            
       
  3082           }
       
  3083           
       
  3084           int surface = 
       
  3085             _blossom_set->join(subblossoms.begin(), subblossoms.end());
       
  3086           (*_blossom_data)[surface].status = EVEN;
       
  3087           (*_blossom_data)[surface].pred = INVALID;
       
  3088           (*_blossom_data)[surface].next = INVALID;
       
  3089           (*_blossom_data)[surface].pot = 0;
       
  3090           (*_blossom_data)[surface].offset = 0;
       
  3091           
       
  3092           _tree_set->insert(surface);
       
  3093           ++_unmatched;
       
  3094         }
       
  3095       }
       
  3096 
       
  3097       for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  3098         int si = (*_node_index)[_graph.u(e)];
       
  3099         int sb = _blossom_set->find(_graph.u(e));
       
  3100         int ti = (*_node_index)[_graph.v(e)];
       
  3101         int tb = _blossom_set->find(_graph.v(e));
       
  3102         if ((*_blossom_data)[sb].status == EVEN &&
       
  3103             (*_blossom_data)[tb].status == EVEN && sb != tb) {
       
  3104           _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
       
  3105                             dualScale * _weight[e]) / 2);
       
  3106         }
       
  3107       }
       
  3108 
       
  3109       for (NodeIt n(_graph); n != INVALID; ++n) {
       
  3110         int nb = _blossom_set->find(n);
       
  3111         if ((*_blossom_data)[nb].status != MATCHED) continue;
       
  3112         int ni = (*_node_index)[n];
       
  3113 
       
  3114         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
       
  3115           Node v = _graph.target(e);
       
  3116           int vb = _blossom_set->find(v);
       
  3117           int vi = (*_node_index)[v];
       
  3118 
       
  3119           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
       
  3120             dualScale * _weight[e];
       
  3121 
       
  3122           if ((*_blossom_data)[vb].status == EVEN) {
       
  3123 
       
  3124             int vt = _tree_set->find(vb);
       
  3125 
       
  3126             typename std::map<int, Arc>::iterator it =
       
  3127               (*_node_data)[ni].heap_index.find(vt);
       
  3128 
       
  3129             if (it != (*_node_data)[ni].heap_index.end()) {
       
  3130               if ((*_node_data)[ni].heap[it->second] > rw) {
       
  3131                 (*_node_data)[ni].heap.replace(it->second, e);
       
  3132                 (*_node_data)[ni].heap.decrease(e, rw);
       
  3133                 it->second = e;
       
  3134               }
       
  3135             } else {
       
  3136               (*_node_data)[ni].heap.push(e, rw);
       
  3137               (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
       
  3138             }
       
  3139           }
       
  3140         }
       
  3141             
       
  3142         if (!(*_node_data)[ni].heap.empty()) {
       
  3143           _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
       
  3144           _delta2->push(nb, _blossom_set->classPrio(nb));
       
  3145         }
       
  3146       }
       
  3147     }
       
  3148 
  2854     /// \brief Start the algorithm
  3149     /// \brief Start the algorithm
  2855     ///
  3150     ///
  2856     /// This function starts the algorithm.
  3151     /// This function starts the algorithm.
  2857     ///
  3152     ///
  2858     /// \pre \ref init() must be called before using this function.
  3153     /// \pre \ref init() or \ref fractionalInit() must be called before
       
  3154     /// using this function.
  2859     bool start() {
  3155     bool start() {
  2860       enum OpType {
  3156       enum OpType {
  2861         D2, D3, D4
  3157         D2, D3, D4
  2862       };
  3158       };
  2863 
  3159 
  2864       int unmatched = _node_num;
  3160       if (_unmatched == -1) return false;
  2865       while (unmatched > 0) {
  3161 
       
  3162       while (_unmatched > 0) {
  2866         Value d2 = !_delta2->empty() ?
  3163         Value d2 = !_delta2->empty() ?
  2867           _delta2->prio() : std::numeric_limits<Value>::max();
  3164           _delta2->prio() : std::numeric_limits<Value>::max();
  2868 
  3165 
  2869         Value d3 = !_delta3->empty() ?
  3166         Value d3 = !_delta3->empty() ?
  2870           _delta3->prio() : std::numeric_limits<Value>::max();
  3167           _delta3->prio() : std::numeric_limits<Value>::max();
  2904 
  3201 
  2905               if (left_tree == right_tree) {
  3202               if (left_tree == right_tree) {
  2906                 shrinkOnEdge(e, left_tree);
  3203                 shrinkOnEdge(e, left_tree);
  2907               } else {
  3204               } else {
  2908                 augmentOnEdge(e);
  3205                 augmentOnEdge(e);
  2909                 unmatched -= 2;
  3206                 _unmatched -= 2;
  2910               }
  3207               }
  2911             }
  3208             }
  2912           } break;
  3209           } break;
  2913         case D4:
  3210         case D4:
  2914           splitBlossom(_delta4->top());
  3211           splitBlossom(_delta4->top());
  2923     ///
  3220     ///
  2924     /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
  3221     /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
  2925     ///
  3222     ///
  2926     /// \note mwpm.run() is just a shortcut of the following code.
  3223     /// \note mwpm.run() is just a shortcut of the following code.
  2927     /// \code
  3224     /// \code
  2928     ///   mwpm.init();
  3225     ///   mwpm.fractionalInit();
  2929     ///   mwpm.start();
  3226     ///   mwpm.start();
  2930     /// \endcode
  3227     /// \endcode
  2931     bool run() {
  3228     bool run() {
  2932       init();
  3229       fractionalInit();
  2933       return start();
  3230       return start();
  2934     }
  3231     }
  2935 
  3232 
  2936     /// @}
  3233     /// @}
  2937 
  3234