1use super::types::*;
7use crate::error::InterpolateResult;
8use scirs2_core::numeric::Float;
9use std::collections::HashMap;
10use std::fmt::Debug;
11
12#[derive(Debug)]
14pub struct DataPatternAnalyzer<F: Float + Debug> {
15 pattern_db: HashMap<PatternSignature, PatternData<F>>,
17 analysis_state: AnalysisState<F>,
19 recognition_model: PatternRecognitionModel<F>,
21}
22
23#[derive(Debug, Clone, Hash, Eq, PartialEq)]
25pub struct PatternSignature {
26 pattern_type: DataPatternType,
28 size_range: (usize, usize),
30 smoothness_profile: SmoothnessProfile,
32}
33
34#[derive(Debug, Clone, Hash, Eq, PartialEq)]
36pub enum SmoothnessProfile {
37 VerySmooth,
39 Smooth,
41 ModeratelySmooth,
43 Continuous,
45 Discontinuous,
47}
48
49#[derive(Debug)]
51pub struct AnalysisState<F: Float> {
52 current_data: Option<DataProfile<F>>,
54 progress: f64,
56 intermediate_results: HashMap<String, f64>,
58 current_stage: AnalysisStage,
60}
61
62#[derive(Debug)]
64pub struct PatternRecognitionModel<F: Float> {
65 feature_extractors: Vec<FeatureExtractor<F>>,
67 classification_weights: HashMap<String, f64>,
69 model_accuracy: f64,
71}
72
73#[derive(Debug)]
75pub struct FeatureExtractor<F: Float> {
76 pub name: String,
78 pub extractor: fn(&[F]) -> f64,
80 pub importance: f64,
82}
83
84#[derive(Debug, Clone)]
86pub struct PatternAnalysisResult<F: Float> {
87 pub pattern_signature: PatternSignature,
89 pub confidence: f64,
91 pub features: HashMap<String, f64>,
93 pub recommended_methods: Vec<InterpolationMethodType>,
95 pub performance_predictions: HashMap<InterpolationMethodType, PerformanceCharacteristics>,
97 pub analysis_metadata: AnalysisMetadata<F>,
99}
100
101#[derive(Debug, Clone)]
103pub struct AnalysisMetadata<F: Float> {
104 pub analysis_time_ms: f64,
106 pub data_quality_score: F,
108 pub feature_count: usize,
110 pub model_version: String,
112}
113
114impl<F: Float + Debug> DataPatternAnalyzer<F> {
115 pub fn new() -> InterpolateResult<Self> {
117 Ok(Self {
118 pattern_db: HashMap::new(),
119 analysis_state: AnalysisState::new()?,
120 recognition_model: PatternRecognitionModel::new()?,
121 })
122 }
123
124 pub fn analyze_patterns(
126 &mut self,
127 data_profile: &DataProfile<F>,
128 ) -> InterpolateResult<PatternAnalysisResult<F>> {
129 let start_time = std::time::Instant::now();
130
131 self.analysis_state.current_data = Some(data_profile.clone());
133 self.analysis_state.progress = 0.0;
134 self.analysis_state.current_stage = AnalysisStage::DataLoading;
135
136 self.analysis_state.current_stage = AnalysisStage::FeatureExtraction;
138 let features = self.extract_features(data_profile)?;
139 self.analysis_state.progress = 0.3;
140
141 self.analysis_state.current_stage = AnalysisStage::PatternRecognition;
143 let pattern_signature = self.identify_pattern_signature(data_profile, &features)?;
144 self.analysis_state.progress = 0.6;
145
146 self.analysis_state.current_stage = AnalysisStage::MethodRecommendation;
148 let recommended_methods = self.recommend_methods(&pattern_signature, &features)?;
149 self.analysis_state.progress = 0.8;
150
151 self.analysis_state.current_stage = AnalysisStage::PerformancePrediction;
153 let performance_predictions =
154 self.predict_performance(&recommended_methods, data_profile, &features)?;
155 self.analysis_state.progress = 0.9;
156
157 let confidence = self.calculate_pattern_confidence(&pattern_signature, &features);
159
160 let analysis_time = start_time.elapsed().as_millis() as f64;
162 let metadata = AnalysisMetadata {
163 analysis_time_ms: analysis_time,
164 data_quality_score: self.assess_data_quality(data_profile),
165 feature_count: features.len(),
166 model_version: "1.0.0".to_string(),
167 };
168
169 self.analysis_state.current_stage = AnalysisStage::Completed;
170 self.analysis_state.progress = 1.0;
171
172 Ok(PatternAnalysisResult {
173 pattern_signature,
174 confidence,
175 features,
176 recommended_methods,
177 performance_predictions,
178 analysis_metadata: metadata,
179 })
180 }
181
182 fn extract_features(
184 &self,
185 data_profile: &DataProfile<F>,
186 ) -> InterpolateResult<HashMap<String, f64>> {
187 let mut features = HashMap::new();
188
189 features.insert("data_size".to_string(), data_profile.size as f64);
191 features.insert(
192 "dimensionality".to_string(),
193 data_profile.dimensionality as f64,
194 );
195 features.insert(
196 "smoothness".to_string(),
197 data_profile.smoothness.to_f64().unwrap_or(0.5),
198 );
199 features.insert(
200 "noise_level".to_string(),
201 data_profile.noise_level.to_f64().unwrap_or(0.1),
202 );
203 features.insert(
204 "sparsity".to_string(),
205 data_profile.sparsity.to_f64().unwrap_or(0.0),
206 );
207
208 let value_range = data_profile.value_range.1 - data_profile.value_range.0;
210 features.insert(
211 "value_range".to_string(),
212 value_range.to_f64().unwrap_or(1.0),
213 );
214
215 features.insert(
217 "mean_gradient".to_string(),
218 data_profile
219 .gradient_stats
220 .mean_magnitude
221 .to_f64()
222 .unwrap_or(0.0),
223 );
224 features.insert(
225 "gradient_variance".to_string(),
226 data_profile.gradient_stats.variance.to_f64().unwrap_or(0.0),
227 );
228 features.insert(
229 "max_gradient".to_string(),
230 data_profile
231 .gradient_stats
232 .max_gradient
233 .to_f64()
234 .unwrap_or(0.0),
235 );
236
237 features.insert(
239 "dominant_frequency".to_string(),
240 data_profile
241 .frequency_content
242 .dominant_frequency
243 .to_f64()
244 .unwrap_or(0.0),
245 );
246 features.insert(
247 "high_freq_ratio".to_string(),
248 data_profile
249 .frequency_content
250 .high_freq_ratio
251 .to_f64()
252 .unwrap_or(0.0),
253 );
254 features.insert(
255 "low_freq_ratio".to_string(),
256 data_profile
257 .frequency_content
258 .low_freq_ratio
259 .to_f64()
260 .unwrap_or(0.0),
261 );
262
263 let complexity_score = self.calculate_complexity_score(data_profile);
265 features.insert("complexity_score".to_string(), complexity_score);
266
267 let regularity_score = self.calculate_regularity_score(data_profile);
268 features.insert("regularity_score".to_string(), regularity_score);
269
270 let interpolation_difficulty = self.calculate_interpolation_difficulty(data_profile);
271 features.insert(
272 "interpolation_difficulty".to_string(),
273 interpolation_difficulty,
274 );
275
276 Ok(features)
277 }
278
279 fn identify_pattern_signature(
281 &self,
282 data_profile: &DataProfile<F>,
283 features: &HashMap<String, f64>,
284 ) -> InterpolateResult<PatternSignature> {
285 let pattern_type = self.classify_pattern_type(features);
287
288 let size_range = match data_profile.size {
290 0..=1000 => (0, 1000),
291 1001..=10000 => (1001, 10000),
292 10001..=100000 => (10001, 100000),
293 _ => (100001, usize::MAX),
294 };
295
296 let smoothness_profile = self.classify_smoothness_profile(features);
298
299 Ok(PatternSignature {
300 pattern_type,
301 size_range,
302 smoothness_profile,
303 })
304 }
305
306 fn classify_pattern_type(&self, features: &HashMap<String, f64>) -> DataPatternType {
308 let smoothness = features.get("smoothness").copied().unwrap_or(0.5);
309 let noise_level = features.get("noise_level").copied().unwrap_or(0.1);
310 let sparsity = features.get("sparsity").copied().unwrap_or(0.0);
311 let high_freq_ratio = features.get("high_freq_ratio").copied().unwrap_or(0.0);
312 let regularity = features.get("regularity_score").copied().unwrap_or(0.5);
313
314 if noise_level > 0.2 {
315 DataPatternType::Noisy
316 } else if sparsity > 0.3 {
317 DataPatternType::Sparse
318 } else if high_freq_ratio > 0.6 {
319 DataPatternType::Oscillatory
320 } else if smoothness > 0.8 && regularity > 0.7 {
321 DataPatternType::Smooth
322 } else if regularity > 0.8 {
323 DataPatternType::Structured
324 } else if smoothness < 0.3 {
325 DataPatternType::Irregular
326 } else {
327 let gradient_variance = features.get("gradient_variance").copied().unwrap_or(1.0);
329 if gradient_variance < 0.1 {
330 DataPatternType::Monotonic
331 } else {
332 DataPatternType::PiecewiseContinuous
333 }
334 }
335 }
336
337 fn classify_smoothness_profile(&self, features: &HashMap<String, f64>) -> SmoothnessProfile {
339 let smoothness = features.get("smoothness").copied().unwrap_or(0.5);
340 let gradient_variance = features.get("gradient_variance").copied().unwrap_or(1.0);
341 let max_gradient = features.get("max_gradient").copied().unwrap_or(1.0);
342
343 if smoothness >= 0.95 && gradient_variance < 0.01 {
344 SmoothnessProfile::VerySmooth
345 } else if smoothness >= 0.8 && gradient_variance < 0.1 {
346 SmoothnessProfile::Smooth
347 } else if smoothness >= 0.6 && max_gradient < 10.0 {
348 SmoothnessProfile::ModeratelySmooth
349 } else if smoothness >= 0.3 {
350 SmoothnessProfile::Continuous
351 } else {
352 SmoothnessProfile::Discontinuous
353 }
354 }
355
356 fn recommend_methods(
358 &self,
359 pattern_signature: &PatternSignature,
360 features: &HashMap<String, f64>,
361 ) -> InterpolateResult<Vec<InterpolationMethodType>> {
362 let mut methods = Vec::new();
363 let data_size = features.get("data_size").copied().unwrap_or(1000.0) as usize;
364 let dimensionality = features.get("dimensionality").copied().unwrap_or(1.0) as usize;
365
366 match &pattern_signature.pattern_type {
367 DataPatternType::Smooth => {
368 methods.push(InterpolationMethodType::CubicSpline);
369 methods.push(InterpolationMethodType::BSpline);
370 if data_size < 5000 {
371 methods.push(InterpolationMethodType::Polynomial);
372 }
373 }
374 DataPatternType::Noisy => {
375 methods.push(InterpolationMethodType::BSpline);
376 methods.push(InterpolationMethodType::Linear);
377 if dimensionality <= 3 {
378 methods.push(InterpolationMethodType::Kriging);
379 }
380 }
381 DataPatternType::Oscillatory => {
382 methods.push(InterpolationMethodType::AkimaSpline);
383 methods.push(InterpolationMethodType::PchipInterpolation);
384 methods.push(InterpolationMethodType::BSpline);
385 }
386 DataPatternType::Sparse => {
387 methods.push(InterpolationMethodType::RadialBasisFunction);
388 methods.push(InterpolationMethodType::NaturalNeighbor);
389 if dimensionality <= 3 {
390 methods.push(InterpolationMethodType::ThinPlateSpline);
391 }
392 }
393 DataPatternType::Irregular => {
394 methods.push(InterpolationMethodType::RadialBasisFunction);
395 methods.push(InterpolationMethodType::ShepardsMethod);
396 methods.push(InterpolationMethodType::NaturalNeighbor);
397 }
398 DataPatternType::Monotonic => {
399 methods.push(InterpolationMethodType::PchipInterpolation);
400 methods.push(InterpolationMethodType::AkimaSpline);
401 methods.push(InterpolationMethodType::CubicSpline);
402 }
403 DataPatternType::Structured => {
404 methods.push(InterpolationMethodType::BSpline);
405 methods.push(InterpolationMethodType::CubicSpline);
406 if data_size > 1000 {
407 methods.push(InterpolationMethodType::Linear);
408 }
409 }
410 DataPatternType::PiecewiseContinuous => {
411 methods.push(InterpolationMethodType::Linear);
412 methods.push(InterpolationMethodType::PchipInterpolation);
413 methods.push(InterpolationMethodType::BSpline);
414 }
415 }
416
417 let complexity = features.get("complexity_score").copied().unwrap_or(0.5);
419 if complexity > 0.8 && data_size < 10000 {
420 methods.push(InterpolationMethodType::QuantumInspired);
421 }
422
423 if methods.is_empty() {
425 methods.push(InterpolationMethodType::Linear);
426 methods.push(InterpolationMethodType::CubicSpline);
427 }
428
429 methods.truncate(5);
431
432 Ok(methods)
433 }
434
435 fn predict_performance(
437 &self,
438 methods: &[InterpolationMethodType],
439 data_profile: &DataProfile<F>,
440 features: &HashMap<String, f64>,
441 ) -> InterpolateResult<HashMap<InterpolationMethodType, PerformanceCharacteristics>> {
442 let mut predictions = HashMap::new();
443
444 for &method in methods {
445 let characteristics =
446 self.predict_method_performance(method, data_profile, features)?;
447 predictions.insert(method, characteristics);
448 }
449
450 Ok(predictions)
451 }
452
453 fn predict_method_performance(
455 &self,
456 method: InterpolationMethodType,
457 data_profile: &DataProfile<F>,
458 features: &HashMap<String, f64>,
459 ) -> InterpolateResult<PerformanceCharacteristics> {
460 let data_size = data_profile.size;
461 let complexity = features.get("complexity_score").copied().unwrap_or(0.5);
462 let noise_level = features.get("noise_level").copied().unwrap_or(0.1);
463
464 let (base_time, base_memory, base_accuracy, base_robustness) = match method {
465 InterpolationMethodType::Linear => (1.0, 1.0, 0.7, 0.9),
466 InterpolationMethodType::CubicSpline => (2.0, 1.5, 0.9, 0.7),
467 InterpolationMethodType::BSpline => (3.0, 2.0, 0.92, 0.8),
468 InterpolationMethodType::RadialBasisFunction => (10.0, 5.0, 0.95, 0.6),
469 InterpolationMethodType::Kriging => (15.0, 8.0, 0.98, 0.9),
470 InterpolationMethodType::Polynomial => (5.0, 3.0, 0.85, 0.5),
471 InterpolationMethodType::PchipInterpolation => (2.5, 1.8, 0.88, 0.85),
472 InterpolationMethodType::AkimaSpline => (2.8, 2.2, 0.87, 0.82),
473 InterpolationMethodType::ThinPlateSpline => (12.0, 6.0, 0.93, 0.75),
474 InterpolationMethodType::NaturalNeighbor => (8.0, 4.0, 0.86, 0.8),
475 InterpolationMethodType::ShepardsMethod => (6.0, 3.0, 0.75, 0.7),
476 InterpolationMethodType::QuantumInspired => (20.0, 10.0, 0.99, 0.95),
477 };
478
479 let size_factor = (data_size as f64).log10() / 3.0; let time_multiplier = base_time * (1.0 + size_factor * complexity);
482 let memory_multiplier = base_memory * (1.0 + size_factor * 0.5);
483
484 let accuracy_penalty = noise_level * 0.3;
486 let expected_accuracy = (base_accuracy - accuracy_penalty).max(0.1);
487
488 let robustness_bonus = if noise_level > 0.1 { 0.1 } else { 0.0 };
490 let robustness_score = (base_robustness + robustness_bonus).min(1.0);
491
492 Ok(PerformanceCharacteristics {
493 throughput: 1.0 / time_multiplier.max(0.1), memory_efficiency: 1.0 / memory_multiplier.max(0.1), accuracy_score: expected_accuracy,
496 stability: robustness_score,
497 scalability: 1.0, })
499 }
500
501 fn calculate_pattern_confidence(
503 &self,
504 _pattern_signature: &PatternSignature,
505 features: &HashMap<String, f64>,
506 ) -> f64 {
507 let smoothness = features.get("smoothness").copied().unwrap_or(0.5);
509 let noise_level = features.get("noise_level").copied().unwrap_or(0.1);
510 let regularity = features.get("regularity_score").copied().unwrap_or(0.5);
511
512 let clarity_score = (smoothness + regularity) / 2.0;
514 let noise_penalty = noise_level * 0.5;
515
516 ((clarity_score - noise_penalty) * self.recognition_model.model_accuracy)
517 .max(0.1)
518 .min(1.0)
519 }
520
521 fn assess_data_quality(&self, data_profile: &DataProfile<F>) -> F {
523 let noise_factor = F::one() - data_profile.noise_level.min(F::one());
524 let sparsity_factor = F::one() - data_profile.sparsity.min(F::one());
525 let size_factor = if data_profile.size > 100 {
526 F::one()
527 } else {
528 F::from(data_profile.size as f64 / 100.0).unwrap()
529 };
530
531 (noise_factor + sparsity_factor + size_factor) / F::from(3.0).unwrap()
532 }
533
534 fn calculate_complexity_score(&self, data_profile: &DataProfile<F>) -> f64 {
536 let gradient_complexity = data_profile.gradient_stats.variance.to_f64().unwrap_or(0.0);
537 let frequency_complexity = data_profile
538 .frequency_content
539 .frequency_spread
540 .to_f64()
541 .unwrap_or(0.0);
542 let dimensional_complexity = (data_profile.dimensionality as f64).log10();
543
544 (gradient_complexity + frequency_complexity + dimensional_complexity) / 3.0
545 }
546
547 fn calculate_regularity_score(&self, data_profile: &DataProfile<F>) -> f64 {
549 let smoothness = data_profile.smoothness.to_f64().unwrap_or(0.5);
550 let low_freq_dominance = data_profile
551 .frequency_content
552 .low_freq_ratio
553 .to_f64()
554 .unwrap_or(0.5);
555 let gradient_consistency =
556 1.0 / (1.0 + data_profile.gradient_stats.variance.to_f64().unwrap_or(1.0));
557
558 (smoothness + low_freq_dominance + gradient_consistency) / 3.0
559 }
560
561 fn calculate_interpolation_difficulty(&self, data_profile: &DataProfile<F>) -> f64 {
563 let noise_difficulty = data_profile.noise_level.to_f64().unwrap_or(0.1);
564 let sparsity_difficulty = data_profile.sparsity.to_f64().unwrap_or(0.0);
565 let irregularity_difficulty = 1.0 - data_profile.smoothness.to_f64().unwrap_or(0.5);
566 let size_difficulty = if data_profile.size > 100000 { 0.3 } else { 0.0 };
567
568 (noise_difficulty + sparsity_difficulty + irregularity_difficulty + size_difficulty) / 4.0
569 }
570
571 pub fn get_analysis_state(&self) -> &AnalysisState<F> {
573 &self.analysis_state
574 }
575
576 pub fn get_pattern_statistics(&self) -> HashMap<String, usize> {
578 let mut stats = HashMap::new();
579
580 stats.insert("total_patterns".to_string(), self.pattern_db.len());
581
582 let mut type_counts = HashMap::new();
584 for signature in self.pattern_db.keys() {
585 let pattern_name = format!("{:?}", signature.pattern_type);
586 *type_counts.entry(pattern_name).or_insert(0) += 1;
587 }
588
589 for (pattern_type, count) in type_counts {
590 stats.insert(pattern_type, count);
591 }
592
593 stats
594 }
595
596 pub fn add_pattern(&mut self, signature: PatternSignature, data: PatternData<F>) {
598 self.pattern_db.insert(signature, data);
599 }
600
601 pub fn update_recognition_model(
603 &mut self,
604 feedback: &[(PatternSignature, bool)],
605 ) -> InterpolateResult<()> {
606 if feedback.len() >= 10 {
607 let success_rate = feedback.iter().filter(|(_, success)| *success).count() as f64
608 / feedback.len() as f64;
609 self.recognition_model.model_accuracy = success_rate * 0.9 + 0.1; }
611 Ok(())
612 }
613}
614
615impl<F: Float> AnalysisState<F> {
616 pub fn new() -> InterpolateResult<Self> {
618 Ok(Self {
619 current_data: None,
620 progress: 0.0,
621 intermediate_results: HashMap::new(),
622 current_stage: AnalysisStage::DataLoading,
623 })
624 }
625
626 pub fn get_progress(&self) -> f64 {
628 self.progress
629 }
630
631 pub fn get_current_stage(&self) -> &AnalysisStage {
633 &self.current_stage
634 }
635
636 pub fn get_intermediate_results(&self) -> &HashMap<String, f64> {
638 &self.intermediate_results
639 }
640}
641
642impl<F: Float> PatternRecognitionModel<F> {
643 pub fn new() -> InterpolateResult<Self> {
645 let mut model = Self {
646 feature_extractors: Vec::new(),
647 classification_weights: HashMap::new(),
648 model_accuracy: 0.8, };
650
651 model.initialize_default_extractors();
653
654 Ok(model)
655 }
656
657 fn initialize_default_extractors(&mut self) {
659 self.feature_extractors.push(FeatureExtractor {
661 name: "mean".to_string(),
662 extractor: |data| {
663 data.iter().map(|x| x.to_f64().unwrap_or(0.0)).sum::<f64>() / data.len() as f64
664 },
665 importance: 0.6,
666 });
667
668 self.feature_extractors.push(FeatureExtractor {
669 name: "variance".to_string(),
670 extractor: |data| {
671 let mean =
672 data.iter().map(|x| x.to_f64().unwrap_or(0.0)).sum::<f64>() / data.len() as f64;
673 data.iter()
674 .map(|x| {
675 let diff = x.to_f64().unwrap_or(0.0) - mean;
676 diff * diff
677 })
678 .sum::<f64>()
679 / data.len() as f64
680 },
681 importance: 0.8,
682 });
683
684 self.classification_weights
686 .insert("smoothness_weight".to_string(), 0.4);
687 self.classification_weights
688 .insert("noise_weight".to_string(), 0.3);
689 self.classification_weights
690 .insert("complexity_weight".to_string(), 0.3);
691 }
692
693 pub fn get_model_accuracy(&self) -> f64 {
695 self.model_accuracy
696 }
697
698 pub fn update_accuracy(&mut self, accuracy: f64) {
700 self.model_accuracy = accuracy.max(0.0).min(1.0);
701 }
702}
703
704#[cfg(test)]
705mod tests {
706 use super::*;
707
708 #[test]
709 fn test_pattern_analyzer_creation() {
710 let analyzer: DataPatternAnalyzer<f64> = DataPatternAnalyzer::new().unwrap();
711 assert_eq!(analyzer.pattern_db.len(), 0);
712 assert_eq!(analyzer.analysis_state.progress, 0.0);
713 }
714
715 #[test]
716 fn test_smoothness_profile_classification() {
717 let analyzer: DataPatternAnalyzer<f64> = DataPatternAnalyzer::new().unwrap();
718 let mut features = HashMap::new();
719
720 features.insert("smoothness".to_string(), 0.95);
721 features.insert("gradient_variance".to_string(), 0.005);
722 let profile = analyzer.classify_smoothness_profile(&features);
723 assert!(matches!(profile, SmoothnessProfile::VerySmooth));
724
725 features.insert("smoothness".to_string(), 0.2);
726 let profile = analyzer.classify_smoothness_profile(&features);
727 assert!(matches!(profile, SmoothnessProfile::Discontinuous));
728 }
729
730 #[test]
731 fn test_pattern_type_classification() {
732 let analyzer: DataPatternAnalyzer<f64> = DataPatternAnalyzer::new().unwrap();
733 let mut features = HashMap::new();
734
735 features.insert("noise_level".to_string(), 0.3);
737 features.insert("smoothness".to_string(), 0.5);
738 features.insert("sparsity".to_string(), 0.1);
739 let pattern = analyzer.classify_pattern_type(&features);
740 assert!(matches!(pattern, DataPatternType::Noisy));
741
742 features.insert("noise_level".to_string(), 0.05);
744 features.insert("smoothness".to_string(), 0.9);
745 features.insert("regularity_score".to_string(), 0.8);
746 let pattern = analyzer.classify_pattern_type(&features);
747 assert!(matches!(pattern, DataPatternType::Smooth));
748 }
749}