Thomas Vachuska

Doh! Forgot to actually check for negative cycles in relaxEdge.

...@@ -148,15 +148,22 @@ public abstract class AbstractGraphPathSearch<V extends Vertex, E extends Edge<V ...@@ -148,15 +148,22 @@ public abstract class AbstractGraphPathSearch<V extends Vertex, E extends Edge<V
148 * If possible, relax the specified edge using the supplied base cost 148 * If possible, relax the specified edge using the supplied base cost
149 * and edge-weight function. 149 * and edge-weight function.
150 * 150 *
151 - * @param e edge to be relaxed 151 + * @param e edge to be relaxed
152 - * @param cost base cost to reach the edge destination vertex 152 + * @param cost base cost to reach the edge destination vertex
153 - * @param ew optional edge weight function 153 + * @param ew optional edge weight function
154 + * @param forbidNegatives if true negative values will forbid the link
154 * @return true if the edge was relaxed; false otherwise 155 * @return true if the edge was relaxed; false otherwise
155 */ 156 */
156 - boolean relaxEdge(E e, double cost, EdgeWeight<V, E> ew) { 157 + boolean relaxEdge(E e, double cost, EdgeWeight<V, E> ew,
158 + boolean... forbidNegatives) {
157 V v = e.dst(); 159 V v = e.dst();
158 double oldCost = cost(v); 160 double oldCost = cost(v);
159 - double newCost = cost + (ew == null ? 1.0 : ew.weight(e)); 161 + double hopCost = ew == null ? 1.0 : ew.weight(e);
162 + if (hopCost < 0 && forbidNegatives.length == 1 && forbidNegatives[0]) {
163 + return false;
164 + }
165 +
166 + double newCost = cost + hopCost;
160 boolean relaxed = newCost < oldCost; 167 boolean relaxed = newCost < oldCost;
161 boolean same = Math.abs(newCost - oldCost) < samenessThreshold; 168 boolean same = Math.abs(newCost - oldCost) < samenessThreshold;
162 if (same || relaxed) { 169 if (same || relaxed) {
......
...@@ -40,7 +40,7 @@ public class DijkstraGraphSearch<V extends Vertex, E extends Edge<V>> ...@@ -40,7 +40,7 @@ public class DijkstraGraphSearch<V extends Vertex, E extends Edge<V>>
40 if (cost < Double.MAX_VALUE) { 40 if (cost < Double.MAX_VALUE) {
41 // If the vertex is reachable, relax all its egress edges. 41 // If the vertex is reachable, relax all its egress edges.
42 for (E e : graph.getEdgesFrom(nearest)) { 42 for (E e : graph.getEdgesFrom(nearest)) {
43 - result.relaxEdge(e, cost, weight); 43 + result.relaxEdge(e, cost, weight, true);
44 } 44 }
45 } 45 }
46 46
......
...@@ -91,4 +91,21 @@ public class DijkstraGraphSearchTest extends BreadthFirstSearchTest { ...@@ -91,4 +91,21 @@ public class DijkstraGraphSearchTest extends BreadthFirstSearchTest {
91 executeSearch(graphSearch(), graph, A, E, weight, 3, 3.0); 91 executeSearch(graphSearch(), graph, A, E, weight, 3, 3.0);
92 } 92 }
93 93
94 + @Test
95 + public void negativeWeights() {
96 + graph = new AdjacencyListsGraph<>(of(A, B, C, D, E, F, G),
97 + of(new TestEdge(A, B, 1),
98 + new TestEdge(A, C, -1),
99 + new TestEdge(B, D, 1),
100 + new TestEdge(D, A, -2),
101 + new TestEdge(C, D, 1),
102 + new TestEdge(D, E, 1),
103 + new TestEdge(D, F, 1),
104 + new TestEdge(E, G, 1),
105 + new TestEdge(F, G, 1),
106 + new TestEdge(G, A, -5),
107 + new TestEdge(A, G, 4)));
108 + executeSearch(graphSearch(), graph, A, G, weight, 3, 4.0);
109 + }
110 +
94 } 111 }
......