use scirs2_core::numeric::{Float, FromPrimitive};
use std::collections::HashMap;
use super::types::{ARFittingMethod, AdaptiveSelectionCriterion, EnsembleCombinationStrategy};
#[derive(Debug, Clone)]
pub struct ExtrapolationParameters<T: Float> {
pub exponential_rate: T,
pub exponential_offset: T,
pub power_exponent: T,
pub power_scale: T,
pub period: T,
}
impl<T: Float> Default for ExtrapolationParameters<T> {
fn default() -> Self {
Self {
exponential_rate: T::one(),
exponential_offset: T::zero(),
power_exponent: -T::one(), power_scale: T::one(),
period: T::from(2.0 * std::f64::consts::PI).expect("Operation failed"),
}
}
}
impl<T: Float> ExtrapolationParameters<T> {
pub fn new() -> Self {
Self::default()
}
pub fn with_exponential_rate(mut self, rate: T) -> Self {
self.exponential_rate = rate;
self
}
pub fn with_exponential_offset(mut self, offset: T) -> Self {
self.exponential_offset = offset;
self
}
pub fn with_power_exponent(mut self, exponent: T) -> Self {
self.power_exponent = exponent;
self
}
pub fn with_power_scale(mut self, scale: T) -> Self {
self.power_scale = scale;
self
}
pub fn with_period(mut self, period: T) -> Self {
self.period = period;
self
}
}
#[derive(Debug, Clone)]
pub struct ConfidenceExtrapolationConfig<T: Float> {
pub bootstrap_samples: usize,
pub confidence_level: T,
pub max_extrapolation_ratio: T,
pub bias_correction: bool,
}
impl<T: Float> Default for ConfidenceExtrapolationConfig<T> {
fn default() -> Self {
Self {
bootstrap_samples: 1000,
confidence_level: T::from(0.95).expect("Operation failed"),
max_extrapolation_ratio: T::from(0.5).expect("Operation failed"),
bias_correction: true,
}
}
}
#[derive(Debug, Clone)]
pub struct ConfidenceExtrapolationResult<T: Float> {
pub value: T,
pub lower_bound: T,
pub upper_bound: T,
pub confidence_level: T,
}
#[derive(Debug, Clone)]
pub struct EnsembleExtrapolationConfig<T: Float> {
pub methods: Vec<super::types::ExtrapolationMethod>,
pub combination_strategy: EnsembleCombinationStrategy,
pub weights: Option<Vec<T>>,
pub include_confidence: bool,
}
impl<T: Float> Default for EnsembleExtrapolationConfig<T> {
fn default() -> Self {
Self {
methods: vec![
super::types::ExtrapolationMethod::Linear,
super::types::ExtrapolationMethod::Quadratic,
super::types::ExtrapolationMethod::Cubic,
],
combination_strategy: EnsembleCombinationStrategy::Mean,
weights: None,
include_confidence: true,
}
}
}
#[derive(Debug, Clone)]
pub struct AdaptiveExtrapolationConfig {
pub selection_criterion: AdaptiveSelectionCriterion,
pub local_window_size: usize,
pub minimum_confidence: f64,
pub cache_selections: bool,
}
impl Default for AdaptiveExtrapolationConfig {
fn default() -> Self {
Self {
selection_criterion: AdaptiveSelectionCriterion::CrossValidationError,
local_window_size: 10,
minimum_confidence: 0.5,
cache_selections: true,
}
}
}
#[derive(Debug, Clone)]
pub struct AutoregressiveExtrapolationConfig<T: Float> {
pub ar_order: usize,
pub fitting_method: ARFittingMethod,
pub max_steps: usize,
pub trend_adjustment: bool,
pub regularization: T,
}
impl<T: Float> Default for AutoregressiveExtrapolationConfig<T> {
fn default() -> Self {
Self {
ar_order: 3,
fitting_method: ARFittingMethod::YuleWalker,
max_steps: 100,
trend_adjustment: true,
regularization: T::from(1e-6).unwrap_or(T::zero()),
}
}
}
#[derive(Debug, Clone)]
pub struct ExtrapolationConfigBuilder<T: Float> {
pub parameters: ExtrapolationParameters<T>,
pub confidence_config: Option<ConfidenceExtrapolationConfig<T>>,
pub ensemble_config: Option<EnsembleExtrapolationConfig<T>>,
pub adaptive_config: Option<AdaptiveExtrapolationConfig>,
pub ar_config: Option<AutoregressiveExtrapolationConfig<T>>,
pub custom_parameters: HashMap<String, T>,
}
impl<T: Float> Default for ExtrapolationConfigBuilder<T> {
fn default() -> Self {
Self {
parameters: ExtrapolationParameters::default(),
confidence_config: None,
ensemble_config: None,
adaptive_config: None,
ar_config: None,
custom_parameters: HashMap::new(),
}
}
}
impl<T: Float> ExtrapolationConfigBuilder<T> {
pub fn new() -> Self {
Self::default()
}
pub fn with_parameters(mut self, parameters: ExtrapolationParameters<T>) -> Self {
self.parameters = parameters;
self
}
pub fn with_confidence(mut self, config: ConfidenceExtrapolationConfig<T>) -> Self {
self.confidence_config = Some(config);
self
}
pub fn with_ensemble(mut self, config: EnsembleExtrapolationConfig<T>) -> Self {
self.ensemble_config = Some(config);
self
}
pub fn with_adaptive(mut self, config: AdaptiveExtrapolationConfig) -> Self {
self.adaptive_config = Some(config);
self
}
pub fn with_autoregressive(mut self, config: AutoregressiveExtrapolationConfig<T>) -> Self {
self.ar_config = Some(config);
self
}
pub fn with_custom_parameter(mut self, name: String, value: T) -> Self {
self.custom_parameters.insert(name, value);
self
}
pub fn build(self) -> ExtrapolationConfig<T> {
ExtrapolationConfig {
parameters: self.parameters,
confidence_config: self.confidence_config,
ensemble_config: self.ensemble_config,
adaptive_config: self.adaptive_config,
ar_config: self.ar_config,
custom_parameters: self.custom_parameters,
}
}
}
#[derive(Debug, Clone)]
pub struct ExtrapolationConfig<T: Float> {
pub parameters: ExtrapolationParameters<T>,
pub confidence_config: Option<ConfidenceExtrapolationConfig<T>>,
pub ensemble_config: Option<EnsembleExtrapolationConfig<T>>,
pub adaptive_config: Option<AdaptiveExtrapolationConfig>,
pub ar_config: Option<AutoregressiveExtrapolationConfig<T>>,
pub custom_parameters: HashMap<String, T>,
}
impl<T: Float> Default for ExtrapolationConfig<T> {
fn default() -> Self {
Self {
parameters: ExtrapolationParameters::default(),
confidence_config: None,
ensemble_config: None,
adaptive_config: None,
ar_config: None,
custom_parameters: HashMap::new(),
}
}
}
impl<T: Float> ExtrapolationConfig<T> {
pub fn new() -> Self {
Self::default()
}
pub fn builder() -> ExtrapolationConfigBuilder<T> {
ExtrapolationConfigBuilder::new()
}
pub fn has_confidence(&self) -> bool {
self.confidence_config.is_some()
}
pub fn has_ensemble(&self) -> bool {
self.ensemble_config.is_some()
}
pub fn has_adaptive(&self) -> bool {
self.adaptive_config.is_some()
}
pub fn has_autoregressive(&self) -> bool {
self.ar_config.is_some()
}
pub fn get_custom_parameter(&self, name: &str) -> Option<&T> {
self.custom_parameters.get(name)
}
}