gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Fractional matching initialization of weighted matchings (#314)
0 2 0
default
2 files changed with 349 insertions and 28 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_MATCHING_H
20 20
#define LEMON_MATCHING_H
21 21

	
22 22
#include <vector>
23 23
#include <queue>
24 24
#include <set>
25 25
#include <limits>
26 26

	
27 27
#include <lemon/core.h>
28 28
#include <lemon/unionfind.h>
29 29
#include <lemon/bin_heap.h>
30 30
#include <lemon/maps.h>
31
#include <lemon/fractional_matching.h>
31 32

	
32 33
///\ingroup matching
33 34
///\file
34 35
///\brief Maximum matching algorithms in general graphs.
35 36

	
36 37
namespace lemon {
37 38

	
38 39
  /// \ingroup matching
39 40
  ///
40 41
  /// \brief Maximum cardinality matching in general graphs
41 42
  ///
42 43
  /// This class implements Edmonds' alternating forest matching algorithm
43 44
  /// for finding a maximum cardinality matching in a general undirected graph.
44 45
  /// It can be started from an arbitrary initial matching
45 46
  /// (the default is the empty one).
46 47
  ///
47 48
  /// The dual solution of the problem is a map of the nodes to
48 49
  /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
49 50
  /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
50 51
  /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
51 52
  /// with factor-critical components, the nodes in \c ODD/A form the
52 53
  /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
53 54
  /// a perfect matching. The number of the factor-critical components
54 55
  /// minus the number of barrier nodes is a lower bound on the
55 56
  /// unmatched nodes, and the matching is optimal if and only if this bound is
56 57
  /// tight. This decomposition can be obtained using \ref status() or
57 58
  /// \ref statusMap() after running the algorithm.
58 59
  ///
59 60
  /// \tparam GR The undirected graph type the algorithm runs on.
60 61
  template <typename GR>
61 62
  class MaxMatching {
62 63
  public:
63 64

	
64 65
    /// The graph type of the algorithm
65 66
    typedef GR Graph;
66 67
    /// The type of the matching map
67 68
    typedef typename Graph::template NodeMap<typename Graph::Arc>
68 69
    MatchingMap;
69 70

	
70 71
    ///\brief Status constants for Gallai-Edmonds decomposition.
71 72
    ///
72 73
    ///These constants are used for indicating the Gallai-Edmonds
73 74
    ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
74 75
    ///induce a subgraph with factor-critical components, the nodes with
75 76
    ///status \c ODD (or \c A) form the canonical barrier, and the nodes
76 77
    ///with status \c MATCHED (or \c C) induce a subgraph having a
77 78
    ///perfect matching.
78 79
    enum Status {
... ...
@@ -752,96 +753,100 @@
752 753
    struct BlossomData {
753 754
      int tree;
754 755
      Status status;
755 756
      Arc pred, next;
756 757
      Value pot, offset;
757 758
      Node base;
758 759
    };
759 760

	
760 761
    IntNodeMap *_blossom_index;
761 762
    BlossomSet *_blossom_set;
762 763
    RangeMap<BlossomData>* _blossom_data;
763 764

	
764 765
    IntNodeMap *_node_index;
765 766
    IntArcMap *_node_heap_index;
766 767

	
767 768
    struct NodeData {
768 769

	
769 770
      NodeData(IntArcMap& node_heap_index)
770 771
        : heap(node_heap_index) {}
771 772

	
772 773
      int blossom;
773 774
      Value pot;
774 775
      BinHeap<Value, IntArcMap> heap;
775 776
      std::map<int, Arc> heap_index;
776 777

	
777 778
      int tree;
778 779
    };
779 780

	
780 781
    RangeMap<NodeData>* _node_data;
781 782

	
782 783
    typedef ExtendFindEnum<IntIntMap> TreeSet;
783 784

	
784 785
    IntIntMap *_tree_set_index;
785 786
    TreeSet *_tree_set;
786 787

	
787 788
    IntNodeMap *_delta1_index;
788 789
    BinHeap<Value, IntNodeMap> *_delta1;
789 790

	
790 791
    IntIntMap *_delta2_index;
791 792
    BinHeap<Value, IntIntMap> *_delta2;
792 793

	
793 794
    IntEdgeMap *_delta3_index;
794 795
    BinHeap<Value, IntEdgeMap> *_delta3;
795 796

	
796 797
    IntIntMap *_delta4_index;
797 798
    BinHeap<Value, IntIntMap> *_delta4;
798 799

	
799 800
    Value _delta_sum;
801
    int _unmatched;
802

	
803
    typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
804
    FractionalMatching *_fractional;
800 805

	
801 806
    void createStructures() {
802 807
      _node_num = countNodes(_graph);
803 808
      _blossom_num = _node_num * 3 / 2;
804 809

	
805 810
      if (!_matching) {
806 811
        _matching = new MatchingMap(_graph);
807 812
      }
808 813
      if (!_node_potential) {
809 814
        _node_potential = new NodePotential(_graph);
810 815
      }
811 816
      if (!_blossom_set) {
812 817
        _blossom_index = new IntNodeMap(_graph);
813 818
        _blossom_set = new BlossomSet(*_blossom_index);
814 819
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
815 820
      }
816 821

	
817 822
      if (!_node_index) {
818 823
        _node_index = new IntNodeMap(_graph);
819 824
        _node_heap_index = new IntArcMap(_graph);
820 825
        _node_data = new RangeMap<NodeData>(_node_num,
821 826
                                              NodeData(*_node_heap_index));
822 827
      }
823 828

	
824 829
      if (!_tree_set) {
825 830
        _tree_set_index = new IntIntMap(_blossom_num);
826 831
        _tree_set = new TreeSet(*_tree_set_index);
827 832
      }
828 833
      if (!_delta1) {
829 834
        _delta1_index = new IntNodeMap(_graph);
830 835
        _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
831 836
      }
832 837
      if (!_delta2) {
833 838
        _delta2_index = new IntIntMap(_blossom_num);
834 839
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
835 840
      }
836 841
      if (!_delta3) {
837 842
        _delta3_index = new IntEdgeMap(_graph);
838 843
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
839 844
      }
840 845
      if (!_delta4) {
841 846
        _delta4_index = new IntIntMap(_blossom_num);
842 847
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
843 848
      }
844 849
    }
845 850

	
846 851
    void destroyStructures() {
847 852
      if (_matching) {
... ...
@@ -1514,252 +1519,397 @@
1514 1519
      }
1515 1520
    }
1516 1521

	
1517 1522
    void extractMatching() {
1518 1523
      std::vector<int> blossoms;
1519 1524
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1520 1525
        blossoms.push_back(c);
1521 1526
      }
1522 1527

	
1523 1528
      for (int i = 0; i < int(blossoms.size()); ++i) {
1524 1529
        if ((*_blossom_data)[blossoms[i]].next != INVALID) {
1525 1530

	
1526 1531
          Value offset = (*_blossom_data)[blossoms[i]].offset;
1527 1532
          (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1528 1533
          for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1529 1534
               n != INVALID; ++n) {
1530 1535
            (*_node_data)[(*_node_index)[n]].pot -= offset;
1531 1536
          }
1532 1537

	
1533 1538
          Arc matching = (*_blossom_data)[blossoms[i]].next;
1534 1539
          Node base = _graph.source(matching);
1535 1540
          extractBlossom(blossoms[i], base, matching);
1536 1541
        } else {
1537 1542
          Node base = (*_blossom_data)[blossoms[i]].base;
1538 1543
          extractBlossom(blossoms[i], base, INVALID);
1539 1544
        }
1540 1545
      }
1541 1546
    }
1542 1547

	
1543 1548
  public:
1544 1549

	
1545 1550
    /// \brief Constructor
1546 1551
    ///
1547 1552
    /// Constructor.
1548 1553
    MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1549 1554
      : _graph(graph), _weight(weight), _matching(0),
1550 1555
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
1551 1556
        _node_num(0), _blossom_num(0),
1552 1557

	
1553 1558
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
1554 1559
        _node_index(0), _node_heap_index(0), _node_data(0),
1555 1560
        _tree_set_index(0), _tree_set(0),
1556 1561

	
1557 1562
        _delta1_index(0), _delta1(0),
1558 1563
        _delta2_index(0), _delta2(0),
1559 1564
        _delta3_index(0), _delta3(0),
1560 1565
        _delta4_index(0), _delta4(0),
1561 1566

	
1562
        _delta_sum() {}
1567
        _delta_sum(), _unmatched(0),
1568

	
1569
        _fractional(0)
1570
    {}
1563 1571

	
1564 1572
    ~MaxWeightedMatching() {
1565 1573
      destroyStructures();
1574
      if (_fractional) {
1575
        delete _fractional;
1576
      }
1566 1577
    }
1567 1578

	
1568 1579
    /// \name Execution Control
1569 1580
    /// The simplest way to execute the algorithm is to use the
1570 1581
    /// \ref run() member function.
1571 1582

	
1572 1583
    ///@{
1573 1584

	
1574 1585
    /// \brief Initialize the algorithm
1575 1586
    ///
1576 1587
    /// This function initializes the algorithm.
1577 1588
    void init() {
1578 1589
      createStructures();
1579 1590

	
1580 1591
      for (ArcIt e(_graph); e != INVALID; ++e) {
1581 1592
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1582 1593
      }
1583 1594
      for (NodeIt n(_graph); n != INVALID; ++n) {
1584 1595
        (*_delta1_index)[n] = _delta1->PRE_HEAP;
1585 1596
      }
1586 1597
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1587 1598
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
1588 1599
      }
1589 1600
      for (int i = 0; i < _blossom_num; ++i) {
1590 1601
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
1591 1602
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
1592 1603
      }
1593 1604

	
1605
      _unmatched = _node_num;
1606

	
1594 1607
      int index = 0;
1595 1608
      for (NodeIt n(_graph); n != INVALID; ++n) {
1596 1609
        Value max = 0;
1597 1610
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1598 1611
          if (_graph.target(e) == n) continue;
1599 1612
          if ((dualScale * _weight[e]) / 2 > max) {
1600 1613
            max = (dualScale * _weight[e]) / 2;
1601 1614
          }
1602 1615
        }
1603 1616
        (*_node_index)[n] = index;
1604 1617
        (*_node_data)[index].pot = max;
1605 1618
        _delta1->push(n, max);
1606 1619
        int blossom =
1607 1620
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
1608 1621

	
1609 1622
        _tree_set->insert(blossom);
1610 1623

	
1611 1624
        (*_blossom_data)[blossom].status = EVEN;
1612 1625
        (*_blossom_data)[blossom].pred = INVALID;
1613 1626
        (*_blossom_data)[blossom].next = INVALID;
1614 1627
        (*_blossom_data)[blossom].pot = 0;
1615 1628
        (*_blossom_data)[blossom].offset = 0;
1616 1629
        ++index;
1617 1630
      }
1618 1631
      for (EdgeIt e(_graph); e != INVALID; ++e) {
1619 1632
        int si = (*_node_index)[_graph.u(e)];
1620 1633
        int ti = (*_node_index)[_graph.v(e)];
1621 1634
        if (_graph.u(e) != _graph.v(e)) {
1622 1635
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1623 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 1778
    /// \brief Start the algorithm
1629 1779
    ///
1630 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 1784
    void start() {
1634 1785
      enum OpType {
1635 1786
        D1, D2, D3, D4
1636 1787
      };
1637 1788

	
1638
      int unmatched = _node_num;
1639
      while (unmatched > 0) {
1789
      while (_unmatched > 0) {
1640 1790
        Value d1 = !_delta1->empty() ?
1641 1791
          _delta1->prio() : std::numeric_limits<Value>::max();
1642 1792

	
1643 1793
        Value d2 = !_delta2->empty() ?
1644 1794
          _delta2->prio() : std::numeric_limits<Value>::max();
1645 1795

	
1646 1796
        Value d3 = !_delta3->empty() ?
1647 1797
          _delta3->prio() : std::numeric_limits<Value>::max();
1648 1798

	
1649 1799
        Value d4 = !_delta4->empty() ?
1650 1800
          _delta4->prio() : std::numeric_limits<Value>::max();
1651 1801

	
1652 1802
        _delta_sum = d3; OpType ot = D3;
1653 1803
        if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
1654 1804
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1655 1805
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1656 1806

	
1657 1807
        switch (ot) {
1658 1808
        case D1:
1659 1809
          {
1660 1810
            Node n = _delta1->top();
1661 1811
            unmatchNode(n);
1662
            --unmatched;
1812
            --_unmatched;
1663 1813
          }
1664 1814
          break;
1665 1815
        case D2:
1666 1816
          {
1667 1817
            int blossom = _delta2->top();
1668 1818
            Node n = _blossom_set->classTop(blossom);
1669 1819
            Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
1670 1820
            if ((*_blossom_data)[blossom].next == INVALID) {
1671 1821
              augmentOnArc(a);
1672
              --unmatched;
1822
              --_unmatched;
1673 1823
            } else {
1674 1824
              extendOnArc(a);
1675 1825
            }
1676 1826
          }
1677 1827
          break;
1678 1828
        case D3:
1679 1829
          {
1680 1830
            Edge e = _delta3->top();
1681 1831

	
1682 1832
            int left_blossom = _blossom_set->find(_graph.u(e));
1683 1833
            int right_blossom = _blossom_set->find(_graph.v(e));
1684 1834

	
1685 1835
            if (left_blossom == right_blossom) {
1686 1836
              _delta3->pop();
1687 1837
            } else {
1688 1838
              int left_tree = _tree_set->find(left_blossom);
1689 1839
              int right_tree = _tree_set->find(right_blossom);
1690 1840

	
1691 1841
              if (left_tree == right_tree) {
1692 1842
                shrinkOnEdge(e, left_tree);
1693 1843
              } else {
1694 1844
                augmentOnEdge(e);
1695
                unmatched -= 2;
1845
                _unmatched -= 2;
1696 1846
              }
1697 1847
            }
1698 1848
          } break;
1699 1849
        case D4:
1700 1850
          splitBlossom(_delta4->top());
1701 1851
          break;
1702 1852
        }
1703 1853
      }
1704 1854
      extractMatching();
1705 1855
    }
1706 1856

	
1707 1857
    /// \brief Run the algorithm.
1708 1858
    ///
1709 1859
    /// This method runs the \c %MaxWeightedMatching algorithm.
1710 1860
    ///
1711 1861
    /// \note mwm.run() is just a shortcut of the following code.
1712 1862
    /// \code
1713
    ///   mwm.init();
1863
    ///   mwm.fractionalInit();
1714 1864
    ///   mwm.start();
1715 1865
    /// \endcode
1716 1866
    void run() {
1717
      init();
1867
      fractionalInit();
1718 1868
      start();
1719 1869
    }
1720 1870

	
1721 1871
    /// @}
1722 1872

	
1723 1873
    /// \name Primal Solution
1724 1874
    /// Functions to get the primal solution, i.e. the maximum weighted
1725 1875
    /// matching.\n
1726 1876
    /// Either \ref run() or \ref start() function should be called before
1727 1877
    /// using them.
1728 1878

	
1729 1879
    /// @{
1730 1880

	
1731 1881
    /// \brief Return the weight of the matching.
1732 1882
    ///
1733 1883
    /// This function returns the weight of the found matching.
1734 1884
    ///
1735 1885
    /// \pre Either run() or start() must be called before using this function.
1736 1886
    Value matchingWeight() const {
1737 1887
      Value sum = 0;
1738 1888
      for (NodeIt n(_graph); n != INVALID; ++n) {
1739 1889
        if ((*_matching)[n] != INVALID) {
1740 1890
          sum += _weight[(*_matching)[n]];
1741 1891
        }
1742 1892
      }
1743 1893
      return sum / 2;
1744 1894
    }
1745 1895

	
1746 1896
    /// \brief Return the size (cardinality) of the matching.
1747 1897
    ///
1748 1898
    /// This function returns the size (cardinality) of the found matching.
1749 1899
    ///
1750 1900
    /// \pre Either run() or start() must be called before using this function.
1751 1901
    int matchingSize() const {
1752 1902
      int num = 0;
1753 1903
      for (NodeIt n(_graph); n != INVALID; ++n) {
1754 1904
        if ((*_matching)[n] != INVALID) {
1755 1905
          ++num;
1756 1906
        }
1757 1907
      }
1758 1908
      return num /= 2;
1759 1909
    }
1760 1910

	
1761 1911
    /// \brief Return \c true if the given edge is in the matching.
1762 1912
    ///
1763 1913
    /// This function returns \c true if the given edge is in the found
1764 1914
    /// matching.
1765 1915
    ///
... ...
@@ -2029,96 +2179,101 @@
2029 2179
      EVEN = -1, MATCHED = 0, ODD = 1
2030 2180
    };
2031 2181

	
2032 2182
    typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2033 2183
    struct BlossomData {
2034 2184
      int tree;
2035 2185
      Status status;
2036 2186
      Arc pred, next;
2037 2187
      Value pot, offset;
2038 2188
    };
2039 2189

	
2040 2190
    IntNodeMap *_blossom_index;
2041 2191
    BlossomSet *_blossom_set;
2042 2192
    RangeMap<BlossomData>* _blossom_data;
2043 2193

	
2044 2194
    IntNodeMap *_node_index;
2045 2195
    IntArcMap *_node_heap_index;
2046 2196

	
2047 2197
    struct NodeData {
2048 2198

	
2049 2199
      NodeData(IntArcMap& node_heap_index)
2050 2200
        : heap(node_heap_index) {}
2051 2201

	
2052 2202
      int blossom;
2053 2203
      Value pot;
2054 2204
      BinHeap<Value, IntArcMap> heap;
2055 2205
      std::map<int, Arc> heap_index;
2056 2206

	
2057 2207
      int tree;
2058 2208
    };
2059 2209

	
2060 2210
    RangeMap<NodeData>* _node_data;
2061 2211

	
2062 2212
    typedef ExtendFindEnum<IntIntMap> TreeSet;
2063 2213

	
2064 2214
    IntIntMap *_tree_set_index;
2065 2215
    TreeSet *_tree_set;
2066 2216

	
2067 2217
    IntIntMap *_delta2_index;
2068 2218
    BinHeap<Value, IntIntMap> *_delta2;
2069 2219

	
2070 2220
    IntEdgeMap *_delta3_index;
2071 2221
    BinHeap<Value, IntEdgeMap> *_delta3;
2072 2222

	
2073 2223
    IntIntMap *_delta4_index;
2074 2224
    BinHeap<Value, IntIntMap> *_delta4;
2075 2225

	
2076 2226
    Value _delta_sum;
2227
    int _unmatched;
2228

	
2229
    typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap> 
2230
    FractionalMatching;
2231
    FractionalMatching *_fractional;
2077 2232

	
2078 2233
    void createStructures() {
2079 2234
      _node_num = countNodes(_graph);
2080 2235
      _blossom_num = _node_num * 3 / 2;
2081 2236

	
2082 2237
      if (!_matching) {
2083 2238
        _matching = new MatchingMap(_graph);
2084 2239
      }
2085 2240
      if (!_node_potential) {
2086 2241
        _node_potential = new NodePotential(_graph);
2087 2242
      }
2088 2243
      if (!_blossom_set) {
2089 2244
        _blossom_index = new IntNodeMap(_graph);
2090 2245
        _blossom_set = new BlossomSet(*_blossom_index);
2091 2246
        _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2092 2247
      }
2093 2248

	
2094 2249
      if (!_node_index) {
2095 2250
        _node_index = new IntNodeMap(_graph);
2096 2251
        _node_heap_index = new IntArcMap(_graph);
2097 2252
        _node_data = new RangeMap<NodeData>(_node_num,
2098 2253
                                            NodeData(*_node_heap_index));
2099 2254
      }
2100 2255

	
2101 2256
      if (!_tree_set) {
2102 2257
        _tree_set_index = new IntIntMap(_blossom_num);
2103 2258
        _tree_set = new TreeSet(*_tree_set_index);
2104 2259
      }
2105 2260
      if (!_delta2) {
2106 2261
        _delta2_index = new IntIntMap(_blossom_num);
2107 2262
        _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2108 2263
      }
2109 2264
      if (!_delta3) {
2110 2265
        _delta3_index = new IntEdgeMap(_graph);
2111 2266
        _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2112 2267
      }
2113 2268
      if (!_delta4) {
2114 2269
        _delta4_index = new IntIntMap(_blossom_num);
2115 2270
        _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2116 2271
      }
2117 2272
    }
2118 2273

	
2119 2274
    void destroyStructures() {
2120 2275
      if (_matching) {
2121 2276
        delete _matching;
2122 2277
      }
2123 2278
      if (_node_potential) {
2124 2279
        delete _node_potential;
... ...
@@ -2744,237 +2899,379 @@
2744 2899
        }
2745 2900
        extractBlossom(subblossoms[ib], base, matching);
2746 2901

	
2747 2902
        int en = _blossom_node_list.size();
2748 2903

	
2749 2904
        _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2750 2905
      }
2751 2906
    }
2752 2907

	
2753 2908
    void extractMatching() {
2754 2909
      std::vector<int> blossoms;
2755 2910
      for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2756 2911
        blossoms.push_back(c);
2757 2912
      }
2758 2913

	
2759 2914
      for (int i = 0; i < int(blossoms.size()); ++i) {
2760 2915

	
2761 2916
        Value offset = (*_blossom_data)[blossoms[i]].offset;
2762 2917
        (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2763 2918
        for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2764 2919
             n != INVALID; ++n) {
2765 2920
          (*_node_data)[(*_node_index)[n]].pot -= offset;
2766 2921
        }
2767 2922

	
2768 2923
        Arc matching = (*_blossom_data)[blossoms[i]].next;
2769 2924
        Node base = _graph.source(matching);
2770 2925
        extractBlossom(blossoms[i], base, matching);
2771 2926
      }
2772 2927
    }
2773 2928

	
2774 2929
  public:
2775 2930

	
2776 2931
    /// \brief Constructor
2777 2932
    ///
2778 2933
    /// Constructor.
2779 2934
    MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2780 2935
      : _graph(graph), _weight(weight), _matching(0),
2781 2936
        _node_potential(0), _blossom_potential(), _blossom_node_list(),
2782 2937
        _node_num(0), _blossom_num(0),
2783 2938

	
2784 2939
        _blossom_index(0), _blossom_set(0), _blossom_data(0),
2785 2940
        _node_index(0), _node_heap_index(0), _node_data(0),
2786 2941
        _tree_set_index(0), _tree_set(0),
2787 2942

	
2788 2943
        _delta2_index(0), _delta2(0),
2789 2944
        _delta3_index(0), _delta3(0),
2790 2945
        _delta4_index(0), _delta4(0),
2791 2946

	
2792
        _delta_sum() {}
2947
        _delta_sum(), _unmatched(0),
2948

	
2949
        _fractional(0)
2950
    {}
2793 2951

	
2794 2952
    ~MaxWeightedPerfectMatching() {
2795 2953
      destroyStructures();
2954
      if (_fractional) {
2955
        delete _fractional;
2956
      }
2796 2957
    }
2797 2958

	
2798 2959
    /// \name Execution Control
2799 2960
    /// The simplest way to execute the algorithm is to use the
2800 2961
    /// \ref run() member function.
2801 2962

	
2802 2963
    ///@{
2803 2964

	
2804 2965
    /// \brief Initialize the algorithm
2805 2966
    ///
2806 2967
    /// This function initializes the algorithm.
2807 2968
    void init() {
2808 2969
      createStructures();
2809 2970

	
2810 2971
      for (ArcIt e(_graph); e != INVALID; ++e) {
2811 2972
        (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2812 2973
      }
2813 2974
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2814 2975
        (*_delta3_index)[e] = _delta3->PRE_HEAP;
2815 2976
      }
2816 2977
      for (int i = 0; i < _blossom_num; ++i) {
2817 2978
        (*_delta2_index)[i] = _delta2->PRE_HEAP;
2818 2979
        (*_delta4_index)[i] = _delta4->PRE_HEAP;
2819 2980
      }
2820 2981

	
2982
      _unmatched = _node_num;
2983

	
2821 2984
      int index = 0;
2822 2985
      for (NodeIt n(_graph); n != INVALID; ++n) {
2823 2986
        Value max = - std::numeric_limits<Value>::max();
2824 2987
        for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2825 2988
          if (_graph.target(e) == n) continue;
2826 2989
          if ((dualScale * _weight[e]) / 2 > max) {
2827 2990
            max = (dualScale * _weight[e]) / 2;
2828 2991
          }
2829 2992
        }
2830 2993
        (*_node_index)[n] = index;
2831 2994
        (*_node_data)[index].pot = max;
2832 2995
        int blossom =
2833 2996
          _blossom_set->insert(n, std::numeric_limits<Value>::max());
2834 2997

	
2835 2998
        _tree_set->insert(blossom);
2836 2999

	
2837 3000
        (*_blossom_data)[blossom].status = EVEN;
2838 3001
        (*_blossom_data)[blossom].pred = INVALID;
2839 3002
        (*_blossom_data)[blossom].next = INVALID;
2840 3003
        (*_blossom_data)[blossom].pot = 0;
2841 3004
        (*_blossom_data)[blossom].offset = 0;
2842 3005
        ++index;
2843 3006
      }
2844 3007
      for (EdgeIt e(_graph); e != INVALID; ++e) {
2845 3008
        int si = (*_node_index)[_graph.u(e)];
2846 3009
        int ti = (*_node_index)[_graph.v(e)];
2847 3010
        if (_graph.u(e) != _graph.v(e)) {
2848 3011
          _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2849 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 3149
    /// \brief Start the algorithm
2855 3150
    ///
2856 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 3155
    bool start() {
2860 3156
      enum OpType {
2861 3157
        D2, D3, D4
2862 3158
      };
2863 3159

	
2864
      int unmatched = _node_num;
2865
      while (unmatched > 0) {
3160
      if (_unmatched == -1) return false;
3161

	
3162
      while (_unmatched > 0) {
2866 3163
        Value d2 = !_delta2->empty() ?
2867 3164
          _delta2->prio() : std::numeric_limits<Value>::max();
2868 3165

	
2869 3166
        Value d3 = !_delta3->empty() ?
2870 3167
          _delta3->prio() : std::numeric_limits<Value>::max();
2871 3168

	
2872 3169
        Value d4 = !_delta4->empty() ?
2873 3170
          _delta4->prio() : std::numeric_limits<Value>::max();
2874 3171

	
2875 3172
        _delta_sum = d3; OpType ot = D3;
2876 3173
        if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
2877 3174
        if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2878 3175

	
2879 3176
        if (_delta_sum == std::numeric_limits<Value>::max()) {
2880 3177
          return false;
2881 3178
        }
2882 3179

	
2883 3180
        switch (ot) {
2884 3181
        case D2:
2885 3182
          {
2886 3183
            int blossom = _delta2->top();
2887 3184
            Node n = _blossom_set->classTop(blossom);
2888 3185
            Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
2889 3186
            extendOnArc(e);
2890 3187
          }
2891 3188
          break;
2892 3189
        case D3:
2893 3190
          {
2894 3191
            Edge e = _delta3->top();
2895 3192

	
2896 3193
            int left_blossom = _blossom_set->find(_graph.u(e));
2897 3194
            int right_blossom = _blossom_set->find(_graph.v(e));
2898 3195

	
2899 3196
            if (left_blossom == right_blossom) {
2900 3197
              _delta3->pop();
2901 3198
            } else {
2902 3199
              int left_tree = _tree_set->find(left_blossom);
2903 3200
              int right_tree = _tree_set->find(right_blossom);
2904 3201

	
2905 3202
              if (left_tree == right_tree) {
2906 3203
                shrinkOnEdge(e, left_tree);
2907 3204
              } else {
2908 3205
                augmentOnEdge(e);
2909
                unmatched -= 2;
3206
                _unmatched -= 2;
2910 3207
              }
2911 3208
            }
2912 3209
          } break;
2913 3210
        case D4:
2914 3211
          splitBlossom(_delta4->top());
2915 3212
          break;
2916 3213
        }
2917 3214
      }
2918 3215
      extractMatching();
2919 3216
      return true;
2920 3217
    }
2921 3218

	
2922 3219
    /// \brief Run the algorithm.
2923 3220
    ///
2924 3221
    /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
2925 3222
    ///
2926 3223
    /// \note mwpm.run() is just a shortcut of the following code.
2927 3224
    /// \code
2928
    ///   mwpm.init();
3225
    ///   mwpm.fractionalInit();
2929 3226
    ///   mwpm.start();
2930 3227
    /// \endcode
2931 3228
    bool run() {
2932
      init();
3229
      fractionalInit();
2933 3230
      return start();
2934 3231
    }
2935 3232

	
2936 3233
    /// @}
2937 3234

	
2938 3235
    /// \name Primal Solution
2939 3236
    /// Functions to get the primal solution, i.e. the maximum weighted
2940 3237
    /// perfect matching.\n
2941 3238
    /// Either \ref run() or \ref start() function should be called before
2942 3239
    /// using them.
2943 3240

	
2944 3241
    /// @{
2945 3242

	
2946 3243
    /// \brief Return the weight of the matching.
2947 3244
    ///
2948 3245
    /// This function returns the weight of the found matching.
2949 3246
    ///
2950 3247
    /// \pre Either run() or start() must be called before using this function.
2951 3248
    Value matchingWeight() const {
2952 3249
      Value sum = 0;
2953 3250
      for (NodeIt n(_graph); n != INVALID; ++n) {
2954 3251
        if ((*_matching)[n] != INVALID) {
2955 3252
          sum += _weight[(*_matching)[n]];
2956 3253
        }
2957 3254
      }
2958 3255
      return sum / 2;
2959 3256
    }
2960 3257

	
2961 3258
    /// \brief Return \c true if the given edge is in the matching.
2962 3259
    ///
2963 3260
    /// This function returns \c true if the given edge is in the found
2964 3261
    /// matching.
2965 3262
    ///
2966 3263
    /// \pre Either run() or start() must be called before using this function.
2967 3264
    bool matching(const Edge& edge) const {
2968 3265
      return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
2969 3266
    }
2970 3267

	
2971 3268
    /// \brief Return the matching arc (or edge) incident to the given node.
2972 3269
    ///
2973 3270
    /// This function returns the matching arc (or edge) incident to the
2974 3271
    /// given node in the found matching or \c INVALID if the node is
2975 3272
    /// not covered by the matching.
2976 3273
    ///
2977 3274
    /// \pre Either run() or start() must be called before using this function.
2978 3275
    Arc matching(const Node& node) const {
2979 3276
      return (*_matching)[node];
2980 3277
    }
Ignore white space 96 line context
... ...
@@ -356,69 +356,93 @@
356 356
      if (s == true && t == true) {
357 357
        rw += mwpm.blossomValue(i);
358 358
      }
359 359
    }
360 360
    rw -= weight[e] * mwpm.dualScale;
361 361

	
362 362
    check(rw >= 0, "Negative reduced weight");
363 363
    check(rw == 0 || !mwpm.matching(e),
364 364
          "Non-zero reduced weight on matching edge");
365 365
  }
366 366

	
367 367
  int pv = 0;
368 368
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
369 369
    check(mwpm.matching(n) != INVALID, "Non perfect");
370 370
    pv += weight[mwpm.matching(n)];
371 371
    SmartGraph::Node o = graph.target(mwpm.matching(n));
372 372
    check(mwpm.mate(n) == o, "Invalid matching");
373 373
    check(mwpm.matching(n) == graph.oppositeArc(mwpm.matching(o)),
374 374
          "Invalid matching");
375 375
  }
376 376

	
377 377
  int dv = 0;
378 378
  for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
379 379
    dv += mwpm.nodeValue(n);
380 380
  }
381 381

	
382 382
  for (int i = 0; i < mwpm.blossomNum(); ++i) {
383 383
    check(mwpm.blossomValue(i) >= 0, "Invalid blossom value");
384 384
    check(mwpm.blossomSize(i) % 2 == 1, "Even blossom size");
385 385
    dv += mwpm.blossomValue(i) * ((mwpm.blossomSize(i) - 1) / 2);
386 386
  }
387 387

	
388 388
  check(pv * mwpm.dualScale == dv * 2, "Wrong duality");
389 389

	
390 390
  return;
391 391
}
392 392

	
393 393

	
394 394
int main() {
395 395

	
396 396
  for (int i = 0; i < lgfn; ++i) {
397 397
    SmartGraph graph;
398 398
    SmartGraph::EdgeMap<int> weight(graph);
399 399

	
400 400
    istringstream lgfs(lgf[i]);
401 401
    graphReader(graph, lgfs).
402 402
      edgeMap("weight", weight).run();
403 403

	
404
    MaxMatching<SmartGraph> mm(graph);
405
    mm.run();
406
    checkMatching(graph, mm);
404
    bool perfect;
405
    {
406
      MaxMatching<SmartGraph> mm(graph);
407
      mm.run();
408
      checkMatching(graph, mm);
409
      perfect = 2 * mm.matchingSize() == countNodes(graph);
410
    }
407 411

	
408
    MaxWeightedMatching<SmartGraph> mwm(graph, weight);
409
    mwm.run();
410
    checkWeightedMatching(graph, weight, mwm);
412
    {
413
      MaxWeightedMatching<SmartGraph> mwm(graph, weight);
414
      mwm.run();
415
      checkWeightedMatching(graph, weight, mwm);
416
    }
411 417

	
412
    MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
413
    bool perfect = mwpm.run();
418
    {
419
      MaxWeightedMatching<SmartGraph> mwm(graph, weight);
420
      mwm.init();
421
      mwm.start();
422
      checkWeightedMatching(graph, weight, mwm);
423
    }
414 424

	
415
    check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
416
          "Perfect matching found");
425
    {
426
      MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
427
      bool result = mwpm.run();
428
      
429
      check(result == perfect, "Perfect matching found");
430
      if (perfect) {
431
        checkWeightedPerfectMatching(graph, weight, mwpm);
432
      }
433
    }
417 434

	
418
    if (perfect) {
419
      checkWeightedPerfectMatching(graph, weight, mwpm);
435
    {
436
      MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
437
      mwpm.init();
438
      bool result = mwpm.start();
439
      
440
      check(result == perfect, "Perfect matching found");
441
      if (perfect) {
442
        checkWeightedPerfectMatching(graph, weight, mwpm);
443
      }
420 444
    }
421 445
  }
422 446

	
423 447
  return 0;
424 448
}
0 comments (0 inline)