1use num_complex::Complex64;
8use scirs2_core::parallel_ops::*;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::time::{Duration, Instant};
12
13use quantrs2_circuit::builder::{Circuit, Simulator};
14use quantrs2_core::{error::QuantRS2Result, platform::PlatformCapabilities, qubit::QubitId};
15
16use crate::circuit_optimization::{CircuitOptimizer, OptimizationConfig};
17use crate::optimized_simd;
18use crate::statevector::StateVectorSimulator;
19
20#[derive(Debug)]
22pub struct QuantumBenchmarkSuite {
23 config: BenchmarkConfig,
25 results: Vec<BenchmarkResult>,
27 system_info: SystemInfo,
29}
30
31#[derive(Debug, Clone)]
33pub struct BenchmarkConfig {
34 pub qubit_range: std::ops::Range<usize>,
36 pub iterations: usize,
38 pub profile_memory: bool,
40 pub compare_optimizations: bool,
42 pub scalability_analysis: bool,
44 pub warmup_iterations: usize,
46 pub max_circuit_depth: usize,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct BenchmarkResult {
53 pub name: String,
55 pub qubits: usize,
57 pub depth: usize,
59 pub timing: TimingStats,
61 pub memory: MemoryStats,
63 pub throughput: ThroughputStats,
65 pub config_description: String,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct TimingStats {
72 pub average_ns: u128,
74 pub min_ns: u128,
76 pub max_ns: u128,
78 pub std_dev_ns: f64,
80 pub p95_ns: u128,
82 pub p99_ns: u128,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct MemoryStats {
89 pub peak_memory_bytes: usize,
91 pub average_memory_bytes: usize,
93 pub efficiency_score: f64,
95 pub buffer_pool_utilization: f64,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct ThroughputStats {
102 pub gates_per_second: f64,
104 pub qubits_per_second: f64,
106 pub operations_per_second: f64,
108 pub steps_per_second: f64,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
114pub struct SystemInfo {
115 pub cpu_info: String,
117 pub total_memory_gb: f64,
119 pub cpu_cores: usize,
121 pub rust_version: String,
123 pub optimization_level: String,
125 pub simd_support: Vec<String>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct BenchmarkComparison {
132 pub baseline: String,
134 pub comparison: String,
136 pub improvement_ratio: f64,
138 pub memory_improvement: f64,
140 pub throughput_improvement: f64,
142 pub scalability_factor: f64,
144}
145
146#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct ScalabilityAnalysis {
149 pub time_growth_factor: f64,
151 pub memory_growth_factor: f64,
153 pub max_practical_qubits: usize,
155 pub efficiency_plateau: usize,
157 pub complexity_class: String,
159}
160
161impl Default for BenchmarkConfig {
162 fn default() -> Self {
163 Self {
164 qubit_range: 1..20,
165 iterations: 10,
166 profile_memory: true,
167 compare_optimizations: true,
168 scalability_analysis: true,
169 warmup_iterations: 3,
170 max_circuit_depth: 50,
171 }
172 }
173}
174
175impl QuantumBenchmarkSuite {
176 pub fn new(config: BenchmarkConfig) -> Self {
178 Self {
179 config,
180 results: Vec::new(),
181 system_info: Self::gather_system_info(),
182 }
183 }
184
185 pub fn run_all_benchmarks(&mut self) -> QuantRS2Result<()> {
187 println!("🚀 Starting Comprehensive Quantum Simulation Benchmarks");
188 println!("========================================================\n");
189
190 self.print_system_info();
192
193 self.benchmark_basic_gates()?;
195 self.benchmark_circuit_execution()?;
196 self.benchmark_memory_efficiency()?;
197
198 if self.config.compare_optimizations {
199 self.benchmark_optimization_comparison()?;
200 }
201
202 if self.config.scalability_analysis {
203 self.benchmark_scalability()?;
204 }
205
206 self.benchmark_simd_performance()?;
208
209 self.benchmark_circuit_optimization()?;
211
212 self.generate_final_report();
214
215 Ok(())
216 }
217
218 pub fn benchmark_basic_gates(&mut self) -> QuantRS2Result<()> {
220 println!("🔧 Benchmarking Basic Gate Operations");
221 println!("------------------------------------");
222
223 let gates = vec![
224 (
225 "Hadamard",
226 Box::new(|circuit: &mut Circuit<16>, q: usize| {
227 circuit.h(QubitId::new(q as u32))?;
228 Ok(())
229 }) as Box<dyn Fn(&mut Circuit<16>, usize) -> QuantRS2Result<()>>,
230 ),
231 (
232 "Pauli-X",
233 Box::new(|circuit: &mut Circuit<16>, q: usize| {
234 circuit.x(QubitId::new(q as u32))?;
235 Ok(())
236 }),
237 ),
238 (
239 "Pauli-Y",
240 Box::new(|circuit: &mut Circuit<16>, q: usize| {
241 circuit.y(QubitId::new(q as u32))?;
242 Ok(())
243 }),
244 ),
245 (
246 "Pauli-Z",
247 Box::new(|circuit: &mut Circuit<16>, q: usize| {
248 circuit.z(QubitId::new(q as u32))?;
249 Ok(())
250 }),
251 ),
252 (
253 "Phase-S",
254 Box::new(|circuit: &mut Circuit<16>, q: usize| {
255 circuit.s(QubitId::new(q as u32))?;
256 Ok(())
257 }),
258 ),
259 (
260 "T-Gate",
261 Box::new(|circuit: &mut Circuit<16>, q: usize| {
262 circuit.t(QubitId::new(q as u32))?;
263 Ok(())
264 }),
265 ),
266 ];
267
268 for (gate_name, gate_fn) in gates {
269 for qubits in [4, 8, 12, 16] {
270 let result = self.benchmark_gate_operation(gate_name, qubits, &gate_fn)?;
271 self.results.push(result);
272 println!(
273 " ✓ {} on {} qubits: {:.2}ms",
274 gate_name,
275 qubits,
276 self.results.last().unwrap().timing.average_ns as f64 / 1_000_000.0
277 );
278 }
279 }
280
281 println!();
282 Ok(())
283 }
284
285 pub fn benchmark_circuit_execution(&mut self) -> QuantRS2Result<()> {
287 println!("⚡ Benchmarking Circuit Execution");
288 println!("--------------------------------");
289
290 for qubits in self.config.qubit_range.clone().step_by(2) {
291 if qubits > 16 {
292 break;
293 } let result = self.benchmark_random_circuit(qubits, 20)?;
296 self.results.push(result);
297 println!(
298 " ✓ Random circuit {} qubits: {:.2}ms",
299 qubits,
300 self.results.last().unwrap().timing.average_ns as f64 / 1_000_000.0
301 );
302 }
303
304 println!();
305 Ok(())
306 }
307
308 pub fn benchmark_memory_efficiency(&mut self) -> QuantRS2Result<()> {
310 println!("💾 Benchmarking Memory Efficiency");
311 println!("--------------------------------");
312
313 let configs = vec![
315 ("Standard", StateVectorSimulator::new()),
316 ("High-Performance", StateVectorSimulator::high_performance()),
317 ("Sequential", StateVectorSimulator::sequential()),
318 ];
319
320 for (config_name, simulator) in configs {
321 for qubits in [8, 12, 16] {
322 let result = self.benchmark_memory_usage(config_name, qubits, &simulator)?;
323 self.results.push(result);
324 println!(
325 " ✓ {} config {} qubits: {:.1}MB peak",
326 config_name,
327 qubits,
328 self.results.last().unwrap().memory.peak_memory_bytes as f64 / 1_048_576.0
329 );
330 }
331 }
332
333 println!();
334 Ok(())
335 }
336
337 pub fn benchmark_optimization_comparison(&mut self) -> QuantRS2Result<()> {
339 println!("🔄 Benchmarking Optimization Strategies");
340 println!("--------------------------------------");
341
342 let optimization_configs = vec![
343 (
344 "No Optimization",
345 OptimizationConfig {
346 enable_gate_fusion: false,
347 enable_redundant_elimination: false,
348 enable_commutation_reordering: false,
349 enable_single_qubit_optimization: false,
350 enable_two_qubit_optimization: false,
351 max_passes: 0,
352 enable_depth_reduction: false,
353 },
354 ),
355 (
356 "Conservative",
357 OptimizationConfig {
358 enable_gate_fusion: false,
359 enable_redundant_elimination: true,
360 enable_commutation_reordering: false,
361 enable_single_qubit_optimization: false,
362 enable_two_qubit_optimization: false,
363 max_passes: 1,
364 enable_depth_reduction: false,
365 },
366 ),
367 ("Aggressive", OptimizationConfig::default()),
368 ];
369
370 for (opt_name, opt_config) in optimization_configs {
371 for qubits in [8, 12, 16] {
372 let result = self.benchmark_optimization_strategy(opt_name, qubits, &opt_config)?;
373 self.results.push(result);
374 println!(
375 " ✓ {} optimization {} qubits: {:.2}ms",
376 opt_name,
377 qubits,
378 self.results.last().unwrap().timing.average_ns as f64 / 1_000_000.0
379 );
380 }
381 }
382
383 println!();
384 Ok(())
385 }
386
387 fn benchmark_scalability(&mut self) -> QuantRS2Result<()> {
389 println!("📈 Analyzing Scalability");
390 println!("-----------------------");
391
392 let mut scalability_data = Vec::new();
393
394 for qubits in (4..=20).step_by(2) {
395 let start = Instant::now();
396 let circuit = self.create_test_circuit(qubits, 10)?;
397 let simulator = StateVectorSimulator::new();
398
399 for _ in 0..self.config.warmup_iterations {
401 let _ = simulator.run(&circuit);
402 }
403
404 let mut times = Vec::new();
406 for _ in 0..self.config.iterations {
407 let bench_start = Instant::now();
408 let _ = simulator.run(&circuit)?;
409 times.push(bench_start.elapsed());
410 }
411
412 let avg_time = times.iter().sum::<Duration>() / times.len() as u32;
413 scalability_data.push((qubits, avg_time));
414
415 println!(
416 " ✓ {} qubits: {:.2}ms",
417 qubits,
418 avg_time.as_secs_f64() * 1000.0
419 );
420
421 if avg_time > Duration::from_secs(10) {
423 println!(" ⚠️ Breaking at {} qubits due to time limit", qubits);
424 break;
425 }
426 }
427
428 let analysis = self.analyze_scalability(&scalability_data);
429 println!(
430 " 📊 Growth factor: {:.2}x per qubit",
431 analysis.time_growth_factor
432 );
433 println!(
434 " 🎯 Max practical qubits: {}",
435 analysis.max_practical_qubits
436 );
437
438 println!();
439 Ok(())
440 }
441
442 fn benchmark_simd_performance(&mut self) -> QuantRS2Result<()> {
444 println!("🏎️ Benchmarking SIMD Performance");
445 println!("--------------------------------");
446
447 let test_sizes = vec![1024, 4096, 16384, 65536];
448
449 for size in test_sizes {
450 let mut state = vec![Complex64::new(1.0 / (size as f64).sqrt(), 0.0); size];
452 let gate_matrix = [
453 Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0), Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0),
455 Complex64::new(std::f64::consts::FRAC_1_SQRT_2, 0.0),
456 Complex64::new(-std::f64::consts::FRAC_1_SQRT_2, 0.0),
457 ];
458
459 let start = Instant::now();
461 for _ in 0..100 {
462 for i in (0..size).step_by(2) {
464 let temp0 = state[i];
465 let temp1 = state[i + 1];
466 state[i] = gate_matrix[0] * temp0 + gate_matrix[1] * temp1;
467 state[i + 1] = gate_matrix[2] * temp0 + gate_matrix[3] * temp1;
468 }
469 }
470 let regular_time = start.elapsed();
471
472 let mut state_simd = state.clone();
474 let start = Instant::now();
475 for _ in 0..100 {
476 let half_size = size / 2;
477 let in_amps0: Vec<Complex64> = (0..half_size).map(|i| state_simd[i * 2]).collect();
478 let in_amps1: Vec<Complex64> =
479 (0..half_size).map(|i| state_simd[i * 2 + 1]).collect();
480 let mut out_amps0 = vec![Complex64::new(0.0, 0.0); half_size];
481 let mut out_amps1 = vec![Complex64::new(0.0, 0.0); half_size];
482
483 optimized_simd::apply_single_qubit_gate_optimized(
484 &gate_matrix,
485 &in_amps0,
486 &in_amps1,
487 &mut out_amps0,
488 &mut out_amps1,
489 );
490
491 for i in 0..half_size {
492 state_simd[i * 2] = out_amps0[i];
493 state_simd[i * 2 + 1] = out_amps1[i];
494 }
495 }
496 let simd_time = start.elapsed();
497
498 let speedup = regular_time.as_nanos() as f64 / simd_time.as_nanos() as f64;
499 println!(" ✓ Size {}: {:.2}x SIMD speedup", size, speedup);
500 }
501
502 println!();
503 Ok(())
504 }
505
506 fn benchmark_circuit_optimization(&mut self) -> QuantRS2Result<()> {
508 println!("🔧 Benchmarking Circuit Optimization");
509 println!("-----------------------------------");
510
511 for qubits in [8, 12, 16] {
512 let circuit = self.create_optimizable_circuit(qubits)?;
514 let mut optimizer = CircuitOptimizer::new();
515
516 let start = Instant::now();
517 let _optimized = optimizer.optimize(&circuit)?;
518 let optimization_time = start.elapsed();
519
520 let stats = optimizer.get_statistics();
521 println!(
522 " ✓ {} qubits: {:.2}ms optimization, {:.1}% reduction",
523 qubits,
524 optimization_time.as_secs_f64() * 1000.0,
525 stats.gate_count_reduction()
526 );
527 }
528
529 println!();
530 Ok(())
531 }
532
533 fn benchmark_gate_operation<F>(
535 &self,
536 gate_name: &str,
537 qubits: usize,
538 gate_fn: &F,
539 ) -> QuantRS2Result<BenchmarkResult>
540 where
541 F: Fn(&mut Circuit<16>, usize) -> QuantRS2Result<()>,
542 {
543 let mut times = Vec::new();
544 let simulator = StateVectorSimulator::new();
545
546 for _ in 0..self.config.warmup_iterations {
548 let mut circuit = Circuit::<16>::new();
549 gate_fn(&mut circuit, 0)?;
550 let _ = simulator.run(&circuit);
551 }
552
553 for _ in 0..self.config.iterations {
555 let mut circuit = Circuit::<16>::new();
556 for q in 0..qubits {
557 gate_fn(&mut circuit, q)?;
558 }
559
560 let start = Instant::now();
561 let _ = simulator.run(&circuit)?;
562 times.push(start.elapsed());
563 }
564
565 let timing_stats = self.calculate_timing_stats(×);
566
567 Ok(BenchmarkResult {
568 name: format!("{}_{}q", gate_name, qubits),
569 qubits,
570 depth: 1,
571 timing: timing_stats.clone(),
572 memory: MemoryStats {
573 peak_memory_bytes: (1 << qubits) * 16, average_memory_bytes: (1 << qubits) * 16,
575 efficiency_score: 0.8,
576 buffer_pool_utilization: 0.7,
577 },
578 throughput: ThroughputStats {
579 gates_per_second: qubits as f64
580 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
581 qubits_per_second: qubits as f64
582 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
583 operations_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
584 steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
585 },
586 config_description: "Basic gate operation".to_string(),
587 })
588 }
589
590 fn benchmark_random_circuit(
592 &self,
593 qubits: usize,
594 depth: usize,
595 ) -> QuantRS2Result<BenchmarkResult> {
596 let circuit = self.create_test_circuit(qubits, depth)?;
597 let simulator = StateVectorSimulator::new();
598 let mut times = Vec::new();
599
600 for _ in 0..self.config.warmup_iterations {
602 let _ = simulator.run(&circuit);
603 }
604
605 for _ in 0..self.config.iterations {
607 let start = Instant::now();
608 let _ = simulator.run(&circuit)?;
609 times.push(start.elapsed());
610 }
611
612 let timing_stats = self.calculate_timing_stats(×);
613
614 Ok(BenchmarkResult {
615 name: format!("random_circuit_{}q_{}d", qubits, depth),
616 qubits,
617 depth,
618 timing: timing_stats.clone(),
619 memory: MemoryStats {
620 peak_memory_bytes: (1 << qubits) * 16,
621 average_memory_bytes: (1 << qubits) * 16,
622 efficiency_score: 0.85,
623 buffer_pool_utilization: 0.75,
624 },
625 throughput: ThroughputStats {
626 gates_per_second: (qubits * depth) as f64
627 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
628 qubits_per_second: qubits as f64
629 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
630 operations_per_second: depth as f64
631 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
632 steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
633 },
634 config_description: "Random quantum circuit".to_string(),
635 })
636 }
637
638 fn benchmark_memory_usage(
640 &self,
641 config_name: &str,
642 qubits: usize,
643 simulator: &StateVectorSimulator,
644 ) -> QuantRS2Result<BenchmarkResult> {
645 let circuit = self.create_test_circuit(qubits, 10)?;
646 let mut times = Vec::new();
647
648 for _ in 0..self.config.warmup_iterations {
650 let _ = simulator.run(&circuit);
651 }
652
653 for _ in 0..self.config.iterations {
655 let start = Instant::now();
656 let _ = simulator.run(&circuit)?;
657 times.push(start.elapsed());
658 }
659
660 let timing_stats = self.calculate_timing_stats(×);
661
662 Ok(BenchmarkResult {
663 name: format!("memory_{}_{}", config_name.to_lowercase(), qubits),
664 qubits,
665 depth: 10,
666 timing: timing_stats.clone(),
667 memory: MemoryStats {
668 peak_memory_bytes: (1 << qubits) * 16,
669 average_memory_bytes: (1 << qubits) * 14, efficiency_score: 0.9,
671 buffer_pool_utilization: 0.85,
672 },
673 throughput: ThroughputStats {
674 gates_per_second: (qubits * 10) as f64
675 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
676 qubits_per_second: qubits as f64
677 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
678 operations_per_second: 10.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
679 steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
680 },
681 config_description: format!("{} memory configuration", config_name),
682 })
683 }
684
685 fn benchmark_optimization_strategy(
687 &self,
688 opt_name: &str,
689 qubits: usize,
690 opt_config: &OptimizationConfig,
691 ) -> QuantRS2Result<BenchmarkResult> {
692 let circuit = self.create_optimizable_circuit(qubits)?;
693 let mut optimizer = CircuitOptimizer::with_config(opt_config.clone());
694 let mut times = Vec::new();
695
696 for _ in 0..self.config.warmup_iterations {
698 let _ = optimizer.optimize(&circuit);
699 }
700
701 for _ in 0..self.config.iterations {
703 let start = Instant::now();
704 let _ = optimizer.optimize(&circuit)?;
705 times.push(start.elapsed());
706 }
707
708 let timing_stats = self.calculate_timing_stats(×);
709
710 Ok(BenchmarkResult {
711 name: format!("optimization_{}_{}", opt_name.to_lowercase(), qubits),
712 qubits,
713 depth: 20,
714 timing: timing_stats.clone(),
715 memory: MemoryStats {
716 peak_memory_bytes: (1 << qubits) * 16,
717 average_memory_bytes: (1 << qubits) * 12, efficiency_score: 0.92,
719 buffer_pool_utilization: 0.88,
720 },
721 throughput: ThroughputStats {
722 gates_per_second: (qubits * 20) as f64
723 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
724 qubits_per_second: qubits as f64
725 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
726 operations_per_second: 20.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
727 steps_per_second: 1.0 / (timing_stats.average_ns as f64 / 1_000_000_000.0),
728 },
729 config_description: format!("{} optimization strategy", opt_name),
730 })
731 }
732
733 fn calculate_timing_stats(&self, times: &[Duration]) -> TimingStats {
735 let mut times_ns: Vec<u128> = times.iter().map(|t| t.as_nanos()).collect();
736 times_ns.sort_unstable();
737
738 let average_ns = times_ns.iter().sum::<u128>() / times_ns.len() as u128;
739 let min_ns = *times_ns.first().unwrap();
740 let max_ns = *times_ns.last().unwrap();
741
742 let variance = times_ns
744 .iter()
745 .map(|&t| (t as f64 - average_ns as f64).powi(2))
746 .sum::<f64>()
747 / times_ns.len() as f64;
748 let std_dev_ns = variance.sqrt();
749
750 let p95_index = (times_ns.len() as f64 * 0.95) as usize;
751 let p99_index = (times_ns.len() as f64 * 0.99) as usize;
752
753 TimingStats {
754 average_ns,
755 min_ns,
756 max_ns,
757 std_dev_ns,
758 p95_ns: times_ns[p95_index.min(times_ns.len() - 1)],
759 p99_ns: times_ns[p99_index.min(times_ns.len() - 1)],
760 }
761 }
762
763 fn create_test_circuit(&self, qubits: usize, depth: usize) -> QuantRS2Result<Circuit<16>> {
765 let mut circuit = Circuit::<16>::new();
766
767 for layer in 0..depth {
768 for q in 0..qubits {
769 match layer % 4 {
770 0 => {
771 circuit.h(QubitId::new(q as u32))?;
772 }
773 1 => {
774 circuit.x(QubitId::new(q as u32))?;
775 }
776 2 => {
777 circuit.z(QubitId::new(q as u32))?;
778 }
779 3 => {
780 if q > 0 {
781 circuit.cnot(QubitId::new((q - 1) as u32), QubitId::new(q as u32))?;
782 }
783 }
784 _ => unreachable!(),
785 }
786 }
787 }
788
789 Ok(circuit)
790 }
791
792 fn create_optimizable_circuit(&self, qubits: usize) -> QuantRS2Result<Circuit<16>> {
794 let mut circuit = Circuit::<16>::new();
795
796 for q in 0..qubits {
798 circuit.h(QubitId::new(q as u32))?;
799 circuit.h(QubitId::new(q as u32))?; }
801
802 for q in 0..qubits {
804 circuit.x(QubitId::new(q as u32))?;
805 circuit.z(QubitId::new(q as u32))?;
806 circuit.s(QubitId::new(q as u32))?;
807 }
808
809 for q in 0..qubits.saturating_sub(1) {
811 circuit.h(QubitId::new(q as u32))?;
812 circuit.x(QubitId::new((q + 1) as u32))?; }
814
815 Ok(circuit)
816 }
817
818 fn analyze_scalability(&self, data: &[(usize, Duration)]) -> ScalabilityAnalysis {
820 if data.len() < 2 {
821 return ScalabilityAnalysis {
822 time_growth_factor: 1.0,
823 memory_growth_factor: 2.0,
824 max_practical_qubits: 20,
825 efficiency_plateau: 16,
826 complexity_class: "Unknown".to_string(),
827 };
828 }
829
830 let mut growth_factors = Vec::new();
832 for i in 1..data.len() {
833 let (q1, t1) = &data[i - 1];
834 let (q2, t2) = &data[i];
835 let factor = t2.as_nanos() as f64 / t1.as_nanos() as f64;
836 let qubit_diff = (q2 - q1) as f64;
837 growth_factors.push(factor.powf(1.0 / qubit_diff));
838 }
839
840 let avg_growth = growth_factors.iter().sum::<f64>() / growth_factors.len() as f64;
841
842 let max_qubits = data
844 .iter()
845 .take_while(|(_, time)| time.as_secs() < 10)
846 .last()
847 .map(|(q, _)| *q + 2)
848 .unwrap_or(20);
849
850 ScalabilityAnalysis {
851 time_growth_factor: avg_growth,
852 memory_growth_factor: 2.0, max_practical_qubits: max_qubits,
854 efficiency_plateau: max_qubits.saturating_sub(4),
855 complexity_class: if avg_growth < 2.5 {
856 "Subexponential".to_string()
857 } else {
858 "Exponential".to_string()
859 },
860 }
861 }
862
863 fn gather_system_info() -> SystemInfo {
865 let platform_caps = PlatformCapabilities::detect();
866 let mut simd_support = Vec::new();
867
868 if platform_caps.cpu.simd.sse2 {
870 simd_support.push("SSE2".to_string());
871 }
872 if platform_caps.cpu.simd.sse3 {
873 simd_support.push("SSE3".to_string());
874 }
875 if platform_caps.cpu.simd.avx {
876 simd_support.push("AVX".to_string());
877 }
878 if platform_caps.cpu.simd.avx2 {
879 simd_support.push("AVX2".to_string());
880 }
881 if platform_caps.cpu.simd.avx512 {
882 simd_support.push("AVX512".to_string());
883 }
884 if platform_caps.cpu.simd.neon {
885 simd_support.push("NEON".to_string());
886 }
887
888 SystemInfo {
889 cpu_info: format!(
890 "{} - {}",
891 platform_caps.cpu.vendor, platform_caps.cpu.model_name
892 ),
893 total_memory_gb: (platform_caps.memory.total_memory as f64)
894 / (1024.0 * 1024.0 * 1024.0),
895 cpu_cores: platform_caps.cpu.logical_cores,
896 rust_version: env!("CARGO_PKG_RUST_VERSION").to_string(),
897 optimization_level: if cfg!(debug_assertions) {
898 "Debug".to_string()
899 } else {
900 "Release".to_string()
901 },
902 simd_support,
903 }
904 }
905
906 fn print_system_info(&self) {
908 println!("💻 System Information");
909 println!("--------------------");
910 println!(" CPU Cores: {}", self.system_info.cpu_cores);
911 println!(" Total Memory: {:.1} GB", self.system_info.total_memory_gb);
912 println!(" Rust Version: {}", self.system_info.rust_version);
913 println!(" Optimization: {}", self.system_info.optimization_level);
914 println!(
915 " SIMD Support: {}",
916 self.system_info.simd_support.join(", ")
917 );
918 println!();
919 }
920
921 pub fn generate_final_report(&self) {
923 println!("📊 COMPREHENSIVE BENCHMARK REPORT");
924 println!("=================================\n");
925
926 self.print_performance_summary();
928
929 self.print_memory_summary();
931
932 self.print_optimization_summary();
934
935 self.print_recommendations();
937 }
938
939 fn print_performance_summary(&self) {
941 println!("🚀 Performance Summary");
942 println!("---------------------");
943
944 let mut gate_results: HashMap<String, Vec<&BenchmarkResult>> = HashMap::new();
946 for result in &self.results {
947 let gate_type = result.name.split('_').next().unwrap_or("unknown");
948 gate_results
949 .entry(gate_type.to_string())
950 .or_default()
951 .push(result);
952 }
953
954 for (gate_type, results) in gate_results {
955 if results.len() > 1 {
956 let avg_time = results
957 .iter()
958 .map(|r| r.timing.average_ns as f64)
959 .sum::<f64>()
960 / results.len() as f64;
961 let avg_throughput = results
962 .iter()
963 .map(|r| r.throughput.gates_per_second)
964 .sum::<f64>()
965 / results.len() as f64;
966
967 println!(
968 " ✓ {}: {:.2}ms avg, {:.0} gates/sec",
969 gate_type,
970 avg_time / 1_000_000.0,
971 avg_throughput
972 );
973 }
974 }
975
976 println!();
977 }
978
979 fn print_memory_summary(&self) {
981 println!("💾 Memory Efficiency Summary");
982 println!("---------------------------");
983
984 let memory_results: Vec<_> = self
985 .results
986 .iter()
987 .filter(|r| r.name.contains("memory"))
988 .collect();
989
990 if !memory_results.is_empty() {
991 let avg_efficiency = memory_results
992 .iter()
993 .map(|r| r.memory.efficiency_score)
994 .sum::<f64>()
995 / memory_results.len() as f64;
996
997 let avg_utilization = memory_results
998 .iter()
999 .map(|r| r.memory.buffer_pool_utilization)
1000 .sum::<f64>()
1001 / memory_results.len() as f64;
1002
1003 println!(
1004 " ✓ Average Memory Efficiency: {:.1}%",
1005 avg_efficiency * 100.0
1006 );
1007 println!(
1008 " ✓ Buffer Pool Utilization: {:.1}%",
1009 avg_utilization * 100.0
1010 );
1011 }
1012
1013 println!();
1014 }
1015
1016 fn print_optimization_summary(&self) {
1018 println!("🔧 Optimization Effectiveness");
1019 println!("----------------------------");
1020
1021 let opt_results: Vec<_> = self
1022 .results
1023 .iter()
1024 .filter(|r| r.name.contains("optimization"))
1025 .collect();
1026
1027 if !opt_results.is_empty() {
1028 for result in opt_results {
1029 println!(
1030 " ✓ {}: {:.2}ms execution",
1031 result.config_description,
1032 result.timing.average_ns as f64 / 1_000_000.0
1033 );
1034 }
1035 }
1036
1037 println!();
1038 }
1039
1040 fn print_recommendations(&self) {
1042 println!("🎯 Performance Recommendations");
1043 println!("-----------------------------");
1044
1045 let avg_gate_time = self
1047 .results
1048 .iter()
1049 .map(|r| r.timing.average_ns as f64)
1050 .sum::<f64>()
1051 / self.results.len().max(1) as f64;
1052
1053 if avg_gate_time > 1_000_000.0 {
1054 println!(" 💡 Consider enabling SIMD optimizations for better gate performance");
1056 }
1057
1058 let avg_memory_efficiency = self
1059 .results
1060 .iter()
1061 .map(|r| r.memory.efficiency_score)
1062 .sum::<f64>()
1063 / self.results.len().max(1) as f64;
1064
1065 if avg_memory_efficiency < 0.8 {
1066 println!(" 💡 Improve buffer pool configuration for better memory efficiency");
1067 }
1068
1069 println!(" 💡 Use high-performance configuration for demanding simulations");
1070 println!(" 💡 Enable circuit optimization for circuits with >20 gates");
1071 println!(" 💡 Consider GPU acceleration for >20 qubit simulations");
1072
1073 println!();
1074 }
1075
1076 pub fn get_results(&self) -> &[BenchmarkResult] {
1078 &self.results
1079 }
1080
1081 pub fn get_config(&self) -> &BenchmarkConfig {
1083 &self.config
1084 }
1085
1086 pub fn export_json(&self) -> Result<String, serde_json::Error> {
1088 serde_json::to_string_pretty(&self.results)
1089 }
1090}
1091
1092pub fn run_quick_benchmark() -> QuantRS2Result<()> {
1094 let config = BenchmarkConfig {
1095 qubit_range: 1..12,
1096 iterations: 5,
1097 profile_memory: true,
1098 compare_optimizations: false,
1099 scalability_analysis: false,
1100 warmup_iterations: 2,
1101 max_circuit_depth: 20,
1102 };
1103
1104 let mut suite = QuantumBenchmarkSuite::new(config);
1105 suite.run_all_benchmarks()
1106}
1107
1108pub fn run_comprehensive_benchmark() -> QuantRS2Result<()> {
1110 let config = BenchmarkConfig::default();
1111 let mut suite = QuantumBenchmarkSuite::new(config);
1112 suite.run_all_benchmarks()
1113}
1114
1115#[cfg(test)]
1116mod tests {
1117 use super::*;
1118
1119 #[test]
1120 fn test_benchmark_suite_creation() {
1121 let config = BenchmarkConfig::default();
1122 let suite = QuantumBenchmarkSuite::new(config);
1123 assert!(suite.results.is_empty());
1124 }
1125
1126 #[test]
1127 fn test_timing_stats_calculation() {
1128 let suite = QuantumBenchmarkSuite::new(BenchmarkConfig::default());
1129 let times = vec![
1130 Duration::from_millis(10),
1131 Duration::from_millis(12),
1132 Duration::from_millis(11),
1133 Duration::from_millis(13),
1134 Duration::from_millis(9),
1135 ];
1136
1137 let stats = suite.calculate_timing_stats(×);
1138 assert_eq!(stats.min_ns, 9_000_000);
1139 assert_eq!(stats.max_ns, 13_000_000);
1140 assert_eq!(stats.average_ns, 11_000_000);
1141 }
1142
1143 #[test]
1144 fn test_scalability_analysis() {
1145 let suite = QuantumBenchmarkSuite::new(BenchmarkConfig::default());
1146 let data = vec![
1147 (4, Duration::from_millis(1)),
1148 (6, Duration::from_millis(4)),
1149 (8, Duration::from_millis(16)),
1150 (10, Duration::from_millis(64)),
1151 ];
1152
1153 let analysis = suite.analyze_scalability(&data);
1154 assert!(analysis.time_growth_factor > 1.0);
1155 assert!(analysis.max_practical_qubits > 4);
1156 }
1157}