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