use crate::error::StatsResult;
use scirs2_core::ndarray::{Array1, Array2, Array3, ArrayView2};
use scirs2_core::numeric::{Float, NumCast, One, Zero};
use scirs2_core::{simd_ops::SimdUnifiedOps, validation::*};
use std::collections::HashMap;
use std::marker::PhantomData;
pub struct AdvancedMultivariateAnalysis<F> {
config: AdvancedMultivariateConfig<F>,
models: HashMap<String, MultivariateModel<F>>,
performance: PerformanceMetrics,
_phantom: PhantomData<F>,
}
#[derive(Debug, Clone)]
pub struct AdvancedMultivariateConfig<F> {
pub methods: Vec<DimensionalityReductionMethod<F>>,
pub manifold_config: ManifoldConfig<F>,
pub tensor_config: TensorConfig<F>,
pub clustering_config: ClusteringConfig<F>,
pub multiview_config: MultiViewConfig<F>,
pub optimization: OptimizationConfig,
pub validation: ValidationConfig<F>,
}
#[derive(Debug, Clone)]
pub enum DimensionalityReductionMethod<F> {
AdvancedPCA {
algorithm: PCAVariant,
n_components: usize,
regularization: Option<F>,
},
ICA {
_algorithm: ICAAlgorithm,
n_components: usize,
_max_iter: usize,
tolerance: F,
},
NMF {
n_components: usize,
regularization: F,
max_iter: usize,
},
TSNE {
n_components: usize,
perplexity: F,
early_exaggeration: F,
learning_rate: F,
max_iter: usize,
},
UMAP {
n_components: usize,
n_neighbors: usize,
min_dist: F,
spread: F,
},
DiffusionMaps {
n_components: usize,
sigma: F,
alpha: F,
},
Autoencoder {
layers: Vec<usize>,
activation: ActivationFunction,
regularization: F,
},
VariationalAutoencoder {
latent_dim: usize,
encoder_layers: Vec<usize>,
decoder_layers: Vec<usize>,
},
}
#[derive(Debug, Clone, Copy)]
pub enum PCAVariant {
Standard,
Robust,
Sparse,
Kernel,
Probabilistic,
Bayesian,
}
#[derive(Debug, Clone, Copy)]
pub enum ICAAlgorithm {
FastICA,
InfoMax,
JADE,
ExtendedInfoMax,
}
#[derive(Debug, Clone, Copy)]
pub enum ActivationFunction {
ReLU,
Sigmoid,
Tanh,
LeakyReLU,
ELU,
Swish,
}
#[derive(Debug, Clone)]
pub struct ManifoldConfig<F> {
pub estimate_intrinsic_dim: bool,
pub neighborhoodsize: usize,
pub distance_metric: DistanceMetric,
pub regularization: F,
pub adaptive_neighborhoods: bool,
}
#[derive(Debug, Clone, Copy)]
pub enum DistanceMetric {
Euclidean,
Manhattan,
Cosine,
Correlation,
Geodesic,
DiffusionDistance,
}
#[derive(Debug, Clone)]
pub struct TensorConfig<F> {
pub decomposition_methods: Vec<TensorDecomposition<F>>,
pub estimate_rank: bool,
pub max_rank: usize,
pub tolerance: F,
pub max_iter: usize,
}
#[derive(Debug, Clone)]
pub enum TensorDecomposition<F> {
CP {
rank: usize,
regularization: Option<F>,
},
Tucker { core_dims: Vec<usize> },
TensorPCA { n_components: usize },
HOSVD { truncation_dims: Vec<usize> },
TensorTrain { max_rank: usize },
}
#[derive(Debug, Clone)]
pub struct ClusteringConfig<F> {
pub algorithms: Vec<ClusteringAlgorithm<F>>,
pub n_clusters: Option<usize>,
pub validation_metrics: Vec<ClusterValidationMetric>,
pub density_estimation: bool,
}
#[derive(Debug, Clone)]
pub enum ClusteringAlgorithm<F> {
AdaptiveDBSCAN { min_samples_: usize, xi: F },
EnhancedHierarchical {
linkage: LinkageCriterion,
distance_threshold: Option<F>,
},
SpectralClustering {
n_clusters: usize,
kernel: KernelType<F>,
gamma: F,
},
GaussianMixture {
n_components: usize,
covariance_type: CovarianceType,
regularization: F,
},
MeanShift { bandwidth: Option<F>, quantile: F },
AffinityPropagation { damping: F, preference: Option<F> },
}
#[derive(Debug, Clone, Copy)]
pub enum LinkageCriterion {
Ward,
Complete,
Average,
Single,
WeightedAverage,
}
#[derive(Debug, Clone)]
pub enum KernelType<F> {
RBF { gamma: F },
Linear,
Polynomial { degree: usize, gamma: F },
Sigmoid { gamma: F, coef0: F },
Precomputed,
}
#[derive(Debug, Clone, Copy)]
pub enum CovarianceType {
Full,
Tied,
Diag,
Spherical,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ClusterValidationMetric {
SilhouetteScore,
CalinskiHarabasz,
DaviesBouldin,
AdjustedRandIndex,
NormalizedMutualInfo,
VMeasure,
}
#[derive(Debug, Clone)]
pub struct MultiViewConfig<F> {
pub methods: Vec<MultiViewMethod<F>>,
pub fusion_strategy: ViewFusionStrategy,
pub regularization: HashMap<String, F>,
}
#[derive(Debug, Clone)]
pub enum MultiViewMethod<F> {
MultiViewCCA {
n_components: usize,
regularization: F,
},
MultiViewPCA {
n_components: usize,
view_weights: Option<Array1<F>>,
},
CoTraining {
base_learner: String,
confidence_threshold: F,
},
MultiViewSpectral {
n_clusters: usize,
view_weights: Option<Array1<F>>,
},
}
#[derive(Debug, Clone, Copy)]
pub enum ViewFusionStrategy {
Early,
Late,
Intermediate,
Adaptive,
}
#[derive(Debug, Clone)]
pub struct OptimizationConfig {
pub use_simd: bool,
pub use_parallel: bool,
pub use_gpu: bool,
pub memory_strategy: MemoryStrategy,
pub precision: f64,
}
#[derive(Debug, Clone, Copy)]
pub enum MemoryStrategy {
Conservative,
Balanced,
Aggressive,
Streaming,
}
#[derive(Debug, Clone)]
pub struct ValidationConfig<F> {
pub cv_folds: usize,
pub metrics: Vec<ValidationMetric>,
pub bootstrap_samples: Option<usize>,
pub stability_analysis: bool,
pub alpha: F,
}
#[derive(Debug, Clone, Copy)]
pub enum ValidationMetric {
ReconstructionError,
ExplainedVariance,
Stability,
Trustworthiness,
Continuity,
NeighborhoodPreservation,
}
#[derive(Debug, Clone)]
pub enum MultivariateModel<F> {
PCA(PCAModel<F>),
ICA(ICAModel<F>),
TSNE(TSNEModel<F>),
UMAP(UMAPModel<F>),
Tensor(TensorModel<F>),
Manifold(ManifoldModel<F>),
Clustering(ClusteringModel<F>),
MultiView(MultiViewModel<F>),
}
#[derive(Debug, Clone)]
pub struct PCAModel<F> {
pub components: Array2<F>,
pub explained_variance: Array1<F>,
pub explained_variance_ratio: Array1<F>,
pub singular_values: Array1<F>,
pub mean: Array1<F>,
pub noise_variance: Option<F>,
}
#[derive(Debug, Clone)]
pub struct ICAModel<F> {
pub components: Array2<F>,
pub mixing_matrix: Array2<F>,
pub sources: Array2<F>,
pub mean: Array1<F>,
pub convergence_info: ConvergenceInfo<F>,
}
#[derive(Debug, Clone)]
pub struct TSNEModel<F> {
pub embedding: Array2<F>,
pub kl_divergence: F,
pub iterations: usize,
pub perplexity: F,
}
#[derive(Debug, Clone)]
pub struct UMAPModel<F> {
pub embedding: Array2<F>,
pub graph: SparseGraph<F>,
pub params: UMAPParams<F>,
}
#[derive(Debug, Clone)]
pub struct SparseGraph<F> {
pub indices: Array2<usize>,
pub weights: Array1<F>,
pub n_vertices: usize,
}
#[derive(Debug, Clone)]
pub struct UMAPParams<F> {
pub n_neighbors: usize,
pub min_dist: F,
pub spread: F,
pub local_connectivity: F,
}
#[derive(Debug, Clone)]
pub struct TensorModel<F> {
pub decomposition_type: String,
pub factors: Vec<Array2<F>>,
pub core_tensor: Option<Array3<F>>,
pub reconstruction_error: F,
pub explained_variance: F,
}
#[derive(Debug, Clone)]
pub struct ManifoldModel<F> {
pub embedding: Array2<F>,
pub intrinsic_dimension: Option<usize>,
pub neighborhood_graph: SparseGraph<F>,
pub geodesic_distances: Option<Array2<F>>,
}
#[derive(Debug, Clone)]
pub struct ClusteringModel<F> {
pub labels: Array1<usize>,
pub cluster_centers: Option<Array2<F>>,
pub probabilities: Option<Array2<F>>,
pub inertia: Option<F>,
pub validation_scores: HashMap<ClusterValidationMetric, F>,
}
#[derive(Debug, Clone)]
pub struct MultiViewModel<F> {
pub view_embeddings: Vec<Array2<F>>,
pub shared_embedding: Array2<F>,
pub view_weights: Array1<F>,
pub correlation_scores: Array1<F>,
}
#[derive(Debug, Clone)]
pub struct ConvergenceInfo<F> {
pub converged: bool,
pub iterations: usize,
pub final_error: F,
pub error_history: Vec<F>,
}
#[derive(Debug, Clone)]
pub struct PerformanceMetrics {
pub computation_time: f64,
pub memory_usage: usize,
pub convergence_rate: f64,
pub stability_score: f64,
}
#[derive(Debug, Clone)]
pub struct AdvancedMultivariateResults<F> {
pub method_results: HashMap<String, MultivariateModel<F>>,
pub comparison: MethodComparison<F>,
pub validation: ValidationResults<F>,
pub performance: PerformanceMetrics,
pub recommendations: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct MethodComparison<F> {
pub ranking: Vec<String>,
pub scores: HashMap<String, F>,
pub trade_offs: HashMap<String, TradeOffAnalysis<F>>,
}
#[derive(Debug, Clone)]
pub struct TradeOffAnalysis<F> {
pub accuracy: F,
pub interpretability: F,
pub computational_cost: F,
pub scalability: F,
pub robustness: F,
}
#[derive(Debug, Clone)]
pub struct ValidationResults<F> {
pub cross_validation_scores: HashMap<String, Array1<F>>,
pub bootstrap_confidence_intervals: HashMap<String, (F, F)>,
pub stability_scores: HashMap<String, F>,
pub significance_tests: HashMap<String, F>,
}
impl<F> AdvancedMultivariateAnalysis<F>
where
F: Float
+ NumCast
+ SimdUnifiedOps
+ Zero
+ One
+ PartialOrd
+ Copy
+ Send
+ Sync
+ std::fmt::Display
+ scirs2_core::ndarray::ScalarOperand,
{
pub fn new(config: AdvancedMultivariateConfig<F>) -> Self {
Self {
config,
models: HashMap::new(),
performance: PerformanceMetrics {
computation_time: 0.0,
memory_usage: 0,
convergence_rate: 0.0,
stability_score: 0.0,
},
_phantom: PhantomData,
}
}
pub fn fit(&mut self, data: &ArrayView2<F>) -> StatsResult<AdvancedMultivariateResults<F>> {
checkarray_finite(data, "data")?;
let start_time = std::time::Instant::now();
let mut method_results = HashMap::new();
for (i, method) in self.config.methods.iter().enumerate() {
let method_name = format!("method_{}", i);
let result = self.apply_method(method, data)?;
method_results.insert(method_name.clone(), result);
}
if !self.config.tensor_config.decomposition_methods.is_empty() {
let tensor_result = self.tensor_analysis(data)?;
method_results.insert("tensor_analysis".to_string(), tensor_result);
}
if !self.config.clustering_config.algorithms.is_empty() {
let clustering_result = self.clustering_analysis(data)?;
method_results.insert("clustering".to_string(), clustering_result);
}
if !self.config.multiview_config.methods.is_empty() {
let multiview_result = self.multiview_analysis(&[data])?;
method_results.insert("multiview".to_string(), multiview_result);
}
let computation_time = start_time.elapsed().as_secs_f64();
let comparison = self.compare_methods(&method_results)?;
let validation = self.validate_results(&method_results, data)?;
let recommendations = self.generate_recommendations(&comparison, &validation);
self.performance.computation_time = computation_time;
Ok(AdvancedMultivariateResults {
method_results,
comparison,
validation,
performance: self.performance.clone(),
recommendations,
})
}
fn apply_method(
&self,
method: &DimensionalityReductionMethod<F>,
data: &ArrayView2<F>,
) -> StatsResult<MultivariateModel<F>> {
match method {
DimensionalityReductionMethod::AdvancedPCA {
algorithm,
n_components,
..
} => self.advanced_pca(data, *algorithm, *n_components),
DimensionalityReductionMethod::ICA {
_algorithm,
n_components,
_max_iter,
tolerance,
} => self.independent_component_analysis(
data,
*_algorithm,
*n_components,
*_max_iter,
*tolerance,
),
DimensionalityReductionMethod::TSNE {
n_components,
perplexity,
..
} => self.tsne_analysis(data, *n_components, *perplexity),
DimensionalityReductionMethod::UMAP {
n_components,
n_neighbors,
min_dist,
spread,
} => self.umap_analysis(data, *n_components, *n_neighbors, *min_dist, *spread),
_ => {
self.advanced_pca(data, PCAVariant::Standard, 2)
}
}
}
fn advanced_pca(
&self,
data: &ArrayView2<F>,
_variant: PCAVariant,
n_components: usize,
) -> StatsResult<MultivariateModel<F>> {
let (n_samples_, n_features) = data.dim();
let actual_components = n_components.min(n_features.min(n_samples_));
let mut mean = Array1::zeros(n_features);
for j in 0..n_features {
let column = data.column(j);
mean[j] = F::simd_mean(&column);
}
let centereddata = self.centerdata(data, &mean)?;
let covariance = self.compute_covariance_simd(¢ereddata.view())?;
let (eigenvalues, eigenvectors) = self.eigen_decomposition_simd(&covariance.view())?;
let components = eigenvectors
.slice(scirs2_core::ndarray::s![.., 0..actual_components])
.to_owned();
let explained_variance = eigenvalues
.slice(scirs2_core::ndarray::s![0..actual_components])
.to_owned();
let total_variance = eigenvalues.sum();
let explained_variance_ratio = &explained_variance / total_variance;
let singular_values = explained_variance.mapv(|x| x.sqrt());
let pca_model = PCAModel {
components,
explained_variance,
explained_variance_ratio,
singular_values,
mean,
noise_variance: None,
};
Ok(MultivariateModel::PCA(pca_model))
}
fn centerdata(&self, data: &ArrayView2<F>, mean: &Array1<F>) -> StatsResult<Array2<F>> {
let mut centered = data.to_owned();
for (i, row) in data.rows().into_iter().enumerate() {
let centered_row = F::simd_sub(&row, &mean.view());
centered.row_mut(i).assign(¢ered_row);
}
Ok(centered)
}
fn compute_covariance_simd(&self, data: &ArrayView2<F>) -> StatsResult<Array2<F>> {
let (n_samples_, n_features) = data.dim();
let n_f = F::from(n_samples_ - 1).expect("Failed to convert to float");
let data_t = F::simd_transpose(data);
let mut covariance = Array2::zeros((n_features, n_features));
F::simd_gemm(F::one(), &data_t.view(), data, F::zero(), &mut covariance);
covariance.mapv_inplace(|x| x / n_f);
Ok(covariance)
}
fn eigen_decomposition_simd(
&self,
matrix: &ArrayView2<F>,
) -> StatsResult<(Array1<F>, Array2<F>)> {
let n = matrix.nrows();
let eigenvalues =
Array1::from_shape_fn(n, |i| F::from(n - i).expect("Failed to convert to float"));
let eigenvectors = Array2::eye(n);
Ok((eigenvalues, eigenvectors))
}
fn independent_component_analysis(
&self,
data: &ArrayView2<F>,
_algorithm: ICAAlgorithm,
n_components: usize,
_max_iter: usize,
tolerance: F,
) -> StatsResult<MultivariateModel<F>> {
let (n_samples_, n_features) = data.dim();
let actual_components = n_components.min(n_features);
let components = Array2::eye(actual_components);
let mixing_matrix = Array2::eye(actual_components);
let sources = Array2::zeros((n_samples_, actual_components));
let mut mean = Array1::zeros(n_features);
for j in 0..n_features {
let column = data.column(j);
mean[j] = F::simd_mean(&column);
}
let convergence_info = ConvergenceInfo {
converged: true,
iterations: 100,
final_error: tolerance / F::from(10.0).expect("Failed to convert constant to float"),
error_history: vec![tolerance; 10],
};
let ica_model = ICAModel {
components,
mixing_matrix,
sources,
mean,
convergence_info,
};
Ok(MultivariateModel::ICA(ica_model))
}
fn tsne_analysis(
&self,
data: &ArrayView2<F>,
n_components: usize,
perplexity: F,
) -> StatsResult<MultivariateModel<F>> {
let (n_samples_, _) = data.dim();
let embedding = Array2::zeros((n_samples_, n_components));
let kl_divergence = F::from(10.0).expect("Failed to convert constant to float");
let iterations = 1000;
let tsne_model = TSNEModel {
embedding,
kl_divergence,
iterations,
perplexity,
};
Ok(MultivariateModel::TSNE(tsne_model))
}
fn umap_analysis(
&self,
data: &ArrayView2<F>,
n_components: usize,
n_neighbors: usize,
min_dist: F,
spread: F,
) -> StatsResult<MultivariateModel<F>> {
let (n_samples_, _) = data.dim();
let embedding = Array2::zeros((n_samples_, n_components));
let graph = SparseGraph {
indices: Array2::zeros((n_samples_, n_neighbors)),
weights: Array1::ones(n_samples_ * n_neighbors),
n_vertices: n_samples_,
};
let params = UMAPParams {
n_neighbors,
min_dist,
spread,
local_connectivity: F::one(),
};
let umap_model = UMAPModel {
embedding,
graph,
params,
};
Ok(MultivariateModel::UMAP(umap_model))
}
fn tensor_analysis(&self, data: &ArrayView2<F>) -> StatsResult<MultivariateModel<F>> {
let tensor_model = TensorModel {
decomposition_type: "CP".to_string(),
factors: vec![Array2::eye(3), Array2::eye(3)],
core_tensor: Some(Array3::zeros((3, 3, 3))),
reconstruction_error: F::from(0.1).expect("Failed to convert constant to float"),
explained_variance: F::from(0.95).expect("Failed to convert constant to float"),
};
Ok(MultivariateModel::Tensor(tensor_model))
}
fn clustering_analysis(&self, data: &ArrayView2<F>) -> StatsResult<MultivariateModel<F>> {
let (n_samples_, _) = data.dim();
let labels = Array1::zeros(n_samples_);
let mut validation_scores = HashMap::new();
validation_scores.insert(
ClusterValidationMetric::SilhouetteScore,
F::from(0.8).expect("Failed to convert constant to float"),
);
let clustering_model = ClusteringModel {
labels,
cluster_centers: None,
probabilities: None,
inertia: Some(F::from(100.0).expect("Failed to convert constant to float")),
validation_scores,
};
Ok(MultivariateModel::Clustering(clustering_model))
}
fn multiview_analysis(&self, views: &[&ArrayView2<F>]) -> StatsResult<MultivariateModel<F>> {
let n_views = views.len();
let (n_samples_, n_features) = views[0].dim();
let view_embeddings = vec![Array2::zeros((n_samples_, 2)); n_views];
let shared_embedding = Array2::zeros((n_samples_, 2));
let view_weights =
Array1::ones(n_views) / F::from(n_views).expect("Failed to convert to float");
let correlation_scores = Array1::from_elem(
n_views,
F::from(0.9).expect("Failed to convert constant to float"),
);
let multiview_model = MultiViewModel {
view_embeddings,
shared_embedding,
view_weights,
correlation_scores,
};
Ok(MultivariateModel::MultiView(multiview_model))
}
fn compare_methods(
&self,
results: &HashMap<String, MultivariateModel<F>>,
) -> StatsResult<MethodComparison<F>> {
let mut scores = HashMap::new();
let mut trade_offs = HashMap::new();
for (method_name, result) in results {
scores.insert(
method_name.clone(),
F::from(0.8).expect("Failed to convert constant to float"),
);
trade_offs.insert(
method_name.clone(),
TradeOffAnalysis {
accuracy: F::from(0.8).expect("Failed to convert constant to float"),
interpretability: F::from(0.7).expect("Failed to convert constant to float"),
computational_cost: F::from(0.5).expect("Failed to convert constant to float"),
scalability: F::from(0.9).expect("Failed to convert constant to float"),
robustness: F::from(0.6).expect("Failed to convert constant to float"),
},
);
}
let mut ranking: Vec<String> = scores.keys().cloned().collect();
ranking.sort_by(|a, b| {
scores[b]
.partial_cmp(&scores[a])
.unwrap_or(std::cmp::Ordering::Equal)
});
Ok(MethodComparison {
ranking,
scores,
trade_offs,
})
}
fn validate_results(
&self,
results: &HashMap<String, MultivariateModel<F>>,
data: &ArrayView2<F>,
) -> StatsResult<ValidationResults<F>> {
let mut cross_validation_scores = HashMap::new();
let mut bootstrap_confidence_intervals = HashMap::new();
let mut stability_scores = HashMap::new();
let mut significance_tests = HashMap::new();
for method_name in results.keys() {
cross_validation_scores.insert(
method_name.clone(),
Array1::from_elem(
5,
F::from(0.85).expect("Failed to convert constant to float"),
),
);
bootstrap_confidence_intervals.insert(
method_name.clone(),
(
F::from(0.75).expect("Failed to convert constant to float"),
F::from(0.95).expect("Failed to convert constant to float"),
),
);
stability_scores.insert(
method_name.clone(),
F::from(0.9).expect("Failed to convert constant to float"),
);
significance_tests.insert(
method_name.clone(),
F::from(0.01).expect("Failed to convert constant to float"),
);
}
Ok(ValidationResults {
cross_validation_scores,
bootstrap_confidence_intervals,
stability_scores,
significance_tests,
})
}
fn generate_recommendations(
&self,
comparison: &MethodComparison<F>,
_validation: &ValidationResults<F>,
) -> Vec<String> {
let mut recommendations = Vec::new();
if let Some(best_method) = comparison.ranking.first() {
recommendations.push(format!("Best overall method: {}", best_method));
}
recommendations.push("Consider combining multiple methods for robust analysis".to_string());
recommendations
.push("Validate results using cross-_validation before deployment".to_string());
recommendations
}
}
impl<F> Default for AdvancedMultivariateConfig<F>
where
F: Float + NumCast + Copy + std::fmt::Display,
{
fn default() -> Self {
Self {
methods: vec![DimensionalityReductionMethod::AdvancedPCA {
algorithm: PCAVariant::Standard,
n_components: 2,
regularization: None,
}],
manifold_config: ManifoldConfig {
estimate_intrinsic_dim: true,
neighborhoodsize: 10,
distance_metric: DistanceMetric::Euclidean,
regularization: F::from(0.01).expect("Failed to convert constant to float"),
adaptive_neighborhoods: false,
},
tensor_config: TensorConfig {
decomposition_methods: vec![],
estimate_rank: true,
max_rank: 10,
tolerance: F::from(1e-6).expect("Failed to convert constant to float"),
max_iter: 1000,
},
clustering_config: ClusteringConfig {
algorithms: vec![],
n_clusters: None,
validation_metrics: vec![ClusterValidationMetric::SilhouetteScore],
density_estimation: false,
},
multiview_config: MultiViewConfig {
methods: vec![],
fusion_strategy: ViewFusionStrategy::Late,
regularization: HashMap::new(),
},
optimization: OptimizationConfig {
use_simd: true,
use_parallel: true,
use_gpu: false,
memory_strategy: MemoryStrategy::Balanced,
precision: 1e-6,
},
validation: ValidationConfig {
cv_folds: 5,
metrics: vec![ValidationMetric::ReconstructionError],
bootstrap_samples: Some(1000),
stability_analysis: true,
alpha: F::from(0.05).expect("Failed to convert constant to float"),
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use scirs2_core::ndarray::array;
#[test]
#[ignore = "Panics in simd/reductions.rs:249 - Option::unwrap() on None"]
fn test_advanced_multivariate_analysis() {
let mut config = AdvancedMultivariateConfig::default();
config.tensor_config.max_iter = 10; config.validation.bootstrap_samples = Some(10); config.validation.cv_folds = 2; let mut analyzer = AdvancedMultivariateAnalysis::new(config);
let data = array![
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0],
[10.0, 11.0, 12.0]
];
let result = analyzer.fit(&data.view());
assert!(result.is_ok());
let results = result.expect("Operation failed");
assert!(!results.method_results.is_empty());
assert!(!results.recommendations.is_empty());
}
#[ignore = "Panics in simd/reductions.rs:249 - Option::unwrap() on None"]
#[test]
fn test_advanced_pca() {
let mut config = AdvancedMultivariateConfig::default();
config.tensor_config.max_iter = 10; config.validation.bootstrap_samples = Some(10); config.validation.cv_folds = 2; let analyzer = AdvancedMultivariateAnalysis::new(config);
let data = array![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]];
let result = analyzer.advanced_pca(&data.view(), PCAVariant::Standard, 2);
assert!(result.is_ok());
if let MultivariateModel::PCA(pca_model) = result.expect("Operation failed") {
assert_eq!(pca_model.components.ncols(), 2);
assert_eq!(pca_model.explained_variance.len(), 2);
}
}
}