Skip to content

Commit 19ccd3a

Browse files
Implement push-back stats facade
Co-authored-by: Ioannis Panagiotas <ioannis.panagiotas@neo4j.com>
1 parent d0c814b commit 19ccd3a

File tree

6 files changed

+185
-1
lines changed

6 files changed

+185
-1
lines changed

procedures/pushback-procedures-facade/src/main/java/org/neo4j/gds/procedures/algorithms/pathfinding/PushbackPathFindingProcedureFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public Stream<MaxFlowStreamResult> maxFlowStream(String graphName, Map<String, O
271271

272272
@Override
273273
public Stream<MaxFlowStatsResult> maxFlowStats(String graphName, Map<String, Object> configuration) {
274-
return Stream.empty(); //todo
274+
return statsProcedureFacade.maxFlow(graphName, configuration);
275275
}
276276

277277
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
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.procedures.algorithms.pathfinding.stats;
21+
22+
import org.neo4j.gds.maxflow.FlowResult;
23+
import org.neo4j.gds.procedures.algorithms.pathfinding.MaxFlowStatsResult;
24+
import org.neo4j.gds.result.TimedAlgorithmResult;
25+
import org.neo4j.gds.results.ResultTransformer;
26+
27+
import java.util.Map;
28+
import java.util.stream.Stream;
29+
30+
class MaxFlowStatsResultTransformer implements ResultTransformer<TimedAlgorithmResult<FlowResult>, Stream<MaxFlowStatsResult>> {
31+
32+
private final Map<String, Object> configuration;
33+
34+
MaxFlowStatsResultTransformer(Map<String, Object> configuration) {
35+
this.configuration = configuration;
36+
}
37+
38+
@Override
39+
public Stream<MaxFlowStatsResult> apply(TimedAlgorithmResult<FlowResult> algorithmResult) {
40+
var spanningTree = algorithmResult.result();
41+
var statsResult = new MaxFlowStatsResult(
42+
0,
43+
algorithmResult.computeMillis(),
44+
spanningTree.totalFlow(),
45+
configuration
46+
);
47+
return Stream.of(statsResult);
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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.procedures.algorithms.pathfinding.stats;
21+
22+
import org.neo4j.gds.core.loading.GraphResources;
23+
import org.neo4j.gds.maxflow.FlowResult;
24+
import org.neo4j.gds.maxflow.MaxFlowStatsConfig;
25+
import org.neo4j.gds.procedures.algorithms.pathfinding.MaxFlowStatsResult;
26+
import org.neo4j.gds.result.TimedAlgorithmResult;
27+
import org.neo4j.gds.results.ResultTransformerBuilder;
28+
29+
import java.util.stream.Stream;
30+
31+
class MaxFlowStatsResultTransformerBuilder implements ResultTransformerBuilder<TimedAlgorithmResult<FlowResult>, Stream<MaxFlowStatsResult>> {
32+
33+
private final MaxFlowStatsConfig config;
34+
35+
MaxFlowStatsResultTransformerBuilder(MaxFlowStatsConfig config) {
36+
this.config = config;
37+
}
38+
39+
@Override
40+
public MaxFlowStatsResultTransformer build(GraphResources graphResources) {
41+
return new MaxFlowStatsResultTransformer(config.toMap());
42+
}
43+
}

procedures/pushback-procedures-facade/src/main/java/org/neo4j/gds/procedures/algorithms/pathfinding/stats/PushbackPathFindingStatsProcedureFacade.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
package org.neo4j.gds.procedures.algorithms.pathfinding.stats;
2121

2222
import org.neo4j.gds.api.GraphName;
23+
import org.neo4j.gds.maxflow.MaxFlowStatsConfig;
2324
import org.neo4j.gds.pathfinding.PathFindingComputeBusinessFacade;
2425
import org.neo4j.gds.paths.bellmanford.AllShortestPathsBellmanFordStatsConfig;
2526
import org.neo4j.gds.paths.delta.config.AllShortestPathsDeltaStatsConfig;
2627
import org.neo4j.gds.paths.traverse.BfsStatsConfig;
2728
import org.neo4j.gds.pcst.PCSTStatsConfig;
2829
import org.neo4j.gds.procedures.algorithms.configuration.UserSpecificConfigurationParser;
2930
import org.neo4j.gds.procedures.algorithms.pathfinding.BellmanFordStatsResult;
31+
import org.neo4j.gds.procedures.algorithms.pathfinding.MaxFlowStatsResult;
3032
import org.neo4j.gds.procedures.algorithms.pathfinding.PrizeCollectingSteinerTreeStatsResult;
3133
import org.neo4j.gds.procedures.algorithms.pathfinding.SpanningTreeStatsResult;
3234
import org.neo4j.gds.procedures.algorithms.pathfinding.SteinerStatsResult;
@@ -109,6 +111,23 @@ public Stream<StandardStatsResult> deltaStepping(
109111
).join();
110112
}
111113

114+
public Stream<MaxFlowStatsResult> maxFlow(String graphName, Map<String, Object> configuration) {
115+
var config = configurationParser.parseConfiguration(
116+
configuration,
117+
MaxFlowStatsConfig::of
118+
);
119+
120+
return businessFacade.maxFlow(
121+
GraphName.parse(graphName),
122+
config.toGraphParameters(),
123+
config.relationshipWeightProperty(),
124+
config.toParameters(),
125+
config.jobId(),
126+
config.logProgress(),
127+
new MaxFlowStatsResultTransformerBuilder(config)
128+
).join();
129+
}
130+
112131
public Stream<PrizeCollectingSteinerTreeStatsResult> prizeCollectingSteinerTree(
113132
String graphName,
114133
Map<String, Object> configuration

procedures/pushback-procedures-facade/src/test/java/org/neo4j/gds/procedures/algorithms/pathfinding/PushbackPathFindingProcedureFacadeTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ void deltaSteppingStats() {
172172
verifyNoInteractions(mutateFacadeMock, streamFacadeMock, writeFacadeMock);
173173
}
174174

175+
@Test
176+
void maxFlowStats() {
177+
facade.maxFlowStats(graphName, config);
178+
verify(statsFacadeMock).maxFlow(graphName, config);
179+
verifyNoInteractions(mutateFacadeMock, streamFacadeMock, writeFacadeMock);
180+
}
181+
175182
@Test
176183
void prizeCollectingSteinerTreeStats() {
177184
facade.prizeCollectingSteinerTreeStats(graphName, config);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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.procedures.algorithms.pathfinding.stats;
21+
22+
import org.junit.jupiter.api.Test;
23+
import org.neo4j.gds.api.Graph;
24+
import org.neo4j.gds.maxflow.FlowResult;
25+
import org.neo4j.gds.result.TimedAlgorithmResult;
26+
27+
import java.util.Map;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.mockito.ArgumentMatchers.anyLong;
31+
import static org.mockito.Mockito.mock;
32+
import static org.mockito.Mockito.when;
33+
34+
class MaxFlowStatsResultTransformerTest {
35+
@Test
36+
void shouldReturnEmptyStreamOnEmptyResult() {
37+
var configuration = Map.<String, Object>of("foo", "bar");
38+
var graphMock = mock(Graph.class);
39+
when(graphMock.nodeCount()).thenReturn(0L);
40+
41+
var transformer = new MaxFlowStatsResultTransformer(configuration);
42+
43+
var statsResult = transformer.apply(TimedAlgorithmResult.empty(FlowResult.EMPTY)).findFirst().orElseThrow();
44+
assertThat(statsResult.preProcessingMillis()).isZero();
45+
assertThat(statsResult.computeMillis()).isZero();
46+
assertThat(statsResult.totalFlow()).isZero();
47+
assertThat(statsResult.configuration()).isEqualTo(configuration);
48+
}
49+
50+
@Test
51+
void shouldTransformNonEmptyResult() {
52+
var configuration = Map.<String, Object>of("foo", "bar");
53+
var graphMock = mock(Graph.class);
54+
when(graphMock.toOriginalNodeId(anyLong())).thenAnswer(invocation -> invocation.getArgument(0));
55+
56+
var transformer = new MaxFlowStatsResultTransformer(configuration);
57+
58+
var flowResult = new FlowResult(null, 4D);
59+
60+
var statsResult = transformer.apply(new TimedAlgorithmResult<>(flowResult, 1L)).findFirst().orElseThrow();
61+
assertThat(statsResult.preProcessingMillis()).isZero();
62+
assertThat(statsResult.computeMillis()).isEqualTo(1L);
63+
assertThat(statsResult.totalFlow()).isEqualTo(4D);
64+
assertThat(statsResult.configuration()).isEqualTo(configuration);
65+
}
66+
}

0 commit comments

Comments
 (0)