Skip to main content

graphforge_core/
embedding_options.rs

1//! Closed typed options for the four embedding-v1 analysis algorithms.
2
3use crate::algorithms::AnalyzeAlgorithm;
4
5/// Maximum embedding width shared by Node2Vec, GraphSAGE, and FastRP.
6pub const MAX_EMBEDDING_DIMENSIONS: usize = 4_096;
7/// Maximum embedding width for HashGNN.
8pub const MAX_HASHGNN_DIMENSIONS: usize = 8_192;
9
10/// One embedding-v1 option family.
11#[derive(Debug, Clone, PartialEq)]
12pub enum EmbeddingOptions {
13    /// `analyze(by="node2vec")`.
14    Node2Vec(Node2VecOptions),
15    /// `analyze(by="graphsage")`.
16    GraphSage(GraphSageOptions),
17    /// `analyze(by="fast_random_projection")`.
18    FastRandomProjection(FastRpOptions),
19    /// `analyze(by="hashgnn")`.
20    HashGnn(HashGnnOptions),
21}
22
23/// Graph-native invocation boundary for an embedding analysis.
24#[derive(Debug, Clone, PartialEq)]
25pub struct EmbeddingAnalyzeOptions {
26    /// Embedding algorithm selected from the closed analysis catalog.
27    pub by: AnalyzeAlgorithm,
28    /// Optional relationship type filter.
29    pub via: Option<String>,
30    /// Whether to treat edges as directed.
31    pub directed: bool,
32    /// Optional edge-weight property.
33    pub weight: Option<String>,
34    /// Closed options for the selected embedding algorithm.
35    pub options: EmbeddingOptions,
36}
37
38/// Node2Vec v1 options.
39#[derive(Debug, Clone, PartialEq)]
40pub struct Node2VecOptions {
41    /// Output vector width.
42    pub dimensions: usize,
43    /// Transitions in each walk.
44    pub walk_length: usize,
45    /// Walks originating at each selected node.
46    pub walks_per_node: usize,
47    /// Return parameter `p`.
48    pub p: f64,
49    /// In/out parameter `q`.
50    pub q: f64,
51    /// Fixed context radius.
52    pub window_size: usize,
53    /// Negative samples per positive context.
54    pub negative_samples: usize,
55    /// Training passes over the fixed corpus.
56    pub epochs: usize,
57    /// Constant SGNS learning rate.
58    pub learning_rate: f64,
59    /// Caller seed; omission normalizes to zero.
60    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/// GraphSAGE v1 aggregator. Version 1 intentionally supports only mean.
81#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
82pub enum GraphSageAggregator {
83    /// Arithmetic mean of the sampled neighborhood.
84    #[default]
85    Mean,
86}
87
88/// Unsupervised GraphSAGE v1 options.
89///
90/// `feature_properties` must be supplied explicitly: the empty default is not a
91/// runnable GraphSAGE configuration.
92#[derive(Debug, Clone, PartialEq)]
93pub struct GraphSageOptions {
94    /// Output vector width.
95    pub dimensions: usize,
96    /// Width of non-final layers.
97    pub hidden_dimensions: usize,
98    /// Number of aggregation layers.
99    pub layers: usize,
100    /// Ordered fanout for each layer.
101    pub sample_sizes: Vec<usize>,
102    /// Version-pinned neighborhood aggregator.
103    pub aggregator: GraphSageAggregator,
104    /// Training epochs.
105    pub epochs: usize,
106    /// Negative samples per positive pair.
107    pub negative_samples: usize,
108    /// Constant Adam learning rate.
109    pub learning_rate: f64,
110    /// Ordered graph-native numeric feature properties.
111    pub feature_properties: Vec<String>,
112    /// Caller seed; omission normalizes to zero.
113    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/// Fast random projection v1 options.
134#[derive(Debug, Clone, PartialEq)]
135pub struct FastRpOptions {
136    /// Output vector width.
137    pub dimensions: usize,
138    /// Ordered coefficients for `H_0..H_t`.
139    pub iteration_weights: Vec<f64>,
140    /// Degree normalization exponent.
141    pub normalization_strength: f64,
142    /// Weight of the optional feature projection.
143    pub feature_weight: f64,
144    /// Ordered graph-native scalar feature properties.
145    pub feature_properties: Vec<String>,
146    /// Caller seed; omission normalizes to zero.
147    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/// HashGNN v1 options.
164#[derive(Debug, Clone, PartialEq)]
165pub struct HashGnnOptions {
166    /// Output vector width.
167    pub dimensions: usize,
168    /// Minhash propagation rounds.
169    pub iterations: usize,
170    /// Initial active-coordinate fraction.
171    pub embedding_density: f64,
172    /// Whether explicit heterogeneous type properties enter hashing.
173    pub heterogeneous: bool,
174    /// Explicit graph-native node type property.
175    pub node_type_property: Option<String>,
176    /// Explicit graph-native relationship type property.
177    pub relationship_type_property: Option<String>,
178    /// Caller seed; omission normalizes to zero.
179    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}