Skip to content

Commit 7f6a290

Browse files
committed
Validate that densityLevel <= dimension
1 parent a8d49e0 commit 7f6a290

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

algo/src/main/java/org/neo4j/gds/embeddings/hashgnn/GenerateFeaturesConfig.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.util.Collections;
2727
import java.util.Map;
2828

29+
import static org.neo4j.gds.utils.StringFormatting.formatWithLocale;
30+
2931
@Configuration
3032
public interface GenerateFeaturesConfig {
3133
@Configuration.IntegerRange(min = 1)
@@ -47,4 +49,11 @@ default Map<String, Object> toMap() {
4749
default Collection<String> configKeys() {
4850
return Collections.emptyList();
4951
}
52+
53+
@Value.Check
54+
default void validate() {
55+
if (densityLevel() > dimension()) {
56+
throw new IllegalArgumentException(formatWithLocale("Generate features requires `densityLevel` to be at most `dimension` but was %d > %d.", densityLevel(), dimension()));
57+
}
58+
}
5059
}

algo/src/test/java/org/neo4j/gds/embeddings/hashgnn/HashGNNConfigTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,16 @@ void requiresFeaturePropertiesIfNoGeneratedFeatures() {
6363
.build();
6464
}).hasMessage("When `generateFeatures` is not given, `featureProperties` must be non-empty.");
6565
}
66+
67+
@Test
68+
void requiresDensityLevelAtMostDensity() {
69+
assertThatThrownBy(() -> {
70+
HashGNNConfigImpl
71+
.builder()
72+
.embeddingDensity(4)
73+
.generateFeatures(Map.of("dimension", 4, "densityLevel", 5))
74+
.iterations(100)
75+
.build();
76+
}).hasMessage("Generate features requires `densityLevel` to be at most `dimension` but was 5 > 4.");
77+
}
6678
}

doc/modules/ROOT/partials/machine-learning/node-embeddings/hashgnn/specific-configuration.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
| heterogeneous | Boolean | false | yes | Whether different relationship types should be treated differently.
55
| neighborInfluence | Float | 1.0 | yes | Controls how often neighbors' features are sampled in each iteration relative to sampling the node's own features. Must be non-negative.
66
| binarizeFeatures | Map | n/a | yes | A map with keys `dimension` and `threshold`. If given, features are transformed into `dimension` binary features via hyperplane rounding. Increasing `threshold` makes the output more sparse, and it defaults to `0`. The value of `dimension` must be at least 1.
7-
| generateFeatures | Map | n/a | yes | A map with keys `dimension` and `densityLevel`. Should be given if and only if `featureProperties` is empty. If given, `dimension` binary features are generated with approximately `densityLevel` active features per node. Both must be at least 1.
7+
| generateFeatures | Map | n/a | yes | A map with keys `dimension` and `densityLevel`. Should be given if and only if `featureProperties` is empty. If given, `dimension` binary features are generated with approximately `densityLevel` active features per node. Both must be at least 1 and `densityLevel` at most `density`.
88
| outputDimension | Integer | n/a | yes | If given, the embeddings are projected randomly into `outputDimension` dense features. Must be at least 1.
99
| randomSeed | Integer | n/a | yes | A random seed which is used for all randomness in computing the embeddings.

0 commit comments

Comments
 (0)