1use crate::gate_translation::GateType;
7use crate::buffer_pool::BufferPool;
9use std::time::{Duration, Instant};
10
11#[derive(Debug, Clone)]
13pub struct QuantumGate {
14 gate_type: GateType,
15 target_qubits: Vec<usize>,
16 control_qubits: Option<Vec<usize>>,
17}
18
19impl QuantumGate {
20 pub fn new(
21 gate_type: GateType,
22 target_qubits: Vec<usize>,
23 control_qubits: Option<Vec<usize>>,
24 ) -> Self {
25 Self {
26 gate_type,
27 target_qubits,
28 control_qubits,
29 }
30 }
31
32 pub fn gate_type(&self) -> &GateType {
33 &self.gate_type
34 }
35
36 pub fn target_qubits(&self) -> &[usize] {
37 &self.target_qubits
38 }
39
40 pub fn control_qubits(&self) -> Option<&[usize]> {
41 self.control_qubits.as_deref()
42 }
43}
44use crate::error::QuantRS2Error;
45use std::collections::{HashMap, VecDeque};
46use scirs2_core::Complex64;
48
49#[derive(Debug, Clone)]
51pub struct PerformanceTracker {
52 gate_timing: HashMap<String, Duration>,
53 memory_usage: Vec<usize>,
54 computation_start: Option<Instant>,
55 total_execution_time: Duration,
56 simd_operations_count: usize,
57 parallel_operations_count: usize,
58}
59
60impl PerformanceTracker {
61 pub fn new() -> Self {
62 Self {
63 gate_timing: HashMap::new(),
64 memory_usage: Vec::new(),
65 computation_start: None,
66 total_execution_time: Duration::new(0, 0),
67 simd_operations_count: 0,
68 parallel_operations_count: 0,
69 }
70 }
71
72 pub fn start_timing(&mut self) {
73 self.computation_start = Some(Instant::now());
74 }
75
76 pub fn record_gate_timing(&mut self, gate_type: &str, duration: Duration) {
77 *self
78 .gate_timing
79 .entry(gate_type.to_string())
80 .or_insert(Duration::new(0, 0)) += duration;
81 }
82
83 pub fn record_memory_usage(&mut self, usage: usize) {
84 self.memory_usage.push(usage);
85 }
86
87 pub fn increment_simd_ops(&mut self) {
88 self.simd_operations_count += 1;
89 }
90
91 pub fn increment_parallel_ops(&mut self) {
92 self.parallel_operations_count += 1;
93 }
94
95 pub fn finish_timing(&mut self) {
96 if let Some(start) = self.computation_start.take() {
97 self.total_execution_time = start.elapsed();
98 }
99 }
100}
101
102#[derive(Debug, Clone)]
104pub struct DebugConfig {
105 pub track_state_vectors: bool,
107 pub analyze_entanglement: bool,
109 pub visualize_amplitudes: bool,
111 pub track_gate_effects: bool,
113 pub max_detailed_qubits: usize,
115 pub sampling_rate: f64,
117 pub enable_breakpoints: bool,
119 pub memory_limit_mb: usize,
121}
122
123impl Default for DebugConfig {
124 fn default() -> Self {
125 Self {
126 track_state_vectors: true,
127 analyze_entanglement: true,
128 visualize_amplitudes: true,
129 track_gate_effects: true,
130 max_detailed_qubits: 10,
131 sampling_rate: 0.1,
132 enable_breakpoints: true,
133 memory_limit_mb: 1024,
134 }
135 }
136}
137
138pub struct QuantumDebugger {
140 config: DebugConfig,
141 execution_trace: Vec<DebugStep>,
142 breakpoints: Vec<Breakpoint>,
143 current_step: usize,
144 state_history: VecDeque<StateSnapshot>,
145 gate_statistics: GateStatistics,
146 buffer_pool: Option<BufferPool<Complex64>>,
147 performance_metrics: PerformanceTracker,
148}
149
150impl QuantumDebugger {
151 pub fn new() -> Self {
153 let config = DebugConfig::default();
154 Self::with_config(config)
155 }
156
157 pub fn with_config(config: DebugConfig) -> Self {
159 let buffer_pool = if config.memory_limit_mb > 0 {
160 Some(BufferPool::<Complex64>::new())
161 } else {
162 None
163 };
164
165 Self {
166 config,
167 execution_trace: Vec::new(),
168 breakpoints: Vec::new(),
169 current_step: 0,
170 state_history: VecDeque::new(),
171 gate_statistics: GateStatistics::new(),
172 buffer_pool,
173 performance_metrics: PerformanceTracker::new(),
174 }
175 }
176
177 pub fn set_breakpoint(&mut self, step: usize, condition: BreakpointCondition) {
179 self.breakpoints.push(Breakpoint {
180 step,
181 condition,
182 enabled: true,
183 });
184 }
185
186 pub fn remove_breakpoint(&mut self, step: usize) {
188 self.breakpoints.retain(|bp| bp.step != step);
189 }
190
191 pub fn debug_circuit(
193 &mut self,
194 circuit: &[QuantumGate],
195 initial_state: &[Complex64],
196 num_qubits: usize,
197 ) -> Result<DebugResult, QuantRS2Error> {
198 self.reset_debug_session();
199
200 self.performance_metrics.start_timing();
202
203 let mut current_state = initial_state.to_vec();
204 let mut step = 0;
205
206 if self.config.track_state_vectors {
208 self.record_state_snapshot(step, ¤t_state, None, num_qubits)?;
209 }
210
211 for (gate_index, gate) in circuit.iter().enumerate() {
212 step += 1;
213
214 if self.should_break_at_step(step, ¤t_state, gate) {
216 return Ok(DebugResult {
217 status: DebugStatus::BreakpointHit(step),
218 final_state: current_state,
219 execution_trace: self.execution_trace.clone(),
220 analysis: self.generate_analysis(num_qubits)?,
221 });
222 }
223
224 let gate_start = Instant::now();
226 let gate_effect =
227 self.apply_gate_with_debugging(gate, &mut current_state, step, num_qubits)?;
228 let gate_duration = gate_start.elapsed();
229
230 let gate_type_str = format!("{:?}", gate.gate_type());
232 self.performance_metrics
233 .record_gate_timing(&gate_type_str, gate_duration);
234 self.performance_metrics
235 .record_memory_usage(current_state.len() * std::mem::size_of::<Complex64>());
236
237 self.execution_trace.push(DebugStep {
238 step,
239 gate: gate.clone(),
240 gate_effect,
241 state_before: if self.config.track_state_vectors {
242 Some(self.get_previous_state())
243 } else {
244 None
245 },
246 state_after: if self.config.track_state_vectors {
247 Some(current_state.clone())
248 } else {
249 None
250 },
251 entanglement_info: if self.config.analyze_entanglement {
252 Some(self.analyze_entanglement(¤t_state, num_qubits)?)
253 } else {
254 None
255 },
256 amplitude_analysis: if self.config.visualize_amplitudes {
257 Some(self.analyze_amplitudes(¤t_state)?)
258 } else {
259 None
260 },
261 });
262
263 if self.config.track_state_vectors {
265 self.record_state_snapshot(step, ¤t_state, Some(gate_index), num_qubits)?;
266 }
267
268 self.gate_statistics.record_gate(gate);
270 }
271
272 self.current_step = step;
273
274 self.performance_metrics.finish_timing();
276
277 Ok(DebugResult {
278 status: DebugStatus::Completed,
279 final_state: current_state,
280 execution_trace: self.execution_trace.clone(),
281 analysis: self.generate_analysis(num_qubits)?,
282 })
283 }
284
285 fn reset_debug_session(&mut self) {
287 self.execution_trace.clear();
288 self.current_step = 0;
289 self.state_history.clear();
290 self.gate_statistics = GateStatistics::new();
291 self.performance_metrics = PerformanceTracker::new();
292 }
293
294 fn should_break_at_step(&self, step: usize, state: &[Complex64], gate: &QuantumGate) -> bool {
296 if !self.config.enable_breakpoints {
297 return false;
298 }
299
300 for breakpoint in &self.breakpoints {
301 if breakpoint.enabled && breakpoint.step == step {
302 match &breakpoint.condition {
303 BreakpointCondition::Always => return true,
304 BreakpointCondition::StateCondition(condition) => {
305 if self.evaluate_state_condition(state, condition) {
306 return true;
307 }
308 }
309 BreakpointCondition::GateType(gate_type) => {
310 if std::mem::discriminant(gate.gate_type())
311 == std::mem::discriminant(gate_type)
312 {
313 return true;
314 }
315 }
316 BreakpointCondition::QubitIndex(qubit) => {
317 if gate.target_qubits().contains(qubit) {
318 return true;
319 }
320 }
321 }
322 }
323 }
324
325 false
326 }
327
328 fn evaluate_state_condition(&self, state: &[Complex64], condition: &StateCondition) -> bool {
330 match condition {
331 StateCondition::AmplitudeThreshold { qubit, threshold } => {
332 if let Some(amplitude) = self.get_qubit_amplitude(state, *qubit) {
333 amplitude.norm_sqr() > *threshold
334 } else {
335 false
336 }
337 }
338 StateCondition::EntanglementThreshold { threshold } => {
339 if let Ok(entanglement) = self.calculate_total_entanglement(state) {
340 entanglement > *threshold
341 } else {
342 false
343 }
344 }
345 StateCondition::PhaseDifference {
346 qubit1,
347 qubit2,
348 threshold,
349 } => {
350 if let (Some(amp1), Some(amp2)) = (
351 self.get_qubit_amplitude(state, *qubit1),
352 self.get_qubit_amplitude(state, *qubit2),
353 ) {
354 let phase_diff = (amp1.arg() - amp2.arg()).abs();
355 phase_diff > *threshold
356 } else {
357 false
358 }
359 }
360 }
361 }
362
363 fn apply_gate_with_debugging(
365 &mut self,
366 gate: &QuantumGate,
367 state: &mut Vec<Complex64>,
368 _step: usize,
369 num_qubits: usize,
370 ) -> Result<GateEffect, QuantRS2Error> {
371 let state_before = state.clone();
372
373 self.apply_gate_to_state(gate, state, num_qubits)?;
375
376 let effect = self.calculate_gate_effect(&state_before, state, gate)?;
378
379 Ok(effect)
380 }
381
382 fn apply_gate_to_state(
384 &self,
385 gate: &QuantumGate,
386 state: &mut Vec<Complex64>,
387 num_qubits: usize,
388 ) -> Result<(), QuantRS2Error> {
389 use crate::gate_translation::GateType;
390
391 match gate.gate_type() {
392 GateType::X => {
393 if let Some(&target) = gate.target_qubits().first() {
394 let target_bit = 1 << target;
395 for i in 0..(1 << num_qubits) {
396 let j = i ^ target_bit;
397 if i < j {
398 state.swap(i, j);
399 }
400 }
401 }
402 }
403 GateType::Y => {
404 if let Some(&target) = gate.target_qubits().first() {
405 let target_bit = 1 << target;
406 for i in 0..(1 << num_qubits) {
407 let j = i ^ target_bit;
408 if i < j {
409 let temp = state[i];
410 state[i] = Complex64::new(0.0, 1.0) * state[j];
411 state[j] = Complex64::new(0.0, -1.0) * temp;
412 }
413 }
414 }
415 }
416 GateType::Z => {
417 if let Some(&target) = gate.target_qubits().first() {
418 let target_bit = 1 << target;
419 for i in 0..(1 << num_qubits) {
420 if i & target_bit != 0 {
421 state[i] *= -1.0;
422 }
423 }
424 }
425 }
426 GateType::H => {
427 if let Some(&target) = gate.target_qubits().first() {
428 let target_bit = 1 << target;
429 let inv_sqrt2 = 1.0 / std::f64::consts::SQRT_2;
430 for i in 0..(1 << num_qubits) {
431 let j = i ^ target_bit;
432 if i < j {
433 let temp = state[i];
434 state[i] = inv_sqrt2 * (temp + state[j]);
435 state[j] = inv_sqrt2 * (temp - state[j]);
436 }
437 }
438 }
439 }
440 GateType::CNOT => {
441 if gate.target_qubits().len() >= 2 {
442 let control = gate.target_qubits()[0];
443 let target = gate.target_qubits()[1];
444 let control_bit = 1 << control;
445 let target_bit = 1 << target;
446
447 for i in 0..(1 << num_qubits) {
448 if i & control_bit != 0 {
449 let j = i ^ target_bit;
450 if i != j {
451 state.swap(i, j);
452 }
453 }
454 }
455 }
456 }
457 _ => {
458 }
460 }
461
462 Ok(())
463 }
464
465 fn calculate_gate_effect(
467 &self,
468 state_before: &[Complex64],
469 state_after: &[Complex64],
470 gate: &QuantumGate,
471 ) -> Result<GateEffect, QuantRS2Error> {
472 let amplitude_changes = self.calculate_amplitude_changes(state_before, state_after);
473 let phase_changes = self.calculate_phase_changes(state_before, state_after);
474 let entanglement_change = self.calculate_entanglement_change(state_before, state_after)?;
475
476 Ok(GateEffect {
477 gate_type: format!("{:?}", gate.gate_type()),
478 target_qubits: gate.target_qubits().to_vec(),
479 amplitude_changes,
480 phase_changes,
481 entanglement_change,
482 fidelity: self.calculate_state_fidelity(state_before, state_after),
483 })
484 }
485
486 fn calculate_amplitude_changes(&self, before: &[Complex64], after: &[Complex64]) -> Vec<f64> {
488 before
489 .iter()
490 .zip(after.iter())
491 .map(|(b, a)| (a.norm() - b.norm()).abs())
492 .collect()
493 }
494
495 fn calculate_phase_changes(&self, before: &[Complex64], after: &[Complex64]) -> Vec<f64> {
497 before
498 .iter()
499 .zip(after.iter())
500 .map(|(b, a)| {
501 if b.norm() > 1e-10 && a.norm() > 1e-10 {
502 (a.arg() - b.arg()).abs()
503 } else {
504 0.0
505 }
506 })
507 .collect()
508 }
509
510 fn calculate_entanglement_change(
512 &self,
513 before: &[Complex64],
514 after: &[Complex64],
515 ) -> Result<f64, QuantRS2Error> {
516 let ent_before = self.calculate_total_entanglement(before)?;
517 let ent_after = self.calculate_total_entanglement(after)?;
518 Ok(ent_after - ent_before)
519 }
520
521 fn calculate_state_fidelity(&self, state1: &[Complex64], state2: &[Complex64]) -> f64 {
523 let overlap: Complex64 = state1
524 .iter()
525 .zip(state2.iter())
526 .map(|(s1, s2)| s1.conj() * s2)
527 .sum();
528 overlap.norm_sqr()
529 }
530
531 fn record_state_snapshot(
533 &mut self,
534 step: usize,
535 state: &[Complex64],
536 gate_index: Option<usize>,
537 num_qubits: usize,
538 ) -> Result<(), QuantRS2Error> {
539 let estimated_size = state.len() * 16; let total_size = self.state_history.len() * estimated_size;
542
543 if total_size > self.config.memory_limit_mb * 1024 * 1024 {
544 while self.state_history.len() > 100 {
546 self.state_history.pop_front();
547 }
548 }
549
550 let snapshot = StateSnapshot {
551 step,
552 gate_index,
553 state: if num_qubits <= self.config.max_detailed_qubits {
554 state.to_vec()
555 } else {
556 self.sample_state(state)?
558 },
559 metadata: StateMetadata {
560 entropy: self.calculate_von_neumann_entropy(state)?,
561 purity: self.calculate_purity(state)?,
562 norm: state.iter().map(|c| c.norm_sqr()).sum::<f64>().sqrt(),
563 },
564 };
565
566 self.state_history.push_back(snapshot);
567 Ok(())
568 }
569
570 fn sample_state(&self, state: &[Complex64]) -> Result<Vec<Complex64>, QuantRS2Error> {
572 let sample_size = (state.len() as f64 * self.config.sampling_rate).ceil() as usize;
573 let step = state.len() / sample_size;
574
575 Ok(state.iter().step_by(step.max(1)).cloned().collect())
576 }
577
578 fn get_previous_state(&self) -> Vec<Complex64> {
580 self.state_history
581 .back()
582 .map(|snapshot| snapshot.state.clone())
583 .unwrap_or_default()
584 }
585
586 fn analyze_entanglement(
588 &self,
589 state: &[Complex64],
590 num_qubits: usize,
591 ) -> Result<EntanglementAnalysis, QuantRS2Error> {
592 let total_entanglement = self.calculate_total_entanglement(state)?;
593 let pairwise_entanglement = self.calculate_pairwise_entanglement(state, num_qubits)?;
594 let entanglement_spectrum = self.calculate_entanglement_spectrum(state, num_qubits)?;
595 let max_entangled_pair = self.find_max_entangled_pair(&pairwise_entanglement);
596
597 Ok(EntanglementAnalysis {
598 total_entanglement,
599 pairwise_entanglement,
600 entanglement_spectrum,
601 max_entangled_pair,
602 })
603 }
604
605 fn calculate_total_entanglement(&self, state: &[Complex64]) -> Result<f64, QuantRS2Error> {
607 let probabilities: Vec<f64> = state.iter().map(|c| c.norm_sqr()).collect();
609 let entropy = -probabilities
610 .iter()
611 .filter(|&&p| p > 1e-15)
612 .map(|&p| p * p.log2())
613 .sum::<f64>();
614 Ok(entropy)
615 }
616
617 fn calculate_pairwise_entanglement(
619 &self,
620 state: &[Complex64],
621 num_qubits: usize,
622 ) -> Result<HashMap<(usize, usize), f64>, QuantRS2Error> {
623 let mut pairwise = HashMap::new();
624
625 for i in 0..num_qubits {
627 for j in (i + 1)..num_qubits {
628 let entanglement =
629 self.calculate_bipartite_entanglement(state, i, j, num_qubits)?;
630 pairwise.insert((i, j), entanglement);
631 }
632 }
633
634 Ok(pairwise)
635 }
636
637 fn calculate_bipartite_entanglement(
639 &self,
640 state: &[Complex64],
641 qubit1: usize,
642 qubit2: usize,
643 num_qubits: usize,
644 ) -> Result<f64, QuantRS2Error> {
645 let mut correlation = 0.0;
647
648 for i in 0..(1 << num_qubits) {
649 let bit1 = (i >> qubit1) & 1;
650 let bit2 = (i >> qubit2) & 1;
651
652 if bit1 == bit2 {
653 correlation += state[i].norm_sqr();
654 } else {
655 correlation -= state[i].norm_sqr();
656 }
657 }
658
659 Ok(correlation.abs())
660 }
661
662 fn calculate_entanglement_spectrum(
664 &self,
665 state: &[Complex64],
666 _num_qubits: usize,
667 ) -> Result<Vec<f64>, QuantRS2Error> {
668 let mut spectrum: Vec<f64> = state.iter().map(|c| c.norm_sqr()).collect();
670 spectrum.sort_by(|a, b| b.partial_cmp(a).unwrap_or(std::cmp::Ordering::Equal));
671 Ok(spectrum)
672 }
673
674 fn find_max_entangled_pair(
676 &self,
677 pairwise: &HashMap<(usize, usize), f64>,
678 ) -> Option<(usize, usize)> {
679 pairwise
680 .iter()
681 .max_by(|(_, v1), (_, v2)| v1.partial_cmp(v2).unwrap_or(std::cmp::Ordering::Equal))
682 .map(|(pair, _)| *pair)
683 }
684
685 fn analyze_amplitudes(&self, state: &[Complex64]) -> Result<AmplitudeAnalysis, QuantRS2Error> {
687 let amplitudes: Vec<f64> = state.iter().map(|c| c.norm()).collect();
688 let phases: Vec<f64> = state.iter().map(|c| c.arg()).collect();
689
690 let max_amplitude_index = amplitudes
691 .iter()
692 .enumerate()
693 .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
694 .map(|(i, _)| i)
695 .unwrap_or(0);
696
697 let mean_amplitude = amplitudes.iter().sum::<f64>() / amplitudes.len() as f64;
698 let amplitude_variance = amplitudes
699 .iter()
700 .map(|a| (a - mean_amplitude).powi(2))
701 .sum::<f64>()
702 / amplitudes.len() as f64;
703
704 let significant_states = self.find_significant_states(&litudes);
705
706 Ok(AmplitudeAnalysis {
707 amplitudes,
708 phases,
709 max_amplitude_index,
710 mean_amplitude,
711 amplitude_variance,
712 significant_states,
713 })
714 }
715
716 fn find_significant_states(&self, amplitudes: &[f64]) -> Vec<usize> {
718 let threshold = 0.1; amplitudes
720 .iter()
721 .enumerate()
722 .filter(|(_, &)| amp > threshold)
723 .map(|(i, _)| i)
724 .collect()
725 }
726
727 fn get_qubit_amplitude(&self, state: &[Complex64], qubit: usize) -> Option<Complex64> {
729 if qubit < 64 && (1 << qubit) < state.len() {
731 Some(state[1 << qubit])
732 } else {
733 None
734 }
735 }
736
737 fn calculate_von_neumann_entropy(&self, state: &[Complex64]) -> Result<f64, QuantRS2Error> {
739 let probabilities: Vec<f64> = state.iter().map(|c| c.norm_sqr()).collect();
740 let entropy = -probabilities
741 .iter()
742 .filter(|&&p| p > 1e-15)
743 .map(|&p| p * p.log2())
744 .sum::<f64>();
745 Ok(entropy)
746 }
747
748 fn calculate_purity(&self, state: &[Complex64]) -> Result<f64, QuantRS2Error> {
750 let purity = state.iter().map(|c| c.norm_sqr().powi(2)).sum::<f64>();
751 Ok(purity)
752 }
753
754 fn generate_analysis(&self, _num_qubits: usize) -> Result<DebugAnalysis, QuantRS2Error> {
756 Ok(DebugAnalysis {
757 gate_statistics: self.gate_statistics.clone(),
758 execution_summary: ExecutionSummary {
759 total_steps: self.execution_trace.len(),
760 total_gates: self.gate_statistics.total_gates(),
761 circuit_depth: self.calculate_circuit_depth(),
762 execution_time: self.performance_metrics.total_execution_time.as_secs_f64(),
763 },
764 performance_metrics: self.calculate_enhanced_performance_metrics()?,
765 recommendations: self.generate_enhanced_recommendations()?,
766 })
767 }
768
769 fn calculate_circuit_depth(&self) -> usize {
771 self.execution_trace.len()
773 }
774
775 fn estimate_execution_time(&self) -> f64 {
777 self.execution_trace.len() as f64 * 0.1
779 }
780
781 fn calculate_enhanced_performance_metrics(&self) -> Result<PerformanceMetrics, QuantRS2Error> {
783 Ok(PerformanceMetrics {
784 average_gate_fidelity: self.calculate_average_fidelity(),
785 entanglement_efficiency: self.calculate_entanglement_efficiency(),
786 state_overlap_preservation: self.calculate_state_overlap_preservation(),
787 })
788 }
789
790 fn calculate_performance_metrics(&self) -> Result<PerformanceMetrics, QuantRS2Error> {
792 self.calculate_enhanced_performance_metrics()
793 }
794
795 fn calculate_average_fidelity(&self) -> f64 {
797 if self.execution_trace.is_empty() {
798 return 1.0;
799 }
800
801 let total_fidelity: f64 = self
802 .execution_trace
803 .iter()
804 .map(|step| step.gate_effect.fidelity)
805 .sum();
806
807 total_fidelity / self.execution_trace.len() as f64
808 }
809
810 fn calculate_entanglement_efficiency(&self) -> f64 {
812 0.85 }
815
816 fn calculate_state_overlap_preservation(&self) -> f64 {
818 0.92 }
821
822 fn generate_enhanced_recommendations(&self) -> Result<Vec<String>, QuantRS2Error> {
824 let mut recommendations = Vec::new();
825
826 if self.gate_statistics.two_qubit_gate_ratio() > 0.5 {
828 recommendations
829 .push("Consider reducing two-qubit gates to improve fidelity".to_string());
830 }
831
832 if self.calculate_circuit_depth() > 100 {
833 recommendations.push("Circuit depth is high - consider parallelization".to_string());
834 }
835
836 if self.performance_metrics.simd_operations_count > 0 {
838 recommendations
839 .push("SIMD operations detected - good use of vectorization".to_string());
840 } else {
841 recommendations
842 .push("Consider enabling SIMD operations for better performance".to_string());
843 }
844
845 if self.performance_metrics.parallel_operations_count > 0 {
846 recommendations
847 .push("Parallel operations used - optimal for multi-core systems".to_string());
848 }
849
850 if let Some(max_memory) = self.performance_metrics.memory_usage.iter().max() {
852 if *max_memory > 1024 * 1024 * 100 {
853 recommendations.push(
855 "High memory usage detected - consider SciRS2 memory optimization".to_string(),
856 );
857 }
858 }
859
860 let avg_gate_time = self.performance_metrics.total_execution_time.as_nanos() as f64
862 / (self.execution_trace.len() as f64 + 1.0);
863 if avg_gate_time > 1000.0 {
864 recommendations.push("Gate execution time is high - consider optimization".to_string());
866 }
867
868 recommendations.push("Apply error mitigation techniques".to_string());
869 recommendations.push("Use SciRS2 advanced quantum state management".to_string());
870
871 Ok(recommendations)
872 }
873
874 fn generate_recommendations(&self) -> Result<Vec<String>, QuantRS2Error> {
876 self.generate_enhanced_recommendations()
877 }
878}
879
880#[derive(Debug, Clone)]
882pub struct DebugStep {
883 pub step: usize,
884 pub gate: QuantumGate,
885 pub gate_effect: GateEffect,
886 pub state_before: Option<Vec<Complex64>>,
887 pub state_after: Option<Vec<Complex64>>,
888 pub entanglement_info: Option<EntanglementAnalysis>,
889 pub amplitude_analysis: Option<AmplitudeAnalysis>,
890}
891
892#[derive(Debug, Clone)]
894pub struct GateEffect {
895 pub gate_type: String,
896 pub target_qubits: Vec<usize>,
897 pub amplitude_changes: Vec<f64>,
898 pub phase_changes: Vec<f64>,
899 pub entanglement_change: f64,
900 pub fidelity: f64,
901}
902
903#[derive(Debug, Clone)]
905pub struct Breakpoint {
906 pub step: usize,
907 pub condition: BreakpointCondition,
908 pub enabled: bool,
909}
910
911#[derive(Debug, Clone)]
913pub enum BreakpointCondition {
914 Always,
915 StateCondition(StateCondition),
916 GateType(GateType),
917 QubitIndex(usize),
918}
919
920#[derive(Debug, Clone)]
922pub enum StateCondition {
923 AmplitudeThreshold {
924 qubit: usize,
925 threshold: f64,
926 },
927 EntanglementThreshold {
928 threshold: f64,
929 },
930 PhaseDifference {
931 qubit1: usize,
932 qubit2: usize,
933 threshold: f64,
934 },
935}
936
937#[derive(Debug, Clone)]
939pub struct StateSnapshot {
940 pub step: usize,
941 pub gate_index: Option<usize>,
942 pub state: Vec<Complex64>,
943 pub metadata: StateMetadata,
944}
945
946#[derive(Debug, Clone)]
948pub struct StateMetadata {
949 pub entropy: f64,
950 pub purity: f64,
951 pub norm: f64,
952}
953
954#[derive(Debug, Clone)]
956pub struct EntanglementAnalysis {
957 pub total_entanglement: f64,
958 pub pairwise_entanglement: HashMap<(usize, usize), f64>,
959 pub entanglement_spectrum: Vec<f64>,
960 pub max_entangled_pair: Option<(usize, usize)>,
961}
962
963#[derive(Debug, Clone)]
965pub struct AmplitudeAnalysis {
966 pub amplitudes: Vec<f64>,
967 pub phases: Vec<f64>,
968 pub max_amplitude_index: usize,
969 pub mean_amplitude: f64,
970 pub amplitude_variance: f64,
971 pub significant_states: Vec<usize>,
972}
973
974#[derive(Debug, Clone)]
976pub struct GateStatistics {
977 gate_counts: HashMap<String, usize>,
978 total_count: usize,
979}
980
981impl GateStatistics {
982 pub fn new() -> Self {
983 Self {
984 gate_counts: HashMap::new(),
985 total_count: 0,
986 }
987 }
988
989 pub fn record_gate(&mut self, gate: &QuantumGate) {
990 let gate_type = format!("{:?}", gate.gate_type());
991 *self.gate_counts.entry(gate_type).or_insert(0) += 1;
992 self.total_count += 1;
993 }
994
995 pub fn total_gates(&self) -> usize {
996 self.total_count
997 }
998
999 pub fn two_qubit_gate_ratio(&self) -> f64 {
1000 let two_qubit_gates =
1001 *self.gate_counts.get("CNOT").unwrap_or(&0) + *self.gate_counts.get("CZ").unwrap_or(&0);
1002 if self.total_count > 0 {
1003 two_qubit_gates as f64 / self.total_count as f64
1004 } else {
1005 0.0
1006 }
1007 }
1008}
1009
1010#[derive(Debug, Clone)]
1012pub struct DebugResult {
1013 pub status: DebugStatus,
1014 pub final_state: Vec<Complex64>,
1015 pub execution_trace: Vec<DebugStep>,
1016 pub analysis: DebugAnalysis,
1017}
1018
1019#[derive(Debug, Clone)]
1021pub enum DebugStatus {
1022 Completed,
1023 BreakpointHit(usize),
1024 Error(String),
1025}
1026
1027#[derive(Debug, Clone)]
1029pub struct DebugAnalysis {
1030 pub gate_statistics: GateStatistics,
1031 pub execution_summary: ExecutionSummary,
1032 pub performance_metrics: PerformanceMetrics,
1033 pub recommendations: Vec<String>,
1034}
1035
1036#[derive(Debug, Clone)]
1038pub struct ExecutionSummary {
1039 pub total_steps: usize,
1040 pub total_gates: usize,
1041 pub circuit_depth: usize,
1042 pub execution_time: f64,
1043}
1044
1045#[derive(Debug, Clone)]
1047pub struct PerformanceMetrics {
1048 pub average_gate_fidelity: f64,
1049 pub entanglement_efficiency: f64,
1050 pub state_overlap_preservation: f64,
1051}
1052
1053#[cfg(test)]
1054mod tests {
1055 use super::*;
1056 use super::{GateType, QuantumGate};
1057
1058 #[test]
1059 fn test_debugger_creation() {
1060 let debugger = QuantumDebugger::new();
1061 assert!(debugger.config.track_state_vectors);
1062 }
1063
1064 #[test]
1065 fn test_breakpoint_setting() {
1066 let mut debugger = QuantumDebugger::new();
1067 debugger.set_breakpoint(5, BreakpointCondition::Always);
1068 assert_eq!(debugger.breakpoints.len(), 1);
1069 assert_eq!(debugger.breakpoints[0].step, 5);
1070 }
1071
1072 #[test]
1073 fn test_gate_statistics() {
1074 let mut stats = GateStatistics::new();
1075 let gate = QuantumGate::new(GateType::H, vec![0], None);
1076 stats.record_gate(&gate);
1077 assert_eq!(stats.total_gates(), 1);
1078 }
1079
1080 #[test]
1081 fn test_simple_circuit_debugging() {
1082 let mut debugger = QuantumDebugger::new();
1083 let circuit = vec![QuantumGate::new(GateType::H, vec![0], None)];
1084
1085 let initial_state = vec![Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)];
1086
1087 let result = debugger.debug_circuit(&circuit, &initial_state, 1).unwrap();
1088 assert!(matches!(result.status, DebugStatus::Completed));
1089 assert_eq!(result.execution_trace.len(), 1);
1090 }
1091
1092 #[test]
1093 fn test_amplitude_analysis() {
1094 let debugger = QuantumDebugger::new();
1095 let state = vec![
1096 Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0),
1097 Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0),
1098 ];
1099
1100 let analysis = debugger.analyze_amplitudes(&state).unwrap();
1101 assert_eq!(analysis.amplitudes.len(), 2);
1102 assert!((analysis.mean_amplitude - std::f64::consts::FRAC_1_SQRT_2).abs() < 1e-4);
1103 }
1104}