Skip to main content

motif_rs/
lib.rs

1pub mod algorithms;
2pub mod core;
3pub mod metrics;
4
5pub use crate::algorithms::ab_join::ab_join;
6pub use crate::algorithms::chains::{allc, atsc, Chain, ChainsResult};
7pub use crate::algorithms::fluss::{fluss, Floss, SegmentationResult};
8pub use crate::algorithms::mass::{find_matches, mass, Match};
9pub use crate::algorithms::mdl::mdl;
10pub use crate::algorithms::mmotifs::{mmotifs, MultiDimensionalMotif};
11pub use crate::algorithms::motifs::{find_discords, find_motifs, Discord, Motif};
12pub use crate::algorithms::mpdist::{mpdist, mpdist_pnorm};
13pub use crate::algorithms::mstump::{mstump, MultiDimensionalProfile};
14pub use crate::algorithms::ostinato::{ostinato, ConsensusMotif};
15pub use crate::algorithms::pnorm::{ab_join_pnorm, stomp_pnorm};
16pub use crate::algorithms::scrump::scrump;
17pub use crate::algorithms::snippets::{find_snippets, SnippetsResult};
18pub use crate::algorithms::stimp::{stimp, PanMatrixProfile};
19pub use crate::algorithms::subspace::subspace;
20pub use crate::algorithms::topk::TopKMatrixProfile;
21pub use crate::core::distance_metric::DistanceMetric;
22pub use crate::core::matrix_profile::{
23    JoinProfile, MatrixProfile, MatrixProfileConfig, RollingStats, DEFAULT_SIGMA_THRESHOLD,
24};
25pub use crate::metrics::absolute::AbsoluteEuclidean;
26pub use crate::metrics::euclidean::ZNormalizedEuclidean;
27
28use crate::algorithms::stampi::Stampi;
29use crate::algorithms::stomp::stomp;
30
31/// High-level facade for matrix profile computation, generic over distance metric.
32///
33/// # Examples
34///
35/// ```
36/// use motif_rs::{EuclideanEngine, MatrixProfileConfig};
37///
38/// let ts = vec![1.0, 2.0, 3.0, 2.0, 1.0, 2.0, 3.0, 2.0, 1.0];
39/// let engine = EuclideanEngine::new(MatrixProfileConfig::new(4));
40/// let mp = engine.compute(&ts);
41/// assert_eq!(mp.profile.len(), ts.len() - 4 + 1);
42/// ```
43pub struct Engine<M: DistanceMetric> {
44    config: MatrixProfileConfig,
45    _metric: std::marker::PhantomData<M>,
46}
47
48impl<M: DistanceMetric> Engine<M> {
49    /// Create a new engine with the given configuration.
50    pub fn new(config: MatrixProfileConfig) -> Self {
51        Self {
52            config,
53            _metric: std::marker::PhantomData,
54        }
55    }
56
57    /// Compute the full matrix profile for a time series (batch STOMP).
58    pub fn compute(&self, ts: &[f64]) -> MatrixProfile {
59        stomp::<M>(ts, &self.config)
60    }
61
62    /// Create a streaming matrix profile from an initial time series.
63    ///
64    /// - `egress=false`: grow mode — time series extends unboundedly.
65    /// - `egress=true`: egress mode — fixed-size sliding window.
66    pub fn streaming(&self, initial_ts: &[f64], egress: bool) -> Stampi<M> {
67        Stampi::<M>::new(initial_ts, self.config.clone(), egress)
68    }
69
70    /// Compute the AB-join between two time series.
71    ///
72    /// Returns two `JoinProfile`s: one for each series against the other.
73    pub fn ab_join(&self, ts_a: &[f64], ts_b: &[f64]) -> (JoinProfile, JoinProfile) {
74        crate::algorithms::ab_join::ab_join::<M>(ts_a, ts_b, self.config.m)
75    }
76
77    /// Compute the top-k matrix profile for a time series.
78    ///
79    /// Stores the k nearest neighbors for each subsequence, rather than just the best one.
80    pub fn compute_topk(&self, ts: &[f64], k: usize) -> TopKMatrixProfile {
81        crate::algorithms::topk::stomp_topk::<M>(ts, &self.config, k)
82    }
83
84    /// Extract `k` representative snippets that best summarize the time series.
85    ///
86    /// Uses z-normalized Euclidean distance profiles regardless of the engine's metric.
87    pub fn snippets(&self, ts: &[f64], k: usize) -> SnippetsResult {
88        crate::algorithms::snippets::find_snippets(ts, self.config.m, k)
89    }
90
91    /// Compute MPdist: a scalar distance between two time series.
92    ///
93    /// Based on the k-th percentile of the concatenated AB-join profiles.
94    pub fn mpdist(&self, ts_a: &[f64], ts_b: &[f64], percentage: Option<f64>) -> f64 {
95        crate::algorithms::mpdist::mpdist::<M>(ts_a, ts_b, self.config.m, percentage)
96    }
97
98    /// Compute an approximate matrix profile using SCRUMP/PreSCRIMP.
99    ///
100    /// `percentage` in (0.0, 1.0] controls the fraction of diagonals sampled.
101    /// At 1.0, delegates to exact STOMP.
102    pub fn scrump(&self, ts: &[f64], percentage: f64) -> MatrixProfile {
103        crate::algorithms::scrump::scrump::<M>(ts, &self.config, percentage)
104    }
105
106    /// Find the consensus motif across multiple time series.
107    ///
108    /// Returns the subsequence (from any series) whose maximum nearest-neighbor
109    /// distance to all other series is minimized.
110    pub fn ostinato(&self, ts_list: &[&[f64]]) -> ConsensusMotif {
111        crate::algorithms::ostinato::ostinato::<M>(ts_list, self.config.m)
112    }
113
114    /// Compute the pan matrix profile across a range of window sizes.
115    ///
116    /// Profiles are normalized by `1/sqrt(2*m)` for cross-window comparability.
117    pub fn stimp(
118        &self,
119        ts: &[f64],
120        min_m: usize,
121        max_m: usize,
122        step: Option<usize>,
123        percentage: Option<f64>,
124    ) -> PanMatrixProfile {
125        crate::algorithms::stimp::stimp::<M>(ts, min_m, max_m, step, percentage)
126    }
127
128    /// Compute the matrix profile using Minkowski p-norm distance.
129    ///
130    /// For `p == 2.0`, delegates to the optimized AAMP path.
131    /// For other values of `p`, uses a diagonal recurrence.
132    /// This is AAMP-only (non-normalized); the engine's metric type `M` is ignored.
133    pub fn compute_pnorm(&self, ts: &[f64], p: f64) -> MatrixProfile {
134        crate::algorithms::pnorm::stomp_pnorm(ts, &self.config, p)
135    }
136
137    /// Compute the AB-join between two time series using Minkowski p-norm distance.
138    ///
139    /// Returns two `JoinProfile`s, one for each series.
140    /// This is AAMP-only (non-normalized); the engine's metric type `M` is ignored.
141    pub fn ab_join_pnorm(&self, ts_a: &[f64], ts_b: &[f64], p: f64) -> (JoinProfile, JoinProfile) {
142        crate::algorithms::pnorm::ab_join_pnorm(ts_a, ts_b, self.config.m, p)
143    }
144
145    /// Compute MPdist using Minkowski p-norm distance.
146    ///
147    /// This is AAMP-only (non-normalized); the engine's metric type `M` is ignored.
148    pub fn mpdist_pnorm(&self, ts_a: &[f64], ts_b: &[f64], p: f64, percentage: Option<f64>) -> f64 {
149        crate::algorithms::mpdist::mpdist_pnorm(ts_a, ts_b, self.config.m, p, percentage)
150    }
151}
152
153/// Convenience type alias for the most common use case.
154pub type EuclideanEngine = Engine<ZNormalizedEuclidean>;
155
156/// Convenience type alias for non-normalized (absolute) Euclidean distance.
157pub type AampEngine = Engine<AbsoluteEuclidean>;