Skip to content

Commit b158b89

Browse files
committed
Add BellmanFordWriteResultTransformer
1 parent 30f653c commit b158b89

File tree

3 files changed

+232
-2
lines changed

3 files changed

+232
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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.write;
21+
22+
import org.neo4j.gds.api.Graph;
23+
import org.neo4j.gds.api.GraphStore;
24+
import org.neo4j.gds.api.ResultStore;
25+
import org.neo4j.gds.applications.algorithms.metadata.RelationshipsWritten;
26+
import org.neo4j.gds.core.utils.ProgressTimer;
27+
import org.neo4j.gds.core.utils.progress.JobId;
28+
import org.neo4j.gds.pathfinding.BellmanFordWriteStep;
29+
import org.neo4j.gds.paths.bellmanford.BellmanFordResult;
30+
import org.neo4j.gds.procedures.algorithms.pathfinding.BellmanFordWriteResult;
31+
import org.neo4j.gds.result.TimedAlgorithmResult;
32+
import org.neo4j.gds.results.ResultTransformer;
33+
34+
import java.util.Map;
35+
import java.util.concurrent.atomic.AtomicLong;
36+
import java.util.stream.Stream;
37+
38+
class BellmanFordWriteResultTransformer implements ResultTransformer<TimedAlgorithmResult<BellmanFordResult>, Stream<BellmanFordWriteResult>> {
39+
40+
private final BellmanFordWriteStep bellmanFordWriteStep;
41+
private final Graph graph;
42+
private final GraphStore graphStore;
43+
@Deprecated(forRemoval = true)
44+
private final ResultStore resultStore;
45+
private final JobId jobId;
46+
private final Map<String, Object> configuration;
47+
48+
BellmanFordWriteResultTransformer(
49+
BellmanFordWriteStep bellmanFordWriteStep,
50+
Graph graph,
51+
GraphStore graphStore,
52+
@Deprecated(forRemoval = true)
53+
ResultStore resultStore,
54+
JobId jobId,
55+
Map<String, Object> configuration
56+
) {
57+
this.bellmanFordWriteStep = bellmanFordWriteStep;
58+
this.graph = graph;
59+
this.graphStore = graphStore;
60+
this.resultStore = resultStore;
61+
this.jobId = jobId;
62+
this.configuration = configuration;
63+
}
64+
65+
@Override
66+
public Stream<BellmanFordWriteResult> apply(TimedAlgorithmResult<BellmanFordResult> algorithmResult) {
67+
68+
RelationshipsWritten relationshipsWritten;
69+
var writeMillis = new AtomicLong();
70+
var result = algorithmResult.result();
71+
try (var ignored = ProgressTimer.start(writeMillis::set)) {
72+
relationshipsWritten = bellmanFordWriteStep.execute(
73+
graph,
74+
graphStore,
75+
resultStore,
76+
result,
77+
jobId
78+
);
79+
}
80+
81+
return Stream.of(
82+
new BellmanFordWriteResult(
83+
0,
84+
algorithmResult.computeMillis(),
85+
writeMillis.get(),
86+
0,
87+
relationshipsWritten.value(),
88+
result.containsNegativeCycle(),
89+
configuration
90+
)
91+
);
92+
}
93+
}

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,24 @@
3131
import java.util.stream.Stream;
3232

