Skip to content

Commit 4cc8ccb

Browse files
committed
Add stats mode for delta stepping
1 parent 93473ff commit 4cc8ccb

File tree

8 files changed

+337
-2
lines changed

8 files changed

+337
-2
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.paths.delta.config;
21+
22+
import org.neo4j.gds.annotation.Configuration;
23+
import org.neo4j.gds.annotation.ValueClass;
24+
import org.neo4j.gds.core.CypherMapWrapper;
25+
26+
@ValueClass
27+
@Configuration
28+
@SuppressWarnings("immutables:subtype")
29+
public interface AllShortestPathsDeltaStatsConfig extends AllShortestPathsDeltaBaseConfig {
30+
31+
static AllShortestPathsDeltaStatsConfig of(CypherMapWrapper userInput) {
32+
return new AllShortestPathsDeltaStatsConfigImpl(userInput);
33+
}
34+
}

doc/asciidoc/algorithms/shortest-path/path-syntax.adoc

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,5 +184,59 @@ endif::[]
184184

185185
======
186186
187+
ifeval::["{algorithm}" == "Delta-Stepping"]
188+
[.include-with-stats]
189+
======
190+
191+
.Run {algorithm} in stats mode on a named graph.
192+
[source, cypher, role=noplay, subs="quotes,attributes+"]
193+
----
194+
CALL {procedure-name}.stats(
195+
graphName: String,
196+
configuration: Map
197+
)
198+
YIELD
199+
preProcessingMillis: Integer,
200+
computeMillis: Integer,
201+
postProcessingMillis: Integer,
202+
configuration: Map
203+
----
204+
205+
include::../common-configuration/common-parameters-named-graph.adoc[]
206+
207+
include::../common-configuration/common-stream-stats-configuration-named-graph.adoc[]
208+
209+
.Algorithm specific configuration
210+
[opts="header",cols="1,1,1m,1,4"]
211+
|===
212+
| Name | Type | Default | Optional | Description
213+
| sourceNode | Integer | n/a | no | The Neo4j source node or node id.
214+
ifeval::["{source-target}" == "true"]
215+
| targetNode | Integer | n/a | no | The Neo4j target node or node id.
216+
endif::[]
217+
ifeval::["{algorithm}" == "A*"]
218+
| latitudeProperty | Float | n/a | no | The node property that stores the latitude value.
219+
| longitudeProperty | Float | n/a | no | The node property that stores the longitude value.
220+
endif::[]
221+
ifeval::["{algorithm}" == "Yen's"]
222+
| k | Integer | 1 | yes | The number of shortest paths to compute between source and target node.
223+
endif::[]
224+
| writeNodeIds | Boolean | false | yes | If true, the written relationship has a nodeIds list property.
225+
| writeCosts | Boolean | false | yes | If true, the written relationship has a costs list property.
226+
|===
227+
228+
.Results
229+
[opts="header",cols="1,1,6"]
230+
|===
231+
| Name | Type | Description
232+
| preProcessingMillis | Integer | Milliseconds for preprocessing the graph.
233+
| computeMillis | Integer | Milliseconds for running the algorithm.
234+
| postProcessingMillis | Integer | Unused.
235+
| configuration | Map | The configuration used for running the algorithm.
236+
|===
237+
238+
======
239+
endif::[]
240+
187241
188242
====

doc/asciidoc/operations-reference/appendix-a-graph-algos.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,15 @@ include::../algorithms/algorithm-tiers.adoc[]
121121
| `gds.eigenvector.stream.estimate`
122122
| `gds.eigenvector.stats`
123123
| `gds.eigenvector.stats.estimate`
124-
.6+<.^| <<algorithms-delta-single-source, All Shortest Paths Delta-Stepping>>
124+
.8+<.^| <<algorithms-delta-single-source, All Shortest Paths Delta-Stepping>>
125125
| `gds.allShortestPaths.delta.stream`
126126
| `gds.allShortestPaths.delta.stream.estimate`
127127
| `gds.allShortestPaths.delta.write`
128128
| `gds.allShortestPaths.delta.write.estimate`
129129
| `gds.allShortestPaths.delta.mutate`
130130
| `gds.allShortestPaths.delta.mutate.estimate`
131+
| `gds.allShortestPaths.delta.stats`
132+
| `gds.allShortestPaths.delta.stats.estimate`
131133
.6+<.^| <<algorithms-dijkstra-source-target, Shortest Path Dijkstra>>
132134
| `gds.shortestPath.dijkstra.stream`
133135
| `gds.shortestPath.dijkstra.stream.estimate`

