1use scirs2_core::random::prelude::*;
4use std::collections::HashMap;
5use std::sync::{Arc, Mutex};
6use std::time::{Duration, Instant};
7
8use scirs2_core::random::Rng;
9
10use scirs2_core::ndarray::{Array1, Array2};
11use quantrs2_circuit::prelude::Circuit;
12use quantrs2_core::qubit::QubitId;
13
14use super::{
15 config::{
16 AdaptationCriteria, AdaptiveDDConfig, ControlAlgorithm, DDPerformanceMetric,
17 DDSequenceType, ExplorationStrategy, FeedbackControlConfig, LearningAlgorithm,
18 LearningConfig, MonitoringConfig, MonitoringMetric,
19 },
20 noise::DDNoiseAnalysis,
21 performance::DDPerformanceAnalysis,
22 sequences::{DDSequence, DDSequenceGenerator},
23 DDCircuitExecutor,
24};
25use crate::{DeviceError, DeviceResult};
26
27#[derive(Debug, Clone)]
29pub struct AdaptiveDDState {
30 pub current_sequence: DDSequence,
32 pub performance_history: Vec<PerformanceRecord>,
34 pub noise_history: Vec<NoiseRecord>,
36 pub adaptation_history: Vec<AdaptationRecord>,
38 pub current_metrics: PerformanceMetrics,
40 pub system_health: SystemHealth,
42}
43
44#[derive(Debug, Clone)]
46pub struct PerformanceRecord {
47 pub timestamp: Instant,
49 pub coherence_time: f64,
51 pub fidelity: f64,
53 pub gate_overhead: f64,
55 pub success_rate: f64,
57 pub resource_utilization: f64,
59}
60
61#[derive(Debug, Clone)]
63pub struct NoiseRecord {
64 pub timestamp: Instant,
66 pub noise_levels: HashMap<String, f64>,
68 pub dominant_sources: Vec<String>,
70 pub environmental_conditions: EnvironmentalConditions,
72}
73
74#[derive(Debug, Clone)]
76pub struct EnvironmentalConditions {
77 pub temperature: f64,
79 pub magnetic_field: f64,
81 pub emi_level: f64,
83 pub vibration_level: f64,
85}
86
87#[derive(Debug, Clone)]
89pub struct AdaptationRecord {
90 pub timestamp: Instant,
92 pub previous_sequence: DDSequenceType,
94 pub new_sequence: DDSequenceType,
96 pub adaptation_reason: AdaptationReason,
98 pub expected_improvement: f64,
100 pub actual_improvement: Option<f64>,
102}
103
104#[derive(Debug, Clone, PartialEq)]
106pub enum AdaptationReason {
107 PerformanceDegradation,
109 NoiseChange,
111 EnvironmentalChange,
113 ScheduledOptimization,
115 LearningImprovement,
117 Emergency,
119}
120
121#[derive(Debug, Clone)]
123pub struct PerformanceMetrics {
124 pub coherence_time: f64,
126 pub fidelity: f64,
128 pub error_rates: HashMap<String, f64>,
130 pub resource_usage: ResourceUsage,
132 pub throughput: f64,
134 pub latency: Duration,
136}
137
138#[derive(Debug, Clone)]
140pub struct ResourceUsage {
141 pub cpu_utilization: f64,
143 pub memory_usage: usize,
145 pub network_usage: f64,
147 pub power_consumption: f64,
149}
150
151#[derive(Debug, Clone)]
153pub struct SystemHealth {
154 pub health_score: f64,
156 pub component_health: HashMap<String, f64>,
158 pub active_alerts: Vec<Alert>,
160 pub predicted_issues: Vec<PredictedIssue>,
162}
163
164#[derive(Debug, Clone)]
166pub struct Alert {
167 pub alert_type: AlertType,
169 pub severity: AlertSeverity,
171 pub message: String,
173 pub timestamp: Instant,
175 pub suggested_actions: Vec<String>,
177}
178
179#[derive(Debug, Clone, PartialEq)]
181pub enum AlertType {
182 PerformanceDegradation,
183 NoiseIncrease,
184 HardwareFailure,
185 TemperatureAnomaly,
186 ResourceExhaustion,
187 CommunicationLoss,
188}
189
190#[derive(Debug, Clone, PartialEq)]
192pub enum AlertSeverity {
193 Info,
194 Warning,
195 Error,
196 Critical,
197}
198
199#[derive(Debug, Clone)]
201pub struct PredictedIssue {
202 pub issue_type: String,
204 pub probability: f64,
206 pub time_to_occurrence: Duration,
208 pub potential_impact: f64,
210 pub prevention_strategies: Vec<String>,
212}
213
214pub struct AdaptiveDDSystem {
216 config: AdaptiveDDConfig,
218 state: Arc<Mutex<AdaptiveDDState>>,
220 available_sequences: Vec<DDSequenceType>,
222 learning_agent: Option<LearningAgent>,
224 feedback_controller: FeedbackController,
226 monitor: RealTimeMonitor,
228 sequence_cache: HashMap<String, DDSequence>,
230}
231
232struct LearningAgent {
234 q_table: HashMap<(String, String), f64>,
236 replay_buffer: Vec<Experience>,
238 exploration_strategy: ExplorationStrategy,
240 learning_stats: LearningStatistics,
242 action_counts: HashMap<String, u32>,
244}
245
246#[derive(Debug, Clone)]
248struct Experience {
249 state: String,
251 action: String,
253 reward: f64,
255 next_state: String,
257 done: bool,
259}
260
261#[derive(Debug, Clone)]
263struct LearningStatistics {
264 total_episodes: usize,
266 average_reward: f64,
268 exploration_rate: f64,
270 learning_rate: f64,
272}
273
274struct FeedbackController {
276 algorithm: ControlAlgorithm,
278 pid_state: PIDState,
280 control_history: Vec<ControlAction>,
282}
283
284#[derive(Debug, Clone)]
286struct PIDState {
287 previous_error: f64,
289 integral: f64,
291 last_update: Instant,
293}
294
295#[derive(Debug, Clone)]
297struct ControlAction {
298 timestamp: Instant,
300 output: f64,
302 target: f64,
304 current: f64,
306 error: f64,
308}
309
310struct RealTimeMonitor {
312 monitoring_enabled: bool,
314 metric_collectors: HashMap<MonitoringMetric, MetricCollector>,
316 alert_manager: AlertManager,
318}
319
320struct MetricCollector {
322 last_value: f64,
324 history: Vec<(Instant, f64)>,
326 moving_average: f64,
328 thresholds: (f64, f64), }
331
332struct AlertManager {
334 active_alerts: Vec<Alert>,
336 alert_history: Vec<Alert>,
338 alert_rules: Vec<AlertRule>,
340}
341
342struct AlertRule {
344 metric: MonitoringMetric,
346 condition: AlertCondition,
348 threshold: f64,
350 severity: AlertSeverity,
352 message_template: String,
354}
355
356#[derive(Debug, Clone, PartialEq)]
358enum AlertCondition {
359 GreaterThan,
360 LessThan,
361 Equal,
362 RateOfChange,
363 Anomaly,
364}
365
366impl AdaptiveDDSystem {
367 pub fn new(
369 config: AdaptiveDDConfig,
370 initial_sequence: DDSequence,
371 available_sequences: Vec<DDSequenceType>,
372 ) -> Self {
373 let initial_state = AdaptiveDDState {
374 current_sequence: initial_sequence,
375 performance_history: Vec::new(),
376 noise_history: Vec::new(),
377 adaptation_history: Vec::new(),
378 current_metrics: PerformanceMetrics {
379 coherence_time: 0.0,
380 fidelity: 0.0,
381 error_rates: HashMap::new(),
382 resource_usage: ResourceUsage {
383 cpu_utilization: 0.0,
384 memory_usage: 0,
385 network_usage: 0.0,
386 power_consumption: 0.0,
387 },
388 throughput: 0.0,
389 latency: Duration::from_nanos(0),
390 },
391 system_health: SystemHealth {
392 health_score: 1.0,
393 component_health: HashMap::new(),
394 active_alerts: Vec::new(),
395 predicted_issues: Vec::new(),
396 },
397 };
398
399 let learning_agent =
400 if config.learning_config.learning_algorithm != LearningAlgorithm::QLearning {
401 None
402 } else {
403 Some(LearningAgent {
404 q_table: HashMap::new(),
405 replay_buffer: Vec::new(),
406 exploration_strategy: ExplorationStrategy::EpsilonGreedy(0.1),
407 learning_stats: LearningStatistics {
408 total_episodes: 0,
409 average_reward: 0.0,
410 exploration_rate: 0.1,
411 learning_rate: config.learning_config.learning_rate,
412 },
413 action_counts: HashMap::new(),
414 })
415 };
416
417 Self {
418 config,
419 state: Arc::new(Mutex::new(initial_state)),
420 available_sequences,
421 learning_agent,
422 feedback_controller: FeedbackController {
423 algorithm: ControlAlgorithm::PID,
424 pid_state: PIDState {
425 previous_error: 0.0,
426 integral: 0.0,
427 last_update: Instant::now(),
428 },
429 control_history: Vec::new(),
430 },
431 monitor: RealTimeMonitor {
432 monitoring_enabled: true,
433 metric_collectors: HashMap::new(),
434 alert_manager: AlertManager {
435 active_alerts: Vec::new(),
436 alert_history: Vec::new(),
437 alert_rules: Vec::new(),
438 },
439 },
440 sequence_cache: HashMap::new(),
441 }
442 }
443
444 pub fn start(&mut self, executor: &dyn DDCircuitExecutor) -> DeviceResult<()> {
446 println!("Starting adaptive DD system");
447
448 self.initialize_monitoring()?;
450
451 self.start_control_loop(executor)?;
453
454 Ok(())
455 }
456
457 pub fn update_performance(
459 &mut self,
460 performance_analysis: &DDPerformanceAnalysis,
461 noise_analysis: &DDNoiseAnalysis,
462 ) -> DeviceResult<()> {
463 let mut state = self.state.lock().unwrap();
464
465 let performance_record = PerformanceRecord {
467 timestamp: Instant::now(),
468 coherence_time: performance_analysis
469 .metrics
470 .get(&DDPerformanceMetric::CoherenceTime)
471 .copied()
472 .unwrap_or(0.0),
473 fidelity: performance_analysis
474 .metrics
475 .get(&DDPerformanceMetric::ProcessFidelity)
476 .copied()
477 .unwrap_or(0.95),
478 gate_overhead: performance_analysis
479 .metrics
480 .get(&DDPerformanceMetric::GateOverhead)
481 .copied()
482 .unwrap_or(1.0),
483 success_rate: performance_analysis
484 .metrics
485 .get(&DDPerformanceMetric::RobustnessScore)
486 .copied()
487 .unwrap_or(0.9),
488 resource_utilization: performance_analysis
489 .metrics
490 .get(&DDPerformanceMetric::ResourceEfficiency)
491 .copied()
492 .unwrap_or(0.8),
493 };
494 state.performance_history.push(performance_record);
495
496 let noise_record = NoiseRecord {
498 timestamp: Instant::now(),
499 noise_levels: noise_analysis
500 .noise_characterization
501 .noise_types
502 .iter()
503 .map(|(noise_type, characteristics)| {
504 (format!("{:?}", noise_type), characteristics.strength)
505 })
506 .collect(),
507 dominant_sources: noise_analysis
508 .noise_characterization
509 .dominant_sources
510 .iter()
511 .map(|source| format!("{:?}", source.source_type))
512 .collect(),
513 environmental_conditions: EnvironmentalConditions {
514 temperature: 20.0, magnetic_field: 0.1,
516 emi_level: 0.05,
517 vibration_level: 0.02,
518 },
519 };
520 state.noise_history.push(noise_record);
521
522 state.current_metrics.coherence_time = performance_analysis
524 .metrics
525 .get(&DDPerformanceMetric::CoherenceTime)
526 .copied()
527 .unwrap_or(0.0);
528 state.current_metrics.fidelity = performance_analysis
529 .metrics
530 .get(&DDPerformanceMetric::ProcessFidelity)
531 .copied()
532 .unwrap_or(0.95);
533
534 if self.should_adapt(&state)? {
536 drop(state); self.trigger_adaptation()?;
538 }
539
540 Ok(())
541 }
542
543 fn should_adapt(&self, state: &AdaptiveDDState) -> DeviceResult<bool> {
545 let criteria = &self.config.adaptation_criteria;
546
547 if state.current_metrics.coherence_time < criteria.coherence_threshold {
549 return Ok(true);
550 }
551
552 if state.current_metrics.fidelity < criteria.fidelity_threshold {
554 return Ok(true);
555 }
556
557 let average_noise: f64 = state.current_metrics.error_rates.values().sum::<f64>()
559 / state.current_metrics.error_rates.len().max(1) as f64;
560 if average_noise > criteria.noise_threshold {
561 return Ok(true);
562 }
563
564 Ok(false)
565 }
566
567 fn trigger_adaptation(&mut self) -> DeviceResult<()> {
569 println!("Triggering DD adaptation");
570
571 let current_state = self.analyze_current_state()?;
573
574 let new_sequence_type = self.select_optimal_sequence(¤t_state)?;
576
577 let new_sequence = self.generate_sequence(&new_sequence_type)?;
579
580 let adaptation_record = AdaptationRecord {
582 timestamp: Instant::now(),
583 previous_sequence: self
584 .state
585 .lock()
586 .unwrap()
587 .current_sequence
588 .sequence_type
589 .clone(),
590 new_sequence: new_sequence_type,
591 adaptation_reason: AdaptationReason::PerformanceDegradation,
592 expected_improvement: 0.1, actual_improvement: None,
594 };
595
596 {
598 let mut state = self.state.lock().unwrap();
599 state.current_sequence = new_sequence;
600 state.adaptation_history.push(adaptation_record);
601 }
602
603 println!("DD adaptation completed");
604 Ok(())
605 }
606
607 fn analyze_current_state(&self) -> DeviceResult<String> {
609 let state = self.state.lock().unwrap();
610
611 let coherence_level = if state.current_metrics.coherence_time > 50e-6 {
613 "high"
614 } else if state.current_metrics.coherence_time > 20e-6 {
615 "medium"
616 } else {
617 "low"
618 };
619
620 let fidelity_level = if state.current_metrics.fidelity > 0.99 {
621 "high"
622 } else if state.current_metrics.fidelity > 0.95 {
623 "medium"
624 } else {
625 "low"
626 };
627
628 let noise_level = {
629 let avg_noise: f64 = state.current_metrics.error_rates.values().sum::<f64>()
630 / state.current_metrics.error_rates.len().max(1) as f64;
631 if avg_noise < 0.01 {
632 "low"
633 } else if avg_noise < 0.05 {
634 "medium"
635 } else {
636 "high"
637 }
638 };
639
640 Ok(format!(
641 "coherence_{}_fidelity_{}_noise_{}",
642 coherence_level, fidelity_level, noise_level
643 ))
644 }
645
646 fn select_optimal_sequence(&mut self, current_state: &str) -> DeviceResult<DDSequenceType> {
648 if let Some(ref mut agent) = self.learning_agent {
650 let available_sequences = self.available_sequences.clone();
652 return Self::select_sequence_with_learning_static(
653 agent,
654 current_state,
655 &available_sequences,
656 );
657 }
658
659 self.select_sequence_rule_based(current_state)
661 }
662
663 fn select_sequence_with_learning_static(
665 agent: &mut LearningAgent,
666 current_state: &str,
667 available_sequences: &[DDSequenceType],
668 ) -> DeviceResult<DDSequenceType> {
669 let mut best_sequence = DDSequenceType::CPMG { n_pulses: 1 };
671 let mut best_q_value = f64::NEG_INFINITY;
672
673 for sequence_type in available_sequences {
674 let action = format!("{:?}", sequence_type);
675 let q_value = agent
676 .q_table
677 .get(&(current_state.to_string(), action))
678 .copied()
679 .unwrap_or(0.0);
680
681 if q_value > best_q_value {
682 best_q_value = q_value;
683 best_sequence = sequence_type.clone();
684 }
685 }
686
687 match agent.exploration_strategy {
689 ExplorationStrategy::EpsilonGreedy(epsilon) => {
690 if thread_rng().gen::<f64>() < epsilon {
691 let random_idx = thread_rng().gen_range(0..available_sequences.len());
693 best_sequence = available_sequences[random_idx].clone();
694 }
695 }
696 ExplorationStrategy::UCB(c) => {
697 let total_visits = agent.action_counts.values().sum::<u32>() as f64;
699 let mut best_ucb = f64::NEG_INFINITY;
700
701 for sequence_type in available_sequences {
702 let action = format!("{:?}", sequence_type);
703 let visits = agent.action_counts.get(&action).copied().unwrap_or(0) as f64;
704 let q_value = agent
705 .q_table
706 .get(&(current_state.to_string(), action.clone()))
707 .copied()
708 .unwrap_or(0.0);
709
710 let ucb_value = if visits > 0.0 {
711 q_value + c * (total_visits.ln() / visits).sqrt()
712 } else {
713 f64::INFINITY };
715
716 if ucb_value > best_ucb {
717 best_ucb = ucb_value;
718 best_sequence = sequence_type.clone();
719 }
720 }
721 }
722 ExplorationStrategy::Boltzmann(temperature) => {
723 let mut probabilities = Vec::new();
725 let mut exp_sum = 0.0;
726
727 for sequence_type in available_sequences {
728 let action = format!("{:?}", sequence_type);
729 let q_value = agent
730 .q_table
731 .get(&(current_state.to_string(), action))
732 .copied()
733 .unwrap_or(0.0);
734 let exp_val = (q_value / temperature).exp();
735 probabilities.push(exp_val);
736 exp_sum += exp_val;
737 }
738
739 for prob in &mut probabilities {
741 *prob /= exp_sum;
742 }
743
744 let mut cumsum = 0.0;
746 let rand_val = thread_rng().gen::<f64>();
747 for (i, prob) in probabilities.iter().enumerate() {
748 cumsum += prob;
749 if rand_val <= cumsum {
750 best_sequence = available_sequences[i].clone();
751 break;
752 }
753 }
754 }
755 ExplorationStrategy::ThompsonSampling => {
756 if thread_rng().gen::<f64>() < 0.1 {
759 let random_idx = thread_rng().gen_range(0..available_sequences.len());
760 best_sequence = available_sequences[random_idx].clone();
761 }
762 }
763 }
764
765 Ok(best_sequence)
766 }
767
768 fn select_sequence_with_learning(
770 &self,
771 agent: &mut LearningAgent,
772 current_state: &str,
773 ) -> DeviceResult<DDSequenceType> {
774 let mut best_sequence = DDSequenceType::CPMG { n_pulses: 1 };
776 let mut best_q_value = f64::NEG_INFINITY;
777
778 for sequence_type in &self.available_sequences {
779 let action = format!("{:?}", sequence_type);
780 let q_value = agent
781 .q_table
782 .get(&(current_state.to_string(), action))
783 .copied()
784 .unwrap_or(0.0);
785
786 if q_value > best_q_value {
787 best_q_value = q_value;
788 best_sequence = sequence_type.clone();
789 }
790 }
791
792 match agent.exploration_strategy {
794 ExplorationStrategy::EpsilonGreedy(epsilon) => {
795 if thread_rng().gen::<f64>() < epsilon {
796 let random_idx =
798 thread_rng().gen_range(0..self.available_sequences.len());
799 best_sequence = self.available_sequences[random_idx].clone();
800 }
801 }
802 _ => {
803 }
805 }
806
807 Ok(best_sequence)
808 }
809
810 fn select_sequence_rule_based(&self, current_state: &str) -> DeviceResult<DDSequenceType> {
812 match current_state {
814 s if s.contains("noise_high") => Ok(DDSequenceType::XY8),
815 s if s.contains("coherence_low") => Ok(DDSequenceType::UDD { n_pulses: 3 }),
816 s if s.contains("fidelity_low") => Ok(DDSequenceType::XY4),
817 _ => Ok(DDSequenceType::CPMG { n_pulses: 1 }),
818 }
819 }
820
821 fn generate_sequence(&mut self, sequence_type: &DDSequenceType) -> DeviceResult<DDSequence> {
823 let cache_key = format!("{:?}", sequence_type);
825 if let Some(cached_sequence) = self.sequence_cache.get(&cache_key) {
826 return Ok(cached_sequence.clone());
827 }
828
829 let target_qubits = vec![
831 quantrs2_core::qubit::QubitId(0),
832 quantrs2_core::qubit::QubitId(1),
833 ];
834 let duration = 100e-6; let sequence =
837 DDSequenceGenerator::generate_base_sequence(sequence_type, &target_qubits, duration)?;
838
839 self.sequence_cache.insert(cache_key, sequence.clone());
841
842 Ok(sequence)
843 }
844
845 fn initialize_monitoring(&mut self) -> DeviceResult<()> {
847 println!("Initializing DD monitoring system");
848
849 for metric in &self.config.monitoring_config.metrics {
851 let collector = MetricCollector {
852 last_value: 0.0,
853 history: Vec::new(),
854 moving_average: 0.0,
855 thresholds: (0.8, 0.6), };
857 self.monitor
858 .metric_collectors
859 .insert(metric.clone(), collector);
860 }
861
862 self.monitor.alert_manager.alert_rules.push(AlertRule {
864 metric: MonitoringMetric::CoherenceTime,
865 condition: AlertCondition::LessThan,
866 threshold: 20e-6, severity: AlertSeverity::Warning,
868 message_template: "Coherence time degraded below threshold".to_string(),
869 });
870
871 self.monitor.alert_manager.alert_rules.push(AlertRule {
872 metric: MonitoringMetric::Fidelity,
873 condition: AlertCondition::LessThan,
874 threshold: 0.95,
875 severity: AlertSeverity::Error,
876 message_template: "Process fidelity degraded below threshold".to_string(),
877 });
878
879 Ok(())
880 }
881
882 fn start_control_loop(&mut self, _executor: &dyn DDCircuitExecutor) -> DeviceResult<()> {
884 println!("Starting DD control loop");
885
886 Ok(())
890 }
891
892 pub fn get_current_state(&self) -> AdaptiveDDState {
894 self.state.lock().unwrap().clone()
895 }
896
897 pub fn get_performance_history(&self) -> Vec<PerformanceRecord> {
899 self.state.lock().unwrap().performance_history.clone()
900 }
901
902 pub fn get_adaptation_statistics(&self) -> AdaptationStatistics {
904 let state = self.state.lock().unwrap();
905
906 let total_adaptations = state.adaptation_history.len();
907 let successful_adaptations = state
908 .adaptation_history
909 .iter()
910 .filter(|record| record.actual_improvement.unwrap_or(0.0) > 0.0)
911 .count();
912
913 let success_rate = if total_adaptations > 0 {
914 successful_adaptations as f64 / total_adaptations as f64
915 } else {
916 0.0
917 };
918
919 let average_improvement = state
920 .adaptation_history
921 .iter()
922 .filter_map(|record| record.actual_improvement)
923 .sum::<f64>()
924 / state.adaptation_history.len().max(1) as f64;
925
926 AdaptationStatistics {
927 total_adaptations,
928 successful_adaptations,
929 success_rate,
930 average_improvement,
931 most_used_sequence: self.get_most_used_sequence(&state),
932 adaptation_frequency: self.calculate_adaptation_frequency(&state),
933 }
934 }
935
936 fn get_most_used_sequence(&self, state: &AdaptiveDDState) -> DDSequenceType {
938 let mut sequence_counts: HashMap<DDSequenceType, usize> = HashMap::new();
939
940 for record in &state.adaptation_history {
941 *sequence_counts
942 .entry(record.new_sequence.clone())
943 .or_insert(0) += 1;
944 }
945
946 sequence_counts
947 .into_iter()
948 .max_by_key(|(_, count)| *count)
949 .map(|(sequence, _)| sequence)
950 .unwrap_or(DDSequenceType::CPMG { n_pulses: 1 })
951 }
952
953 fn calculate_adaptation_frequency(&self, state: &AdaptiveDDState) -> f64 {
955 if state.adaptation_history.len() < 2 {
956 return 0.0;
957 }
958
959 let first_adaptation = state.adaptation_history.first().unwrap().timestamp;
960 let last_adaptation = state.adaptation_history.last().unwrap().timestamp;
961 let time_span = last_adaptation
962 .duration_since(first_adaptation)
963 .as_secs_f64();
964
965 if time_span > 0.0 {
966 state.adaptation_history.len() as f64 / time_span
967 } else {
968 0.0
969 }
970 }
971}
972
973#[derive(Debug, Clone)]
975pub struct AdaptationStatistics {
976 pub total_adaptations: usize,
978 pub successful_adaptations: usize,
980 pub success_rate: f64,
982 pub average_improvement: f64,
984 pub most_used_sequence: DDSequenceType,
986 pub adaptation_frequency: f64,
988}
989
990#[cfg(test)]
991mod tests {
992 use super::*;
993 use crate::dynamical_decoupling::{
994 config::DDSequenceType,
995 sequences::{DDSequence, DDSequenceProperties, ResourceRequirements, SequenceSymmetry},
996 };
997
998 fn create_test_sequence() -> DDSequence {
999 DDSequence {
1000 sequence_type: DDSequenceType::CPMG { n_pulses: 1 },
1001 target_qubits: vec![quantrs2_core::qubit::QubitId(0)],
1002 duration: 100e-6,
1003 circuit: Circuit::<32>::new(),
1004 pulse_timings: vec![50e-6],
1005 pulse_phases: vec![std::f64::consts::PI],
1006 properties: DDSequenceProperties {
1007 pulse_count: 1,
1008 sequence_order: 1,
1009 periodicity: 1,
1010 symmetry: SequenceSymmetry {
1011 time_reversal: true,
1012 phase_symmetry: true,
1013 rotational_symmetry: false,
1014 inversion_symmetry: true,
1015 },
1016 noise_suppression: std::collections::HashMap::new(),
1017 resource_requirements: ResourceRequirements {
1018 gate_count: 1,
1019 circuit_depth: 1,
1020 required_connectivity: Vec::new(),
1021 execution_time: 100e-6,
1022 memory_requirements: 8,
1023 },
1024 },
1025 }
1026 }
1027
1028 #[test]
1029 fn test_adaptive_dd_system_creation() {
1030 let config = AdaptiveDDConfig::default();
1031 let initial_sequence = create_test_sequence();
1032 let available_sequences = vec![
1033 DDSequenceType::CPMG { n_pulses: 1 },
1034 DDSequenceType::XY4,
1035 DDSequenceType::XY8,
1036 ];
1037
1038 let system = AdaptiveDDSystem::new(config, initial_sequence, available_sequences);
1039 let state = system.get_current_state();
1040
1041 assert!(matches!(
1042 state.current_sequence.sequence_type,
1043 DDSequenceType::CPMG { .. }
1044 ));
1045 assert_eq!(state.system_health.health_score, 1.0);
1046 }
1047
1048 #[test]
1049 fn test_rule_based_sequence_selection() {
1050 let config = AdaptiveDDConfig::default();
1051 let initial_sequence = create_test_sequence();
1052 let available_sequences = vec![
1053 DDSequenceType::CPMG { n_pulses: 1 },
1054 DDSequenceType::XY4,
1055 DDSequenceType::XY8,
1056 ];
1057
1058 let system = AdaptiveDDSystem::new(config, initial_sequence, available_sequences);
1059
1060 let high_noise_state = "coherence_medium_fidelity_medium_noise_high";
1061 let low_coherence_state = "coherence_low_fidelity_medium_noise_medium";
1062 let low_fidelity_state = "coherence_medium_fidelity_low_noise_medium";
1063
1064 assert_eq!(
1065 system.select_sequence_rule_based(high_noise_state).unwrap(),
1066 DDSequenceType::XY8
1067 );
1068 assert_eq!(
1069 system
1070 .select_sequence_rule_based(low_coherence_state)
1071 .unwrap(),
1072 DDSequenceType::UDD { n_pulses: 3 }
1073 );
1074 assert_eq!(
1075 system
1076 .select_sequence_rule_based(low_fidelity_state)
1077 .unwrap(),
1078 DDSequenceType::XY4
1079 );
1080 }
1081
1082 #[test]
1083 fn test_adaptation_statistics() {
1084 let config = AdaptiveDDConfig::default();
1085 let initial_sequence = create_test_sequence();
1086 let available_sequences = vec![DDSequenceType::CPMG { n_pulses: 1 }, DDSequenceType::XY4];
1087
1088 let system = AdaptiveDDSystem::new(config, initial_sequence, available_sequences);
1089 let stats = system.get_adaptation_statistics();
1090
1091 assert_eq!(stats.total_adaptations, 0);
1092 assert_eq!(stats.success_rate, 0.0);
1093 assert!(matches!(
1094 stats.most_used_sequence,
1095 DDSequenceType::CPMG { .. }
1096 ));
1097 }
1098}