Skip to content

Commit 35072a5

Browse files
IoannisPanagiotasvnickolov
authored andcommitted
Implement Random walk mutate result transformer
1 parent ed90832 commit 35072a5

File tree

4 files changed

+253
-3
lines changed

4 files changed

+253
-3
lines changed

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.neo4j.gds.procedures.algorithms.pathfinding.mutate;
2121

2222
import org.neo4j.gds.api.GraphName;
23+
import org.neo4j.gds.applications.algorithms.machinery.MutateNodePropertyService;
2324
import org.neo4j.gds.applications.algorithms.machinery.MutateRelationshipService;
2425
import org.neo4j.gds.pathfinding.PathFindingComputeBusinessFacade;
2526
import org.neo4j.gds.paths.astar.config.ShortestPathAStarMutateConfig;
@@ -52,16 +53,19 @@ public final class PushbackPathFindingMutateProcedureFacade {
5253
private final UserSpecificConfigurationParser configurationParser;
5354

5455
private final MutateRelationshipService mutateRelationshipService;
56+
private final MutateNodePropertyService mutateNodePropertyService;
5557

5658

5759
public PushbackPathFindingMutateProcedureFacade(
5860
PathFindingComputeBusinessFacade businessFacade,
5961
UserSpecificConfigurationParser configurationParser,
60-
MutateRelationshipService mutateRelationshipService
62+
MutateRelationshipService mutateRelationshipService,
63+
MutateNodePropertyService mutateNodePropertyService
6164
) {
6265
this.businessFacade = businessFacade;
6366
this.configurationParser = configurationParser;
6467
this.mutateRelationshipService = mutateRelationshipService;
68+
this.mutateNodePropertyService = mutateNodePropertyService;
6569
}
6670

6771
public Stream<BellmanFordMutateResult> bellmanFord(String graphName, Map<String, Object> configuration) {
@@ -159,14 +163,14 @@ public Stream<RandomWalkMutateResult> randomWalk(String graphName, Map<String, O
159163
RandomWalkMutateConfig::of
160164
);
161165

162-
return businessFacade.randomWalk(
166+
return businessFacade.randomWalkCountingNodeVisits(
163167
GraphName.parse(graphName),
164168
config.toGraphParameters(),
165169
config.relationshipWeightProperty(),
166170
config.toParameters(),
167171
config.jobId(),
168172
config.logProgress(),
169-
(g, gs) -> (r) -> Stream.<RandomWalkMutateResult>empty()
173+
new RandomWalkMutateResultTransformerBuilder(mutateNodePropertyService,config)
170174
).join();
171175
}
172176

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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.mutate;
21+
22+
import org.neo4j.gds.api.Graph;
23+
import org.neo4j.gds.api.GraphStore;
24+
import org.neo4j.gds.applications.algorithms.metadata.NodePropertiesWritten;
25+
import org.neo4j.gds.collections.haa.HugeAtomicLongArray;
26+
import org.neo4j.gds.core.utils.ProgressTimer;
27+
import org.neo4j.gds.pathfinding.RandomWalkCountingNodeVisitsMutateStep;
28+
import org.neo4j.gds.procedures.algorithms.pathfinding.RandomWalkMutateResult;
29+
import org.neo4j.gds.result.TimedAlgorithmResult;
30+
import org.neo4j.gds.results.ResultTransformer;
31+
32+
import java.util.Map;
33+
import java.util.concurrent.atomic.AtomicLong;
34+
import java.util.stream.Stream;
35+
36+
public class RandomWalkMutateResultTransformer implements ResultTransformer<TimedAlgorithmResult<HugeAtomicLongArray>, Stream<RandomWalkMutateResult>> {
37+
38+
private final RandomWalkCountingNodeVisitsMutateStep mutateStep;
39+
private final Graph graph;
40+
private final GraphStore graphStore;
41+
private final Map<String, Object> configuration;
42+
43+
public RandomWalkMutateResultTransformer(
44+
RandomWalkCountingNodeVisitsMutateStep mutateStep,
45+
Graph graph,
46+
GraphStore graphStore,
47+
Map<String, Object> configuration
48+
) {
49+
this.mutateStep = mutateStep;
50+
this.graph = graph;
51+
this.graphStore = graphStore;
52+
this.configuration = configuration;
53+
}
54+
55+
@Override
56+
public Stream<RandomWalkMutateResult> apply(TimedAlgorithmResult<HugeAtomicLongArray> algorithmResult) {
57+
NodePropertiesWritten nodePropertiesWritten;
58+
var mutateMillis = new AtomicLong();
59+
try (var ignored = ProgressTimer.start(mutateMillis::set)) {
60+
nodePropertiesWritten = mutateStep.execute(graph, graphStore, algorithmResult.result());
61+
}
62+
63+
return Stream.of(
64+
new RandomWalkMutateResult(
65+
0,
66+
algorithmResult.computeMillis(),
67+
mutateMillis.get(),
68+
0,
69+
nodePropertiesWritten.value(),
70+
configuration
71+
72+
)
73+
);
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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.mutate;
21+
22+
import org.neo4j.gds.api.Graph;
23+
import org.neo4j.gds.api.GraphStore;
24+
import org.neo4j.gds.applications.algorithms.machinery.MutateNodePropertyService;
25+
import org.neo4j.gds.collections.haa.HugeAtomicLongArray;
26+
import org.neo4j.gds.pathfinding.RandomWalkCountingNodeVisitsMutateStep;
27+
import org.neo4j.gds.procedures.algorithms.pathfinding.RandomWalkMutateResult;
28+
import org.neo4j.gds.result.TimedAlgorithmResult;
29+
import org.neo4j.gds.results.ResultTransformerBuilder;
30+
import org.neo4j.gds.traversal.RandomWalkMutateConfig;
31+
32+
import java.util.stream.Stream;
33+
34+
class RandomWalkMutateResultTransformerBuilder implements ResultTransformerBuilder<TimedAlgorithmResult<HugeAtomicLongArray>, Stream<RandomWalkMutateResult>> {
35+
36+
private final MutateNodePropertyService mutateNodePropertyService;
37+
private final RandomWalkMutateConfig configuration;
38+
39+
RandomWalkMutateResultTransformerBuilder(
40+
MutateNodePropertyService mutateNodePropertyService,
41+
RandomWalkMutateConfig configuration
42+
) {
43+
this.mutateNodePropertyService = mutateNodePropertyService;
44+
this.configuration = configuration;
45+
}
46+
47+
@Override
48+
public RandomWalkMutateResultTransformer build(
49+
Graph graph,
50+
GraphStore graphStore
51+
) {
52+
var mutateStep = new RandomWalkCountingNodeVisitsMutateStep(
53+
configuration.nodeLabels(),
54+
configuration.mutateProperty(),
55+
mutateNodePropertyService
56+
);
57+
return new RandomWalkMutateResultTransformer(
58+
mutateStep,
59+
graph,
60+
graphStore,
61+
configuration.toMap()
62+
);
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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.mutate;
21+
22+
import org.junit.jupiter.api.Test;
23+
import org.neo4j.gds.api.Graph;
24+
import org.neo4j.gds.api.GraphStore;
25+
import org.neo4j.gds.applications.algorithms.machinery.MutateNodePropertyService;
26+
import org.neo4j.gds.applications.algorithms.metadata.NodePropertiesWritten;
27+
import org.neo4j.gds.collections.haa.HugeAtomicLongArray;
28+
import org.neo4j.gds.core.concurrency.Concurrency;
29+
import org.neo4j.gds.core.utils.paged.ParalleLongPageCreator;
30+
import org.neo4j.gds.logging.Log;
31+
import org.neo4j.gds.pathfinding.RandomWalkCountingNodeVisitsMutateStep;
32+
import org.neo4j.gds.result.TimedAlgorithmResult;
33+
34+
import java.util.List;
35+
import java.util.Map;
36+
37+
import static org.assertj.core.api.Assertions.assertThat;
38+
import static org.mockito.ArgumentMatchers.any;
39+
import static org.mockito.Mockito.mock;
40+
import static org.mockito.Mockito.times;
41+
import static org.mockito.Mockito.verify;
42+
import static org.mockito.Mockito.verifyNoMoreInteractions;
43+
import static org.mockito.Mockito.when;
44+
45+
class RandomWalkMutateResultTransformerTest {
46+
47+
@Test
48+
void shouldTransformToMutateResult() {
49+
var config = Map.<String, Object>of("foo", "bar");
50+
var graph = mock(Graph.class);
51+
var graphStore = mock(GraphStore.class);
52+
var mutateStep = mock(RandomWalkCountingNodeVisitsMutateStep.class);
53+
54+
var algoResult = mock(HugeAtomicLongArray.class);
55+
56+
var nodePropsWritten = new NodePropertiesWritten(5L);
57+
when(mutateStep.execute(any(), any(), any())).thenReturn(nodePropsWritten);
58+
59+
var timedResult = new TimedAlgorithmResult<>(algoResult, 123L);
60+
61+
var transformer = new RandomWalkMutateResultTransformer(mutateStep, graph, graphStore, config);
62+
63+
var resultStream = transformer.apply(timedResult);
64+
var result = resultStream.findFirst().orElseThrow();
65+
66+
assertThat(result.preProcessingMillis()).isZero();
67+
assertThat(result.computeMillis()).isEqualTo(123L);
68+
assertThat(result.mutateMillis()).isNotNegative();
69+
assertThat(result.postProcessingMillis()).isZero();
70+
assertThat(result.configuration()).isEqualTo(config);
71+
assertThat(result.nodePropertiesWritten()).isEqualTo(5L);
72+
73+
verify(mutateStep, times(1)).execute(graph, graphStore, algoResult);
74+
verifyNoMoreInteractions(mutateStep);
75+
}
76+
77+
@Test
78+
void shouldTransformEmptyResultToMutateResult() {
79+
var config = Map.<String, Object>of("boo", "foo");
80+
var graph = mock(Graph.class);
81+
var graphStore = mock(GraphStore.class);
82+
var mutateNodePropertyService = new MutateNodePropertyService(Log.noOpLog());
83+
var mutateStep = new RandomWalkCountingNodeVisitsMutateStep(
84+
List.of("FOO"),
85+
"bar",
86+
mutateNodePropertyService
87+
);
88+
89+
var algoResult = HugeAtomicLongArray.of(0, ParalleLongPageCreator.identity(new Concurrency(1)));
90+
91+
var timedResult = new TimedAlgorithmResult<>(algoResult, 123L);
92+
93+
var transformer = new RandomWalkMutateResultTransformer(mutateStep, graph, graphStore, config);
94+
95+
var resultStream = transformer.apply(timedResult);
96+
var result = resultStream.findFirst().orElseThrow();
97+
98+
assertThat(result.preProcessingMillis()).isZero();
99+
assertThat(result.computeMillis()).isEqualTo(123L);
100+
assertThat(result.mutateMillis()).isNotNegative();
101+
assertThat(result.postProcessingMillis()).isZero();
102+
assertThat(result.configuration()).isEqualTo(config);
103+
assertThat(result.nodePropertiesWritten()).isEqualTo(0);
104+
105+
}
106+
107+
}

0 commit comments

Comments
 (0)