cvx_query/
types.rs

1//! Query type definitions.
2
3use cvx_core::types::{ChangePoint, TemporalFilter, TemporalPoint};
4use serde::{Deserialize, Serialize};
5
6/// A temporal query request.
7#[derive(Debug, Clone, Serialize, Deserialize)]
8#[serde(tag = "type", rename_all = "snake_case")]
9pub enum TemporalQuery {
10    /// k-nearest neighbors at a specific timestamp.
11    SnapshotKnn {
12        /// Query vector.
13        vector: Vec<f32>,
14        /// Exact timestamp.
15        timestamp: i64,
16        /// Number of results.
17        k: usize,
18    },
19    /// k-nearest neighbors over a time range.
20    RangeKnn {
21        /// Query vector.
22        vector: Vec<f32>,
23        /// Start timestamp (inclusive).
24        start: i64,
25        /// End timestamp (inclusive).
26        end: i64,
27        /// Number of results.
28        k: usize,
29        /// Semantic vs temporal weight.
30        alpha: f32,
31    },
32    /// Full trajectory for an entity.
33    Trajectory {
34        /// Entity identifier.
35        entity_id: u64,
36        /// Temporal filter.
37        filter: TemporalFilter,
38    },
39    /// Velocity at a given timestamp.
40    Velocity {
41        /// Entity identifier.
42        entity_id: u64,
43        /// Timestamp to compute velocity at.
44        timestamp: i64,
45    },
46    /// Predict future vector state.
47    Prediction {
48        /// Entity identifier.
49        entity_id: u64,
50        /// Target timestamp for prediction.
51        target_timestamp: i64,
52    },
53    /// Detect change points in a time window.
54    ChangePointDetect {
55        /// Entity identifier.
56        entity_id: u64,
57        /// Start timestamp.
58        start: i64,
59        /// End timestamp.
60        end: i64,
61    },
62    /// Drift magnitude between two timestamps.
63    DriftQuant {
64        /// Entity identifier.
65        entity_id: u64,
66        /// Start timestamp.
67        t1: i64,
68        /// End timestamp.
69        t2: i64,
70        /// Number of top dimensions to report.
71        top_n: usize,
72    },
73    /// Temporal analogy: "entity A at t1 is to A at t2 as B at t3 is to ?"
74    Analogy {
75        /// Source entity.
76        entity_a: u64,
77        /// Source timestamp 1.
78        t1: i64,
79        /// Source timestamp 2.
80        t2: i64,
81        /// Target entity.
82        entity_b: u64,
83        /// Target timestamp.
84        t3: i64,
85    },
86    /// Counterfactual trajectory analysis.
87    Counterfactual {
88        /// Entity identifier.
89        entity_id: u64,
90        /// Change point timestamp.
91        change_point: i64,
92    },
93    /// Granger causality test between two entities.
94    GrangerCausality {
95        /// First entity (potential cause).
96        entity_a: u64,
97        /// Second entity (potential effect).
98        entity_b: u64,
99        /// Maximum lag to test.
100        max_lag: usize,
101        /// Significance threshold (e.g., 0.05).
102        significance: f64,
103    },
104    /// Discover recurring motifs in an entity's trajectory.
105    DiscoverMotifs {
106        /// Entity identifier.
107        entity_id: u64,
108        /// Subsequence window size (number of time steps).
109        window: usize,
110        /// Maximum number of motifs to return.
111        max_motifs: usize,
112    },
113    /// Discover anomalous subsequences (discords) in an entity's trajectory.
114    DiscoverDiscords {
115        /// Entity identifier.
116        entity_id: u64,
117        /// Subsequence window size (number of time steps).
118        window: usize,
119        /// Maximum number of discords to return.
120        max_discords: usize,
121    },
122    /// Temporal join: find convergence windows between two entities.
123    TemporalJoin {
124        /// First entity.
125        entity_a: u64,
126        /// Second entity.
127        entity_b: u64,
128        /// Distance threshold for convergence.
129        epsilon: f32,
130        /// Window size in microseconds.
131        window_us: i64,
132    },
133    /// Causal search: semantic kNN + temporal edge context (RFC-010).
134    CausalSearch {
135        /// Query vector.
136        vector: Vec<f32>,
137        /// Number of results.
138        k: usize,
139        /// Temporal filter.
140        filter: TemporalFilter,
141        /// Semantic vs temporal weight.
142        alpha: f32,
143        /// Reference timestamp.
144        query_timestamp: i64,
145        /// Steps of temporal context (forward and backward).
146        temporal_context: usize,
147    },
148    /// Cohort drift analysis across multiple entities.
149    CohortDrift {
150        /// Entity identifiers in the cohort.
151        entity_ids: Vec<u64>,
152        /// Start timestamp.
153        t1: i64,
154        /// End timestamp.
155        t2: i64,
156        /// Number of top dimensions to report.
157        top_n: usize,
158    },
159}
160
161/// Query result types.
162#[derive(Debug, Clone)]
163pub enum QueryResult {
164    /// kNN results with scores.
165    Knn(Vec<KnnResult>),
166    /// Trajectory points.
167    Trajectory(Vec<TemporalPoint>),
168    /// Velocity vector.
169    Velocity(Vec<f32>),
170    /// Predicted vector.
171    Prediction(PredictionResult),
172    /// Detected change points.
173    ChangePoints(Vec<ChangePoint>),
174    /// Drift report.
175    Drift(DriftResult),
176    /// Analogy result.
177    Analogy(Vec<f32>),
178    /// Counterfactual result.
179    Counterfactual(CounterfactualQueryResult),
180    /// Granger causality result.
181    Granger(GrangerCausalityResult),
182    /// Discovered motifs.
183    Motifs(Vec<MotifResult>),
184    /// Discovered discords.
185    Discords(Vec<DiscordResult>),
186    /// Temporal join results.
187    TemporalJoin(Vec<TemporalJoinResultEntry>),
188    /// Cohort drift report.
189    CohortDrift(CohortDriftResult),
190    /// Causal search results.
191    CausalSearch(Vec<CausalSearchResultEntry>),
192}
193
194/// A causal search result with temporal context.
195#[derive(Debug, Clone)]
196pub struct CausalSearchResultEntry {
197    /// Node ID.
198    pub node_id: u32,
199    /// Distance score.
200    pub score: f32,
201    /// Entity ID.
202    pub entity_id: u64,
203    /// Temporal successors: (node_id, timestamp).
204    pub successors: Vec<(u32, i64)>,
205    /// Temporal predecessors: (node_id, timestamp).
206    pub predecessors: Vec<(u32, i64)>,
207}
208
209/// A convergence window from a temporal join query.
210#[derive(Debug, Clone)]
211pub struct TemporalJoinResultEntry {
212    /// Start of the convergence window.
213    pub start: i64,
214    /// End of the convergence window.
215    pub end: i64,
216    /// Mean distance during convergence.
217    pub mean_distance: f32,
218    /// Minimum distance during convergence.
219    pub min_distance: f32,
220    /// Points from entity A in window.
221    pub points_a: usize,
222    /// Points from entity B in window.
223    pub points_b: usize,
224}
225
226/// Counterfactual analysis result for query layer.
227#[derive(Debug, Clone)]
228pub struct CounterfactualQueryResult {
229    /// Change point timestamp.
230    pub change_point: i64,
231    /// Total divergence (area under curve).
232    pub total_divergence: f64,
233    /// Timestamp of maximum divergence.
234    pub max_divergence_time: i64,
235    /// Maximum divergence value.
236    pub max_divergence_value: f32,
237    /// Divergence curve: `(timestamp, distance)`.
238    pub divergence_curve: Vec<(i64, f32)>,
239    /// Method used.
240    pub method: String,
241}
242
243/// Granger causality test result.
244#[derive(Debug, Clone)]
245pub struct GrangerCausalityResult {
246    /// Detected direction.
247    pub direction: String,
248    /// Optimal lag.
249    pub optimal_lag: usize,
250    /// F-statistic.
251    pub f_statistic: f64,
252    /// Combined p-value.
253    pub p_value: f64,
254    /// Effect size (partial R²).
255    pub effect_size: f64,
256    /// Per-dimension F-statistics for A→B.
257    pub per_dimension_a_to_b: Vec<f64>,
258    /// Per-dimension F-statistics for B→A.
259    pub per_dimension_b_to_a: Vec<f64>,
260}
261
262/// A discovered motif result.
263#[derive(Debug, Clone)]
264pub struct MotifResult {
265    /// Index of the canonical occurrence.
266    pub canonical_index: usize,
267    /// All occurrences with timestamps and distances.
268    pub occurrences: Vec<MotifOccurrenceResult>,
269    /// Detected period (None if aperiodic).
270    pub period: Option<usize>,
271    /// Mean match distance.
272    pub mean_match_distance: f32,
273}
274
275/// A single motif occurrence.
276#[derive(Debug, Clone)]
277pub struct MotifOccurrenceResult {
278    /// Start index in trajectory.
279    pub start_index: usize,
280    /// Timestamp.
281    pub timestamp: i64,
282    /// Distance to canonical.
283    pub distance: f32,
284}
285
286/// A discovered discord result.
287#[derive(Debug, Clone)]
288pub struct DiscordResult {
289    /// Start index in trajectory.
290    pub start_index: usize,
291    /// Timestamp.
292    pub timestamp: i64,
293    /// Nearest-neighbor distance (higher = more anomalous).
294    pub nn_distance: f32,
295}
296
297/// Cohort drift analysis result.
298#[derive(Debug, Clone)]
299pub struct CohortDriftResult {
300    /// Number of entities analyzed.
301    pub n_entities: usize,
302    /// Mean L2 drift across the cohort.
303    pub mean_drift_l2: f32,
304    /// Median L2 drift.
305    pub median_drift_l2: f32,
306    /// Standard deviation of drift magnitudes.
307    pub std_drift_l2: f32,
308    /// Centroid L2 drift magnitude.
309    pub centroid_l2_magnitude: f32,
310    /// Centroid cosine drift.
311    pub centroid_cosine_drift: f32,
312    /// Dispersion at t1.
313    pub dispersion_t1: f32,
314    /// Dispersion at t2.
315    pub dispersion_t2: f32,
316    /// Dispersion change (positive = diverging).
317    pub dispersion_change: f32,
318    /// Convergence score (0 = random, 1 = same direction).
319    pub convergence_score: f32,
320    /// Top changed dimensions: (index, absolute_change).
321    pub top_dimensions: Vec<(usize, f32)>,
322    /// Outlier entities.
323    pub outliers: Vec<CohortOutlierResult>,
324}
325
326/// An outlier entity in cohort drift analysis.
327#[derive(Debug, Clone)]
328pub struct CohortOutlierResult {
329    /// Entity identifier.
330    pub entity_id: u64,
331    /// Individual drift magnitude.
332    pub drift_magnitude: f32,
333    /// Z-score relative to cohort.
334    pub z_score: f32,
335    /// Alignment with cohort mean drift direction.
336    pub drift_direction_alignment: f32,
337}
338
339/// A single kNN result.
340#[derive(Debug, Clone)]
341pub struct KnnResult {
342    /// Entity identifier.
343    pub entity_id: u64,
344    /// Timestamp of the matched point.
345    pub timestamp: i64,
346    /// Combined spatiotemporal score.
347    pub score: f32,
348}
349
350/// Prediction result with confidence.
351#[derive(Debug, Clone)]
352pub struct PredictionResult {
353    /// Predicted vector.
354    pub vector: Vec<f32>,
355    /// Target timestamp.
356    pub timestamp: i64,
357    /// Prediction method used.
358    pub method: PredictionMethod,
359}
360
361/// Method used for prediction.
362#[derive(Debug, Clone, Copy)]
363pub enum PredictionMethod {
364    /// Linear extrapolation from last two points.
365    Linear,
366    /// Neural ODE integration.
367    NeuralOde,
368}
369
370/// Drift quantification result.
371#[derive(Debug, Clone)]
372pub struct DriftResult {
373    /// L2 drift magnitude.
374    pub l2_magnitude: f32,
375    /// Cosine drift.
376    pub cosine_drift: f32,
377    /// Top changed dimensions: (index, absolute_change).
378    pub top_dimensions: Vec<(usize, f32)>,
379}