fdars_core/frechet/mod.rs
1//! Fréchet / object-data regression and statistics (FRE-01).
2//!
3//! Metric-space (object-data) regression and statistics in the style of the R
4//! `frechet` package: a [`MetricSpace`] abstraction (distance + weighted-Fréchet-
5//! mean solver) with a 1D-Wasserstein (density-response) backend
6//! ([`WassersteinDensitySpace`]) as the first concrete space, the sample Fréchet
7//! [`frechet_mean`] / [`frechet_variance`], the 1D 2-Wasserstein distance
8//! ([`wasserstein2_distance`]), global and local (kernel-weighted) Fréchet
9//! regression over Euclidean predictors, density-response regression, and a
10//! Fréchet ANOVA group-difference test.
11//!
12//! # R baselines
13//!
14//! * Global / local Fréchet regression — `frechet::GloWassReg` / `LocWassReg`
15//! (Petersen & Müller 2019, *Annals of Statistics* 47(2)).
16//! * Fréchet ANOVA — `frechet::DenANOVA` (Dubey & Müller 2019, *Biometrika* 106(4)).
17//!
18//! # Reuse & conventions
19//!
20//! The density backend reuses DENS-01's quantile/Wasserstein machinery
21//! ([`crate::density_fda`]) rather than re-deriving it. All public functions
22//! return `Result<_, FdarError>` and validate inputs at entry (never panic).
23//! Any permutation path uses per-thread seeded RNG
24//! (`StdRng::seed_from_u64(seed + k)`) with a default of 999 replications. Result
25//! structs derive `Debug, Clone, PartialEq` and are serde-gated.
26//!
27//! # Divergence
28//!
29//! Global/local Fréchet regression weights can be negative; where R uses an
30//! `osqp` quadratic program to enforce a monotone predicted quantile, this crate
31//! uses a zero-dependency sort-based isotonic projection (see the regression
32//! submodule).
33
34mod anova;
35mod mean;
36mod regression;
37mod space;
38mod spaces;
39
40pub use anova::{frechet_anova, frechet_anova_space};
41pub use mean::{frechet_mean, frechet_variance};
42pub use regression::{
43 frechet_global_reg, frechet_global_reg_space, frechet_local_reg, frechet_local_reg_space,
44};
45pub use space::{wasserstein2_distance, MetricSpace, WassersteinDensitySpace};
46pub use spaces::{
47 CorrelationMatrixSpace, NetworkSpace, PointProcessSpace, SpdMatrixSpace, SpdMetric,
48 SphericalSpace,
49};
50
51use crate::matrix::FdMatrix;
52
53/// Result of global Fréchet regression ([`frechet_global_reg`]).
54///
55/// Predicts a conditional Fréchet-mean density response at each `xout` row via the
56/// Petersen–Müller global linear weight scheme.
57#[derive(Debug, Clone, PartialEq)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59#[non_exhaustive]
60pub struct FrechetGlobalRegResult {
61 /// Predicted density responses, shape n_out × m (row i = prediction at `xout` row i).
62 pub predicted: FdMatrix,
63 /// The predictor values predictions were made at, shape n_out × p.
64 pub xout: FdMatrix,
65 /// Column means of the training predictors, length p.
66 pub x_bar: Vec<f64>,
67}
68
69/// Result of local (local-linear, kernel-weighted) Fréchet regression
70/// ([`frechet_local_reg`]).
71#[derive(Debug, Clone, PartialEq)]
72#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
73#[non_exhaustive]
74pub struct FrechetLocalRegResult {
75 /// Predicted density responses, shape n_out × m.
76 pub predicted: FdMatrix,
77 /// The predictor values predictions were made at, shape n_out × p.
78 pub xout: FdMatrix,
79 /// The kernel bandwidth used.
80 pub bandwidth: f64,
81}
82
83/// Result of a Fréchet ANOVA group-difference test ([`frechet_anova`]).
84///
85/// The Dubey–Müller `Tₙ` statistic with a primary seeded permutation p-value and
86/// a secondary asymptotic χ²(k−1) p-value.
87#[derive(Debug, Clone, PartialEq)]
88#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89#[non_exhaustive]
90pub struct FrechetAnovaResult {
91 /// Dubey–Müller `Tₙ` test statistic.
92 pub statistic: f64,
93 /// Asymptotic χ²(k−1) p-value (secondary inference).
94 pub p_value_asymptotic: f64,
95 /// Seeded-permutation p-value (primary reported inference).
96 pub p_value_permutation: f64,
97 /// Number of permutations used.
98 pub n_perm: usize,
99 /// Per-group Fréchet variances V̂ₗ (length k).
100 pub group_frechet_variances: Vec<f64>,
101 /// Pooled Fréchet variance V̂ₚ.
102 pub pooled_frechet_variance: f64,
103 /// The Fₙ variance-contrast component.
104 pub fn_statistic: f64,
105 /// The Uₙ pairwise-dispersion component.
106 pub un_statistic: f64,
107 /// The group labels used (contiguous 0..k).
108 pub group_labels: Vec<usize>,
109}