Doh! Forgot to actually check for negative cycles in relaxEdge.
Showing
3 changed files
with
30 additions
and
6 deletions
| ... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment