Skip to content

Commit afeaaca

Browse files
Add kmeans to business facade
1 parent 8aa0a6f commit afeaaca

File tree

4 files changed

+124
-29
lines changed

4 files changed

+124
-29
lines changed

algorithms-compute-business-facade/src/main/java/org/neo4j/gds/community/CommunityComputeBusinessFacade.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.neo4j.gds.api.DatabaseId;
2424
import org.neo4j.gds.api.GraphName;
2525
import org.neo4j.gds.api.User;
26+
import org.neo4j.gds.api.nodeproperties.ValueType;
2627
import org.neo4j.gds.approxmaxkcut.ApproxMaxKCutParameters;
2728
import org.neo4j.gds.approxmaxkcut.ApproxMaxKCutResult;
2829
import org.neo4j.gds.cliqueCounting.CliqueCountingResult;
@@ -34,16 +35,20 @@
3435
import org.neo4j.gds.core.loading.GraphStoreCatalogService;
3536
import org.neo4j.gds.core.loading.validation.NoAlgorithmValidation;
3637
import org.neo4j.gds.core.loading.validation.NodePropertyAnyExistsGraphStoreValidation;
38+
import org.neo4j.gds.core.loading.validation.NodePropertyTypeGraphStoreValidation;
3739
import org.neo4j.gds.core.loading.validation.UndirectedOnlyGraphStoreValidation;
3840
import org.neo4j.gds.hdbscan.HDBScanParameters;
3941
import org.neo4j.gds.hdbscan.Labels;
4042
import org.neo4j.gds.k1coloring.K1ColoringParameters;
4143
import org.neo4j.gds.k1coloring.K1ColoringResult;
4244
import org.neo4j.gds.kcore.KCoreDecompositionParameters;
4345
import org.neo4j.gds.kcore.KCoreDecompositionResult;
46+
import org.neo4j.gds.kmeans.KmeansParameters;
47+
import org.neo4j.gds.kmeans.KmeansResult;
4448
import org.neo4j.gds.result.TimedAlgorithmResult;
4549
import org.neo4j.gds.results.ResultTransformerBuilder;
4650

51+
import java.util.List;
4752
import java.util.Optional;
4853
import java.util.concurrent.CompletableFuture;
4954

@@ -249,4 +254,34 @@ public <TR> CompletableFuture<TR> kCoreDecomposition(
249254
).thenApply(resultTransformerBuilder.build(graphResources));
250255
}
251256

257+
public <TR> CompletableFuture<TR> kMeans(
258+
GraphName graphName,
259+
GraphParameters graphParameters,
260+
Optional<String> relationshipProperty,
261+
KmeansParameters parameters,
262+
JobId jobId,
263+
boolean logProgress,
264+
ResultTransformerBuilder<TimedAlgorithmResult<KmeansResult>, TR> resultTransformerBuilder
265+
) {
266+
// Fetch the Graph the algorithm will operate on
267+
var graphResources = graphStoreCatalogService.fetchGraphResources(
268+
graphName,
269+
graphParameters,
270+
relationshipProperty,
271+
new NodePropertyTypeGraphStoreValidation("nodeProperty", List.of(ValueType.DOUBLE_ARRAY, ValueType.FLOAT_ARRAY,ValueType.DOUBLE)),
272+
Optional.empty(),
273+
user,
274+
databaseId
275+
);
276+
var graph = graphResources.graph();
277+
278+
return computeFacade.kMeans(
279+
graph,
280+
parameters,
281+
jobId,
282+
logProgress
283+
284+
).thenApply(resultTransformerBuilder.build(graphResources));
285+
}
286+
252287
}

algorithms-compute-business-facade/src/main/java/org/neo4j/gds/pathfinding/validation/PCSTGraphStoreValidation.java

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,26 @@
2525
import org.neo4j.gds.api.nodeproperties.ValueType;
2626
import org.neo4j.gds.core.loading.validation.GraphStoreValidation;
2727
import org.neo4j.gds.core.loading.validation.NodePropertyAllExistsGraphStoreValidation;
28+
import org.neo4j.gds.core.loading.validation.NodePropertyTypeGraphStoreValidation;
2829
import org.neo4j.gds.core.loading.validation.UndirectedOnlyGraphStoreValidation;
29-
import org.neo4j.gds.utils.StringFormatting;
3030

3131
import java.util.Collection;
32+
import java.util.List;
3233

3334
public class PCSTGraphStoreValidation extends GraphStoreValidation {
3435

35-
private final String prizeProperty;
3636
private final UndirectedOnlyGraphStoreValidation undirectedOnlyGraphStoreValidation;
3737
private final NodePropertyAllExistsGraphStoreValidation nodePropertyAllExistsGraphStoreValidation;
38+
private final NodePropertyTypeGraphStoreValidation nodePropertyTypeGraphStoreValidation;
3839

3940

4041
public PCSTGraphStoreValidation(
41-
String prizeProperty,
4242
UndirectedOnlyGraphStoreValidation undirectedOnlyGraphStoreValidation,
43-
NodePropertyAllExistsGraphStoreValidation nodePropertyAllExistsGraphStoreValidation
43+
NodePropertyAllExistsGraphStoreValidation nodePropertyAllExistsGraphStoreValidation,
44+
NodePropertyTypeGraphStoreValidation nodePropertyTypeGraphStoreValidation
4445
) {
45-
this.prizeProperty = prizeProperty;
46+
this.nodePropertyTypeGraphStoreValidation = nodePropertyTypeGraphStoreValidation;
47+
;
4648
this.undirectedOnlyGraphStoreValidation = undirectedOnlyGraphStoreValidation;
4749
this.nodePropertyAllExistsGraphStoreValidation = nodePropertyAllExistsGraphStoreValidation;
4850
}
@@ -51,12 +53,14 @@ public static PCSTGraphStoreValidation create(String prizeProperty) {
5153

5254
var nodePropertyAllExistsGraphStoreValidation = new NodePropertyAllExistsGraphStoreValidation(prizeProperty);
5355
var undirectedOnlyGraphStoreValidation = new UndirectedOnlyGraphStoreValidation("Prize-collecting Steiner Tree");
54-
55-
return new PCSTGraphStoreValidation(
56+
var nodePropertyTypeGraphStoreValidation = new NodePropertyTypeGraphStoreValidation(
5657
prizeProperty,
58+
List.of(ValueType.DOUBLE)
59+
);
60+
return new PCSTGraphStoreValidation(
5761
undirectedOnlyGraphStoreValidation,
58-
nodePropertyAllExistsGraphStoreValidation
59-
62+
nodePropertyAllExistsGraphStoreValidation,
63+
nodePropertyTypeGraphStoreValidation
6064
);
6165
}
6266

@@ -68,22 +72,10 @@ protected void validateAlgorithmRequirements(
6872
) {
6973
undirectedOnlyGraphStoreValidation.validateAlgorithmRequirements(graphStore,selectedLabels,selectedRelationshipTypes);
7074
nodePropertyAllExistsGraphStoreValidation.validateAlgorithmRequirements(graphStore,selectedLabels,selectedRelationshipTypes);
71-
validatePropertyType(graphStore);
75+
nodePropertyTypeGraphStoreValidation.validateAlgorithmRequirements(graphStore,selectedLabels,selectedRelationshipTypes);
7276
}
7377

7478

75-
void validatePropertyType(GraphStore graphStore){
76-
var valueType = graphStore.nodeProperty(prizeProperty).valueType();
77-
if (valueType == ValueType.DOUBLE) {
78-
return;
79-
}
80-
throw new IllegalArgumentException(
81-
StringFormatting.formatWithLocale(
82-
"Unsupported node property value type [%s]. Value type required: [%s]",
83-
valueType,
84-
ValueType.DOUBLE
85-
)
86-
);
87-
}
79+
8880

8981
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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.core.loading.validation;
21+
22+
import org.neo4j.gds.NodeLabel;
23+
import org.neo4j.gds.RelationshipType;
24+
import org.neo4j.gds.api.GraphStore;
25+
import org.neo4j.gds.api.nodeproperties.ValueType;
26+
import org.neo4j.gds.utils.StringFormatting;
27+
import org.neo4j.gds.utils.StringJoining;
28+
29+
import java.util.Collection;
30+
import java.util.List;
31+
32+
public class NodePropertyTypeGraphStoreValidation extends GraphStoreValidation {
33+
private final String nodeProperty;
34+
private final List<ValueType> allowedValueTypes;
35+
36+
public NodePropertyTypeGraphStoreValidation(String nodeProperty, List<ValueType> allowedValueTypes) {
37+
this.nodeProperty = nodeProperty;
38+
this.allowedValueTypes = allowedValueTypes;
39+
}
40+
41+
@Override
42+
public void validateAlgorithmRequirements(
43+
GraphStore graphStore,
44+
Collection<NodeLabel> selectedLabels,
45+
Collection<RelationshipType> selectedRelationshipTypes
46+
) {
47+
validatePropertyType(graphStore);
48+
49+
}
50+
51+
void validatePropertyType(GraphStore graphStore){
52+
var valueType = graphStore.nodeProperty(nodeProperty).valueType();
53+
for (var currentValueType : allowedValueTypes){
54+
if (valueType == currentValueType) {
55+
return;
56+
}
57+
}
58+
throw new IllegalArgumentException(
59+
StringFormatting.formatWithLocale(
60+
"Unsupported node property value type for property `%s`: %s. Value types accepted: %s",
61+
nodeProperty,
62+
valueType,
63+
StringJoining.join(allowedValueTypes.stream().map(Enum::name))
64+
)
65+
);
66+
}
67+
}

procedures/pushback-procedures-facade/src/test/java/org/neo4j/gds/pathfinding/validation/PCSTGraphStoreValidationTest.java renamed to core/src/test/java/org/neo4j/gds/core/loading/validation/NodePropertyTypeGraphStoreValidationTest.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,22 @@
1717
* You should have received a copy of the GNU General Public License
1818
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1919
*/
20-
package org.neo4j.gds.pathfinding.validation;
20+
package org.neo4j.gds.core.loading.validation;
2121

2222
import org.junit.jupiter.api.Test;
2323
import org.neo4j.gds.api.GraphStore;
2424
import org.neo4j.gds.api.nodeproperties.ValueType;
2525
import org.neo4j.gds.api.properties.nodes.NodeProperty;
2626

27+
import java.util.List;
28+
2729
import static org.assertj.core.api.Assertions.assertThatNoException;
2830
import static org.assertj.core.api.Assertions.assertThatThrownBy;
2931
import static org.mockito.ArgumentMatchers.anyString;
3032
import static org.mockito.Mockito.mock;
3133
import static org.mockito.Mockito.when;
3234

33-
class PCSTGraphStoreValidationTest {
35+
class NodePropertyTypeGraphStoreValidationTest {
3436

3537
@Test
3638
void shouldNotThrowForValidPropertyType() {
@@ -39,7 +41,7 @@ void shouldNotThrowForValidPropertyType() {
3941
when(nodeProperty.valueType()).thenReturn(ValueType.DOUBLE);
4042
when(graphStore.nodeProperty(anyString())).thenReturn(nodeProperty);
4143

42-
var validation = PCSTGraphStoreValidation.create("p");
44+
var validation = new NodePropertyTypeGraphStoreValidation("p", List.of(ValueType.DOUBLE));
4345

4446
assertThatNoException().isThrownBy(() -> validation.validatePropertyType(
4547
graphStore
@@ -55,13 +57,12 @@ void shouldThrowForInvalidType() {
5557
when(nodeProperty.valueType()).thenReturn(ValueType.FLOAT_ARRAY);
5658
when(graphStore.nodeProperty(anyString())).thenReturn(nodeProperty);
5759

58-
59-
var validation = PCSTGraphStoreValidation.create("p");
60+
var validation = new NodePropertyTypeGraphStoreValidation("p", List.of(ValueType.DOUBLE, ValueType.LONG));
6061

6162
assertThatThrownBy(() -> validation.validatePropertyType(
6263
graphStore
6364
))
64-
.hasMessageContaining("Unsupported node property value type [FLOAT_ARRAY]. Value type required: [DOUBLE]");
65+
.hasMessageContaining("Unsupported node property value type for property `p`: FLOAT_ARRAY. Value types accepted: ['DOUBLE', 'LONG']");
6566

6667
}
6768

0 commit comments

Comments
 (0)