1#![allow(dead_code)]
8#![allow(clippy::too_many_arguments)]
9
10use crate::error::{IoError, Result};
11use scirs2_core::ndarray::{Array1, Array2};
12use scirs2_core::random::Rng;
13use statrs::statistics::Statistics;
14use std::collections::{HashMap, VecDeque};
15use std::time::Instant;
16
17#[derive(Debug)]
19pub struct AdvancedPatternRecognizer {
20 pattern_networks: Vec<PatternNetwork>,
22 pattern_database: HashMap<String, PatternMetadata>,
24 analysis_buffer: VecDeque<PatternInstance>,
26 learning_rate: f32,
28}
29
30impl Default for AdvancedPatternRecognizer {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl AdvancedPatternRecognizer {
37 pub fn new() -> Self {
39 let pattern_networks = vec![
40 PatternNetwork::new("repetition", 16, 8, 4),
41 PatternNetwork::new("sequential", 16, 8, 4),
42 PatternNetwork::new("fractal", 32, 16, 8),
43 PatternNetwork::new("entropy", 16, 8, 4),
44 PatternNetwork::new("compression", 24, 12, 6),
45 ];
46
47 Self {
48 pattern_networks,
49 pattern_database: HashMap::new(),
50 analysis_buffer: VecDeque::with_capacity(1000),
51 learning_rate: 0.001,
52 }
53 }
54
55 pub fn analyze_patterns(&mut self, data: &[u8]) -> Result<AdvancedPatternAnalysis> {
57 let mut pattern_scores = HashMap::new();
58 let mut emergent_patterns = Vec::new();
59
60 let features = self.extract_multiscale_features(data)?;
62
63 let data_characteristics = self.characterize_data(data);
65
66 let mut network_results = Vec::new();
68 for network in &mut self.pattern_networks {
69 let score = network.analyze(&features)?;
70 let pattern_type = network.pattern_type.clone();
71 network_results.push((pattern_type, score));
72 }
73
74 for (pattern_type, score) in network_results {
76 let is_novel = self.is_novel_pattern(&pattern_type, score);
78
79 pattern_scores.insert(pattern_type.clone(), score);
80
81 if score > 0.8 && is_novel {
83 emergent_patterns.push(EmergentPattern {
84 pattern_type,
85 confidence: score,
86 discovered_at: Instant::now(),
87 data_characteristics: data_characteristics.clone(),
88 });
89 }
90 }
91
92 self.update_pattern_database(data, &pattern_scores)?;
94
95 let meta_patterns = self.detect_meta_patterns(&pattern_scores)?;
97 let optimization_recommendations =
98 self.generate_optimization_recommendations(&pattern_scores);
99
100 Ok(AdvancedPatternAnalysis {
101 pattern_scores,
102 emergent_patterns,
103 meta_patterns,
104 complexity_index: self.calculate_complexity_index(&features),
105 predictability_score: self.calculate_predictability(data),
106 optimization_recommendations,
107 })
108 }
109
110 fn extract_multiscale_features(&self, data: &[u8]) -> Result<Array2<f32>> {
112 let byte_features = self.extract_byte_level_features(data);
114 let local_features_4 = self.extract_local_structure_features(data, 4);
115 let local_features_16 = self.extract_local_structure_features(data, 16);
116 let global_features = self.extract_global_structure_features(data);
117
118 let max_features = [
120 byte_features.len(),
121 local_features_4.len(),
122 local_features_16.len(),
123 global_features.len(),
124 ]
125 .into_iter()
126 .max()
127 .unwrap_or(0);
128
129 let mut padded_features = Vec::with_capacity(4 * max_features);
131
132 let pad_features = |mut features: Vec<f32>, target_len: usize| {
134 features.resize(target_len, 0.0);
135 features
136 };
137
138 padded_features.extend(pad_features(byte_features, max_features));
140 padded_features.extend(pad_features(local_features_4, max_features));
141 padded_features.extend(pad_features(local_features_16, max_features));
142 padded_features.extend(pad_features(global_features, max_features));
143
144 let feature_array = Array2::from_shape_vec((4, max_features), padded_features)
146 .map_err(|e| IoError::Other(format!("Feature extraction error: {e}")))?;
147
148 Ok(feature_array)
149 }
150
151 fn extract_byte_level_features(&self, data: &[u8]) -> Vec<f32> {
153 let mut frequency = [0u32; 256];
154 for &byte in data {
155 frequency[byte as usize] += 1;
156 }
157
158 let len = data.len() as f32;
159 let mut features = Vec::new();
160
161 let mean = data.iter().map(|&x| x as f32).sum::<f32>() / len;
163 let variance = data.iter().map(|&x| (x as f32 - mean).powi(2)).sum::<f32>() / len;
164 let skewness = data.iter().map(|&x| (x as f32 - mean).powi(3)).sum::<f32>()
165 / (len * variance.powf(1.5));
166 let kurtosis =
167 data.iter().map(|&x| (x as f32 - mean).powi(4)).sum::<f32>() / (len * variance.powi(2));
168
169 features.extend(&[mean / 255.0, variance / (255.0 * 255.0), skewness, kurtosis]);
170
171 let mut shannon_entropy = 0.0;
173 let mut gini_index = 0.0;
174
175 for &freq in &frequency {
176 if freq > 0 {
177 let p = freq as f32 / len;
178 shannon_entropy -= p * p.log2();
179 gini_index += p * p;
180 }
181 }
182
183 features.push(shannon_entropy / 8.0);
184 features.push(1.0 - gini_index);
185
186 features
187 }
188
189 fn extract_local_structure_features(&self, data: &[u8], window_size: usize) -> Vec<f32> {
191 let mut features = Vec::new();
192
193 if data.len() < window_size {
194 return vec![0.0; 4]; }
196
197 let mut autocorrelations = Vec::new();
198 let mut transitions = 0;
199 let mut periodicity_score: f32 = 0.0;
200
201 for lag in 1..window_size.min(8) {
203 let mut correlation = 0.0;
204 let mut count = 0;
205
206 for i in 0..(data.len() - lag) {
207 if i + lag < data.len() {
208 correlation += (data[i] as f32) * (data[i + lag] as f32);
209 count += 1;
210 }
211 }
212
213 if count > 0 {
214 autocorrelations.push(correlation / count as f32);
215 }
216 }
217
218 for window in data.windows(window_size) {
220 for i in 1..window.len() {
221 if window[i] != window[i - 1] {
222 transitions += 1;
223 }
224 }
225 }
226
227 for period in 2..window_size.min(16) {
229 let mut matches = 0;
230 let mut total = 0;
231
232 for i in 0..(data.len() - period) {
233 if data[i] == data[i + period] {
234 matches += 1;
235 }
236 total += 1;
237 }
238
239 if total > 0 {
240 periodicity_score = periodicity_score.max(matches as f32 / total as f32);
241 }
242 }
243
244 features.push(
245 autocorrelations.iter().sum::<f32>()
246 / autocorrelations.len().max(1) as f32
247 / (255.0 * 255.0),
248 );
249 features.push(transitions as f32 / data.len() as f32);
250 features.push(periodicity_score);
251 features.push(autocorrelations.len() as f32 / 8.0);
252
253 features
254 }
255
256 fn extract_global_structure_features(&self, data: &[u8]) -> Vec<f32> {
258 let mut features = Vec::new();
259
260 let lz_complexity = self.calculate_lempel_ziv_complexity(data);
262 features.push(lz_complexity);
263
264 let reversed_data: Vec<u8> = data.iter().rev().cloned().collect();
266 let lcs_ratio = self.calculate_lcs_ratio(data, &reversed_data);
267 features.push(lcs_ratio);
268
269 let fractal_dimension = self.estimate_fractal_dimension(data);
271 features.push(fractal_dimension);
272
273 let rle_ratio = self.calculate_rle_ratio(data);
275 features.push(rle_ratio);
276
277 features
278 }
279
280 fn calculate_lempel_ziv_complexity(&self, data: &[u8]) -> f32 {
282 let mut dictionary = std::collections::HashSet::new();
283 let mut i = 0;
284 let mut complexity = 0;
285
286 while i < data.len() {
287 let mut j = i + 1;
288 while j <= data.len() && dictionary.contains(&data[i..j]) {
289 j += 1;
290 }
291
292 if j <= data.len() {
293 dictionary.insert(data[i..j].to_vec());
294 }
295
296 complexity += 1;
297 i = j.min(data.len());
298 }
299
300 complexity as f32 / data.len() as f32
301 }
302
303 fn calculate_lcs_ratio(&self, data1: &[u8], data2: &[u8]) -> f32 {
305 let len1 = data1.len();
306 let len2 = data2.len();
307
308 if len1 == 0 || len2 == 0 {
309 return 0.0;
310 }
311
312 let sample_size = 100.min(len1).min(len2);
314 let mut dp = vec![vec![0; sample_size + 1]; sample_size + 1];
315
316 for i in 1..=sample_size {
317 for j in 1..=sample_size {
318 if data1[i - 1] == data2[j - 1] {
319 dp[i][j] = dp[i - 1][j - 1] + 1;
320 } else {
321 dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]);
322 }
323 }
324 }
325
326 dp[sample_size][sample_size] as f32 / sample_size as f32
327 }
328
329 fn estimate_fractal_dimension(&self, data: &[u8]) -> f32 {
331 if data.len() < 4 {
332 return 1.0;
333 }
334
335 let mut dimensions = Vec::new();
336
337 for scale in [2, 4, 8, 16].iter() {
338 if data.len() >= *scale {
339 let mut boxes = std::collections::HashSet::new();
340
341 for chunk in data.chunks(*scale) {
342 let min_val = *chunk.iter().min().unwrap_or(&0);
343 let max_val = *chunk.iter().max().unwrap_or(&255);
344 boxes.insert((min_val / 16, max_val / 16)); }
346
347 if !boxes.is_empty() {
348 dimensions.push(((*scale as f32).ln(), (boxes.len() as f32).ln()));
349 }
350 }
351 }
352
353 if dimensions.len() < 2 {
354 return 1.0;
355 }
356
357 let n = dimensions.len() as f32;
359 let sum_x: f32 = dimensions.iter().map(|(x, _)| *x).sum();
360 let sum_y: f32 = dimensions.iter().map(|(_, y)| y).sum();
361 let sum_xy: f32 = dimensions.iter().map(|(x, y)| x * y).sum();
362 let sum_x2: f32 = dimensions.iter().map(|(x, _)| x * x).sum();
363
364 let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x);
365 slope.abs().min(2.0) }
367
368 fn calculate_rle_ratio(&self, data: &[u8]) -> f32 {
370 if data.is_empty() {
371 return 1.0;
372 }
373
374 let mut compressed_size = 0;
375 let mut i = 0;
376
377 while i < data.len() {
378 let current_byte = data[i];
379 let mut run_length = 1;
380
381 while i + run_length < data.len() && data[i + run_length] == current_byte {
382 run_length += 1;
383 }
384
385 compressed_size += if run_length > 3 { 2 } else { run_length }; i += run_length;
387 }
388
389 compressed_size as f32 / data.len() as f32
390 }
391
392 fn is_novel_pattern(&self, pattern_type: &str, score: f32) -> bool {
394 if let Some(metadata) = self.pattern_database.get(pattern_type) {
395 score > metadata.max_score * 1.1 } else {
397 true }
399 }
400
401 fn characterize_data(&self, data: &[u8]) -> DataCharacteristics {
403 DataCharacteristics {
404 size: data.len(),
405 entropy: self.calculate_shannon_entropy(data),
406 mean: data.iter().map(|&x| x as f32).sum::<f32>() / data.len() as f32,
407 variance: {
408 let mean = data.iter().map(|&x| x as f32).sum::<f32>() / data.len() as f32;
409 data.iter().map(|&x| (x as f32 - mean).powi(2)).sum::<f32>() / data.len() as f32
410 },
411 }
412 }
413
414 fn calculate_shannon_entropy(&self, data: &[u8]) -> f32 {
416 let mut frequency = [0u32; 256];
417 for &byte in data {
418 frequency[byte as usize] += 1;
419 }
420
421 let len = data.len() as f32;
422 let mut entropy = 0.0;
423
424 for &freq in &frequency {
425 if freq > 0 {
426 let p = freq as f32 / len;
427 entropy -= p * p.log2();
428 }
429 }
430
431 entropy / 8.0
432 }
433
434 fn update_pattern_database(
436 &mut self,
437 data: &[u8],
438 pattern_scores: &HashMap<String, f32>,
439 ) -> Result<()> {
440 let data_characteristics = self.characterize_data(data);
441
442 for (pattern_type, &score) in pattern_scores {
443 let metadata = self
444 .pattern_database
445 .entry(pattern_type.clone())
446 .or_insert_with(|| PatternMetadata {
447 pattern_type: pattern_type.clone(),
448 observation_count: 0,
449 max_score: 0.0,
450 avg_score: 0.0,
451 last_seen: Instant::now(),
452 associated_data_characteristics: Vec::new(),
453 });
454
455 metadata.observation_count += 1;
456 metadata.max_score = metadata.max_score.max(score);
457 metadata.avg_score = (metadata.avg_score * (metadata.observation_count - 1) as f32
458 + score)
459 / metadata.observation_count as f32;
460 metadata.last_seen = Instant::now();
461 metadata
462 .associated_data_characteristics
463 .push(data_characteristics.clone());
464
465 if metadata.associated_data_characteristics.len() > 100 {
467 metadata.associated_data_characteristics.remove(0);
468 }
469 }
470
471 Ok(())
472 }
473
474 fn detect_meta_patterns(
476 &self,
477 pattern_scores: &HashMap<String, f32>,
478 ) -> Result<Vec<MetaPattern>> {
479 let mut meta_patterns = Vec::new();
480
481 let score_pairs: Vec<_> = pattern_scores.iter().collect();
483
484 for i in 0..score_pairs.len() {
485 for j in (i + 1)..score_pairs.len() {
486 let (type1, &score1) = score_pairs[i];
487 let (type2, &score2) = score_pairs[j];
488
489 if score1 > 0.7 && score2 > 0.7 {
491 meta_patterns.push(MetaPattern {
492 pattern_combination: vec![type1.clone(), type2.clone()],
493 correlation_strength: (score1 * score2).sqrt(),
494 synergy_type: self.determine_synergy_type(type1, type2),
495 });
496 }
497 }
498 }
499
500 Ok(meta_patterns)
501 }
502
503 fn determine_synergy_type(&self, type1: &str, type2: &str) -> SynergyType {
505 match (type1, type2) {
506 ("repetition", "compression") => SynergyType::ReinforcingCompression,
507 ("sequential", "entropy") => SynergyType::ContrastedRandomness,
508 ("fractal", "periodicity") => SynergyType::HierarchicalStructure,
509 _ => SynergyType::Unknown,
510 }
511 }
512
513 fn calculate_complexity_index(&self, features: &Array2<f32>) -> f32 {
515 let weights = Array1::from(vec![0.4, 0.3, 0.2, 0.1]); let scale_complexities = features.mean_axis(scirs2_core::ndarray::Axis(1)).unwrap();
518 weights.dot(&scale_complexities)
519 }
520
521 fn calculate_predictability(&self, data: &[u8]) -> f32 {
523 if data.len() < 10 {
524 return 0.5;
525 }
526
527 let mut correct_predictions = 0;
528 let prediction_window = 5.min(data.len() - 1);
529
530 for i in prediction_window..data.len() {
531 let recent_bytes = &data[i - prediction_window..i];
533 let predicted = self.predict_next_byte(recent_bytes);
534
535 if predicted == data[i] {
536 correct_predictions += 1;
537 }
538 }
539
540 correct_predictions as f32 / (data.len() - prediction_window) as f32
541 }
542
543 fn predict_next_byte(&self, history: &[u8]) -> u8 {
545 if history.is_empty() {
546 return 0;
547 }
548
549 let mut frequency = [0u32; 256];
551 for &byte in history {
552 frequency[byte as usize] += 1;
553 }
554
555 frequency
556 .iter()
557 .enumerate()
558 .max_by_key(|(_, &count)| count)
559 .map(|(byte, _)| byte as u8)
560 .unwrap_or(0)
561 }
562
563 fn generate_optimization_recommendations(
565 &self,
566 pattern_scores: &HashMap<String, f32>,
567 ) -> Vec<OptimizationRecommendation> {
568 let mut recommendations = Vec::new();
569
570 for (pattern_type, &score) in pattern_scores {
571 match pattern_type.as_str() {
572 "repetition" if score > 0.8 => {
573 recommendations.push(OptimizationRecommendation {
574 optimization_type: "compression".to_string(),
575 reason: "High repetition detected - compression will be highly effective"
576 .to_string(),
577 expected_improvement: score * 0.7,
578 confidence: score,
579 });
580 }
581 "sequential" if score > 0.7 => {
582 recommendations.push(OptimizationRecommendation {
583 optimization_type: "streaming".to_string(),
584 reason: "Sequential access pattern - streaming optimization recommended"
585 .to_string(),
586 expected_improvement: score * 0.5,
587 confidence: score,
588 });
589 }
590 "fractal" if score > 0.8 => {
591 recommendations.push(OptimizationRecommendation {
592 optimization_type: "hierarchical_processing".to_string(),
593 reason:
594 "Fractal structure detected - hierarchical processing will be efficient"
595 .to_string(),
596 expected_improvement: score * 0.6,
597 confidence: score,
598 });
599 }
600 "entropy" if score < 0.3 => {
601 recommendations.push(OptimizationRecommendation {
602 optimization_type: "aggressive_compression".to_string(),
603 reason: "Low entropy - aggressive compression algorithms recommended"
604 .to_string(),
605 expected_improvement: (1.0 - score) * 0.8,
606 confidence: 1.0 - score,
607 });
608 }
609 _ => {}
610 }
611 }
612
613 recommendations
614 }
615}
616
617#[derive(Debug)]
619struct PatternNetwork {
620 pattern_type: String,
621 weights: Array2<f32>,
622 bias: Array1<f32>,
623 activation_history: VecDeque<f32>,
624}
625
626impl PatternNetwork {
627 fn new(pattern_type: &str, input_size: usize, hidden_size: usize, _output_size: usize) -> Self {
628 let scale = (2.0 / (input_size + hidden_size) as f32).sqrt();
630 let mut rng = scirs2_core::random::rng();
631 let weights = Array2::from_shape_fn((hidden_size, input_size), |_| {
632 (rng.random::<f32>() - 0.5) * 2.0 * scale
633 });
634
635 Self {
636 pattern_type: pattern_type.to_string(),
637 weights,
638 bias: Array1::zeros(hidden_size),
639 activation_history: VecDeque::with_capacity(100),
640 }
641 }
642
643 fn analyze(&mut self, features: &Array2<f32>) -> Result<f32> {
644 let flattened = features.as_slice().unwrap();
646 let input = Array1::from(flattened.to_vec());
647
648 let network_input = if input.len() > self.weights.ncols() {
650 input
651 .slice(scirs2_core::ndarray::s![..self.weights.ncols()])
652 .to_owned()
653 } else {
654 let mut padded = Array1::zeros(self.weights.ncols());
655 padded
656 .slice_mut(scirs2_core::ndarray::s![..input.len()])
657 .assign(&input);
658 padded
659 };
660
661 let hidden = self.weights.dot(&network_input) + &self.bias;
663 let activated = hidden.mapv(Self::relu);
664
665 let score = match self.pattern_type.as_str() {
667 "repetition" => self.score_repetition_pattern(&activated),
668 "sequential" => self.score_sequential_pattern(&activated),
669 "fractal" => self.score_fractal_pattern(&activated),
670 "entropy" => self.score_entropy_pattern(&activated),
671 "compression" => self.score_compression_pattern(&activated),
672 _ => activated.mean().unwrap_or(0.0),
673 };
674
675 self.activation_history.push_back(score);
676 if self.activation_history.len() > 100 {
677 self.activation_history.pop_front();
678 }
679
680 Ok(score.clamp(0.0, 1.0))
681 }
682
683 fn relu(x: f32) -> f32 {
684 x.max(0.0)
685 }
686
687 fn score_repetition_pattern(&self, activations: &Array1<f32>) -> f32 {
688 let mut max_repetition: f32 = 0.0;
690
691 for window_size in 2..=activations.len() / 2 {
692 let mut repetition_score = 0.0;
693 let mut count = 0;
694
695 for i in 0..=(activations.len() - 2 * window_size) {
696 let window1 = activations.slice(scirs2_core::ndarray::s![i..i + window_size]);
697 let window2 = activations.slice(scirs2_core::ndarray::s![
698 i + window_size..i + 2 * window_size
699 ]);
700
701 let similarity = window1
702 .iter()
703 .zip(window2.iter())
704 .map(|(a, b)| 1.0 - (a - b).abs())
705 .sum::<f32>()
706 / window_size as f32;
707
708 repetition_score += similarity;
709 count += 1;
710 }
711
712 if count > 0 {
713 max_repetition = max_repetition.max(repetition_score / count as f32);
714 }
715 }
716
717 max_repetition
718 }
719
720 fn score_sequential_pattern(&self, activations: &Array1<f32>) -> f32 {
721 if activations.len() < 2 {
722 return 0.0;
723 }
724
725 let mut increasing = 0;
727 let mut decreasing = 0;
728
729 for i in 1..activations.len() {
730 if activations[i] > activations[i - 1] {
731 increasing += 1;
732 } else if activations[i] < activations[i - 1] {
733 decreasing += 1;
734 }
735 }
736
737 let total_transitions = activations.len() - 1;
738 let max_direction = increasing.max(decreasing);
739
740 max_direction as f32 / total_transitions as f32
741 }
742
743 fn score_fractal_pattern(&self, activations: &Array1<f32>) -> f32 {
744 let mut fractal_score = 0.0;
746 let mut scale_count = 0;
747
748 for scale in [2, 4, 8].iter() {
749 if activations.len() >= scale * 2 {
750 let downsampled1 = self.downsample(activations, *scale, 0);
751 let downsampled2 = self.downsample(activations, *scale, *scale);
752
753 if !downsampled1.is_empty() && !downsampled2.is_empty() {
754 let similarity = self.calculate_similarity(&downsampled1, &downsampled2);
755 fractal_score += similarity;
756 scale_count += 1;
757 }
758 }
759 }
760
761 if scale_count > 0 {
762 fractal_score / scale_count as f32
763 } else {
764 0.0
765 }
766 }
767
768 fn score_entropy_pattern(&self, activations: &Array1<f32>) -> f32 {
769 let quantized: Vec<u8> = activations.iter().map(|&x| (x * 255.0) as u8).collect();
771
772 let mut frequency = [0u32; 256];
773 for &val in &quantized {
774 frequency[val as usize] += 1;
775 }
776
777 let len = quantized.len() as f32;
778 let mut entropy = 0.0;
779
780 for &freq in &frequency {
781 if freq > 0 {
782 let p = freq as f32 / len;
783 entropy -= p * p.log2();
784 }
785 }
786
787 entropy / 8.0 }
789
790 fn score_compression_pattern(&self, activations: &Array1<f32>) -> f32 {
791 let quantized: Vec<u8> = activations.iter().map(|&x| (x * 255.0) as u8).collect();
793
794 let mut compressed_size = 0;
795 let mut i = 0;
796
797 while i < quantized.len() {
798 let current = quantized[i];
799 let mut run_length = 1;
800
801 while i + run_length < quantized.len() && quantized[i + run_length] == current {
802 run_length += 1;
803 }
804
805 compressed_size += if run_length > 2 { 2 } else { run_length };
806 i += run_length;
807 }
808
809 1.0 - (compressed_size as f32 / quantized.len() as f32)
810 }
811
812 fn downsample(&self, data: &Array1<f32>, scale: usize, offset: usize) -> Vec<f32> {
813 data.iter().skip(offset).step_by(scale).cloned().collect()
814 }
815
816 fn calculate_similarity(&self, data1: &[f32], data2: &[f32]) -> f32 {
817 if data1.is_empty() || data2.is_empty() {
818 return 0.0;
819 }
820
821 let min_len = data1.len().min(data2.len());
822 let mut similarity = 0.0;
823
824 for i in 0..min_len {
825 similarity += 1.0 - (data1[i] - data2[i]).abs();
826 }
827
828 similarity / min_len as f32
829 }
830}
831
832#[derive(Debug, Clone)]
836pub struct AdvancedPatternAnalysis {
837 pub pattern_scores: HashMap<String, f32>,
839 pub emergent_patterns: Vec<EmergentPattern>,
841 pub meta_patterns: Vec<MetaPattern>,
843 pub complexity_index: f32,
845 pub predictability_score: f32,
847 pub optimization_recommendations: Vec<OptimizationRecommendation>,
849}
850
851#[derive(Debug, Clone)]
853pub struct EmergentPattern {
854 pub pattern_type: String,
856 pub confidence: f32,
858 pub discovered_at: Instant,
860 pub data_characteristics: DataCharacteristics,
862}
863
864#[derive(Debug, Clone)]
866pub struct MetaPattern {
867 pub pattern_combination: Vec<String>,
869 pub correlation_strength: f32,
871 pub synergy_type: SynergyType,
873}
874
875#[derive(Debug, Clone)]
877pub enum SynergyType {
878 ReinforcingCompression,
880 ContrastedRandomness,
882 HierarchicalStructure,
884 Unknown,
886}
887
888#[derive(Debug, Clone)]
890pub struct OptimizationRecommendation {
891 pub optimization_type: String,
893 pub reason: String,
895 pub expected_improvement: f32,
897 pub confidence: f32,
899}
900
901#[derive(Debug, Clone)]
902struct PatternMetadata {
903 pattern_type: String,
904 observation_count: usize,
905 max_score: f32,
906 avg_score: f32,
907 last_seen: Instant,
908 associated_data_characteristics: Vec<DataCharacteristics>,
909}
910
911#[derive(Debug, Clone)]
912pub struct DataCharacteristics {
914 pub size: usize,
916 pub entropy: f32,
918 pub mean: f32,
920 pub variance: f32,
922}
923
924#[derive(Debug, Clone)]
925struct PatternInstance {
926 pattern_type: String,
927 score: f32,
928 timestamp: Instant,
929 data_hash: u64,
930}
931
932#[cfg(test)]
933mod tests {
934 use super::*;
935
936 #[test]
937 fn test_advanced_pattern_recognizer_creation() {
938 let recognizer = AdvancedPatternRecognizer::new();
939 assert_eq!(recognizer.pattern_networks.len(), 5);
940 }
941
942 #[test]
943 fn test_pattern_analysis() {
944 let mut recognizer = AdvancedPatternRecognizer::new();
945 let test_data = vec![1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
946
947 let analysis = recognizer.analyze_patterns(&test_data).unwrap();
948 assert!(!analysis.pattern_scores.is_empty());
949 assert!(analysis.complexity_index >= 0.0 && analysis.complexity_index <= 1.0);
950 assert!(analysis.predictability_score >= 0.0 && analysis.predictability_score <= 1.0);
951 }
952
953 #[test]
954 fn test_multiscale_feature_extraction() {
955 let recognizer = AdvancedPatternRecognizer::new();
956 let test_data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
957
958 let features = recognizer.extract_multiscale_features(&test_data).unwrap();
959 assert_eq!(features.nrows(), 4); assert!(features.ncols() > 0);
961 }
962
963 #[test]
964 fn test_lempel_ziv_complexity() {
965 let recognizer = AdvancedPatternRecognizer::new();
966
967 let repetitive_data = vec![1, 1, 1, 1, 1, 1, 1, 1];
969 let complexity1 = recognizer.calculate_lempel_ziv_complexity(&repetitive_data);
970
971 let random_data = vec![1, 2, 3, 4, 5, 6, 7, 8];
973 let complexity2 = recognizer.calculate_lempel_ziv_complexity(&random_data);
974
975 assert!(complexity2 > complexity1); }
977
978 #[test]
979 fn test_pattern_network() {
980 let mut network = PatternNetwork::new("test", 10, 5, 3);
981 let mut rng = scirs2_core::random::rng();
982 let features = Array2::from_shape_fn((2, 5), |_| rng.random::<f32>());
983
984 let score = network.analyze(&features).unwrap();
985 assert!((0.0..=1.0).contains(&score));
986 }
987}