Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Commit dd13a39

Browse files
mknblchmneedham
authored andcommitted
Fix SharedIntPriorityQueue usage (#725)
* user testcase * WIP * WIP * changed IntPrioQueue in Dijkstra to Javas own PrioQueue * replace SharedIntPrioQueue in Dijkstra (used in YKSP) * Fix updateCosts * ignore testcase * adapt testcase * WIP * WIP * WIP * Prim test * rm example airport-graph tests * WIP * rm usertest * rm prim user test
1 parent 6bb0baf commit dd13a39

File tree

8 files changed

+73
-63
lines changed

8 files changed

+73
-63
lines changed

algo/src/main/java/org/neo4j/graphalgo/impl/Prim.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
*/
4646
public class Prim extends Algorithm<Prim> {
4747

48+
public static final int UNUSED = 42;
4849
private final RelationshipIterator relationshipIterator;
4950
private final RelationshipWeights weights;
5051
private final int nodeCount;
@@ -90,11 +91,16 @@ private SpanningTree prim(int startNode, boolean max) {
9091
if (visited.contains(t)) {
9192
return true;
9293
}
93-
// invert weight to calculate maximum
94+
// inverting the weight calculates maximum- instead of minimum spanning tree
9495
final double w = max ? -weights.weightOf(s, t) : weights.weightOf(s, t);
9596
if (w < cost.getOrDefault(t, Double.MAX_VALUE)) {
96-
cost.put(t, w);
97-
queue.add(t, -1.0);
97+
if (cost.containsKey(t)) {
98+
cost.put(t, w);
99+
queue.update(t);
100+
} else {
101+
cost.put(t, w);
102+
queue.add(t, w);
103+
}
98104
spanningTree.parent[t] = s;
99105
}
100106
return true;

algo/src/main/java/org/neo4j/graphalgo/impl/ShortestPathDijkstra.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class ShortestPathDijkstra extends Algorithm<ShortestPathDijkstra> {
3939

4040
private static final int PATH_END = -1;
4141
public static final double NO_PATH_FOUND = -1.0;
42+
public static final int UNUSED = 42;
4243

4344
private Graph graph;
4445

@@ -152,28 +153,28 @@ private void run(int goal, Direction direction) {
152153
graph.forEachRelationship(
153154
node,
154155
direction, (source, target, relId, weight) -> {
155-
boolean oldCostChanged = updateCosts(source, target, weight + costs);
156-
if (!visited.get(target)) {
157-
if (oldCostChanged) {
158-
queue.update(target);
159-
} else {
160-
queue.add(target, 0);
161-
}
162-
}
156+
updateCosts(source, target, weight + costs);
163157
return true;
164158
});
165159
progressLogger.logProgress((double) node / (nodeCount - 1));
166160
}
167161
}
168162

169-
private boolean updateCosts(int source, int target, double newCosts) {
170-
double oldCosts = costs.getOrDefault(target, Double.MAX_VALUE);
171-
if (newCosts < oldCosts) {
172-
costs.put(target, newCosts);
173-
path.put(target, source);
174-
return oldCosts < Double.MAX_VALUE;
163+
private void updateCosts(int source, int target, double newCosts) {
164+
165+
if (costs.containsKey(target)) {
166+
if (newCosts < costs.getOrDefault(target, Double.MAX_VALUE)) {
167+
costs.put(target, newCosts);
168+
path.put(target, source);
169+
queue.update(target);
170+
}
171+
} else {
172+
if (newCosts < costs.getOrDefault(target, Double.MAX_VALUE)) {
173+
costs.put(target, newCosts);
174+
path.put(target, source);
175+
queue.add(target, newCosts);
176+
}
175177
}
176-
return false;
177178
}
178179

179180
@Override

algo/src/main/java/org/neo4j/graphalgo/impl/ShortestPaths.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ private void run() {
9999
final double targetCosts = this.costs.getOrDefault(target, Double.POSITIVE_INFINITY);
100100
if (weight + sourceCosts < targetCosts) {
101101
costs.put(target, weight + sourceCosts);
102-
queue.set(target, targetCosts);
102+
queue.set(target, weight + sourceCosts);
103103
}
104104
return true;
105105
});

algo/src/main/java/org/neo4j/graphalgo/impl/spanningTrees/KSpanningTree.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import org.neo4j.graphalgo.results.AbstractResultBuilder;
3030

3131
/**
32-
* Sequential Single-Source minimum weight spanning tree algorithm (PRIM).
33-
* <p>
3432
* The algorithm computes the MST by traversing all nodes from a given
3533
* startNodeId. It aggregates all transitions into a MinPriorityQueue
3634
* and visits each (unvisited) connected node by following only the

algo/src/main/java/org/neo4j/graphalgo/impl/spanningTrees/Prim.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,13 @@ private SpanningTree prim(int startNode, boolean max) {
8686
// invert weight to calculate maximum
8787
final double w = max ? -weights.weightOf(s, t) : weights.weightOf(s, t);
8888
if (w < cost.getOrDefault(t, Double.MAX_VALUE)) {
89-
cost.put(t, w);
90-
queue.add(t, -1.0);
89+
if (cost.containsKey(t)) {
90+
cost.put(t, w);
91+
queue.update(t);
92+
} else {
93+
cost.put(t, w);
94+
queue.add(t, -1.0);
95+
}
9196
parent[t] = s;
9297
}
9398
return true;

algo/src/main/java/org/neo4j/graphalgo/impl/yens/Dijkstra.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import org.neo4j.graphalgo.core.utils.TerminationFlag;
2525
import org.neo4j.graphalgo.core.utils.queue.IntPriorityQueue;
2626
import org.neo4j.graphalgo.core.utils.queue.SharedIntPriorityQueue;
27-
import org.neo4j.graphalgo.core.utils.traverse.SimpleBitSet;
2827
import org.neo4j.graphdb.Direction;
2928

3029
import java.util.Arrays;
@@ -38,18 +37,19 @@
3837
public class Dijkstra {
3938

4039
// initial weighted path capacity
40+
4141
public static final int INITIAL_CAPACITY = 64;
4242

4343
private static final int PATH_END = -1;
44-
4544
private final Graph graph;
45+
4646
private final int nodeCount;
4747

4848
private TerminationFlag terminationFlag = TerminationFlag.RUNNING_TRUE;
49-
5049
// node to cost map
5150
private final IntDoubleMap costs;
5251
// next node priority queue
52+
5353
private final IntPriorityQueue queue;
5454
// auxiliary path map
5555
private final IntIntMap path;
@@ -157,7 +157,8 @@ private boolean dijkstra(int source, int target, Direction direction, int maxDep
157157
visited.clear();
158158
costs.put(source, 0.0);
159159
queue.add(source, 0.0);
160-
Arrays.fill(depth, 1);
160+
Arrays.fill(depth, 0);
161+
depth[source] = 1;
161162
while (!queue.isEmpty() && terminationFlag.running()) {
162163
int node = queue.pop();
163164
final int d = depth[node];
@@ -176,32 +177,49 @@ private boolean dijkstra(int source, int target, Direction direction, int maxDep
176177
return true;
177178
}
178179
final double w = graph.weightOf(s, t);
179-
final boolean updateCosts = updateCosts(s, t, w + costs);
180+
final UpdateResult updateCosts = updateCosts(s, t, w + costs);
180181
if (!visited.get(t)) {
181-
depth[t] = d + 1;
182-
if (updateCosts) {
183-
queue.update(t);
184-
} else {
185-
queue.add(t, w);
182+
switch (updateCosts) {
183+
case NO_PREVIOUS_COSTS:
184+
queue.add(t, w);
185+
break;
186+
case UPDATED_COST:
187+
queue.update(t);
188+
break;
189+
default:
190+
break;
186191
}
192+
depth[t] = depth[s] + 1;
187193
}
188194
return terminationFlag.running();
189195
});
190196
}
191197
return false;
192198
}
193199

200+
194201
/**
195202
* update cost map
196203
*/
197-
private boolean updateCosts(int source, int target, double newCosts) {
204+
private UpdateResult updateCosts(int source, int target, double newCosts) {
198205
double oldCosts = costs.getOrDefault(target, Double.MAX_VALUE);
206+
if (oldCosts == Double.MAX_VALUE) {
207+
if (!costs.containsKey(target)) {
208+
costs.put(target, newCosts);
209+
path.put(target, source);
210+
return UpdateResult.NO_PREVIOUS_COSTS;
211+
}
212+
}
199213
if (newCosts < oldCosts) {
200214
costs.put(target, newCosts);
201215
path.put(target, source);
202-
return oldCosts < Double.MAX_VALUE;
216+
return UpdateResult.UPDATED_COST;
203217
}
204-
return false;
218+
return UpdateResult.COST_NOT_COMPETITIVE;
219+
}
220+
221+
private enum UpdateResult {
222+
NO_PREVIOUS_COSTS, UPDATED_COST, COST_NOT_COMPETITIVE;
205223
}
206224

207225
}

benchmark/src/main/java/org/neo4j/graphalgo/bench/AllShortestPathsComparisionBenchmark.java

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,37 @@
11
/**
22
* Copyright (c) 2017 "Neo4j, Inc." <http://neo4j.com>
3-
*
3+
* <p>
44
* This file is part of Neo4j Graph Algorithms <http://github.com/neo4j-contrib/neo4j-graph-algorithms>.
5-
*
5+
* <p>
66
* Neo4j Graph Algorithms is free software: you can redistribute it and/or modify
77
* it under the terms of the GNU General Public License as published by
88
* the Free Software Foundation, either version 3 of the License, or
99
* (at your option) any later version.
10-
*
10+
* <p>
1111
* This program is distributed in the hope that it will be useful,
1212
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1313
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414
* GNU General Public License for more details.
15-
*
15+
* <p>
1616
* You should have received a copy of the GNU General Public License
1717
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919
package org.neo4j.graphalgo.bench;
2020

21-
import org.neo4j.graphalgo.ShortestPathDeltaSteppingProc;
22-
import org.neo4j.graphalgo.ShortestPathsProc;
2321
import org.neo4j.graphalgo.api.Graph;
2422
import org.neo4j.graphalgo.api.HugeGraph;
2523
import org.neo4j.graphalgo.core.GraphLoader;
26-
import org.neo4j.graphalgo.core.heavyweight.HeavyGraphFactory;
2724
import org.neo4j.graphalgo.core.huge.HugeGraphFactory;
2825
import org.neo4j.graphalgo.core.utils.Pools;
2926
import org.neo4j.graphalgo.core.utils.paged.AllocationTracker;
3027
import org.neo4j.graphalgo.impl.AllShortestPaths;
3128
import org.neo4j.graphalgo.impl.HugeMSBFSAllShortestPaths;
3229
import org.neo4j.graphalgo.impl.MSBFSAllShortestPaths;
33-
import org.neo4j.graphdb.Node;
34-
import org.neo4j.graphdb.Relationship;
35-
import org.neo4j.graphdb.RelationshipType;
36-
import org.neo4j.graphdb.Transaction;
37-
import org.neo4j.graphdb.Direction;
30+
import org.neo4j.graphdb.*;
3831
import org.neo4j.internal.kernel.api.exceptions.KernelException;
39-
import org.neo4j.kernel.impl.proc.Procedures;
4032
import org.neo4j.kernel.internal.GraphDatabaseAPI;
4133
import org.neo4j.test.TestGraphDatabaseFactory;
42-
import org.openjdk.jmh.annotations.Benchmark;
43-
import org.openjdk.jmh.annotations.BenchmarkMode;
44-
import org.openjdk.jmh.annotations.Fork;
45-
import org.openjdk.jmh.annotations.Measurement;
46-
import org.openjdk.jmh.annotations.Mode;
47-
import org.openjdk.jmh.annotations.OutputTimeUnit;
48-
import org.openjdk.jmh.annotations.Scope;
49-
import org.openjdk.jmh.annotations.Setup;
50-
import org.openjdk.jmh.annotations.State;
51-
import org.openjdk.jmh.annotations.TearDown;
52-
import org.openjdk.jmh.annotations.Threads;
53-
import org.openjdk.jmh.annotations.Warmup;
34+
import org.openjdk.jmh.annotations.*;
5435

5536
import java.util.ArrayList;
5637
import java.util.HashMap;
@@ -143,7 +124,7 @@ private static Relationship createRelation(Node from, Node to) {
143124

144125
@Benchmark
145126
public long _01_benchmark_ASP() {
146-
return new AllShortestPaths(graph, Pools.DEFAULT, 8, Direction.OUTGOING)
127+
return new AllShortestPaths(graph, Pools.DEFAULT, 8, Direction.OUTGOING)
147128
.resultStream()
148129
.count();
149130
}

core/src/main/java/org/neo4j/graphalgo/core/utils/queue/IntPriorityQueue.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,10 @@ private void downHeap(int i) {
239239

240240
private void ensureCapacityForInsert() {
241241
if (size >= heap.length) {
242+
final int oversize = ArrayUtil.oversize(size + 1, Integer.BYTES);
242243
heap = Arrays.copyOf(
243244
heap,
244-
ArrayUtil.oversize(size + 1, Integer.BYTES));
245+
oversize);
245246
}
246247
}
247248

0 commit comments

Comments
 (0)