1use nalgebra::{Complex, DMatrix, DVector, RealField};
2use ndarray::{Array1, Array2, Array3};
3use rayon::prelude::*;
5use std::collections::HashMap;
6
7pub type StateSpace = Vec<String>;
9pub type ProbabilityTensor = Array3<f64>;
10pub type QuantumState = Array1<Complex<f64>>;
11
12#[derive(Debug, Clone)]
13pub struct AdvancedTransitionModel {
14 pub contexts: HashMap<Vec<String>, ContextNode>,
16 pub max_order: usize,
17 pub quantum_representation: Option<QuantumState>,
18 pub spectral_decomposition: Option<SpectralAnalysis>,
19}
20
21#[derive(Debug, Clone)]
22pub struct ContextNode {
23 pub counts: HashMap<String, usize>,
24 pub probabilities: HashMap<String, f64>,
25 pub information_content: f64,
26 pub entropy: f64,
27 pub kl_divergence: f64,
28}
29
30#[derive(Debug, Clone)]
31pub struct SpectralAnalysis {
32 pub eigenvalues: DVector<Complex<f64>>,
33 pub eigenvectors: DMatrix<Complex<f64>>,
34 pub stationary_distribution: DVector<f64>,
35 pub mixing_time: f64,
36 pub spectral_gap: f64,
37}
38
39#[derive(Debug, Clone)]
40pub struct AnomalyScore {
41 pub state_sequence: Vec<String>,
42 pub likelihood: f64,
43 pub information_theoretic_score: f64,
44 pub spectral_anomaly_score: f64,
45 pub quantum_coherence_measure: f64,
46 pub topological_signature: Vec<f64>,
47 pub confidence_interval: (f64, f64),
48}
49
50impl AdvancedTransitionModel {
51 pub fn new(max_order: usize) -> Self {
52 Self {
53 contexts: HashMap::new(),
54 max_order,
55 quantum_representation: None,
56 spectral_decomposition: None,
57 }
58 }
59
60 pub fn build_context_tree(&mut self, sequence: &[String]) -> Result<(), String> {
62 self.contexts.clear();
64
65 if sequence.len() < 2 {
67 return Ok(());
68 }
69
70 let max_len = std::cmp::min(sequence.len(), 200);
72 let limited_sequence = &sequence[..max_len];
73
74 for window_size in 1..=std::cmp::min(self.max_order, 3) {
76 for window in limited_sequence.windows(window_size + 1) {
78 let context = window[..window_size].to_vec();
79 let next_state = &window[window_size];
80
81 let node = self
82 .contexts
83 .entry(context.clone())
84 .or_insert_with(|| ContextNode::new());
85
86 *node.counts.entry(next_state.clone()).or_insert(0) += 1;
87
88 if self.contexts.len() > 500 {
90 break;
91 }
92 }
93
94 if self.contexts.len() > 500 {
96 break;
97 }
98 }
99
100 self.calculate_information_measures()?;
102
103 self.perform_spectral_analysis()?;
106 self.generate_quantum_representation()?;
107
108 Ok(())
109 }
110
111 fn calculate_information_measures(&mut self) -> Result<(), String> {
113 for (_context, node) in &mut self.contexts {
114 let total_count: usize = node.counts.values().sum();
115
116 for (state, &count) in &node.counts {
118 let prob = count as f64 / total_count as f64;
119 node.probabilities.insert(state.clone(), prob);
120 }
121
122 node.entropy = node
124 .probabilities
125 .values()
126 .map(|&p| if p > 0.0 { -p * p.log2() } else { 0.0 })
127 .sum();
128
129 node.information_content = -node.entropy.log2();
131
132 let uniform_prob = 1.0 / node.probabilities.len() as f64;
134 node.kl_divergence = node
135 .probabilities
136 .values()
137 .map(|&p| {
138 if p > 0.0 {
139 p * (p / uniform_prob).log2()
140 } else {
141 0.0
142 }
143 })
144 .sum();
145 }
146 Ok(())
147 }
148
149 fn perform_spectral_analysis(&mut self) -> Result<(), String> {
168 if self.contexts.is_empty() {
172 return Ok(());
173 }
174
175 let states = self.get_unique_states();
177 let n_states = states.len();
178
179 if n_states == 0 {
180 return Ok(());
181 }
182
183 let eigenvalues = DVector::from_element(n_states, Complex::new(1.0, 0.0));
185 let stationary_dist = DVector::from_element(n_states, 1.0 / n_states as f64);
186
187 self.spectral_decomposition = Some(SpectralAnalysis {
188 eigenvalues,
189 eigenvectors: DMatrix::identity(n_states, n_states).map(|v| Complex::new(v, 0.0)),
190 stationary_distribution: stationary_dist,
191 mixing_time: 10.0, spectral_gap: 0.5, });
194
195 Ok(())
196 }
197
198 fn generate_quantum_representation(&mut self) -> Result<(), String> {
272 let states = self.get_unique_states();
273 let n_states = states.len();
274
275 if n_states == 0 {
276 return Ok(());
277 }
278
279 let max_states = std::cmp::min(n_states, 50);
281 let mut quantum_state = Array1::zeros(max_states);
282
283 let amplitude = 1.0 / (max_states as f64).sqrt();
285 for i in 0..max_states {
286 quantum_state[i] = Complex::new(amplitude, 0.0);
287 }
288
289 self.quantum_representation = Some(quantum_state);
290 Ok(())
291 }
292
293 pub fn detect_advanced_anomalies(
295 &self,
296 sequence: &[String],
297 _threshold: f64,
298 ) -> Vec<AnomalyScore> {
299 sequence
300 .windows(self.max_order + 1)
301 .par_bridge()
302 .filter_map(|window| self.calculate_comprehensive_anomaly_score(window))
305 .collect()
306 }
307
308 fn calculate_comprehensive_anomaly_score(&self, sequence: &[String]) -> Option<AnomalyScore> {
310 let likelihood = self.calculate_sequence_likelihood(sequence)?;
312
313 let info_score = self.calculate_information_score(sequence)?;
315
316 let spectral_score = self.calculate_spectral_anomaly_score(sequence)?;
318
319 let quantum_score = self.calculate_quantum_coherence(sequence)?;
321
322 let topo_signature = self.calculate_topological_signature(sequence)?;
324
325 let confidence_interval = self.calculate_bayesian_confidence_interval(sequence)?;
327
328 Some(AnomalyScore {
329 state_sequence: sequence.to_vec(),
330 likelihood,
331 information_theoretic_score: info_score,
332 spectral_anomaly_score: spectral_score,
333 quantum_coherence_measure: quantum_score,
334 topological_signature: topo_signature,
335 confidence_interval,
336 })
337 }
338
339 fn calculate_sequence_likelihood(&self, sequence: &[String]) -> Option<f64> {
341 let mut likelihood = 1.0;
342
343 for i in 1..sequence.len() {
344 let max_context_len = std::cmp::min(i, self.max_order);
345 let mut best_prob = 0.0;
346
347 for context_len in 1..=max_context_len {
348 let context = sequence[i - context_len..i].to_vec();
349 if let Some(node) = self.contexts.get(&context) {
350 if let Some(&prob) = node.probabilities.get(&sequence[i]) {
351 best_prob = best_prob.max(prob);
354 }
355 }
356 }
357
358 if best_prob > 0.0 {
359 likelihood *= best_prob;
360 } else {
361 likelihood *= 1e-10;
363 }
364 }
365
366 Some(likelihood)
367 }
368
369 fn calculate_information_score(&self, sequence: &[String]) -> Option<f64> {
371 let mut total_surprise = 0.0;
372 let mut context_entropy = 0.0;
373
374 for i in 1..sequence.len() {
375 let context_len = std::cmp::min(i, self.max_order);
376 let context = sequence[i - context_len..i].to_vec();
377
378 if let Some(node) = self.contexts.get(&context) {
379 context_entropy += node.entropy;
381
382 if let Some(&prob) = node.probabilities.get(&sequence[i]) {
384 total_surprise += -prob.log2();
385 }
386 }
387 }
388
389 Some((total_surprise + context_entropy) / sequence.len() as f64)
391 }
392
393 fn calculate_spectral_anomaly_score(&self, sequence: &[String]) -> Option<f64> {
395 let spectral = self.spectral_decomposition.as_ref()?;
396
397 let mut deviation = 0.0;
399 let states = self.get_unique_states();
400
401 for (_, state) in sequence.iter().enumerate() {
402 if let Some(state_idx) = states.iter().position(|s| s == state) {
403 let expected_prob = spectral.stationary_distribution[state_idx];
404 let observed_freq = self.calculate_observed_frequency(state, sequence);
405 deviation += (observed_freq - expected_prob).abs();
406 }
407 }
408
409 Some(deviation / sequence.len() as f64)
410 }
411
412 fn calculate_quantum_coherence(&self, _sequence: &[String]) -> Option<f64> {
414 let quantum_state = self.quantum_representation.as_ref()?;
415 let states = self.get_unique_states();
416
417 let mut density_matrix = Array2::zeros((states.len(), states.len()));
419
420 for i in 0..states.len() {
421 for j in 0..states.len() {
422 density_matrix[[i, j]] = (quantum_state[i].conj() * quantum_state[j]).re;
423 }
424 }
425
426 let trace = (0..states.len())
428 .map(|i| density_matrix[[i, i]])
429 .sum::<f64>();
430 let coherence = 1.0 - trace / states.len() as f64;
431
432 Some(coherence)
433 }
434
435 fn calculate_topological_signature(&self, sequence: &[String]) -> Option<Vec<f64>> {
437 let mut signature = Vec::new();
441
442 let components = self.count_connected_components(sequence);
445 signature.push(components as f64);
446
447 let cycles = self.count_approximate_cycles(sequence);
449 signature.push(cycles as f64);
450
451 let clustering = self.calculate_local_clustering(sequence);
453 signature.push(clustering);
454
455 Some(signature)
456 }
457
458 fn calculate_bayesian_confidence_interval(&self, sequence: &[String]) -> Option<(f64, f64)> {
460 let likelihood = self.calculate_sequence_likelihood(sequence)?;
464 let log_likelihood = likelihood.ln();
465
466 let std_error = (1.0 / sequence.len() as f64).sqrt();
468 let margin = 1.96 * std_error; Some((
471 (log_likelihood - margin).exp(),
472 (log_likelihood + margin).exp(),
473 ))
474 }
475
476 fn get_unique_states(&self) -> Vec<String> {
503 let mut states = std::collections::HashSet::new();
504 for context in self.contexts.keys() {
505 for state in context {
506 states.insert(state.clone());
507 }
508 }
509 for node in self.contexts.values() {
510 for state in node.counts.keys() {
511 states.insert(state.clone());
512 }
513 }
514 states.into_iter().collect()
515 }
516
517 fn calculate_observed_frequency(&self, target_state: &str, sequence: &[String]) -> f64 {
518 let count = sequence.iter().filter(|&s| s == target_state).count();
519 count as f64 / sequence.len() as f64
520 }
521
522 fn count_connected_components(&self, _sequence: &[String]) -> usize {
523 self.contexts.len()
525 }
526
527 fn count_approximate_cycles(&self, sequence: &[String]) -> usize {
528 let mut cycles = 0;
530 for len in 2..=sequence.len() / 2 {
531 for i in 0..=sequence.len() - 2 * len {
532 if sequence[i..i + len] == sequence[i + len..i + 2 * len] {
533 cycles += 1;
534 }
535 }
536 }
537 cycles
538 }
539
540 fn calculate_local_clustering(&self, _sequence: &[String]) -> f64 {
541 let mut clustering_sum = 0.0;
543 let mut node_count = 0;
544
545 for (_context, node) in &self.contexts {
546 if node.counts.len() > 1 {
547 let connections = node.counts.len();
548 let possible_connections = connections * (connections - 1) / 2;
549 if possible_connections > 0 {
550 clustering_sum += connections as f64 / possible_connections as f64;
551 node_count += 1;
552 }
553 }
554 }
555
556 if node_count > 0 {
557 clustering_sum / node_count as f64
558 } else {
559 0.0
560 }
561 }
562}
563
564impl ContextNode {
565 fn new() -> Self {
566 Self {
567 counts: HashMap::new(),
568 probabilities: HashMap::new(),
569 information_content: 0.0,
570 entropy: 0.0,
571 kl_divergence: 0.0,
572 }
573 }
574}
575
576pub fn batch_process_sequences(
578 sequences: &[Vec<String>],
579 max_order: usize,
580 threshold: f64,
581) -> Vec<Vec<AnomalyScore>> {
582 sequences
583 .par_iter()
584 .map(|sequence| {
585 let mut model = AdvancedTransitionModel::new(max_order);
586 model.build_context_tree(sequence).unwrap_or_else(|e| {
587 eprintln!("Error building context tree: {}", e);
588 });
589 model.detect_advanced_anomalies(sequence, threshold)
590 })
591 .collect()
592}
593
594#[cfg(test)]
595mod tests {
596 use super::*;
597
598 #[test]
599 fn test_advanced_anomaly_detection() {
600 let sequence: Vec<String> = vec!["A", "B", "C", "A", "B", "C", "A", "D", "E", "F", "A"]
601 .into_iter()
602 .map(String::from)
603 .collect();
604
605 let mut model = AdvancedTransitionModel::new(3);
606 model.build_context_tree(&sequence).unwrap();
607
608 let anomalies = model.detect_advanced_anomalies(&sequence, 0.1);
609
610 assert!(!anomalies.is_empty());
611
612 for anomaly in &anomalies {
613 println!("Advanced Anomaly Detected:");
614 println!(" Sequence: {:?}", anomaly.state_sequence);
615 println!(" Likelihood: {:.6}", anomaly.likelihood);
616 println!(
617 " Information Score: {:.6}",
618 anomaly.information_theoretic_score
619 );
620 println!(" Spectral Score: {:.6}", anomaly.spectral_anomaly_score);
621 println!(
622 " Quantum Coherence: {:.6}",
623 anomaly.quantum_coherence_measure
624 );
625 println!(" Confidence Interval: {:?}", anomaly.confidence_interval);
626 println!(
627 " Topological Signature: {:?}",
628 anomaly.topological_signature
629 );
630 println!();
631 }
632 }
633
634 #[test]
635 fn test_spectral_analysis() {
636 let sequence: Vec<String> = vec!["A", "B", "A", "B", "A", "C", "A", "C"]
637 .into_iter()
638 .map(String::from)
639 .collect();
640
641 let mut model = AdvancedTransitionModel::new(2);
642 model.build_context_tree(&sequence).unwrap();
643
644 assert!(model.spectral_decomposition.is_some());
645
646 let spectral = model.spectral_decomposition.as_ref().unwrap();
647 println!("Spectral Analysis:");
648 println!(" Mixing time: {:.4}", spectral.mixing_time);
649 println!(" Spectral gap: {:.4}", spectral.spectral_gap);
650 println!(
651 " Stationary distribution: {:?}",
652 spectral.stationary_distribution
653 );
654 }
655}
656pub mod func_tests;
657pub mod test_runner;