1use crate::{
15 error::{QuantRS2Error, QuantRS2Result},
16 noise_characterization::{
17 CrossEntropyBenchmarking, DDSequenceType, DynamicalDecoupling, ExtrapolationMethod,
18 NoiseModel, ZeroNoiseExtrapolation,
19 },
20 qaoa::{CostHamiltonian, MixerHamiltonian, QAOACircuit, QAOAOptimizer, QAOAParams},
21 quantum_volume_tomography::{QuantumProcessTomography, QuantumVolume},
22};
23use scirs2_core::random::prelude::*;
24use scirs2_core::Complex64;
25use std::collections::HashMap;
26use std::time::{Duration, Instant};
27
28#[derive(Debug, Clone)]
30pub struct BenchmarkResult {
31 pub algorithm: String,
33 pub execution_time: Duration,
35 pub fidelity: f64,
37 pub success_rate: f64,
39 pub mitigation_improvement: Option<f64>,
41 pub resource_usage: ResourceUsage,
43}
44
45#[derive(Debug, Clone)]
46pub struct ResourceUsage {
47 pub gate_count: usize,
49 pub circuit_depth: usize,
51 pub num_qubits: usize,
53 pub num_measurements: usize,
55}
56
57pub struct QuantumBenchmarkSuite {
59 pub noise_model: NoiseModel,
61 pub enable_mitigation: bool,
63 pub config: BenchmarkConfig,
65}
66
67#[derive(Debug, Clone)]
68pub struct BenchmarkConfig {
69 pub num_iterations: usize,
71 pub detailed_profiling: bool,
73 pub compare_ideal: bool,
75 pub max_time: Duration,
77}
78
79impl Default for BenchmarkConfig {
80 fn default() -> Self {
81 Self {
82 num_iterations: 100,
83 detailed_profiling: true,
84 compare_ideal: true,
85 max_time: Duration::from_secs(300),
86 }
87 }
88}
89
90impl QuantumBenchmarkSuite {
91 pub fn new(noise_model: NoiseModel, config: BenchmarkConfig) -> Self {
93 Self {
94 noise_model,
95 enable_mitigation: true,
96 config,
97 }
98 }
99
100 pub fn benchmark_qaoa_with_mitigation(
102 &self,
103 num_qubits: usize,
104 edges: Vec<(usize, usize)>,
105 num_layers: usize,
106 ) -> QuantRS2Result<QAOABenchmarkResult> {
107 let start_time = Instant::now();
108
109 let cost_hamiltonian = CostHamiltonian::MaxCut(edges.clone());
111 let mixer_hamiltonian = MixerHamiltonian::TransverseField;
112 let params = QAOAParams::random(num_layers);
113
114 let circuit = QAOACircuit::new(
115 num_qubits,
116 cost_hamiltonian.clone(),
117 mixer_hamiltonian,
118 params.clone(),
119 );
120
121 let noisy_result = self.run_qaoa_noisy(&circuit)?;
123
124 let mitigated_result = if self.enable_mitigation {
126 Some(self.run_qaoa_with_zne(&circuit)?)
127 } else {
128 None
129 };
130
131 let ideal_result = if self.config.compare_ideal {
133 Some(self.run_qaoa_ideal(&circuit)?)
134 } else {
135 None
136 };
137
138 let execution_time = start_time.elapsed();
139
140 let mitigation_improvement = if let (Some(mitigated), Some(ideal)) =
142 (mitigated_result.as_ref(), ideal_result.as_ref())
143 {
144 let noisy_error = (noisy_result - ideal).abs();
145 let mitigated_error = (mitigated - ideal).abs();
146 Some(noisy_error / mitigated_error.max(1e-10))
147 } else {
148 None
149 };
150
151 Ok(QAOABenchmarkResult {
152 num_qubits,
153 num_edges: edges.len(),
154 num_layers,
155 noisy_expectation: noisy_result,
156 mitigated_expectation: mitigated_result,
157 ideal_expectation: ideal_result,
158 mitigation_improvement,
159 execution_time,
160 noise_model: self.noise_model.clone(),
161 })
162 }
163
164 fn run_qaoa_noisy(&self, circuit: &QAOACircuit) -> QuantRS2Result<f64> {
166 let state_size = 1 << circuit.num_qubits;
167 let mut state = vec![Complex64::new(0.0, 0.0); state_size];
168
169 circuit.execute(&mut state);
171
172 self.apply_noise_to_state(&mut state)?;
174
175 Ok(circuit.compute_expectation(&state))
177 }
178
179 fn run_qaoa_with_zne(&self, circuit: &QAOACircuit) -> QuantRS2Result<f64> {
181 let zne = ZeroNoiseExtrapolation::new(vec![1.0, 2.0, 3.0], ExtrapolationMethod::Linear);
182
183 let result = zne.mitigate(|noise_scale| {
185 let state_size = 1 << circuit.num_qubits;
186 let mut state = vec![Complex64::new(0.0, 0.0); state_size];
187
188 circuit.execute(&mut state);
189
190 let scaled_noise = NoiseModel {
192 single_qubit_depolarizing: self.noise_model.single_qubit_depolarizing * noise_scale,
193 two_qubit_depolarizing: self.noise_model.two_qubit_depolarizing * noise_scale,
194 ..self.noise_model.clone()
195 };
196
197 let _ = scaled_noise;
199
200 circuit.compute_expectation(&state)
201 })?;
202
203 Ok(result)
204 }
205
206 fn run_qaoa_ideal(&self, circuit: &QAOACircuit) -> QuantRS2Result<f64> {
208 let state_size = 1 << circuit.num_qubits;
209 let mut state = vec![Complex64::new(0.0, 0.0); state_size];
210
211 circuit.execute(&mut state);
212 Ok(circuit.compute_expectation(&state))
213 }
214
215 fn apply_noise_to_state(&self, state: &mut [Complex64]) -> QuantRS2Result<()> {
217 let mut rng = thread_rng();
218 let depolarizing_prob = self.noise_model.single_qubit_depolarizing;
219
220 for amplitude in state.iter_mut() {
222 if rng.gen::<f64>() < depolarizing_prob {
223 *amplitude *= Complex64::new(0.9, 0.0);
225 }
226 }
227
228 Ok(())
229 }
230
231 pub fn benchmark_quantum_volume(
233 &self,
234 max_qubits: usize,
235 ) -> QuantRS2Result<QuantumVolumeBenchmarkResult> {
236 let start_time = Instant::now();
237
238 let mut qv = QuantumVolume::new(max_qubits, 100, 1000);
239
240 let circuit_executor = |_gates: &[Box<dyn crate::gate::GateOp>], num_shots: usize| {
242 let mut results = Vec::with_capacity(num_shots);
244 let mut rng = thread_rng();
245 let max_value = 1 << max_qubits;
246 for _ in 0..num_shots {
247 let random_val = (rng.gen::<u64>() as usize) % max_value;
249 results.push(random_val);
250 }
251 results
252 };
253
254 let result = qv.run(circuit_executor)?;
255 let execution_time = start_time.elapsed();
256
257 Ok(QuantumVolumeBenchmarkResult {
258 quantum_volume: result.quantum_volume,
259 qubits_achieved: result.num_qubits_achieved(),
260 success_rates: result.success_rates,
261 execution_time,
262 noise_model: self.noise_model.clone(),
263 })
264 }
265
266 pub fn benchmark_with_dynamical_decoupling(
268 &self,
269 dd_sequence: DDSequenceType,
270 num_pulses: usize,
271 idle_time: f64,
272 ) -> QuantRS2Result<DDEffectivenessResult> {
273 let dd = DynamicalDecoupling::new(dd_sequence, num_pulses);
274
275 let sequence = dd.generate_sequence(idle_time);
277
278 let improvement_factor = dd.coherence_improvement_factor(
280 self.noise_model.t2_dephasing,
281 self.noise_model.gate_duration,
282 );
283
284 let overhead = sequence.len() as f64 * self.noise_model.gate_duration;
286 let overhead_fraction = overhead / idle_time;
287
288 Ok(DDEffectivenessResult {
289 sequence_type: dd_sequence,
290 num_pulses,
291 coherence_improvement: improvement_factor,
292 time_overhead: overhead,
293 overhead_fraction,
294 effective_t2: self.noise_model.t2_dephasing * improvement_factor,
295 })
296 }
297
298 pub fn benchmark_algorithm<F>(
300 &self,
301 algorithm_name: &str,
302 algorithm: F,
303 ) -> QuantRS2Result<BenchmarkResult>
304 where
305 F: Fn() -> (f64, ResourceUsage),
306 {
307 let start_time = Instant::now();
308
309 let mut total_fidelity = 0.0;
310 let mut total_success = 0.0;
311 let mut resource_usage = None;
312
313 for _ in 0..self.config.num_iterations {
314 let (result, usage) = algorithm();
315 total_fidelity += result;
316 total_success += if result > 0.5 { 1.0 } else { 0.0 };
317 resource_usage = Some(usage);
318 }
319
320 let execution_time = start_time.elapsed();
321 let avg_fidelity = total_fidelity / (self.config.num_iterations as f64);
322 let success_rate = total_success / (self.config.num_iterations as f64);
323
324 Ok(BenchmarkResult {
325 algorithm: algorithm_name.to_string(),
326 execution_time,
327 fidelity: avg_fidelity,
328 success_rate,
329 mitigation_improvement: None,
330 resource_usage: resource_usage.unwrap_or(ResourceUsage {
331 gate_count: 0,
332 circuit_depth: 0,
333 num_qubits: 0,
334 num_measurements: 0,
335 }),
336 })
337 }
338}
339
340#[derive(Debug, Clone)]
342pub struct QAOABenchmarkResult {
343 pub num_qubits: usize,
345 pub num_edges: usize,
347 pub num_layers: usize,
349 pub noisy_expectation: f64,
351 pub mitigated_expectation: Option<f64>,
353 pub ideal_expectation: Option<f64>,
355 pub mitigation_improvement: Option<f64>,
357 pub execution_time: Duration,
359 pub noise_model: NoiseModel,
361}
362
363impl QAOABenchmarkResult {
364 pub fn approximation_ratio(&self) -> Option<f64> {
366 self.ideal_expectation.map(|ideal| {
367 if ideal.abs() > 1e-10 {
368 self.noisy_expectation / ideal
369 } else {
370 0.0
371 }
372 })
373 }
374
375 pub fn mitigated_approximation_ratio(&self) -> Option<f64> {
377 if let (Some(mitigated), Some(ideal)) = (self.mitigated_expectation, self.ideal_expectation)
378 {
379 if ideal.abs() > 1e-10 {
380 Some(mitigated / ideal)
381 } else {
382 Some(0.0)
383 }
384 } else {
385 None
386 }
387 }
388
389 pub fn print_report(&self) {
391 println!("╔════════════════════════════════════════════════════════╗");
392 println!("║ QAOA Benchmark Report ║");
393 println!("╠════════════════════════════════════════════════════════╣");
394 println!("║ Problem Size: ║");
395 println!(
396 "║ Qubits: {:4} Edges: {:4} Layers: {:4} ║",
397 self.num_qubits, self.num_edges, self.num_layers
398 );
399 println!("║ ║");
400 println!("║ Results: ║");
401 println!(
402 "║ Noisy Expectation: {:8.4} ║",
403 self.noisy_expectation
404 );
405
406 if let Some(mitigated) = self.mitigated_expectation {
407 println!(
408 "║ Mitigated Expectation: {:8.4} ║",
409 mitigated
410 );
411 }
412
413 if let Some(ideal) = self.ideal_expectation {
414 println!(
415 "║ Ideal Expectation: {:8.4} ║",
416 ideal
417 );
418 }
419
420 if let Some(improvement) = self.mitigation_improvement {
421 println!(
422 "║ Mitigation Improvement: {:7.2}x ║",
423 improvement
424 );
425 }
426
427 println!("║ ║");
428 println!(
429 "║ Execution Time: {:?} ║",
430 self.execution_time
431 );
432 println!("╚════════════════════════════════════════════════════════╝");
433 }
434}
435
436#[derive(Debug, Clone)]
438pub struct QuantumVolumeBenchmarkResult {
439 pub quantum_volume: usize,
441 pub qubits_achieved: usize,
443 pub success_rates: HashMap<usize, f64>,
445 pub execution_time: Duration,
447 pub noise_model: NoiseModel,
449}
450
451#[derive(Debug, Clone)]
453pub struct DDEffectivenessResult {
454 pub sequence_type: DDSequenceType,
456 pub num_pulses: usize,
458 pub coherence_improvement: f64,
460 pub time_overhead: f64,
462 pub overhead_fraction: f64,
464 pub effective_t2: f64,
466}
467
468pub struct ComparativeBenchmark {
470 pub suite: QuantumBenchmarkSuite,
472 pub results: Vec<BenchmarkResult>,
474}
475
476impl ComparativeBenchmark {
477 pub fn new(suite: QuantumBenchmarkSuite) -> Self {
479 Self {
480 suite,
481 results: Vec::new(),
482 }
483 }
484
485 pub fn add_result(&mut self, result: BenchmarkResult) {
487 self.results.push(result);
488 }
489
490 pub fn generate_report(&self) -> String {
492 let mut report = String::from("Comparative Benchmark Report\n");
493 report.push_str("================================\n\n");
494
495 for result in &self.results {
496 report.push_str(&format!("Algorithm: {}\n", result.algorithm));
497 report.push_str(&format!(" Fidelity: {:.4}\n", result.fidelity));
498 report.push_str(&format!(
499 " Success Rate: {:.2}%\n",
500 result.success_rate * 100.0
501 ));
502 report.push_str(&format!(" Execution Time: {:?}\n", result.execution_time));
503
504 if let Some(improvement) = result.mitigation_improvement {
505 report.push_str(&format!(" Mitigation Improvement: {:.2}x\n", improvement));
506 }
507
508 report.push_str(&format!(
509 " Resources: {} gates, depth {}, {} qubits\n",
510 result.resource_usage.gate_count,
511 result.resource_usage.circuit_depth,
512 result.resource_usage.num_qubits,
513 ));
514 report.push_str("\n");
515 }
516
517 report
518 }
519
520 pub fn best_algorithm(&self) -> Option<&BenchmarkResult> {
522 self.results.iter().max_by(|a, b| {
523 a.fidelity
524 .partial_cmp(&b.fidelity)
525 .unwrap_or(std::cmp::Ordering::Equal)
526 })
527 }
528}
529
530#[cfg(test)]
531mod tests {
532 use super::*;
533
534 #[test]
535 fn test_benchmark_suite_creation() {
536 let noise_model = NoiseModel::default();
537 let config = BenchmarkConfig::default();
538 let suite = QuantumBenchmarkSuite::new(noise_model, config);
539
540 assert!(suite.enable_mitigation);
541 assert_eq!(suite.config.num_iterations, 100);
542 }
543
544 #[test]
545 fn test_qaoa_benchmark() {
546 let noise_model = NoiseModel::new(0.001, 0.01, 50.0, 70.0, 0.02);
547 let config = BenchmarkConfig {
548 num_iterations: 10,
549 detailed_profiling: false,
550 compare_ideal: true,
551 max_time: Duration::from_secs(60),
552 };
553
554 let suite = QuantumBenchmarkSuite::new(noise_model, config);
555
556 let edges = vec![(0, 1), (1, 2)];
558 let result = suite.benchmark_qaoa_with_mitigation(3, edges, 1).unwrap();
559
560 assert_eq!(result.num_qubits, 3);
561 assert_eq!(result.num_edges, 2);
562 assert!(result.noisy_expectation.is_finite());
563
564 println!("QAOA Benchmark:");
565 println!(" Noisy: {:.4}", result.noisy_expectation);
566 if let Some(mitigated) = result.mitigated_expectation {
567 println!(" Mitigated: {:.4}", mitigated);
568 }
569 if let Some(ideal) = result.ideal_expectation {
570 println!(" Ideal: {:.4}", ideal);
571 }
572 }
573
574 #[test]
575 fn test_dd_effectiveness() {
576 let noise_model = NoiseModel::default();
577 let config = BenchmarkConfig::default();
578 let suite = QuantumBenchmarkSuite::new(noise_model, config);
579
580 let result = suite
581 .benchmark_with_dynamical_decoupling(DDSequenceType::CPMG, 10, 1.0)
582 .unwrap();
583
584 assert!(result.coherence_improvement > 1.0);
585 assert!(result.overhead_fraction >= 0.0); println!("DD Effectiveness:");
588 println!(" Sequence: {:?}", result.sequence_type);
589 println!(" Improvement: {:.2}x", result.coherence_improvement);
590 println!(" Overhead: {:.2}%", result.overhead_fraction * 100.0);
591 println!(" Effective T2: {:.2} μs", result.effective_t2);
592 }
593
594 #[test]
595 fn test_comparative_benchmark() {
596 let noise_model = NoiseModel::default();
597 let config = BenchmarkConfig::default();
598 let suite = QuantumBenchmarkSuite::new(noise_model, config);
599
600 let mut comparative = ComparativeBenchmark::new(suite);
601
602 comparative.add_result(BenchmarkResult {
604 algorithm: "Algorithm A".to_string(),
605 execution_time: Duration::from_millis(100),
606 fidelity: 0.95,
607 success_rate: 0.90,
608 mitigation_improvement: Some(2.0),
609 resource_usage: ResourceUsage {
610 gate_count: 100,
611 circuit_depth: 10,
612 num_qubits: 5,
613 num_measurements: 1000,
614 },
615 });
616
617 let report = comparative.generate_report();
618 assert!(report.contains("Algorithm A"));
619
620 let best = comparative.best_algorithm().unwrap();
621 assert_eq!(best.algorithm, "Algorithm A");
622 }
623
624 #[test]
625 fn test_qaoa_report_printing() {
626 let result = QAOABenchmarkResult {
627 num_qubits: 4,
628 num_edges: 5,
629 num_layers: 2,
630 noisy_expectation: 3.2,
631 mitigated_expectation: Some(3.8),
632 ideal_expectation: Some(4.0),
633 mitigation_improvement: Some(2.5),
634 execution_time: Duration::from_millis(250),
635 noise_model: NoiseModel::default(),
636 };
637
638 result.print_report();
639
640 assert_eq!(result.approximation_ratio(), Some(0.8));
641 assert_eq!(result.mitigated_approximation_ratio(), Some(0.95));
642 }
643}