Skip to main content

egobox_moe/
types.rs

1use crate::gaussian_mixture::GaussianMixture;
2use crate::{FullGpSurrogate, GpSurrogate, GpSurrogateExt, IaeAlphaPlotData};
3use bitflags::bitflags;
4#[allow(unused_imports)]
5use egobox_gp::correlation_models::{
6    AbsoluteExponentialCorr, Matern32Corr, Matern52Corr, SquaredExponentialCorr,
7};
8#[allow(unused_imports)]
9use egobox_gp::mean_models::{ConstantMean, LinearMean, QuadraticMean};
10use linfa::Float;
11use ndarray::{Array1, Array2};
12use std::fmt::Display;
13
14#[cfg(feature = "serializable")]
15use serde::{Deserialize, Serialize};
16
17/// Enumeration of recombination modes handled by the mixture
18#[derive(Clone, Copy, PartialEq, Eq, Debug)]
19#[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
20pub enum Recombination<F: Float> {
21    /// prediction is taken from the expert with highest responsability
22    /// resulting in a model with discontinuities
23    Hard,
24    /// Prediction is a combination experts prediction wrt their responsabilities,
25    /// an optional heaviside factor might be used control steepness of the change between
26    /// experts regions.
27    Smooth(Option<F>),
28}
29
30impl<F: Float> Display for Recombination<F> {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        let recomb = match self {
33            Recombination::Hard => "Hard".to_string(),
34            Recombination::Smooth(Some(f)) => format!("Smooth({f})"),
35            Recombination::Smooth(None) => "Smooth".to_string(),
36        };
37        write!(f, "Mixture[{}]", &recomb)
38    }
39}
40
41bitflags! {
42    /// Flags to specify tested regression models during experts selection (see [`regression_spec()`](egobox_moe::GpMixtureParams::regression_spec)).
43    ///
44    /// Flags can be combine with bit-wise `or` operator to select two or more models.
45    /// ```ignore
46    /// let spec = RegressionSpec::CONSTANT | RegressionSpec::LINEAR;
47    /// ```
48    ///
49    /// See [bitflags::bitflags]
50    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
51    #[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
52    pub struct RegressionSpec: u8 {
53        /// Constant regression
54        const CONSTANT = 0x01;
55        /// Linear regression
56        const LINEAR = 0x02;
57        /// 2-degree polynomial regression
58        const QUADRATIC = 0x04;
59        /// All regression models available
60        const ALL = RegressionSpec::CONSTANT.bits()
61                    | RegressionSpec::LINEAR.bits()
62                    | RegressionSpec::QUADRATIC.bits();
63    }
64}
65
66bitflags! {
67    /// Flags to specify tested correlation models during experts selection (see [`correlation_spec()`](egobox_moe::GpMixtureParams::correlation_spec)).
68    ///
69    /// Flags can be combine with bit-wise `or` operator to select two or more models.
70    /// ```ignore
71    /// let spec = CorrelationSpec::MATERN32 | CorrelationSpec::Matern52;
72    /// ```
73    ///
74    /// See [bitflags::bitflags]
75    #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
76    #[cfg_attr(feature = "serializable", derive(Serialize, Deserialize), serde(transparent))]
77    pub struct CorrelationSpec: u8 {
78        /// Squared exponential correlation model
79        const SQUAREDEXPONENTIAL = 0x01;
80        /// Absolute exponential correlation model
81        const ABSOLUTEEXPONENTIAL = 0x02;
82        /// Matern 3/2 correlation model
83        const MATERN32 = 0x04;
84        /// Matern 5/2 correlation model
85        const MATERN52 = 0x08;
86        /// All correlation models available
87        const ALL = CorrelationSpec::SQUAREDEXPONENTIAL.bits()
88                    | CorrelationSpec::ABSOLUTEEXPONENTIAL.bits()
89                    | CorrelationSpec::MATERN32.bits()
90                    | CorrelationSpec::MATERN52.bits();
91    }
92}
93
94/// A trait to represent clustered structure
95pub trait Clustered {
96    /// Number of clusters
97    fn n_clusters(&self) -> usize;
98    /// Recombination mode between the clusters
99    fn recombination(&self) -> Recombination<f64>;
100    /// Get clustering structure
101    fn to_clustering(&self) -> Clustering;
102}
103
104/// A structure for clustering
105#[derive(Clone, Debug)]
106#[cfg_attr(feature = "serializable", derive(Serialize, Deserialize))]
107pub struct Clustering {
108    /// Recombination between the clusters
109    pub(crate) recombination: Recombination<f64>,
110    /// Clusters
111    pub(crate) gmx: GaussianMixture<f64>,
112}
113
114impl Clustering {
115    /// Constructor
116    pub fn new(gmx: GaussianMixture<f64>, recombination: Recombination<f64>) -> Self {
117        Clustering { gmx, recombination }
118    }
119
120    /// Recombination mode between the clusters
121    pub fn recombination(&self) -> Recombination<f64> {
122        self.recombination
123    }
124
125    /// Get clustering Gaussian Mixture structure
126    pub fn gmx(&self) -> &GaussianMixture<f64> {
127        &self.gmx
128    }
129}
130
131/// Enum of available metrics for Gaussian Process quality assessment
132#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
133pub enum GpMetric {
134    /// Coefficient of determination
135    Q2,
136    /// Predictive Variance Adequacy
137    Pva,
138    /// Integrated Absolute Error on alpha
139    IAEAlpha,
140    /// Integrated Absolute Error on alpha with plot data
141    IAEAlphaWithPlot,
142}
143
144/// Result of a GP quality assessment metric
145#[derive(Clone, Debug)]
146pub struct GpMetricResult {
147    /// Metric used
148    pub metric: GpMetric,
149    /// Metric value
150    pub value: f64,
151    /// Optional plot data for IAEAlphaWithPlot
152    pub plot_data: Option<IaeAlphaPlotData>,
153}
154
155/// A trait for GP surrogate quality assessment
156#[cfg_attr(feature = "serializable", typetag::serde(tag = "type_gpqa"))]
157pub trait GpQualityAssurance {
158    /// Return the training data (xt, yt)
159    fn training_data(&self) -> &(Array2<f64>, Array1<f64>);
160
161    /// Evaluate a given metric with k-fold cross validation
162    fn score(&self, metric: GpMetric, kfold: usize) -> GpMetricResult {
163        match metric {
164            GpMetric::Q2 => GpMetricResult {
165                metric: GpMetric::Q2,
166                value: self.q2_k(kfold),
167                plot_data: None,
168            },
169            GpMetric::Pva => GpMetricResult {
170                metric: GpMetric::Pva,
171                value: self.pva_k(kfold),
172                plot_data: None,
173            },
174            GpMetric::IAEAlpha => GpMetricResult {
175                metric: GpMetric::IAEAlpha,
176                value: self.iae_alpha_k(kfold),
177                plot_data: None,
178            },
179            GpMetric::IAEAlphaWithPlot => {
180                let mut plot_data = IaeAlphaPlotData::default();
181                let value = self.iae_alpha_k_score_with_plot(kfold, &mut plot_data);
182                GpMetricResult {
183                    metric: GpMetric::IAEAlphaWithPlot,
184                    value,
185                    plot_data: Some(plot_data),
186                }
187            }
188        }
189    }
190
191    /// Evaluate Q2 metric with k-fold cross validation
192    fn q2_k(&self, kfold: usize) -> f64;
193    /// Evaluate Q2 metric with Leave-One-Out cross validation
194    fn q2(&self) -> f64;
195
196    /// Evaluate PVA metric with k-fold cross validation    
197    fn pva_k(&self, kfold: usize) -> f64;
198    /// Evaluate PVA metric with Leave-One-Out cross validation
199    fn pva(&self) -> f64;
200
201    /// Evaluate IAEAlpha metric with k-fold cross validation
202    fn iae_alpha_k(&self, kfold: usize) -> f64;
203    /// Evaluate IAEAlpha metric with Leave-One-Out cross validation
204    fn iae_alpha_k_score_with_plot(&self, kfold: usize, plot_data: &mut IaeAlphaPlotData) -> f64;
205    /// Evaluate IAEAlpha metric with Leave-One-Out cross validation
206    fn iae_alpha(&self) -> f64;
207}
208
209/// A trait for Mixture of GP surrogates with derivatives using clustering
210#[cfg_attr(feature = "serializable", typetag::serde(tag = "type_mixture"))]
211pub trait MixtureGpSurrogate:
212    Clustered + GpSurrogate + GpSurrogateExt + GpQualityAssurance + Display
213{
214    /// Get model experts
215    fn experts(&self) -> &Vec<Box<dyn FullGpSurrogate>>;
216}
217
218#[derive(Default, Debug)]
219/// An enumeration of Gpx available file format
220pub enum GpFileFormat {
221    /// Human readable format
222    #[default]
223    Json,
224    /// Binary format
225    Binary,
226}