3333
class BellmanFordWriteResultTransformerBuilder implements ResultTransformerBuilder<TimedAlgorithmResult<BellmanFordResult>, Stream<BellmanFordWriteResult>> {
34-
BellmanFordWriteResultTransformerBuilder(BellmanFordWriteStep writeStep, AllShortestPathsBellmanFordWriteConfig config) {}
34+
private final BellmanFordWriteStep writeStep;
35+
private final AllShortestPathsBellmanFordWriteConfig config;
36+
37+
BellmanFordWriteResultTransformerBuilder(BellmanFordWriteStep writeStep, AllShortestPathsBellmanFordWriteConfig config) {this.writeStep = writeStep;
38+
this.config = config;
39+
}
3540

3641
@Override
3742
public ResultTransformer<TimedAlgorithmResult<BellmanFordResult>, Stream<BellmanFordWriteResult>> build(
3843
GraphResources graphResources
3944
) {
40-
return ar -> Stream.empty();
45+
return new BellmanFordWriteResultTransformer(
46+
writeStep,
47+
graphResources.graph(),
48+
graphResources.graphStore(),
49+
graphResources.resultStore(),
50+
config.jobId(),
51+
config.toMap()
52+
);
4153
}
4254
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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.write;
21+
22+
import org.junit.jupiter.api.BeforeEach;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
import org.mockito.Mock;
26+
import org.mockito.junit.jupiter.MockitoExtension;
27+
import org.neo4j.gds.api.Graph;
28+
import org.neo4j.gds.api.GraphStore;
29+
import org.neo4j.gds.api.ResultStore;
30+
import org.neo4j.gds.applications.algorithms.metadata.RelationshipsWritten;
31+
import org.neo4j.gds.core.utils.progress.JobId;
32+
import org.neo4j.gds.pathfinding.BellmanFordWriteStep;
33+
import org.neo4j.gds.paths.bellmanford.BellmanFordResult;
34+
import org.neo4j.gds.procedures.algorithms.pathfinding.BellmanFordWriteResult;
35+
import org.neo4j.gds.result.TimedAlgorithmResult;
36+
37+
import java.util.Map;
38+
import java.util.stream.Stream;
39+
40+
import static org.assertj.core.api.Assertions.assertThat;
41+
import static org.mockito.Mockito.mock;
42+
import static org.mockito.Mockito.when;
43+
44+
@ExtendWith(MockitoExtension.class)
45+
class BellmanFordWriteResultTransformerTest {
46+
47+
@Mock
48+
private BellmanFordWriteStep bellmanFordWriteStep;
49+
@Mock
50+
private Graph graph;
51+
@Mock
52+
private GraphStore graphStore;
53+
@Mock
54+
private ResultStore resultStore;
55+
@Mock
56+
private JobId jobId;
57+
58+
@Mock
59+
private TimedAlgorithmResult<BellmanFordResult> timedResultMock;
60+
61+
private Map<String, Object> configuration;
62+
private BellmanFordWriteResultTransformer transformer;
63+
64+
@BeforeEach
65+
void setUp() {
66+
bellmanFordWriteStep = mock(BellmanFordWriteStep.class);
67+
graph = mock(Graph.class);
68+
graphStore = mock(GraphStore.class);
69+
resultStore = mock(ResultStore.class);
70+
jobId = mock(JobId.class);
71+
configuration = Map.of("key", "value");
72+
transformer = new BellmanFordWriteResultTransformer(
73+
bellmanFordWriteStep,
74+
graph,
75+
graphStore,
76+
resultStore,
77+
jobId,
78+
configuration
79+
);
80+
}
81+
82+
@Test
83+
void shouldTransformResultCorrectly() {
84+
var bellmanFordResult = mock(BellmanFordResult.class);
85+
when(bellmanFordResult.containsNegativeCycle()).thenReturn(false);
86+
87+
when(timedResultMock.result()).thenReturn(bellmanFordResult);
88+
when(timedResultMock.computeMillis()).thenReturn(123L);
89+
90+
var relationshipsWritten = new RelationshipsWritten(42);
91+
92+
when(bellmanFordWriteStep.execute(graph, graphStore, resultStore, bellmanFordResult, jobId))
93+
.thenReturn(relationshipsWritten);
94+
95+
Stream<BellmanFordWriteResult> resultStream = transformer.apply(timedResultMock);
96+
BellmanFordWriteResult result = resultStream.findFirst().orElseThrow();
97+
98+
assertThat(result.computeMillis()).isEqualTo(123L);
99+
assertThat(result.writeMillis()).isGreaterThanOrEqualTo(0L);
100+
assertThat(result.relationshipsWritten()).isEqualTo(42L);
101+
assertThat(result.containsNegativeCycle()).isFalse();
102+
assertThat(result.configuration()).isEqualTo(configuration);
103+
}
104+
105+
@Test
106+
void shouldHandleNegativeCycle() {
107+
var bellmanFordResult = mock(BellmanFordResult.class);
108+
when(bellmanFordResult.containsNegativeCycle()).thenReturn(true);
109+
110+
when(timedResultMock.result()).thenReturn(bellmanFordResult);
111+
when(timedResultMock.computeMillis()).thenReturn(0L);
112+
113+
var relationshipsWritten = new RelationshipsWritten(0);
114+
115+
when(bellmanFordWriteStep.execute(graph, graphStore, resultStore, bellmanFordResult, jobId))
116+
.thenReturn(relationshipsWritten);
117+
118+
var resultStream = transformer.apply(timedResultMock);
119+
var result = resultStream.findFirst().orElseThrow();
120+
121+
assertThat(result.containsNegativeCycle()).isTrue();
122+
assertThat(result.relationshipsWritten()).isZero();
123+
}
124+
125+
}

0 commit comments

Comments
 (0)