1use crate::gate_translation::GateType;
7use crate::buffer_pool::BufferPool;
9use crate::parallel_ops_stubs::*;
11
12#[derive(Debug, Clone)]
14pub struct QuantumGate {
15 gate_type: GateType,
16 target_qubits: Vec<usize>,
17 control_qubits: Option<Vec<usize>>,
18}
19
20impl QuantumGate {
21 pub fn new(
22 gate_type: GateType,
23 target_qubits: Vec<usize>,
24 control_qubits: Option<Vec<usize>>,
25 ) -> Self {
26 Self {
27 gate_type,
28 target_qubits,
29 control_qubits,
30 }
31 }
32
33 pub fn gate_type(&self) -> &GateType {
34 &self.gate_type
35 }
36
37 pub fn target_qubits(&self) -> &[usize] {
38 &self.target_qubits
39 }
40
41 pub fn control_qubits(&self) -> Option<&[usize]> {
42 self.control_qubits.as_deref()
43 }
44}
45use crate::error::QuantRS2Error;
46use std::collections::HashMap;
47
48#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
50pub struct ResourceEstimationConfig {
51 pub error_correction_code: ErrorCorrectionCode,
53 pub physical_error_rate: f64,
55 pub target_logical_error_rate: f64,
57 pub estimation_mode: EstimationMode,
59 pub include_hardware_overhead: bool,
61 pub hardware_platform: HardwarePlatform,
63 pub detailed_analysis: bool,
65}
66
67impl Default for ResourceEstimationConfig {
68 fn default() -> Self {
69 Self {
70 error_correction_code: ErrorCorrectionCode::SurfaceCode,
71 physical_error_rate: 1e-3,
72 target_logical_error_rate: 1e-12,
73 estimation_mode: EstimationMode::Realistic,
74 include_hardware_overhead: true,
75 hardware_platform: HardwarePlatform::Superconducting,
76 detailed_analysis: true,
77 }
78 }
79}
80
81#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
83pub enum ErrorCorrectionCode {
84 SurfaceCode,
85 ColorCode,
86 ToricCode,
87 ShorCode,
88 StabilizerCode(usize), }
90
91#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
93pub enum EstimationMode {
94 Conservative, Optimistic, Realistic, }
98
99#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
101pub enum HardwarePlatform {
102 Superconducting,
103 TrappedIon,
104 Photonic,
105 NeutralAtom,
106 SiliconQuantumDots,
107 TopologicalQubits,
108}
109
110pub struct ResourceEstimator {
112 config: ResourceEstimationConfig,
113 buffer_pool: Option<BufferPool<f64>>,
114}
115
116impl ResourceEstimator {
117 pub fn new() -> Self {
119 let config = ResourceEstimationConfig::default();
120 Self::with_config(config)
121 }
122
123 pub fn with_config(config: ResourceEstimationConfig) -> Self {
125 let buffer_pool = if config.include_hardware_overhead {
126 Some(BufferPool::<f64>::new())
127 } else {
128 None
129 };
130
131 Self {
132 config,
133 buffer_pool,
134 }
135 }
136
137 pub fn estimate_resources(
139 &self,
140 circuit: &[QuantumGate],
141 num_qubits: usize,
142 ) -> Result<ResourceEstimate, QuantRS2Error> {
143 let gate_analysis = self.analyze_gates(circuit)?;
144 let logical_analysis = self.analyze_logical_requirements(&gate_analysis, num_qubits)?;
145 let physical_analysis = self.analyze_physical_requirements(&logical_analysis)?;
146 let time_analysis = self.analyze_execution_time(&gate_analysis)?;
147
148 let detailed_analysis = if self.config.detailed_analysis {
149 Some(DetailedAnalysis {
150 bottlenecks: self.identify_bottlenecks(&gate_analysis)?,
151 optimization_suggestions: self.generate_optimization_suggestions(&gate_analysis)?,
152 scaling_analysis: self.analyze_scaling(&gate_analysis, num_qubits)?,
153 error_analysis: self.analyze_error_propagation(&gate_analysis)?,
154 })
155 } else {
156 None
157 };
158
159 Ok(ResourceEstimate {
160 logical_qubits: logical_analysis.logical_qubits,
161 physical_qubits: physical_analysis.physical_qubits,
162 total_gates: gate_analysis.total_gates,
163 gate_breakdown: gate_analysis.gate_breakdown.clone(),
164 circuit_depth: gate_analysis.circuit_depth,
165 execution_time: time_analysis.total_time,
166 time_breakdown: time_analysis.time_breakdown,
167 error_budget: physical_analysis.error_budget,
168 overhead_factor: physical_analysis.overhead_factor,
169 magic_states: logical_analysis.magic_states,
170 distillation_overhead: logical_analysis.distillation_overhead,
171 spatial_overhead: physical_analysis.spatial_overhead,
172 temporal_overhead: time_analysis.temporal_overhead,
173 detailed_analysis,
174 })
175 }
176
177 fn analyze_gates(&self, circuit: &[QuantumGate]) -> Result<GateAnalysis, QuantRS2Error> {
179 let mut gate_breakdown = HashMap::new();
180 let mut depth_counter = HashMap::new();
181 let mut max_depth = 0;
182
183 if circuit.len() > 1000 {
185 let gate_counts: HashMap<String, usize> = circuit
187 .par_iter()
188 .map(|gate| format!("{:?}", gate.gate_type()))
189 .fold(HashMap::new, |mut acc, gate_type| {
190 *acc.entry(gate_type).or_insert(0) += 1;
191 acc
192 })
193 .reduce(HashMap::new, |mut acc1, acc2| {
194 for (key, value) in acc2 {
195 *acc1.entry(key).or_insert(0) += value;
196 }
197 acc1
198 });
199 gate_breakdown = gate_counts;
200 } else {
201 for gate in circuit {
203 let gate_type = format!("{:?}", gate.gate_type());
204 *gate_breakdown.entry(gate_type).or_insert(0) += 1;
205 }
206 }
207
208 for gate in circuit {
210 for &qubit in gate.target_qubits() {
211 let qubit_depth = depth_counter.entry(qubit).or_insert(0);
212 *qubit_depth += 1;
213 max_depth = max_depth.max(*qubit_depth);
214 }
215 }
216
217 let two_qubit_count = self.count_two_qubit_gates(circuit);
219 let _complexity_score =
220 self.calculate_complexity_score(circuit.len(), max_depth, two_qubit_count);
221
222 Ok(GateAnalysis {
223 total_gates: circuit.len(),
224 gate_breakdown,
225 circuit_depth: max_depth,
226 clifford_gates: self.count_clifford_gates(circuit),
227 non_clifford_gates: self.count_non_clifford_gates(circuit),
228 two_qubit_gates: self.count_two_qubit_gates(circuit),
229 measurement_gates: self.count_measurement_gates(circuit),
230 })
231 }
232
233 fn count_clifford_gates(&self, circuit: &[QuantumGate]) -> usize {
235 use crate::gate_translation::GateType;
236
237 circuit
238 .iter()
239 .filter(|gate| {
240 matches!(
241 gate.gate_type(),
242 GateType::X
243 | GateType::Y
244 | GateType::Z
245 | GateType::H
246 | GateType::CNOT
247 | GateType::CZ
248 | GateType::S
249 )
250 })
251 .count()
252 }
253
254 fn count_non_clifford_gates(&self, circuit: &[QuantumGate]) -> usize {
256 use crate::gate_translation::GateType;
257
258 circuit
259 .iter()
260 .filter(|gate| {
261 matches!(
262 gate.gate_type(),
263 GateType::T
264 | GateType::Phase(_)
265 | GateType::Rx(_)
266 | GateType::Ry(_)
267 | GateType::Rz(_)
268 )
269 })
270 .count()
271 }
272
273 fn count_two_qubit_gates(&self, circuit: &[QuantumGate]) -> usize {
275 circuit
276 .iter()
277 .filter(|gate| gate.target_qubits().len() >= 2)
278 .count()
279 }
280
281 fn count_measurement_gates(&self, circuit: &[QuantumGate]) -> usize {
283 use crate::gate_translation::GateType;
284
285 circuit
286 .iter()
287 .filter(
288 |gate| matches!(gate.gate_type(), GateType::Custom(ref name) if name == "Measure"),
289 )
290 .count()
291 }
292
293 fn analyze_logical_requirements(
295 &self,
296 gate_analysis: &GateAnalysis,
297 num_qubits: usize,
298 ) -> Result<LogicalAnalysis, QuantRS2Error> {
299 let magic_states = self.estimate_magic_states(gate_analysis)?;
300 let distillation_overhead = self.calculate_distillation_overhead(magic_states)?;
301
302 Ok(LogicalAnalysis {
303 logical_qubits: num_qubits,
304 magic_states,
305 distillation_overhead,
306 ancilla_qubits: self.estimate_ancilla_qubits(gate_analysis)?,
307 workspace_qubits: self.estimate_workspace_qubits(gate_analysis)?,
308 })
309 }
310
311 fn estimate_magic_states(&self, gate_analysis: &GateAnalysis) -> Result<usize, QuantRS2Error> {
313 let t_gates = gate_analysis.non_clifford_gates;
315
316 let additional = match self.config.estimation_mode {
318 EstimationMode::Conservative => (t_gates as f64 * 1.5) as usize,
319 EstimationMode::Optimistic => t_gates,
320 EstimationMode::Realistic => (t_gates as f64 * 1.2) as usize,
321 };
322
323 Ok(additional)
324 }
325
326 fn calculate_distillation_overhead(&self, magic_states: usize) -> Result<f64, QuantRS2Error> {
328 if magic_states == 0 {
329 return Ok(1.0);
330 }
331
332 let base_ratio = match self.config.error_correction_code {
334 ErrorCorrectionCode::SurfaceCode => 15.0, ErrorCorrectionCode::ColorCode => 12.0,
336 ErrorCorrectionCode::ToricCode => 15.0,
337 ErrorCorrectionCode::ShorCode => 20.0,
338 ErrorCorrectionCode::StabilizerCode(_) => 15.0,
339 };
340
341 let error_factor = (-self.config.target_logical_error_rate.log10() / 3.0).max(1.0);
342
343 Ok(base_ratio * error_factor)
344 }
345
346 fn estimate_ancilla_qubits(
348 &self,
349 gate_analysis: &GateAnalysis,
350 ) -> Result<usize, QuantRS2Error> {
351 let syndrome_qubits = match self.config.error_correction_code {
353 ErrorCorrectionCode::SurfaceCode => gate_analysis.total_gates / 10,
354 ErrorCorrectionCode::ColorCode => gate_analysis.total_gates / 12,
355 _ => gate_analysis.total_gates / 15,
356 };
357
358 Ok(syndrome_qubits.max(10)) }
360
361 fn estimate_workspace_qubits(
363 &self,
364 gate_analysis: &GateAnalysis,
365 ) -> Result<usize, QuantRS2Error> {
366 let workspace = gate_analysis.two_qubit_gates / 5;
368
369 Ok(workspace.max(5)) }
371
372 fn analyze_physical_requirements(
374 &self,
375 logical_analysis: &LogicalAnalysis,
376 ) -> Result<PhysicalAnalysis, QuantRS2Error> {
377 let code_distance = self.calculate_code_distance()?;
378 let qubits_per_logical = self.calculate_qubits_per_logical(code_distance)?;
379
380 let total_logical = logical_analysis.logical_qubits
381 + logical_analysis.ancilla_qubits
382 + logical_analysis.workspace_qubits;
383
384 let physical_qubits = total_logical * qubits_per_logical;
385
386 let overhead_factor = physical_qubits as f64 / logical_analysis.logical_qubits as f64;
387
388 Ok(PhysicalAnalysis {
389 physical_qubits,
390 code_distance,
391 qubits_per_logical,
392 overhead_factor,
393 spatial_overhead: self.calculate_spatial_overhead(physical_qubits)?,
394 error_budget: self.calculate_error_budget()?,
395 })
396 }
397
398 fn calculate_code_distance(&self) -> Result<usize, QuantRS2Error> {
400 let p = self.config.physical_error_rate;
401 let p_target = self.config.target_logical_error_rate;
402
403 let threshold = match self.config.error_correction_code {
405 ErrorCorrectionCode::SurfaceCode => 1e-2,
406 ErrorCorrectionCode::ColorCode => 8e-3,
407 _ => 1e-2,
408 };
409
410 if p > threshold {
411 return Err(QuantRS2Error::UnsupportedOperation(
412 "Physical error rate exceeds threshold".into(),
413 ));
414 }
415
416 let ratio = p / threshold;
418 let distance = (-p_target.log10() / ratio.log10()).ceil() as usize;
419
420 Ok(if distance % 2 == 0 {
422 distance + 1
423 } else {
424 distance
425 }
426 .max(3))
427 }
428
429 fn calculate_qubits_per_logical(&self, distance: usize) -> Result<usize, QuantRS2Error> {
431 match self.config.error_correction_code {
432 ErrorCorrectionCode::SurfaceCode => Ok(2 * distance * distance - 2 * distance + 1),
433 ErrorCorrectionCode::ColorCode => Ok(3 * distance * distance),
434 ErrorCorrectionCode::ToricCode => Ok(2 * distance * distance),
435 ErrorCorrectionCode::ShorCode => Ok(9),
436 ErrorCorrectionCode::StabilizerCode(d) => Ok(d * d),
437 }
438 }
439
440 fn calculate_spatial_overhead(&self, physical_qubits: usize) -> Result<f64, QuantRS2Error> {
442 let base_overhead = match self.config.hardware_platform {
443 HardwarePlatform::Superconducting => 1.5,
444 HardwarePlatform::TrappedIon => 2.0,
445 HardwarePlatform::Photonic => 3.0,
446 HardwarePlatform::NeutralAtom => 1.8,
447 HardwarePlatform::SiliconQuantumDots => 2.5,
448 HardwarePlatform::TopologicalQubits => 1.2,
449 };
450
451 let scaling_factor = 1.0 + (physical_qubits as f64).log10() * 0.1;
453
454 Ok(base_overhead * scaling_factor)
455 }
456
457 fn calculate_error_budget(&self) -> Result<ErrorBudget, QuantRS2Error> {
459 let total_budget = self.config.target_logical_error_rate;
460
461 let gate_errors = total_budget * 0.4;
463 let measurement_errors = total_budget * 0.2;
464 let memory_errors = total_budget * 0.3;
465 let correction_errors = total_budget * 0.1;
466
467 Ok(ErrorBudget {
468 total: total_budget,
469 gate_errors,
470 measurement_errors,
471 memory_errors,
472 correction_errors,
473 })
474 }
475
476 fn analyze_execution_time(
478 &self,
479 gate_analysis: &GateAnalysis,
480 ) -> Result<TimeAnalysis, QuantRS2Error> {
481 let gate_times = self.get_gate_timing_parameters()?;
482
483 let mut time_breakdown = HashMap::new();
484 let mut total_time = 0.0;
485
486 for (gate_type, count) in &gate_analysis.gate_breakdown {
487 let gate_time = gate_times.get(gate_type).unwrap_or(&1e-6); let total_gate_time = *gate_time * (*count as f64);
489 time_breakdown.insert(gate_type.clone(), total_gate_time);
490 total_time += total_gate_time;
491 }
492
493 let correction_overhead = total_time * 0.5; total_time += correction_overhead;
496
497 let temporal_overhead = self.calculate_temporal_overhead(total_time)?;
498
499 Ok(TimeAnalysis {
500 total_time,
501 time_breakdown,
502 correction_overhead,
503 temporal_overhead,
504 })
505 }
506
507 fn get_gate_timing_parameters(&self) -> Result<HashMap<String, f64>, QuantRS2Error> {
509 let mut timings = HashMap::new();
510
511 match self.config.hardware_platform {
512 HardwarePlatform::Superconducting => {
513 timings.insert("X".to_string(), 20e-9);
514 timings.insert("Y".to_string(), 20e-9);
515 timings.insert("Z".to_string(), 1e-9);
516 timings.insert("H".to_string(), 20e-9);
517 timings.insert("CNOT".to_string(), 40e-9);
518 timings.insert("T".to_string(), 20e-9);
519 timings.insert("Measure".to_string(), 300e-9);
520 }
521 HardwarePlatform::TrappedIon => {
522 timings.insert("X".to_string(), 10e-6);
523 timings.insert("Y".to_string(), 10e-6);
524 timings.insert("Z".to_string(), 1e-6);
525 timings.insert("H".to_string(), 10e-6);
526 timings.insert("CNOT".to_string(), 100e-6);
527 timings.insert("T".to_string(), 10e-6);
528 timings.insert("Measure".to_string(), 100e-6);
529 }
530 HardwarePlatform::Photonic => {
531 timings.insert("X".to_string(), 1e-9);
532 timings.insert("Y".to_string(), 1e-9);
533 timings.insert("Z".to_string(), 1e-9);
534 timings.insert("H".to_string(), 1e-9);
535 timings.insert("CNOT".to_string(), 10e-9);
536 timings.insert("T".to_string(), 1e-9);
537 timings.insert("Measure".to_string(), 1e-9);
538 }
539 _ => {
540 timings.insert("X".to_string(), 1e-6);
542 timings.insert("Y".to_string(), 1e-6);
543 timings.insert("Z".to_string(), 1e-6);
544 timings.insert("H".to_string(), 1e-6);
545 timings.insert("CNOT".to_string(), 2e-6);
546 timings.insert("T".to_string(), 1e-6);
547 timings.insert("Measure".to_string(), 10e-6);
548 }
549 }
550
551 Ok(timings)
552 }
553
554 fn calculate_temporal_overhead(&self, _base_time: f64) -> Result<f64, QuantRS2Error> {
556 let overhead = match self.config.hardware_platform {
557 HardwarePlatform::Superconducting => 1.3,
558 HardwarePlatform::TrappedIon => 1.8,
559 HardwarePlatform::Photonic => 1.1,
560 HardwarePlatform::NeutralAtom => 1.5,
561 HardwarePlatform::SiliconQuantumDots => 2.0,
562 HardwarePlatform::TopologicalQubits => 1.1,
563 };
564
565 Ok(overhead)
566 }
567
568 fn identify_bottlenecks(
570 &self,
571 gate_analysis: &GateAnalysis,
572 ) -> Result<Vec<String>, QuantRS2Error> {
573 let mut bottlenecks = Vec::new();
574
575 if gate_analysis.circuit_depth > 1000 {
576 bottlenecks.push("High circuit depth may lead to decoherence issues".to_string());
577 }
578
579 if gate_analysis.two_qubit_gates > gate_analysis.total_gates / 2 {
580 bottlenecks.push("High ratio of two-qubit gates increases error rates".to_string());
581 }
582
583 if gate_analysis.non_clifford_gates > 100 {
584 bottlenecks
585 .push("Large number of non-Clifford gates requires many magic states".to_string());
586 }
587
588 Ok(bottlenecks)
589 }
590
591 fn calculate_complexity_score(
593 &self,
594 total_gates: usize,
595 depth: usize,
596 two_qubit_gates: usize,
597 ) -> f64 {
598 let gate_complexity = total_gates as f64;
600 let depth_complexity = depth as f64 * 1.5; let two_qubit_complexity = two_qubit_gates as f64 * 2.0; (gate_complexity + depth_complexity + two_qubit_complexity) / (total_gates as f64 + 1.0)
604 }
605
606 fn generate_optimization_suggestions(
608 &self,
609 gate_analysis: &GateAnalysis,
610 ) -> Result<Vec<String>, QuantRS2Error> {
611 let mut suggestions = Vec::new();
612
613 let complexity_score = self.calculate_complexity_score(
615 gate_analysis.total_gates,
616 gate_analysis.circuit_depth,
617 gate_analysis.two_qubit_gates,
618 );
619
620 if gate_analysis.circuit_depth > 500 {
621 suggestions.push("Consider circuit parallelization to reduce depth".to_string());
622 if complexity_score > 3.0 {
623 suggestions.push(
624 "Use SciRS2 parallel gate scheduling for improved performance".to_string(),
625 );
626 }
627 }
628
629 if gate_analysis.non_clifford_gates > 50 {
630 suggestions.push("Apply Clifford+T optimization to reduce T-gate count".to_string());
631 if self.config.detailed_analysis {
632 suggestions.push("Consider SciRS2 magic state optimization algorithms".to_string());
633 }
634 }
635
636 if gate_analysis.two_qubit_gates > gate_analysis.total_gates / 3 {
637 suggestions.push(
638 "High two-qubit gate ratio detected - consider gate fusion optimization"
639 .to_string(),
640 );
641 }
642
643 match self.config.hardware_platform {
645 HardwarePlatform::Superconducting => {
646 suggestions.push("Optimize for superconducting hardware connectivity".to_string());
647 }
648 HardwarePlatform::TrappedIon => {
649 suggestions
650 .push("Leverage all-to-all connectivity for trapped ion systems".to_string());
651 }
652 _ => {
653 suggestions.push("Consider hardware-specific gate set optimization".to_string());
654 }
655 }
656
657 suggestions.push("Consider using error mitigation techniques".to_string());
658 suggestions.push("Apply SciRS2 memory-efficient state vector simulation".to_string());
659
660 Ok(suggestions)
661 }
662
663 fn analyze_scaling(
665 &self,
666 gate_analysis: &GateAnalysis,
667 num_qubits: usize,
668 ) -> Result<ScalingAnalysis, QuantRS2Error> {
669 let time_complexity = if gate_analysis.two_qubit_gates > 0 {
670 format!(
671 "O(n^{})",
672 (gate_analysis.two_qubit_gates as f64 / num_qubits as f64)
673 .log2()
674 .ceil()
675 )
676 } else {
677 "O(n)".to_string()
678 };
679
680 let space_complexity = "O(2^n)".to_string(); Ok(ScalingAnalysis {
683 time_complexity,
684 space_complexity,
685 predicted_scaling: self.predict_scaling_factors(num_qubits)?,
686 })
687 }
688
689 fn predict_scaling_factors(
691 &self,
692 _num_qubits: usize,
693 ) -> Result<HashMap<String, f64>, QuantRS2Error> {
694 let mut factors = HashMap::new();
695
696 factors.insert("10_qubits".to_string(), 1.0);
697 factors.insert("20_qubits".to_string(), 4.0);
698 factors.insert("50_qubits".to_string(), 100.0);
699 factors.insert("100_qubits".to_string(), 10000.0);
700
701 Ok(factors)
702 }
703
704 fn analyze_error_propagation(
706 &self,
707 gate_analysis: &GateAnalysis,
708 ) -> Result<ErrorPropagationAnalysis, QuantRS2Error> {
709 let error_accumulation = gate_analysis.total_gates as f64 * self.config.physical_error_rate;
710 let error_amplification = 1.0 + (gate_analysis.two_qubit_gates as f64 * 0.1);
711
712 Ok(ErrorPropagationAnalysis {
713 error_accumulation,
714 error_amplification,
715 critical_paths: vec!["Long sequences of two-qubit gates".to_string()],
716 })
717 }
718}
719
720#[derive(Debug, Clone)]
722pub struct ResourceEstimate {
723 pub logical_qubits: usize,
725 pub physical_qubits: usize,
727 pub total_gates: usize,
729 pub gate_breakdown: HashMap<String, usize>,
731 pub circuit_depth: usize,
733 pub execution_time: f64,
735 pub time_breakdown: HashMap<String, f64>,
737 pub error_budget: ErrorBudget,
739 pub overhead_factor: f64,
741 pub magic_states: usize,
743 pub distillation_overhead: f64,
745 pub spatial_overhead: f64,
747 pub temporal_overhead: f64,
749 pub detailed_analysis: Option<DetailedAnalysis>,
751}
752
753#[derive(Debug, Clone)]
755struct GateAnalysis {
756 total_gates: usize,
757 gate_breakdown: HashMap<String, usize>,
758 circuit_depth: usize,
759 clifford_gates: usize,
760 non_clifford_gates: usize,
761 two_qubit_gates: usize,
762 measurement_gates: usize,
763}
764
765#[derive(Debug, Clone)]
767struct LogicalAnalysis {
768 logical_qubits: usize,
769 magic_states: usize,
770 distillation_overhead: f64,
771 ancilla_qubits: usize,
772 workspace_qubits: usize,
773}
774
775#[derive(Debug, Clone)]
777struct PhysicalAnalysis {
778 physical_qubits: usize,
779 code_distance: usize,
780 qubits_per_logical: usize,
781 overhead_factor: f64,
782 spatial_overhead: f64,
783 error_budget: ErrorBudget,
784}
785
786#[derive(Debug, Clone)]
788struct TimeAnalysis {
789 total_time: f64,
790 time_breakdown: HashMap<String, f64>,
791 correction_overhead: f64,
792 temporal_overhead: f64,
793}
794
795#[derive(Debug, Clone)]
797pub struct ErrorBudget {
798 pub total: f64,
799 pub gate_errors: f64,
800 pub measurement_errors: f64,
801 pub memory_errors: f64,
802 pub correction_errors: f64,
803}
804
805#[derive(Debug, Clone)]
807pub struct DetailedAnalysis {
808 pub bottlenecks: Vec<String>,
809 pub optimization_suggestions: Vec<String>,
810 pub scaling_analysis: ScalingAnalysis,
811 pub error_analysis: ErrorPropagationAnalysis,
812}
813
814#[derive(Debug, Clone)]
816pub struct ScalingAnalysis {
817 pub time_complexity: String,
818 pub space_complexity: String,
819 pub predicted_scaling: HashMap<String, f64>,
820}
821
822#[derive(Debug, Clone)]
824pub struct ErrorPropagationAnalysis {
825 pub error_accumulation: f64,
826 pub error_amplification: f64,
827 pub critical_paths: Vec<String>,
828}
829
830#[cfg(test)]
831mod tests {
832 use super::*;
833 use super::{GateType, QuantumGate};
834
835 #[test]
836 fn test_resource_estimator_creation() {
837 let estimator = ResourceEstimator::new();
838 assert!(matches!(
839 estimator.config.error_correction_code,
840 ErrorCorrectionCode::SurfaceCode
841 ));
842 }
843
844 #[test]
845 fn test_gate_analysis() {
846 let estimator = ResourceEstimator::new();
847 let circuit = vec![
848 QuantumGate::new(GateType::H, vec![0], None),
849 QuantumGate::new(GateType::CNOT, vec![0, 1], None),
850 QuantumGate::new(GateType::T, vec![0], None),
851 ];
852
853 let analysis = estimator.analyze_gates(&circuit).unwrap();
854 assert_eq!(analysis.total_gates, 3);
855 assert_eq!(analysis.clifford_gates, 2);
856 assert_eq!(analysis.non_clifford_gates, 1);
857 }
858
859 #[test]
860 fn test_magic_state_estimation() {
861 let estimator = ResourceEstimator::new();
862 let gate_analysis = GateAnalysis {
863 total_gates: 10,
864 gate_breakdown: HashMap::new(),
865 circuit_depth: 5,
866 clifford_gates: 7,
867 non_clifford_gates: 3,
868 two_qubit_gates: 2,
869 measurement_gates: 0,
870 };
871
872 let magic_states = estimator.estimate_magic_states(&gate_analysis).unwrap();
873 assert!(magic_states >= 3); }
875
876 #[test]
877 fn test_code_distance_calculation() {
878 let mut config = ResourceEstimationConfig::default();
879 config.physical_error_rate = 1e-3;
880 config.target_logical_error_rate = 1e-12;
881
882 let estimator = ResourceEstimator::with_config(config);
883 let distance = estimator.calculate_code_distance().unwrap();
884 assert!(distance >= 3);
885 assert!(distance % 2 == 1); }
887
888 #[test]
889 fn test_resource_estimation_small_circuit() {
890 let estimator = ResourceEstimator::new();
891 let circuit = vec![
892 QuantumGate::new(GateType::H, vec![0], None),
893 QuantumGate::new(GateType::CNOT, vec![0, 1], None),
894 ];
895
896 let estimate = estimator.estimate_resources(&circuit, 2).unwrap();
897 assert!(estimate.logical_qubits > 0);
898 assert!(estimate.physical_qubits > estimate.logical_qubits);
899 assert!(estimate.execution_time > 0.0);
900 }
901}