1use crate::algorithms::AnalyzeAlgorithm;
4
5pub const MAX_EMBEDDING_DIMENSIONS: usize = 4_096;
7pub const MAX_HASHGNN_DIMENSIONS: usize = 8_192;
9
10#[derive(Debug, Clone, PartialEq)]
12pub enum EmbeddingOptions {
13 Node2Vec(Node2VecOptions),
15 GraphSage(GraphSageOptions),
17 FastRandomProjection(FastRpOptions),
19 HashGnn(HashGnnOptions),
21}
22
23#[derive(Debug, Clone, PartialEq)]
25pub struct EmbeddingAnalyzeOptions {
26 pub by: AnalyzeAlgorithm,
28 pub via: Option<String>,
30 pub directed: bool,
32 pub weight: Option<String>,
34 pub options: EmbeddingOptions,
36}
37
38#[derive(Debug, Clone, PartialEq)]
40pub struct Node2VecOptions {
41 pub dimensions: usize,
43 pub walk_length: usize,
45 pub walks_per_node: usize,
47 pub p: f64,
49 pub q: f64,
51 pub window_size: usize,
53 pub negative_samples: usize,
55 pub epochs: usize,
57 pub learning_rate: f64,
59 pub seed: u64,
61}
62
63impl Default for Node2VecOptions {
64 fn default() -> Self {
65 Self {
66 dimensions: 128,
67 walk_length: 80,
68 walks_per_node: 10,
69 p: 1.0,
70 q: 1.0,
71 window_size: 10,
72 negative_samples: 5,
73 epochs: 1,
74 learning_rate: 0.025,
75 seed: 0,
76 }
77 }
78}
79
80#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
82pub enum GraphSageAggregator {
83 #[default]
85 Mean,
86}
87
88#[derive(Debug, Clone, PartialEq)]
93pub struct GraphSageOptions {
94 pub dimensions: usize,
96 pub hidden_dimensions: usize,
98 pub layers: usize,
100 pub sample_sizes: Vec<usize>,
102 pub aggregator: GraphSageAggregator,
104 pub epochs: usize,
106 pub negative_samples: usize,
108 pub learning_rate: f64,
110 pub feature_properties: Vec<String>,
112 pub seed: u64,
114}
115
116impl Default for GraphSageOptions {
117 fn default() -> Self {
118 Self {
119 dimensions: 256,
120 hidden_dimensions: 256,
121 layers: 2,
122 sample_sizes: vec![25, 10],
123 aggregator: GraphSageAggregator::Mean,
124 epochs: 1,
125 negative_samples: 20,
126 learning_rate: 0.000_002,
127 feature_properties: Vec::new(),
128 seed: 0,
129 }
130 }
131}
132
133#[derive(Debug, Clone, PartialEq)]
135pub struct FastRpOptions {
136 pub dimensions: usize,
138 pub iteration_weights: Vec<f64>,
140 pub normalization_strength: f64,
142 pub feature_weight: f64,
144 pub feature_properties: Vec<String>,
146 pub seed: u64,
148}
149
150impl Default for FastRpOptions {
151 fn default() -> Self {
152 Self {
153 dimensions: 128,
154 iteration_weights: vec![0.0, 1.0, 1.0],
155 normalization_strength: 0.0,
156 feature_weight: 0.0,
157 feature_properties: Vec::new(),
158 seed: 0,
159 }
160 }
161}
162
163#[derive(Debug, Clone, PartialEq)]
165pub struct HashGnnOptions {
166 pub dimensions: usize,
168 pub iterations: usize,
170 pub embedding_density: f64,
172 pub heterogeneous: bool,
174 pub node_type_property: Option<String>,
176 pub relationship_type_property: Option<String>,
178 pub seed: u64,
180}
181
182impl Default for HashGnnOptions {
183 fn default() -> Self {
184 Self {
185 dimensions: 256,
186 iterations: 2,
187 embedding_density: 0.25,
188 heterogeneous: false,
189 node_type_property: None,
190 relationship_type_property: None,
191 seed: 0,
192 }
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199
200 #[test]
201 fn embedding_defaults_are_the_complete_frozen_public_contract() {
202 let node2vec = Node2VecOptions::default();
203 assert_eq!(
204 (
205 node2vec.dimensions,
206 node2vec.walk_length,
207 node2vec.walks_per_node
208 ),
209 (128, 80, 10)
210 );
211 assert_eq!(
212 (node2vec.p, node2vec.q, node2vec.learning_rate),
213 (1.0, 1.0, 0.025)
214 );
215 assert_eq!(
216 (
217 node2vec.window_size,
218 node2vec.negative_samples,
219 node2vec.epochs,
220 node2vec.seed
221 ),
222 (10, 5, 1, 0)
223 );
224
225 let sage = GraphSageOptions::default();
226 assert_eq!(
227 (sage.dimensions, sage.hidden_dimensions, sage.layers),
228 (256, 256, 2)
229 );
230 assert_eq!(sage.sample_sizes, [25, 10]);
231 assert_eq!(sage.aggregator, GraphSageAggregator::Mean);
232 assert_eq!((sage.epochs, sage.negative_samples, sage.seed), (1, 20, 0));
233 assert_eq!(sage.learning_rate, 0.000_002);
234 assert!(sage.feature_properties.is_empty());
235
236 let fastrp = FastRpOptions::default();
237 assert_eq!(fastrp.dimensions, 128);
238 assert_eq!(fastrp.iteration_weights, [0.0, 1.0, 1.0]);
239 assert_eq!(
240 (fastrp.normalization_strength, fastrp.feature_weight),
241 (0.0, 0.0)
242 );
243 assert!(fastrp.feature_properties.is_empty());
244 assert_eq!(fastrp.seed, 0);
245
246 let hashgnn = HashGnnOptions::default();
247 assert_eq!((hashgnn.dimensions, hashgnn.iterations), (256, 2));
248 assert_eq!(hashgnn.embedding_density, 0.25);
249 assert!(!hashgnn.heterogeneous);
250 assert_eq!(hashgnn.node_type_property, None);
251 assert_eq!(hashgnn.relationship_type_property, None);
252 assert_eq!(hashgnn.seed, 0);
253 }
254}