[Lemon-commits] Balazs Dezso: Paremeter to stop matching calcula...
Lemon HG
hg at lemon.cs.elte.hu
Mon Nov 5 17:50:24 CET 2018
details: http://lemon.cs.elte.hu/hg/lemon/rev/8c567e298d7f
changeset: 1423:8c567e298d7f
user: Balazs Dezso <deba [at] google.com>
date: Sat Oct 27 13:00:48 2018 +0200
description:
Paremeter to stop matching calculation when only single node is
unmatched
diffstat:
lemon/matching.h | 44 ++++++++++++++++++++++--------
test/matching_test.cc | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 103 insertions(+), 12 deletions(-)
diffs (246 lines):
diff --git a/lemon/matching.h b/lemon/matching.h
--- a/lemon/matching.h
+++ b/lemon/matching.h
@@ -115,7 +115,7 @@
NodeQueue _node_queue;
int _process, _postpone, _last;
- int _node_num;
+ int _node_num, _unmatched;
private:
@@ -179,6 +179,7 @@
extendOnArc(a);
} else if ((*_status)[v] == UNMATCHED) {
augmentOnArc(a);
+ --_unmatched;
return;
}
}
@@ -204,6 +205,7 @@
extendOnArc(b);
} else if ((*_status)[x] == UNMATCHED) {
augmentOnArc(b);
+ --_unmatched;
return;
}
}
@@ -228,6 +230,7 @@
extendOnArc(a);
} else if ((*_status)[v] == UNMATCHED) {
augmentOnArc(a);
+ --_unmatched;
return;
}
}
@@ -437,6 +440,7 @@
(*_matching)[n] = INVALID;
(*_status)[n] = UNMATCHED;
}
+ _unmatched = _node_num;
}
/// \brief Find an initial matching in a greedy way.
@@ -448,6 +452,7 @@
(*_matching)[n] = INVALID;
(*_status)[n] = UNMATCHED;
}
+ _unmatched = _node_num;
for (NodeIt n(_graph); n != INVALID; ++n) {
if ((*_matching)[n] == INVALID) {
for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
@@ -457,6 +462,7 @@
(*_status)[n] = MATCHED;
(*_matching)[v] = _graph.oppositeArc(a);
(*_status)[v] = MATCHED;
+ _unmatched -= 2;
break;
}
}
@@ -479,6 +485,7 @@
(*_matching)[n] = INVALID;
(*_status)[n] = UNMATCHED;
}
+ _unmatched = _node_num;
for(EdgeIt e(_graph); e!=INVALID; ++e) {
if (matching[e]) {
@@ -491,6 +498,8 @@
if ((*_matching)[v] != INVALID) return false;
(*_matching)[v] = _graph.direct(e, false);
(*_status)[v] = MATCHED;
+
+ _unmatched -= 2;
}
}
return true;
@@ -498,16 +507,20 @@
/// \brief Start Edmonds' algorithm
///
- /// This function runs the original Edmonds' algorithm.
+ /// This function runs the original Edmonds' algorithm. If the
+ /// \c decomposition parameter is set to false, then the Gallai-Edmonds
+ /// decomposition is not computed.
///
/// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
/// called before using this function.
- void startSparse() {
- for(NodeIt n(_graph); n != INVALID; ++n) {
+ void startSparse(bool decomposition = true) {
+ int _unmatched_limit = decomposition ? 0 : 1;
+ for(NodeIt n(_graph); _unmatched > _unmatched_limit; ++n) {
if ((*_status)[n] == UNMATCHED) {
(*_blossom_rep)[_blossom_set->insert(n)] = n;
_tree_set->insert(n);
(*_status)[n] = EVEN;
+ --_unmatched;
processSparse(n);
}
}
@@ -517,16 +530,20 @@
/// for dense graphs
///
/// This function runs Edmonds' algorithm with a heuristic of postponing
- /// shrinks, therefore resulting in a faster algorithm for dense graphs.
+ /// shrinks, therefore resulting in a faster algorithm for dense graphs. If
+ /// the \c decomposition parameter is set to false, then the Gallai-Edmonds
+ /// decomposition is not computed.
///
/// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
/// called before using this function.
- void startDense() {
- for(NodeIt n(_graph); n != INVALID; ++n) {
+ void startDense(bool decomposition = true) {
+ int _unmatched_limit = decomposition ? 0 : 1;
+ for(NodeIt n(_graph); _unmatched > _unmatched_limit; ++n) {
if ((*_status)[n] == UNMATCHED) {
(*_blossom_rep)[_blossom_set->insert(n)] = n;
_tree_set->insert(n);
(*_status)[n] = EVEN;
+ --_unmatched;
processDense(n);
}
}
@@ -536,15 +553,18 @@
/// \brief Run Edmonds' algorithm
///
/// This function runs Edmonds' algorithm. An additional heuristic of
- /// postponing shrinks is used for relatively dense graphs
- /// (for which <tt>m>=2*n</tt> holds).
- void run() {
+ /// postponing shrinks is used for relatively dense graphs (for which
+ /// <tt>m>=2*n</tt> holds). If the \c decomposition parameter is set to
+ /// false, then the Gallai-Edmonds decomposition is not computed. In some
+ /// cases, this can speed up the algorithm significantly, especially when a
+ /// maximum matching is computed in a dense graph with odd number of nodes.
+ void run(bool decomposition = true) {
if (countEdges(_graph) < 2 * countNodes(_graph)) {
greedyInit();
- startSparse();
+ startSparse(decomposition);
} else {
init();
- startDense();
+ startDense(decomposition);
}
}
diff --git a/test/matching_test.cc b/test/matching_test.cc
--- a/test/matching_test.cc
+++ b/test/matching_test.cc
@@ -134,6 +134,9 @@
mat_test.startSparse();
mat_test.startDense();
mat_test.run();
+ mat_test.startSparse(false);
+ mat_test.startDense(false);
+ mat_test.run(false);
const_mat_test.matchingSize();
const_mat_test.matching(e);
@@ -402,15 +405,83 @@
graphReader(graph, lgfs).
edgeMap("weight", weight).run();
+ int size;
bool perfect;
{
MaxMatching<SmartGraph> mm(graph);
mm.run();
checkMatching(graph, mm);
+ size = mm.matchingSize();
perfect = 2 * mm.matchingSize() == countNodes(graph);
}
{
+ MaxMatching<SmartGraph> mm(graph);
+ mm.init();
+ mm.startSparse();
+ checkMatching(graph, mm);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.init();
+ mm.startDense();
+ checkMatching(graph, mm);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.greedyInit();
+ mm.startSparse();
+ checkMatching(graph, mm);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.greedyInit();
+ mm.startDense();
+ checkMatching(graph, mm);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.run(false);
+ check(size == mm.matchingSize(), "Inconsistent max cardinality matching");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.init();
+ mm.startSparse(false);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.init();
+ mm.startDense(false);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.greedyInit();
+ mm.startSparse(false);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
+ MaxMatching<SmartGraph> mm(graph);
+ mm.greedyInit();
+ mm.startDense(false);
+ check(size == mm.matchingSize(), "Inconsistent matching size");
+ }
+
+ {
MaxWeightedMatching<SmartGraph> mwm(graph, weight);
mwm.run();
checkWeightedMatching(graph, weight, mwm);
More information about the Lemon-commits
mailing list