open-packaging/src/test/java/org/neo4j/gds/OpenGdsProcedureSmokeTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ class OpenGdsProcedureSmokeTest extends BaseProcTest {
219219
"gds.allShortestPaths.delta.mutate.estimate",
220220
"gds.allShortestPaths.delta.write",
221221
"gds.allShortestPaths.delta.write.estimate",
222+
"gds.allShortestPaths.delta.stats",
223+
"gds.allShortestPaths.delta.stats.estimate",
222224

223225
"gds.betweenness.mutate",
224226
"gds.betweenness.mutate.estimate",
@@ -440,7 +442,7 @@ void countShouldMatch() {
440442
);
441443

442444
// If you find yourself updating this count, please also update the count in SmokeTest.kt
443-
int expectedCount = 300;
445+
int expectedCount = 302;
444446
assertEquals(
445447
expectedCount,
446448
registeredProcedures.size(),
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.paths.singlesource.delta;
21+
22+
import org.neo4j.gds.BaseProc;
23+
import org.neo4j.gds.executor.MemoryEstimationExecutor;
24+
import org.neo4j.gds.executor.ProcedureExecutor;
25+
import org.neo4j.gds.executor.ProcedureExecutorSpec;
26+
import org.neo4j.gds.paths.delta.DeltaStepping;
27+
import org.neo4j.gds.paths.delta.config.AllShortestPathsDeltaStatsConfig;
28+
import org.neo4j.gds.paths.dijkstra.DijkstraResult;
29+
import org.neo4j.gds.results.MemoryEstimateResult;
30+
import org.neo4j.gds.results.StandardStatsResult;
31+
import org.neo4j.procedure.Description;
32+
import org.neo4j.procedure.Name;
33+
import org.neo4j.procedure.Procedure;
34+
35+
import java.util.Map;
36+
import java.util.stream.Stream;
37+
38+
import static org.neo4j.procedure.Mode.READ;
39+
40+
public class AllShortestPathsDeltaStatsProc extends BaseProc {
41+
42+
@Procedure(name = "gds.allShortestPaths.delta.stats", mode = READ)
43+
@Description(DeltaStepping.DESCRIPTION)
44+
public Stream<StandardStatsResult> stats(
45+
@Name(value = "graphName") String graphName,
46+
@Name(value = "configuration", defaultValue = "{}") Map<String, Object> configuration
47+
) {
48+
var statsSpec = new AllShortestPathsDeltaStatsSpec();
49+
var pipelineSpec = new ProcedureExecutorSpec<DeltaStepping, DijkstraResult, AllShortestPathsDeltaStatsConfig>();
50+
51+
return new ProcedureExecutor<>(
52+
statsSpec,
53+
pipelineSpec,
54+
executionContext()
55+
).compute(graphName, configuration, false, false);
56+
}
57+
58+
@Procedure(name = "gds.allShortestPaths.delta.stats.estimate", mode = READ)
59+
@Description(ESTIMATE_DESCRIPTION)
60+
public Stream<MemoryEstimateResult> estimate(
61+
@Name(value = "graphNameOrConfiguration") Object graphNameOrConfiguration,
62+
@Name(value = "algoConfiguration") Map<String, Object> algoConfiguration
63+
) {
64+
var statsSpec = new AllShortestPathsDeltaStatsSpec();
65+
var pipelineSpec = new ProcedureExecutorSpec<DeltaStepping, DijkstraResult, AllShortestPathsDeltaStatsConfig>();
66+
67+
return new MemoryEstimationExecutor<>(
68+
statsSpec,
69+
pipelineSpec,
70+
executionContext()
71+
).computeEstimate(graphNameOrConfiguration, algoConfiguration);
72+
}
73+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.paths.singlesource.delta;
21+
22+
import org.neo4j.gds.executor.AlgorithmSpec;
23+
import org.neo4j.gds.executor.ComputationResultConsumer;
24+
import org.neo4j.gds.executor.GdsCallable;
25+
import org.neo4j.gds.executor.NewConfigFunction;
26+
import org.neo4j.gds.paths.delta.DeltaStepping;
27+
import org.neo4j.gds.paths.delta.DeltaSteppingFactory;
28+
import org.neo4j.gds.paths.delta.config.AllShortestPathsDeltaStatsConfig;
29+
import org.neo4j.gds.paths.dijkstra.DijkstraResult;
30+
import org.neo4j.gds.results.StandardStatsResult;
31+
32+
import java.util.stream.Stream;
33+
34+
import static org.neo4j.gds.executor.ExecutionMode.STATS;
35+
36+
@GdsCallable(name = "gds.allShortestPaths.delta.stats", description = DeltaStepping.DESCRIPTION, executionMode = STATS)
37+
public class AllShortestPathsDeltaStatsSpec implements AlgorithmSpec<DeltaStepping, DijkstraResult, AllShortestPathsDeltaStatsConfig, Stream<StandardStatsResult>, DeltaSteppingFactory<AllShortestPathsDeltaStatsConfig>> {
38+
39+
@Override
40+
public String name() {
41+
return "gds.allShortestPaths.delta.stats";
42+
}
43+
44+
@Override
45+
public DeltaSteppingFactory<AllShortestPathsDeltaStatsConfig> algorithmFactory() {
46+
return new DeltaSteppingFactory<>();
47+
}
48+
49+
@Override
50+
public NewConfigFunction<AllShortestPathsDeltaStatsConfig> newConfigFunction() {
51+
return (username, configuration) -> AllShortestPathsDeltaStatsConfig.of(configuration);
52+
}
53+
54+
@SuppressWarnings("unchecked")
55+
@Override
56+
public ComputationResultConsumer<DeltaStepping, DijkstraResult, AllShortestPathsDeltaStatsConfig, Stream<StandardStatsResult>> computationResultConsumer() {
57+
return (computationResult, executionContext) ->
58+
Stream.of(new StandardStatsResult(
59+
computationResult.preProcessingMillis(),
60+
computationResult.computeMillis(),
61+
0,
62+
computationResult.config().toMap()
63+
));
64+
}
65+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.paths.singlesource;
21+
22+
import org.junit.jupiter.api.Test;
23+
import org.neo4j.gds.GdsCypher;
24+
import org.neo4j.gds.compat.GraphDatabaseApiProxy;
25+
26+
import java.util.List;
27+
import java.util.Map;
28+
29+
import static org.hamcrest.Matchers.greaterThan;
30+
import static org.hamcrest.Matchers.instanceOf;
31+
32+
public abstract class AllShortestPathsStatsProcTest extends AllShortestPathsProcTest {
33+
34+
@Test
35+
void testStats() {
36+
var query = GdsCypher.call("graph")
37+
.algo(getProcedureName())
38+
.statsMode()
39+
.addParameter("sourceNode", idFunction.of("a"))
40+
.addParameter("relationshipWeightProperty", "cost")
41+
.yields("preProcessingMillis", "computeMillis", "postProcessingMillis", "configuration");
42+
43+
//@formatter:off
44+
GraphDatabaseApiProxy.runInTransaction(db, tx -> {
45+
assertCypherResult(query, List.of(Map.of(
46+
"preProcessingMillis", greaterThan(0L),
47+
"computeMillis", greaterThan(0L),
48+
"postProcessingMillis", 0L,
49+
"configuration", instanceOf(Map.class)
50+
)));
51+
});
52+
//@formatter:on
53+
}
54+
55+
@Test
56+
void testMemoryEstimation() {
57+
var query = GdsCypher.call("graph")
58+
.algo(getProcedureName())
59+
.statsEstimation()
60+
.addParameter("sourceNode", idFunction.of("a"))
61+
.yields("bytesMin", "bytesMax", "nodeCount", "relationshipCount");
62+
63+
assertCypherResult(query, List.of(Map.of(
64+
"bytesMin", greaterThan(0L),
65+
"bytesMax", greaterThan(0L),
66+
"nodeCount", 6L,
67+
"relationshipCount", 7L
68+
)));
69+
}
70+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.paths.singlesource.deltastepping;
21+
22+
import org.neo4j.gds.paths.singlesource.AllShortestPathsStatsProcTest;
23+
import org.neo4j.gds.paths.singlesource.delta.AllShortestPathsDeltaStatsProc;
24+
25+
class AllShortestPathsDeltaStatsProcTest extends AllShortestPathsStatsProcTest {
26+
@Override
27+
public Class<?> getProcedureClazz() {
28+
return AllShortestPathsDeltaStatsProc.class;
29+
}
30+
31+
@Override
32+
public String getProcedureName() {
33+
return "gds.allShortestPaths.delta";
34+
}
35+
}

0 commit comments

Comments
 (0)