Changes in / [874:d8ea85825e02:873:23da1b807280] in lemon-main
- Files:
-
- 2 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/groups.dox
r874 r873 387 387 problem of maximum flow. 388 388 389 \ref Circulation is a preflow push-relabel algorithm implemented directly 389 \ref Circulation is a preflow push-relabel algorithm implemented directly 390 390 for finding feasible circulations, which is a somewhat different problem, 391 391 but it is strongly related to maximum flow. … … 523 523 Edmond's blossom shrinking algorithm for calculating maximum weighted 524 524 perfect matching in general graphs. 525 - \ref MaxFractionalMatching Push-relabel algorithm for calculating526 maximum cardinality fractional matching in general graphs.527 - \ref MaxWeightedFractionalMatching Augmenting path algorithm for calculating528 maximum weighted fractional matching in general graphs.529 - \ref MaxWeightedPerfectFractionalMatching530 Augmenting path algorithm for calculating maximum weighted531 perfect fractional matching in general graphs.532 525 533 526 \image html matching.png -
lemon/Makefile.am
r874 r864 85 85 lemon/euler.h \ 86 86 lemon/fib_heap.h \ 87 lemon/fractional_matching.h \88 87 lemon/full_graph.h \ 89 88 lemon/glpk.h \ -
lemon/matching.h
r870 r651 17 17 */ 18 18 19 #ifndef LEMON_MA TCHING_H20 #define LEMON_MA TCHING_H19 #ifndef LEMON_MAX_MATCHING_H 20 #define LEMON_MAX_MATCHING_H 21 21 22 22 #include <vector> … … 29 29 #include <lemon/bin_heap.h> 30 30 #include <lemon/maps.h> 31 #include <lemon/fractional_matching.h>32 31 33 32 ///\ingroup matching … … 43 42 /// This class implements Edmonds' alternating forest matching algorithm 44 43 /// for finding a maximum cardinality matching in a general undirected graph. 45 /// It can be started from an arbitrary initial matching 44 /// It can be started from an arbitrary initial matching 46 45 /// (the default is the empty one). 47 46 /// … … 71 70 ///\brief Status constants for Gallai-Edmonds decomposition. 72 71 /// 73 ///These constants are used for indicating the Gallai-Edmonds 72 ///These constants are used for indicating the Gallai-Edmonds 74 73 ///decomposition of a graph. The nodes with status \c EVEN (or \c D) 75 74 ///induce a subgraph with factor-critical components, the nodes with 76 75 ///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 76 ///with status \c MATCHED (or \c C) induce a subgraph having a 78 77 ///perfect matching. 79 78 enum Status { … … 514 513 } 515 514 516 /// \brief Start Edmonds' algorithm with a heuristic improvement 515 /// \brief Start Edmonds' algorithm with a heuristic improvement 517 516 /// for dense graphs 518 517 /// … … 536 535 /// \brief Run Edmonds' algorithm 537 536 /// 538 /// This function runs Edmonds' algorithm. An additional heuristic of 539 /// postponing shrinks is used for relatively dense graphs 537 /// This function runs Edmonds' algorithm. An additional heuristic of 538 /// postponing shrinks is used for relatively dense graphs 540 539 /// (for which <tt>m>=2*n</tt> holds). 541 540 void run() { … … 558 557 /// \brief Return the size (cardinality) of the matching. 559 558 /// 560 /// This function returns the size (cardinality) of the current matching. 559 /// This function returns the size (cardinality) of the current matching. 561 560 /// After run() it returns the size of the maximum matching in the graph. 562 561 int matchingSize() const { … … 572 571 /// \brief Return \c true if the given edge is in the matching. 573 572 /// 574 /// This function returns \c true if the given edge is in the current 573 /// This function returns \c true if the given edge is in the current 575 574 /// matching. 576 575 bool matching(const Edge& edge) const { … … 581 580 /// 582 581 /// This function returns the matching arc (or edge) incident to the 583 /// given node in the current matching or \c INVALID if the node is 582 /// given node in the current matching or \c INVALID if the node is 584 583 /// not covered by the matching. 585 584 Arc matching(const Node& n) const { … … 597 596 /// \brief Return the mate of the given node. 598 597 /// 599 /// This function returns the mate of the given node in the current 598 /// This function returns the mate of the given node in the current 600 599 /// matching or \c INVALID if the node is not covered by the matching. 601 600 Node mate(const Node& n) const { … … 607 606 608 607 /// \name Dual Solution 609 /// Functions to get the dual solution, i.e. the Gallai-Edmonds 608 /// Functions to get the dual solution, i.e. the Gallai-Edmonds 610 609 /// decomposition. 611 610 … … 650 649 /// \f$O(nm\log n)\f$ time complexity. 651 650 /// 652 /// The maximum weighted matching problem is to find a subset of the 653 /// edges in an undirected graph with maximum overall weight for which 651 /// The maximum weighted matching problem is to find a subset of the 652 /// edges in an undirected graph with maximum overall weight for which 654 653 /// each node has at most one incident edge. 655 654 /// It can be formulated with the following linear program. … … 675 674 \frac{\vert B \vert - 1}{2}z_B\f] */ 676 675 /// 677 /// The algorithm can be executed with the run() function. 676 /// The algorithm can be executed with the run() function. 678 677 /// After it the matching (the primal solution) and the dual solution 679 /// can be obtained using the query functions and the 680 /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, 681 /// which is able to iterate on the nodes of a blossom. 678 /// can be obtained using the query functions and the 679 /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, 680 /// which is able to iterate on the nodes of a blossom. 682 681 /// If the value type is integer, then the dual solution is multiplied 683 682 /// by \ref MaxWeightedMatching::dualScale "4". 684 683 /// 685 684 /// \tparam GR The undirected graph type the algorithm runs on. 686 /// \tparam WM The type edge weight map. The default type is 685 /// \tparam WM The type edge weight map. The default type is 687 686 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>". 688 687 #ifdef DOXYGEN … … 747 746 748 747 enum Status { 749 EVEN = -1, MATCHED = 0, ODD = 1 748 EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2 750 749 }; 751 750 … … 799 798 800 799 Value _delta_sum; 801 int _unmatched;802 803 typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;804 FractionalMatching *_fractional;805 800 806 801 void createStructures() { … … 850 845 851 846 void destroyStructures() { 847 _node_num = countNodes(_graph); 848 _blossom_num = _node_num * 3 / 2; 849 852 850 if (_matching) { 853 851 delete _matching; … … 925 923 _delta3->push(e, rw / 2); 926 924 } 925 } else if ((*_blossom_data)[vb].status == UNMATCHED) { 926 if (_delta3->state(e) != _delta3->IN_HEAP) { 927 _delta3->push(e, rw); 928 } 927 929 } else { 930 typename std::map<int, Arc>::iterator it = 931 (*_node_data)[vi].heap_index.find(tree); 932 933 if (it != (*_node_data)[vi].heap_index.end()) { 934 if ((*_node_data)[vi].heap[it->second] > rw) { 935 (*_node_data)[vi].heap.replace(it->second, e); 936 (*_node_data)[vi].heap.decrease(e, rw); 937 it->second = e; 938 } 939 } else { 940 (*_node_data)[vi].heap.push(e, rw); 941 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e)); 942 } 943 944 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) { 945 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio()); 946 947 if ((*_blossom_data)[vb].status == MATCHED) { 948 if (_delta2->state(vb) != _delta2->IN_HEAP) { 949 _delta2->push(vb, _blossom_set->classPrio(vb) - 950 (*_blossom_data)[vb].offset); 951 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) - 952 (*_blossom_data)[vb].offset){ 953 _delta2->decrease(vb, _blossom_set->classPrio(vb) - 954 (*_blossom_data)[vb].offset); 955 } 956 } 957 } 958 } 959 } 960 } 961 (*_blossom_data)[blossom].offset = 0; 962 } 963 964 void matchedToOdd(int blossom) { 965 if (_delta2->state(blossom) == _delta2->IN_HEAP) { 966 _delta2->erase(blossom); 967 } 968 (*_blossom_data)[blossom].offset += _delta_sum; 969 if (!_blossom_set->trivial(blossom)) { 970 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 + 971 (*_blossom_data)[blossom].offset); 972 } 973 } 974 975 void evenToMatched(int blossom, int tree) { 976 if (!_blossom_set->trivial(blossom)) { 977 (*_blossom_data)[blossom].pot += 2 * _delta_sum; 978 } 979 980 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); 981 n != INVALID; ++n) { 982 int ni = (*_node_index)[n]; 983 (*_node_data)[ni].pot -= _delta_sum; 984 985 _delta1->erase(n); 986 987 for (InArcIt e(_graph, n); e != INVALID; ++e) { 988 Node v = _graph.source(e); 989 int vb = _blossom_set->find(v); 990 int vi = (*_node_index)[v]; 991 992 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - 993 dualScale * _weight[e]; 994 995 if (vb == blossom) { 996 if (_delta3->state(e) == _delta3->IN_HEAP) { 997 _delta3->erase(e); 998 } 999 } else if ((*_blossom_data)[vb].status == EVEN) { 1000 1001 if (_delta3->state(e) == _delta3->IN_HEAP) { 1002 _delta3->erase(e); 1003 } 1004 1005 int vt = _tree_set->find(vb); 1006 1007 if (vt != tree) { 1008 1009 Arc r = _graph.oppositeArc(e); 1010 1011 typename std::map<int, Arc>::iterator it = 1012 (*_node_data)[ni].heap_index.find(vt); 1013 1014 if (it != (*_node_data)[ni].heap_index.end()) { 1015 if ((*_node_data)[ni].heap[it->second] > rw) { 1016 (*_node_data)[ni].heap.replace(it->second, r); 1017 (*_node_data)[ni].heap.decrease(r, rw); 1018 it->second = r; 1019 } 1020 } else { 1021 (*_node_data)[ni].heap.push(r, rw); 1022 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r)); 1023 } 1024 1025 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) { 1026 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio()); 1027 1028 if (_delta2->state(blossom) != _delta2->IN_HEAP) { 1029 _delta2->push(blossom, _blossom_set->classPrio(blossom) - 1030 (*_blossom_data)[blossom].offset); 1031 } else if ((*_delta2)[blossom] > 1032 _blossom_set->classPrio(blossom) - 1033 (*_blossom_data)[blossom].offset){ 1034 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) - 1035 (*_blossom_data)[blossom].offset); 1036 } 1037 } 1038 } 1039 1040 } else if ((*_blossom_data)[vb].status == UNMATCHED) { 1041 if (_delta3->state(e) == _delta3->IN_HEAP) { 1042 _delta3->erase(e); 1043 } 1044 } else { 1045 1046 typename std::map<int, Arc>::iterator it = 1047 (*_node_data)[vi].heap_index.find(tree); 1048 1049 if (it != (*_node_data)[vi].heap_index.end()) { 1050 (*_node_data)[vi].heap.erase(it->second); 1051 (*_node_data)[vi].heap_index.erase(it); 1052 if ((*_node_data)[vi].heap.empty()) { 1053 _blossom_set->increase(v, std::numeric_limits<Value>::max()); 1054 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) { 1055 _blossom_set->increase(v, (*_node_data)[vi].heap.prio()); 1056 } 1057 1058 if ((*_blossom_data)[vb].status == MATCHED) { 1059 if (_blossom_set->classPrio(vb) == 1060 std::numeric_limits<Value>::max()) { 1061 _delta2->erase(vb); 1062 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) - 1063 (*_blossom_data)[vb].offset) { 1064 _delta2->increase(vb, _blossom_set->classPrio(vb) - 1065 (*_blossom_data)[vb].offset); 1066 } 1067 } 1068 } 1069 } 1070 } 1071 } 1072 } 1073 1074 void oddToMatched(int blossom) { 1075 (*_blossom_data)[blossom].offset -= _delta_sum; 1076 1077 if (_blossom_set->classPrio(blossom) != 1078 std::numeric_limits<Value>::max()) { 1079 _delta2->push(blossom, _blossom_set->classPrio(blossom) - 1080 (*_blossom_data)[blossom].offset); 1081 } 1082 1083 if (!_blossom_set->trivial(blossom)) { 1084 _delta4->erase(blossom); 1085 } 1086 } 1087 1088 void oddToEven(int blossom, int tree) { 1089 if (!_blossom_set->trivial(blossom)) { 1090 _delta4->erase(blossom); 1091 (*_blossom_data)[blossom].pot -= 1092 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset); 1093 } 1094 1095 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); 1096 n != INVALID; ++n) { 1097 int ni = (*_node_index)[n]; 1098 1099 _blossom_set->increase(n, std::numeric_limits<Value>::max()); 1100 1101 (*_node_data)[ni].heap.clear(); 1102 (*_node_data)[ni].heap_index.clear(); 1103 (*_node_data)[ni].pot += 1104 2 * _delta_sum - (*_blossom_data)[blossom].offset; 1105 1106 _delta1->push(n, (*_node_data)[ni].pot); 1107 1108 for (InArcIt e(_graph, n); e != INVALID; ++e) { 1109 Node v = _graph.source(e); 1110 int vb = _blossom_set->find(v); 1111 int vi = (*_node_index)[v]; 1112 1113 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - 1114 dualScale * _weight[e]; 1115 1116 if ((*_blossom_data)[vb].status == EVEN) { 1117 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) { 1118 _delta3->push(e, rw / 2); 1119 } 1120 } else if ((*_blossom_data)[vb].status == UNMATCHED) { 1121 if (_delta3->state(e) != _delta3->IN_HEAP) { 1122 _delta3->push(e, rw); 1123 } 1124 } else { 1125 928 1126 typename std::map<int, Arc>::iterator it = 929 1127 (*_node_data)[vi].heap_index.find(tree); … … 960 1158 } 961 1159 962 void matchedToOdd(int blossom) { 1160 1161 void matchedToUnmatched(int blossom) { 963 1162 if (_delta2->state(blossom) == _delta2->IN_HEAP) { 964 1163 _delta2->erase(blossom); 965 }966 (*_blossom_data)[blossom].offset += _delta_sum;967 if (!_blossom_set->trivial(blossom)) {968 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +969 (*_blossom_data)[blossom].offset);970 }971 }972 973 void evenToMatched(int blossom, int tree) {974 if (!_blossom_set->trivial(blossom)) {975 (*_blossom_data)[blossom].pot += 2 * _delta_sum;976 1164 } 977 1165 … … 979 1167 n != INVALID; ++n) { 980 1168 int ni = (*_node_index)[n]; 981 (*_node_data)[ni].pot -= _delta_sum; 982 983 _delta1->erase(n); 1169 1170 _blossom_set->increase(n, std::numeric_limits<Value>::max()); 1171 1172 (*_node_data)[ni].heap.clear(); 1173 (*_node_data)[ni].heap_index.clear(); 1174 1175 for (OutArcIt e(_graph, n); e != INVALID; ++e) { 1176 Node v = _graph.target(e); 1177 int vb = _blossom_set->find(v); 1178 int vi = (*_node_index)[v]; 1179 1180 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - 1181 dualScale * _weight[e]; 1182 1183 if ((*_blossom_data)[vb].status == EVEN) { 1184 if (_delta3->state(e) != _delta3->IN_HEAP) { 1185 _delta3->push(e, rw); 1186 } 1187 } 1188 } 1189 } 1190 } 1191 1192 void unmatchedToMatched(int blossom) { 1193 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); 1194 n != INVALID; ++n) { 1195 int ni = (*_node_index)[n]; 984 1196 985 1197 for (InArcIt e(_graph, n); e != INVALID; ++e) { … … 1003 1215 int vt = _tree_set->find(vb); 1004 1216 1005 if (vt != tree) { 1006 1007 Arc r = _graph.oppositeArc(e); 1008 1009 typename std::map<int, Arc>::iterator it = 1010 (*_node_data)[ni].heap_index.find(vt); 1011 1012 if (it != (*_node_data)[ni].heap_index.end()) { 1013 if ((*_node_data)[ni].heap[it->second] > rw) { 1014 (*_node_data)[ni].heap.replace(it->second, r); 1015 (*_node_data)[ni].heap.decrease(r, rw); 1016 it->second = r; 1017 } 1018 } else { 1019 (*_node_data)[ni].heap.push(r, rw); 1020 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r)); 1021 } 1022 1023 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) { 1024 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio()); 1025 1026 if (_delta2->state(blossom) != _delta2->IN_HEAP) { 1027 _delta2->push(blossom, _blossom_set->classPrio(blossom) - 1028 (*_blossom_data)[blossom].offset); 1029 } else if ((*_delta2)[blossom] > 1030 _blossom_set->classPrio(blossom) - 1031 (*_blossom_data)[blossom].offset){ 1032 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) - 1033 (*_blossom_data)[blossom].offset); 1034 } 1035 } 1036 } 1037 } else { 1217 Arc r = _graph.oppositeArc(e); 1038 1218 1039 1219 typename std::map<int, Arc>::iterator it = 1040 (*_node_data)[vi].heap_index.find(tree); 1041 1042 if (it != (*_node_data)[vi].heap_index.end()) { 1043 (*_node_data)[vi].heap.erase(it->second); 1044 (*_node_data)[vi].heap_index.erase(it); 1045 if ((*_node_data)[vi].heap.empty()) { 1046 _blossom_set->increase(v, std::numeric_limits<Value>::max()); 1047 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) { 1048 _blossom_set->increase(v, (*_node_data)[vi].heap.prio()); 1049 } 1050 1051 if ((*_blossom_data)[vb].status == MATCHED) { 1052 if (_blossom_set->classPrio(vb) == 1053 std::numeric_limits<Value>::max()) { 1054 _delta2->erase(vb); 1055 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) - 1056 (*_blossom_data)[vb].offset) { 1057 _delta2->increase(vb, _blossom_set->classPrio(vb) - 1058 (*_blossom_data)[vb].offset); 1059 } 1060 } 1061 } 1062 } 1063 } 1064 } 1065 } 1066 1067 void oddToMatched(int blossom) { 1068 (*_blossom_data)[blossom].offset -= _delta_sum; 1069 1070 if (_blossom_set->classPrio(blossom) != 1071 std::numeric_limits<Value>::max()) { 1072 _delta2->push(blossom, _blossom_set->classPrio(blossom) - 1073 (*_blossom_data)[blossom].offset); 1074 } 1075 1076 if (!_blossom_set->trivial(blossom)) { 1077 _delta4->erase(blossom); 1078 } 1079 } 1080 1081 void oddToEven(int blossom, int tree) { 1082 if (!_blossom_set->trivial(blossom)) { 1083 _delta4->erase(blossom); 1084 (*_blossom_data)[blossom].pot -= 1085 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset); 1086 } 1087 1088 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom); 1089 n != INVALID; ++n) { 1090 int ni = (*_node_index)[n]; 1091 1092 _blossom_set->increase(n, std::numeric_limits<Value>::max()); 1093 1094 (*_node_data)[ni].heap.clear(); 1095 (*_node_data)[ni].heap_index.clear(); 1096 (*_node_data)[ni].pot += 1097 2 * _delta_sum - (*_blossom_data)[blossom].offset; 1098 1099 _delta1->push(n, (*_node_data)[ni].pot); 1100 1101 for (InArcIt e(_graph, n); e != INVALID; ++e) { 1102 Node v = _graph.source(e); 1103 int vb = _blossom_set->find(v); 1104 int vi = (*_node_index)[v]; 1105 1106 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot - 1107 dualScale * _weight[e]; 1108 1109 if ((*_blossom_data)[vb].status == EVEN) { 1110 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) { 1111 _delta3->push(e, rw / 2); 1112 } 1113 } else { 1114 1115 typename std::map<int, Arc>::iterator it = 1116 (*_node_data)[vi].heap_index.find(tree); 1117 1118 if (it != (*_node_data)[vi].heap_index.end()) { 1119 if ((*_node_data)[vi].heap[it->second] > rw) { 1120 (*_node_data)[vi].heap.replace(it->second, e); 1121 (*_node_data)[vi].heap.decrease(e, rw); 1122 it->second = e; 1220 (*_node_data)[ni].heap_index.find(vt); 1221 1222 if (it != (*_node_data)[ni].heap_index.end()) { 1223 if ((*_node_data)[ni].heap[it->second] > rw) { 1224 (*_node_data)[ni].heap.replace(it->second, r); 1225 (*_node_data)[ni].heap.decrease(r, rw); 1226 it->second = r; 1123 1227 } 1124 1228 } else { 1125 (*_node_data)[vi].heap.push(e, rw); 1126 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e)); 1127 } 1128 1129 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) { 1130 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio()); 1131 1132 if ((*_blossom_data)[vb].status == MATCHED) { 1133 if (_delta2->state(vb) != _delta2->IN_HEAP) { 1134 _delta2->push(vb, _blossom_set->classPrio(vb) - 1135 (*_blossom_data)[vb].offset); 1136 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) - 1137 (*_blossom_data)[vb].offset) { 1138 _delta2->decrease(vb, _blossom_set->classPrio(vb) - 1139 (*_blossom_data)[vb].offset); 1140 } 1229 (*_node_data)[ni].heap.push(r, rw); 1230 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r)); 1231 } 1232 1233 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) { 1234 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio()); 1235 1236 if (_delta2->state(blossom) != _delta2->IN_HEAP) { 1237 _delta2->push(blossom, _blossom_set->classPrio(blossom) - 1238 (*_blossom_data)[blossom].offset); 1239 } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)- 1240 (*_blossom_data)[blossom].offset){ 1241 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) - 1242 (*_blossom_data)[blossom].offset); 1141 1243 } 1142 1244 } 1245 1246 } else if ((*_blossom_data)[vb].status == UNMATCHED) { 1247 if (_delta3->state(e) == _delta3->IN_HEAP) { 1248 _delta3->erase(e); 1249 } 1143 1250 } 1144 1251 } 1145 1252 } 1146 (*_blossom_data)[blossom].offset = 0;1147 1253 } 1148 1254 … … 1189 1295 destroyTree(tree); 1190 1296 1297 (*_blossom_data)[blossom].status = UNMATCHED; 1191 1298 (*_blossom_data)[blossom].base = node; 1192 (*_blossom_data)[blossom].next = INVALID; 1193 } 1299 matchedToUnmatched(blossom); 1300 } 1301 1194 1302 1195 1303 void augmentOnEdge(const Edge& edge) { … … 1198 1306 int right = _blossom_set->find(_graph.v(edge)); 1199 1307 1200 int left_tree = _tree_set->find(left); 1201 alternatePath(left, left_tree); 1202 destroyTree(left_tree); 1203 1204 int right_tree = _tree_set->find(right); 1205 alternatePath(right, right_tree); 1206 destroyTree(right_tree); 1308 if ((*_blossom_data)[left].status == EVEN) { 1309 int left_tree = _tree_set->find(left); 1310 alternatePath(left, left_tree); 1311 destroyTree(left_tree); 1312 } else { 1313 (*_blossom_data)[left].status = MATCHED; 1314 unmatchedToMatched(left); 1315 } 1316 1317 if ((*_blossom_data)[right].status == EVEN) { 1318 int right_tree = _tree_set->find(right); 1319 alternatePath(right, right_tree); 1320 destroyTree(right_tree); 1321 } else { 1322 (*_blossom_data)[right].status = MATCHED; 1323 unmatchedToMatched(right); 1324 } 1207 1325 1208 1326 (*_blossom_data)[left].next = _graph.direct(edge, true); 1209 1327 (*_blossom_data)[right].next = _graph.direct(edge, false); 1210 }1211 1212 void augmentOnArc(const Arc& arc) {1213 1214 int left = _blossom_set->find(_graph.source(arc));1215 int right = _blossom_set->find(_graph.target(arc));1216 1217 (*_blossom_data)[left].status = MATCHED;1218 1219 int right_tree = _tree_set->find(right);1220 alternatePath(right, right_tree);1221 destroyTree(right_tree);1222 1223 (*_blossom_data)[left].next = arc;1224 (*_blossom_data)[right].next = _graph.oppositeArc(arc);1225 1328 } 1226 1329 … … 1427 1530 (*_blossom_data)[sb].pred = pred; 1428 1531 (*_blossom_data)[sb].next = 1429 _graph.oppositeArc((*_blossom_data)[tb].next);1532 _graph.oppositeArc((*_blossom_data)[tb].next); 1430 1533 1431 1534 pred = (*_blossom_data)[ub].next; … … 1527 1630 1528 1631 for (int i = 0; i < int(blossoms.size()); ++i) { 1529 if ((*_blossom_data)[blossoms[i]]. next != INVALID) {1632 if ((*_blossom_data)[blossoms[i]].status == MATCHED) { 1530 1633 1531 1634 Value offset = (*_blossom_data)[blossoms[i]].offset; … … 1565 1668 _delta4_index(0), _delta4(0), 1566 1669 1567 _delta_sum(), _unmatched(0), 1568 1569 _fractional(0) 1570 {} 1670 _delta_sum() {} 1571 1671 1572 1672 ~MaxWeightedMatching() { 1573 1673 destroyStructures(); 1574 if (_fractional) {1575 delete _fractional;1576 }1577 1674 } 1578 1675 … … 1602 1699 (*_delta4_index)[i] = _delta4->PRE_HEAP; 1603 1700 } 1604 1605 _unmatched = _node_num;1606 1701 1607 1702 int index = 0; … … 1639 1734 } 1640 1735 1641 /// \brief Initialize the algorithm with fractional matching1642 ///1643 /// This function initializes the algorithm with a fractional1644 /// 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 1778 1736 /// \brief Start the algorithm 1779 1737 /// 1780 1738 /// This function starts the algorithm. 1781 1739 /// 1782 /// \pre \ref init() or \ref fractionalInit() must be called 1783 /// before using this function. 1740 /// \pre \ref init() must be called before using this function. 1784 1741 void start() { 1785 1742 enum OpType { … … 1787 1744 }; 1788 1745 1789 while (_unmatched > 0) { 1746 int unmatched = _node_num; 1747 while (unmatched > 0) { 1790 1748 Value d1 = !_delta1->empty() ? 1791 1749 _delta1->prio() : std::numeric_limits<Value>::max(); … … 1800 1758 _delta4->prio() : std::numeric_limits<Value>::max(); 1801 1759 1802 _delta_sum = d3; OpType ot = D3; 1803 if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; } 1760 _delta_sum = d1; OpType ot = D1; 1804 1761 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; } 1762 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; } 1805 1763 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; } 1764 1806 1765 1807 1766 switch (ot) { … … 1810 1769 Node n = _delta1->top(); 1811 1770 unmatchNode(n); 1812 -- _unmatched;1771 --unmatched; 1813 1772 } 1814 1773 break; … … 1817 1776 int blossom = _delta2->top(); 1818 1777 Node n = _blossom_set->classTop(blossom); 1819 Arc a = (*_node_data)[(*_node_index)[n]].heap.top(); 1820 if ((*_blossom_data)[blossom].next == INVALID) { 1821 augmentOnArc(a); 1822 --_unmatched; 1823 } else { 1824 extendOnArc(a); 1825 } 1778 Arc e = (*_node_data)[(*_node_index)[n]].heap.top(); 1779 extendOnArc(e); 1826 1780 } 1827 1781 break; … … 1836 1790 _delta3->pop(); 1837 1791 } else { 1838 int left_tree = _tree_set->find(left_blossom); 1839 int right_tree = _tree_set->find(right_blossom); 1792 int left_tree; 1793 if ((*_blossom_data)[left_blossom].status == EVEN) { 1794 left_tree = _tree_set->find(left_blossom); 1795 } else { 1796 left_tree = -1; 1797 ++unmatched; 1798 } 1799 int right_tree; 1800 if ((*_blossom_data)[right_blossom].status == EVEN) { 1801 right_tree = _tree_set->find(right_blossom); 1802 } else { 1803 right_tree = -1; 1804 ++unmatched; 1805 } 1840 1806 1841 1807 if (left_tree == right_tree) { … … 1843 1809 } else { 1844 1810 augmentOnEdge(e); 1845 _unmatched -= 2;1811 unmatched -= 2; 1846 1812 } 1847 1813 } … … 1861 1827 /// \note mwm.run() is just a shortcut of the following code. 1862 1828 /// \code 1863 /// mwm. fractionalInit();1829 /// mwm.init(); 1864 1830 /// mwm.start(); 1865 1831 /// \endcode 1866 1832 void run() { 1867 fractionalInit();1833 init(); 1868 1834 start(); 1869 1835 } … … 1872 1838 1873 1839 /// \name Primal Solution 1874 /// Functions to get the primal solution, i.e. the maximum weighted 1840 /// Functions to get the primal solution, i.e. the maximum weighted 1875 1841 /// matching.\n 1876 1842 /// Either \ref run() or \ref start() function should be called before … … 1891 1857 } 1892 1858 } 1893 return sum / 2;1859 return sum /= 2; 1894 1860 } 1895 1861 … … 1911 1877 /// \brief Return \c true if the given edge is in the matching. 1912 1878 /// 1913 /// This function returns \c true if the given edge is in the found 1879 /// This function returns \c true if the given edge is in the found 1914 1880 /// matching. 1915 1881 /// … … 1922 1888 /// 1923 1889 /// This function returns the matching arc (or edge) incident to the 1924 /// given node in the found matching or \c INVALID if the node is 1890 /// given node in the found matching or \c INVALID if the node is 1925 1891 /// not covered by the matching. 1926 1892 /// … … 1940 1906 /// \brief Return the mate of the given node. 1941 1907 /// 1942 /// This function returns the mate of the given node in the found 1908 /// This function returns the mate of the given node in the found 1943 1909 /// matching or \c INVALID if the node is not covered by the matching. 1944 1910 /// … … 1960 1926 /// \brief Return the value of the dual solution. 1961 1927 /// 1962 /// This function returns the value of the dual solution. 1963 /// It should be equal to the primal value scaled by \ref dualScale 1928 /// This function returns the value of the dual solution. 1929 /// It should be equal to the primal value scaled by \ref dualScale 1964 1930 /// "dual scale". 1965 1931 /// … … 2016 1982 /// \brief Iterator for obtaining the nodes of a blossom. 2017 1983 /// 2018 /// This class provides an iterator for obtaining the nodes of the 1984 /// This class provides an iterator for obtaining the nodes of the 2019 1985 /// given blossom. It lists a subset of the nodes. 2020 /// Before using this iterator, you must allocate a 1986 /// Before using this iterator, you must allocate a 2021 1987 /// MaxWeightedMatching class and execute it. 2022 1988 class BlossomIt { … … 2027 1993 /// Constructor to get the nodes of the given variable. 2028 1994 /// 2029 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or 2030 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be 1995 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or 1996 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be 2031 1997 /// called before initializing this iterator. 2032 1998 BlossomIt(const MaxWeightedMatching& algorithm, int variable) … … 2081 2047 /// \f$O(nm\log n)\f$ time complexity. 2082 2048 /// 2083 /// The maximum weighted perfect matching problem is to find a subset of 2084 /// the edges in an undirected graph with maximum overall weight for which 2049 /// The maximum weighted perfect matching problem is to find a subset of 2050 /// the edges in an undirected graph with maximum overall weight for which 2085 2051 /// each node has exactly one incident edge. 2086 2052 /// It can be formulated with the following linear program. … … 2105 2071 \frac{\vert B \vert - 1}{2}z_B\f] */ 2106 2072 /// 2107 /// The algorithm can be executed with the run() function. 2073 /// The algorithm can be executed with the run() function. 2108 2074 /// After it the matching (the primal solution) and the dual solution 2109 /// can be obtained using the query functions and the 2110 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, 2111 /// which is able to iterate on the nodes of a blossom. 2075 /// can be obtained using the query functions and the 2076 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, 2077 /// which is able to iterate on the nodes of a blossom. 2112 2078 /// If the value type is integer, then the dual solution is multiplied 2113 2079 /// by \ref MaxWeightedMatching::dualScale "4". 2114 2080 /// 2115 2081 /// \tparam GR The undirected graph type the algorithm runs on. 2116 /// \tparam WM The type edge weight map. The default type is 2082 /// \tparam WM The type edge weight map. The default type is 2117 2083 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>". 2118 2084 #ifdef DOXYGEN … … 2225 2191 2226 2192 Value _delta_sum; 2227 int _unmatched;2228 2229 typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>2230 FractionalMatching;2231 FractionalMatching *_fractional;2232 2193 2233 2194 void createStructures() { … … 2273 2234 2274 2235 void destroyStructures() { 2236 _node_num = countNodes(_graph); 2237 _blossom_num = _node_num * 3 / 2; 2238 2275 2239 if (_matching) { 2276 2240 delete _matching; … … 2945 2909 _delta4_index(0), _delta4(0), 2946 2910 2947 _delta_sum(), _unmatched(0), 2948 2949 _fractional(0) 2950 {} 2911 _delta_sum() {} 2951 2912 2952 2913 ~MaxWeightedPerfectMatching() { 2953 2914 destroyStructures(); 2954 if (_fractional) {2955 delete _fractional;2956 }2957 2915 } 2958 2916 … … 2979 2937 (*_delta4_index)[i] = _delta4->PRE_HEAP; 2980 2938 } 2981 2982 _unmatched = _node_num;2983 2939 2984 2940 int index = 0; … … 3015 2971 } 3016 2972 3017 /// \brief Initialize the algorithm with fractional matching3018 ///3019 /// This function initializes the algorithm with a fractional3020 /// 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 3149 2973 /// \brief Start the algorithm 3150 2974 /// 3151 2975 /// This function starts the algorithm. 3152 2976 /// 3153 /// \pre \ref init() or \ref fractionalInit() must be called before 3154 /// using this function. 2977 /// \pre \ref init() must be called before using this function. 3155 2978 bool start() { 3156 2979 enum OpType { … … 3158 2981 }; 3159 2982 3160 if (_unmatched == -1) return false; 3161 3162 while (_unmatched > 0) { 2983 int unmatched = _node_num; 2984 while (unmatched > 0) { 3163 2985 Value d2 = !_delta2->empty() ? 3164 2986 _delta2->prio() : std::numeric_limits<Value>::max(); … … 3170 2992 _delta4->prio() : std::numeric_limits<Value>::max(); 3171 2993 3172 _delta_sum = d 3; OpType ot = D3;3173 if (d 2 < _delta_sum) { _delta_sum = d2; ot = D2; }2994 _delta_sum = d2; OpType ot = D2; 2995 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; } 3174 2996 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; } 3175 2997 … … 3204 3026 } else { 3205 3027 augmentOnEdge(e); 3206 _unmatched -= 2;3028 unmatched -= 2; 3207 3029 } 3208 3030 } … … 3223 3045 /// \note mwpm.run() is just a shortcut of the following code. 3224 3046 /// \code 3225 /// mwpm. fractionalInit();3047 /// mwpm.init(); 3226 3048 /// mwpm.start(); 3227 3049 /// \endcode 3228 3050 bool run() { 3229 fractionalInit();3051 init(); 3230 3052 return start(); 3231 3053 } … … 3234 3056 3235 3057 /// \name Primal Solution 3236 /// Functions to get the primal solution, i.e. the maximum weighted 3058 /// Functions to get the primal solution, i.e. the maximum weighted 3237 3059 /// perfect matching.\n 3238 3060 /// Either \ref run() or \ref start() function should be called before … … 3253 3075 } 3254 3076 } 3255 return sum / 2;3077 return sum /= 2; 3256 3078 } 3257 3079 3258 3080 /// \brief Return \c true if the given edge is in the matching. 3259 3081 /// 3260 /// This function returns \c true if the given edge is in the found 3082 /// This function returns \c true if the given edge is in the found 3261 3083 /// matching. 3262 3084 /// … … 3269 3091 /// 3270 3092 /// This function returns the matching arc (or edge) incident to the 3271 /// given node in the found matching or \c INVALID if the node is 3093 /// given node in the found matching or \c INVALID if the node is 3272 3094 /// not covered by the matching. 3273 3095 /// … … 3287 3109 /// \brief Return the mate of the given node. 3288 3110 /// 3289 /// This function returns the mate of the given node in the found 3111 /// This function returns the mate of the given node in the found 3290 3112 /// matching or \c INVALID if the node is not covered by the matching. 3291 3113 /// … … 3306 3128 /// \brief Return the value of the dual solution. 3307 3129 /// 3308 /// This function returns the value of the dual solution. 3309 /// It should be equal to the primal value scaled by \ref dualScale 3130 /// This function returns the value of the dual solution. 3131 /// It should be equal to the primal value scaled by \ref dualScale 3310 3132 /// "dual scale". 3311 3133 /// … … 3362 3184 /// \brief Iterator for obtaining the nodes of a blossom. 3363 3185 /// 3364 /// This class provides an iterator for obtaining the nodes of the 3186 /// This class provides an iterator for obtaining the nodes of the 3365 3187 /// given blossom. It lists a subset of the nodes. 3366 /// Before using this iterator, you must allocate a 3188 /// Before using this iterator, you must allocate a 3367 3189 /// MaxWeightedPerfectMatching class and execute it. 3368 3190 class BlossomIt { … … 3373 3195 /// Constructor to get the nodes of the given variable. 3374 3196 /// 3375 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" 3376 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" 3197 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" 3198 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" 3377 3199 /// must be called before initializing this iterator. 3378 3200 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable) … … 3420 3242 } //END OF NAMESPACE LEMON 3421 3243 3422 #endif //LEMON_MA TCHING_H3244 #endif //LEMON_MAX_MATCHING_H -
test/CMakeLists.txt
r874 r799 22 22 error_test 23 23 euler_test 24 fractional_matching_test25 24 gomory_hu_test 26 25 graph_copy_test -
test/Makefile.am
r874 r799 24 24 test/error_test \ 25 25 test/euler_test \ 26 test/fractional_matching_test \27 26 test/gomory_hu_test \ 28 27 test/graph_copy_test \ … … 73 72 test_error_test_SOURCES = test/error_test.cc 74 73 test_euler_test_SOURCES = test/euler_test.cc 75 test_fractional_matching_test_SOURCES = test/fractional_matching_test.cc76 74 test_gomory_hu_test_SOURCES = test/gomory_hu_test.cc 77 75 test_graph_copy_test_SOURCES = test/graph_copy_test.cc -
test/matching_test.cc
r870 r594 402 402 edgeMap("weight", weight).run(); 403 403 404 bool perfect; 405 { 406 MaxMatching<SmartGraph> mm(graph); 407 mm.run(); 408 checkMatching(graph, mm); 409 perfect = 2 * mm.matchingSize() == countNodes(graph); 410 } 411 412 { 413 MaxWeightedMatching<SmartGraph> mwm(graph, weight); 414 mwm.run(); 415 checkWeightedMatching(graph, weight, mwm); 416 } 417 418 { 419 MaxWeightedMatching<SmartGraph> mwm(graph, weight); 420 mwm.init(); 421 mwm.start(); 422 checkWeightedMatching(graph, weight, mwm); 423 } 424 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 } 434 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 } 404 MaxMatching<SmartGraph> mm(graph); 405 mm.run(); 406 checkMatching(graph, mm); 407 408 MaxWeightedMatching<SmartGraph> mwm(graph, weight); 409 mwm.run(); 410 checkWeightedMatching(graph, weight, mwm); 411 412 MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight); 413 bool perfect = mwpm.run(); 414 415 check(perfect == (mm.matchingSize() * 2 == countNodes(graph)), 416 "Perfect matching found"); 417 418 if (perfect) { 419 checkWeightedPerfectMatching(graph, weight, mwpm); 444 420 } 445 421 }
Note: See TracChangeset
for help on using the changeset viewer.