[Lemon-commits] Peter Kovacs: Add negativeCycle() function to Be...
Lemon HG
hg at lemon.cs.elte.hu
Mon Aug 31 08:38:24 CEST 2009
details: http://lemon.cs.elte.hu/hg/lemon/rev/75325dfccf38
changeset: 752:75325dfccf38
user: Peter Kovacs <kpeter [at] inf.elte.hu>
date: Mon Aug 03 00:54:04 2009 +0200
description:
Add negativeCycle() function to BellmanFord (#51)
diffstat:
lemon/bellman_ford.h | 66 ++++++++++++++-------------------
test/bellman_ford_test.cc | 56 ++++++++++++++++++++++++++++
2 files changed, 84 insertions(+), 38 deletions(-)
diffs (144 lines):
diff --git a/lemon/bellman_ford.h b/lemon/bellman_ford.h
--- a/lemon/bellman_ford.h
+++ b/lemon/bellman_ford.h
@@ -770,44 +770,34 @@
return (*_dist)[v] != OperationTraits::infinity();
}
- // TODO: implement negative cycle
-// /// \brief Gives back a negative cycle.
-// ///
-// /// This function gives back a negative cycle.
-// /// If the algorithm have not found yet negative cycle it will give back
-// /// an empty path.
-// Path negativeCycle() {
-// typename Digraph::template NodeMap<int> state(*digraph, 0);
-// for (ActiveIt it(*this); it != INVALID; ++it) {
-// if (state[it] == 0) {
-// for (Node t = it; predArc(t) != INVALID; t = predNode(t)) {
-// if (state[t] == 0) {
-// state[t] = 1;
-// } else if (state[t] == 2) {
-// break;
-// } else {
-// p.clear();
-// typename Path::Builder b(p);
-// b.setStartNode(t);
-// b.pushFront(predArc(t));
-// for(Node s = predNode(t); s != t; s = predNode(s)) {
-// b.pushFront(predArc(s));
-// }
-// b.commit();
-// return true;
-// }
-// }
-// for (Node t = it; predArc(t) != INVALID; t = predNode(t)) {
-// if (state[t] == 1) {
-// state[t] = 2;
-// } else {
-// break;
-// }
-// }
-// }
-// }
-// return false;
-// }
+ /// \brief Gives back a negative cycle.
+ ///
+ /// This function gives back a directed cycle with negative total
+ /// length if the algorithm has already found one.
+ /// Otherwise it gives back an empty path.
+ lemon::Path<Digraph> negativeCycle() {
+ typename Digraph::template NodeMap<int> state(*_gr, -1);
+ lemon::Path<Digraph> cycle;
+ for (int i = 0; i < int(_process.size()); ++i) {
+ if (state[_process[i]] != -1) continue;
+ for (Node v = _process[i]; (*_pred)[v] != INVALID;
+ v = _gr->source((*_pred)[v])) {
+ if (state[v] == i) {
+ cycle.addFront((*_pred)[v]);
+ for (Node u = _gr->source((*_pred)[v]); u != v;
+ u = _gr->source((*_pred)[u])) {
+ cycle.addFront((*_pred)[u]);
+ }
+ return cycle;
+ }
+ else if (state[v] >= 0) {
+ break;
+ }
+ state[v] = i;
+ }
+ }
+ return cycle;
+ }
///@}
};
diff --git a/test/bellman_ford_test.cc b/test/bellman_ford_test.cc
--- a/test/bellman_ford_test.cc
+++ b/test/bellman_ford_test.cc
@@ -220,8 +220,64 @@
}
}
+void checkBellmanFordNegativeCycle() {
+ DIGRAPH_TYPEDEFS(SmartDigraph);
+
+ SmartDigraph gr;
+ IntArcMap length(gr);
+
+ Node n1 = gr.addNode();
+ Node n2 = gr.addNode();
+ Node n3 = gr.addNode();
+ Node n4 = gr.addNode();
+
+ Arc a1 = gr.addArc(n1, n2);
+ Arc a2 = gr.addArc(n2, n2);
+
+ length[a1] = 2;
+ length[a2] = -1;
+
+ {
+ BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
+ bf.run(n1);
+ StaticPath<SmartDigraph> p = bf.negativeCycle();
+ check(p.length() == 1 && p.front() == p.back() && p.front() == a2,
+ "Wrong negative cycle.");
+ }
+
+ length[a2] = 0;
+
+ {
+ BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
+ bf.run(n1);
+ check(bf.negativeCycle().empty(),
+ "Negative cycle should not be found.");
+ }
+
+ length[gr.addArc(n1, n3)] = 5;
+ length[gr.addArc(n4, n3)] = 1;
+ length[gr.addArc(n2, n4)] = 2;
+ length[gr.addArc(n3, n2)] = -4;
+
+ {
+ BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
+ bf.init();
+ bf.addSource(n1);
+ for (int i = 0; i < 4; ++i) {
+ check(bf.negativeCycle().empty(),
+ "Negative cycle should not be found.");
+ bf.processNextRound();
+ }
+ StaticPath<SmartDigraph> p = bf.negativeCycle();
+ check(p.length() == 3, "Wrong negative cycle.");
+ check(length[p.nth(0)] + length[p.nth(1)] + length[p.nth(2)] == -1,
+ "Wrong negative cycle.");
+ }
+}
+
int main() {
checkBellmanFord<ListDigraph, int>();
checkBellmanFord<SmartDigraph, double>();
+ checkBellmanFordNegativeCycle();
return 0;
}
More information about the Lemon-commits
mailing list