1use crate::error::QuantRS2Error;
8use crate::gate_translation::GateType;
9use crate::scirs2_quantum_profiler::{
10 CircuitProfilingResult, GateProfilingResult, MemoryAnalysis, OptimizationRecommendation,
11 ProfilingPrecision, QuantumGate, SimdAnalysis,
12};
13use scirs2_core::Complex64;
14use crate::parallel_ops_stubs::*;
16use crate::buffer_pool::BufferPool;
18use crate::platform::PlatformCapabilities;
19use scirs2_core::ndarray::{Array1, Array2, ArrayView1};
20use serde::{Deserialize, Serialize};
21use std::collections::{BTreeMap, HashMap, VecDeque};
22use std::io::Write;
23use std::sync::{
24 atomic::{AtomicU64, AtomicUsize, Ordering},
25 Arc, Mutex,
26};
27use std::time::{Duration, Instant};
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct EnhancedProfilingConfig {
32 pub precision: ProfilingPrecision,
34
35 pub enable_deep_analysis: bool,
37
38 pub track_memory_patterns: bool,
40
41 pub profile_simd_operations: bool,
43
44 pub track_parallel_patterns: bool,
46
47 pub enable_cache_analysis: bool,
49
50 pub track_memory_bandwidth: bool,
52
53 pub enable_instruction_profiling: bool,
55
56 pub enable_resource_estimation: bool,
58
59 pub analyze_noise_impact: bool,
61
62 pub generate_optimizations: bool,
64
65 pub bottleneck_detection_depth: usize,
67
68 pub enable_performance_prediction: bool,
70
71 pub hardware_aware_profiling: bool,
73
74 pub export_formats: Vec<ExportFormat>,
76}
77
78impl Default for EnhancedProfilingConfig {
79 fn default() -> Self {
80 Self {
81 precision: ProfilingPrecision::High,
82 enable_deep_analysis: true,
83 track_memory_patterns: true,
84 profile_simd_operations: true,
85 track_parallel_patterns: true,
86 enable_cache_analysis: true,
87 track_memory_bandwidth: true,
88 enable_instruction_profiling: false,
89 enable_resource_estimation: true,
90 analyze_noise_impact: true,
91 generate_optimizations: true,
92 bottleneck_detection_depth: 5,
93 enable_performance_prediction: true,
94 hardware_aware_profiling: true,
95 export_formats: vec![ExportFormat::JSON, ExportFormat::HTML, ExportFormat::CSV],
96 }
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
102pub enum ExportFormat {
103 JSON,
104 HTML,
105 CSV,
106 LaTeX,
107 Markdown,
108 Binary,
109}
110
111#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
113pub enum MetricType {
114 ExecutionTime,
115 MemoryUsage,
116 CacheHitRate,
117 SimdUtilization,
118 ParallelEfficiency,
119 MemoryBandwidth,
120 InstructionCount,
121 BranchMisprediction,
122 PowerConsumption,
123 ThermalThrottle,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct PerformanceMetrics {
129 pub values: HashMap<MetricType, f64>,
131
132 pub time_series: HashMap<MetricType, Vec<(f64, f64)>>,
134
135 pub statistics: MetricStatistics,
137
138 pub correlations: HashMap<(MetricType, MetricType), f64>,
140
141 pub anomalies: Vec<AnomalyEvent>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct MetricStatistics {
148 pub mean: HashMap<MetricType, f64>,
149 pub std_dev: HashMap<MetricType, f64>,
150 pub min: HashMap<MetricType, f64>,
151 pub max: HashMap<MetricType, f64>,
152 pub percentiles: HashMap<MetricType, BTreeMap<u8, f64>>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct AnomalyEvent {
158 pub timestamp: f64,
159 pub metric: MetricType,
160 pub severity: AnomalySeverity,
161 pub description: String,
162 pub impact: f64,
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
166pub enum AnomalySeverity {
167 Low,
168 Medium,
169 High,
170 Critical,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct BottleneckAnalysis {
176 pub bottlenecks: Vec<Bottleneck>,
178
179 pub impact_analysis: HashMap<String, f64>,
181
182 pub opportunities: Vec<OptimizationOpportunity>,
184
185 pub resource_heatmap: Array2<f64>,
187}
188
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct Bottleneck {
191 pub location: CircuitLocation,
192 pub bottleneck_type: BottleneckType,
193 pub severity: f64,
194 pub impact_percentage: f64,
195 pub suggested_fixes: Vec<String>,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
199pub enum BottleneckType {
200 MemoryBandwidth,
201 ComputeIntensive,
202 CacheMiss,
203 ParallelizationIssue,
204 SimdUnderutilization,
205 DataDependency,
206 ResourceContention,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct CircuitLocation {
211 pub gate_index: usize,
212 pub layer: usize,
213 pub qubits: Vec<usize>,
214 pub context: String,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct OptimizationOpportunity {
219 pub opportunity_type: OpportunityType,
220 pub estimated_improvement: f64,
221 pub difficulty: Difficulty,
222 pub implementation: String,
223 pub trade_offs: Vec<String>,
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
227pub enum OpportunityType {
228 GateFusion,
229 Parallelization,
230 SimdOptimization,
231 MemoryReordering,
232 CacheOptimization,
233 AlgorithmicImprovement,
234 HardwareSpecific,
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
238pub enum Difficulty {
239 Trivial,
240 Easy,
241 Medium,
242 Hard,
243 Expert,
244}
245
246#[derive(Serialize, Deserialize)]
248pub struct HardwarePerformanceModel {
249 #[serde(skip, default = "PlatformCapabilities::detect")]
251 pub platform: PlatformCapabilities,
252
253 pub characteristics: HardwareCharacteristics,
255
256 pub scaling_models: HashMap<String, ScalingModel>,
258
259 pub optimization_strategies: Vec<HardwareOptimizationStrategy>,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
264pub struct HardwareCharacteristics {
265 pub cpu_frequency: f64,
266 pub cache_sizes: Vec<usize>,
267 pub memory_bandwidth: f64,
268 pub simd_width: usize,
269 pub num_cores: usize,
270 pub gpu_available: bool,
271 pub gpu_memory: Option<usize>,
272 pub quantum_accelerator: Option<String>,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
276pub struct ScalingModel {
277 pub model_type: ScalingType,
278 pub parameters: HashMap<String, f64>,
279 pub confidence: f64,
280}
281
282#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
283pub enum ScalingType {
284 Linear,
285 Logarithmic,
286 Polynomial,
287 Exponential,
288 Custom,
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct HardwareOptimizationStrategy {
293 pub strategy_name: String,
294 pub applicable_conditions: Vec<String>,
295 pub expected_speedup: f64,
296 pub implementation_cost: f64,
297}
298
299pub struct EnhancedQuantumProfiler {
301 config: EnhancedProfilingConfig,
302 platform_caps: PlatformCapabilities,
303 buffer_pool: Arc<BufferPool<Complex64>>,
304 metrics_collector: Arc<MetricsCollector>,
305 hardware_model: Option<HardwarePerformanceModel>,
306 profiling_state: Arc<Mutex<ProfilingState>>,
307}
308
309struct MetricsCollector {
311 execution_times: Mutex<HashMap<String, Vec<Duration>>>,
312 memory_usage: AtomicUsize,
313 simd_ops_count: AtomicU64,
314 parallel_ops_count: AtomicU64,
315 cache_hits: AtomicU64,
316 cache_misses: AtomicU64,
317 bandwidth_bytes: AtomicU64,
318 start_time: Instant,
319}
320
321impl MetricsCollector {
322 fn new() -> Self {
323 Self {
324 execution_times: Mutex::new(HashMap::new()),
325 memory_usage: AtomicUsize::new(0),
326 simd_ops_count: AtomicU64::new(0),
327 parallel_ops_count: AtomicU64::new(0),
328 cache_hits: AtomicU64::new(0),
329 cache_misses: AtomicU64::new(0),
330 bandwidth_bytes: AtomicU64::new(0),
331 start_time: Instant::now(),
332 }
333 }
334
335 fn record_execution(&self, operation: &str, duration: Duration) {
336 let mut times = self
337 .execution_times
338 .lock()
339 .expect("Execution times lock poisoned");
340 times
341 .entry(operation.to_string())
342 .or_insert_with(Vec::new)
343 .push(duration);
344 }
345
346 fn record_memory(&self, bytes: usize) {
347 self.memory_usage.fetch_add(bytes, Ordering::Relaxed);
348 }
349
350 fn record_simd_op(&self) {
351 self.simd_ops_count.fetch_add(1, Ordering::Relaxed);
352 }
353
354 fn record_parallel_op(&self) {
355 self.parallel_ops_count.fetch_add(1, Ordering::Relaxed);
356 }
357
358 fn record_cache_access(&self, hit: bool) {
359 if hit {
360 self.cache_hits.fetch_add(1, Ordering::Relaxed);
361 } else {
362 self.cache_misses.fetch_add(1, Ordering::Relaxed);
363 }
364 }
365
366 fn record_bandwidth(&self, bytes: usize) {
367 self.bandwidth_bytes
368 .fetch_add(bytes as u64, Ordering::Relaxed);
369 }
370
371 fn get_elapsed(&self) -> Duration {
372 self.start_time.elapsed()
373 }
374}
375
376struct ProfilingState {
378 current_depth: usize,
379 call_stack: Vec<String>,
380 gate_timings: HashMap<usize, GateTimingInfo>,
381 memory_snapshots: VecDeque<MemorySnapshot>,
382 anomaly_detector: AnomalyDetector,
383}
384
385#[derive(Debug, Clone)]
386struct GateTimingInfo {
387 gate_type: GateType,
388 start_time: Instant,
389 end_time: Option<Instant>,
390 memory_before: usize,
391 memory_after: Option<usize>,
392 simd_ops: u64,
393 parallel_ops: u64,
394}
395
396#[derive(Debug, Clone)]
397struct MemorySnapshot {
398 timestamp: Instant,
399 total_memory: usize,
400 heap_memory: usize,
401 stack_memory: usize,
402 buffer_pool_memory: usize,
403}
404
405struct AnomalyDetector {
407 baseline_metrics: HashMap<MetricType, (f64, f64)>, detection_threshold: f64,
409 history_window: usize,
410 metric_history: HashMap<MetricType, VecDeque<f64>>,
411}
412
413impl AnomalyDetector {
414 fn new(detection_threshold: f64, history_window: usize) -> Self {
415 Self {
416 baseline_metrics: HashMap::new(),
417 detection_threshold,
418 history_window,
419 metric_history: HashMap::new(),
420 }
421 }
422
423 fn update_metric(&mut self, metric: MetricType, value: f64) -> Option<AnomalyEvent> {
424 let history = self
425 .metric_history
426 .entry(metric)
427 .or_insert_with(VecDeque::new);
428 history.push_back(value);
429
430 if history.len() > self.history_window {
431 history.pop_front();
432 }
433
434 if history.len() >= 10 {
436 let mean: f64 = history.iter().sum::<f64>() / history.len() as f64;
437 let variance: f64 =
438 history.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / history.len() as f64;
439 let std_dev = variance.sqrt();
440
441 self.baseline_metrics.insert(metric, (mean, std_dev));
442
443 if let Some(&(baseline_mean, baseline_std)) = self.baseline_metrics.get(&metric) {
445 let z_score = (value - baseline_mean).abs() / baseline_std;
446
447 if z_score > self.detection_threshold {
448 let severity = match z_score {
449 z if z < 3.0 => AnomalySeverity::Low,
450 z if z < 4.0 => AnomalySeverity::Medium,
451 z if z < 5.0 => AnomalySeverity::High,
452 _ => AnomalySeverity::Critical,
453 };
454
455 return Some(AnomalyEvent {
456 timestamp: history.len() as f64,
457 metric,
458 severity,
459 description: format!("Anomaly detected: z-score = {z_score:.2}"),
460 impact: z_score / 10.0, });
462 }
463 }
464 }
465
466 None
467 }
468}
469
470impl EnhancedQuantumProfiler {
471 pub fn new() -> Self {
473 Self::with_config(EnhancedProfilingConfig::default())
474 }
475
476 pub fn with_config(config: EnhancedProfilingConfig) -> Self {
478 let platform_caps = PlatformCapabilities::detect();
479 let buffer_pool = Arc::new(BufferPool::new());
480 let metrics_collector = Arc::new(MetricsCollector::new());
481
482 let hardware_model = if config.hardware_aware_profiling {
483 Some(Self::build_hardware_model(&platform_caps))
484 } else {
485 None
486 };
487
488 let profiling_state = Arc::new(Mutex::new(ProfilingState {
489 current_depth: 0,
490 call_stack: Vec::new(),
491 gate_timings: HashMap::new(),
492 memory_snapshots: VecDeque::new(),
493 anomaly_detector: AnomalyDetector::new(3.0, 100),
494 }));
495
496 Self {
497 config,
498 platform_caps,
499 buffer_pool,
500 metrics_collector,
501 hardware_model,
502 profiling_state,
503 }
504 }
505
506 fn gpu_total_memory_bytes(platform_caps: &PlatformCapabilities) -> Option<usize> {
510 if !platform_caps.gpu.available {
511 return None;
512 }
513 let devices = &platform_caps.gpu.devices;
514 let primary = platform_caps.gpu.primary_device.unwrap_or(0);
515 devices
516 .get(primary)
517 .or_else(|| devices.first())
518 .map(|device| device.memory_bytes)
519 .filter(|&bytes| bytes > 0)
520 }
521
522 fn build_hardware_model(platform_caps: &PlatformCapabilities) -> HardwarePerformanceModel {
524 let characteristics = HardwareCharacteristics {
525 cpu_frequency: 3.0e9, cache_sizes: vec![32 * 1024, 256 * 1024, 8 * 1024 * 1024], memory_bandwidth: 50.0e9, simd_width: if platform_caps.simd_available() {
529 256
530 } else {
531 128
532 },
533 num_cores: platform_caps.cpu.logical_cores,
534 gpu_available: platform_caps.gpu_available(),
535 gpu_memory: Self::gpu_total_memory_bytes(platform_caps),
539 quantum_accelerator: None,
540 };
541
542 let mut scaling_models = HashMap::new();
543 scaling_models.insert(
544 "gate_execution".to_string(),
545 ScalingModel {
546 model_type: ScalingType::Linear,
547 parameters: vec![("slope".to_string(), 1e-6), ("intercept".to_string(), 1e-7)]
548 .into_iter()
549 .collect(),
550 confidence: 0.95,
551 },
552 );
553
554 scaling_models.insert(
555 "memory_access".to_string(),
556 ScalingModel {
557 model_type: ScalingType::Logarithmic,
558 parameters: vec![("base".to_string(), 2.0), ("coefficient".to_string(), 1e-8)]
559 .into_iter()
560 .collect(),
561 confidence: 0.90,
562 },
563 );
564
565 let optimization_strategies = vec![
566 HardwareOptimizationStrategy {
567 strategy_name: "SIMD Vectorization".to_string(),
568 applicable_conditions: vec!["vector_friendly_gates".to_string()],
569 expected_speedup: 4.0,
570 implementation_cost: 0.2,
571 },
572 HardwareOptimizationStrategy {
573 strategy_name: "Parallel Execution".to_string(),
574 applicable_conditions: vec!["independent_gates".to_string()],
575 expected_speedup: characteristics.num_cores as f64 * 0.8,
576 implementation_cost: 0.3,
577 },
578 HardwareOptimizationStrategy {
579 strategy_name: "Cache Optimization".to_string(),
580 applicable_conditions: vec!["repeated_access_patterns".to_string()],
581 expected_speedup: 2.0,
582 implementation_cost: 0.1,
583 },
584 ];
585
586 HardwarePerformanceModel {
587 platform: PlatformCapabilities::detect(),
588 characteristics,
589 scaling_models,
590 optimization_strategies,
591 }
592 }
593
594 pub fn profile_circuit(
596 &self,
597 circuit: &[QuantumGate],
598 num_qubits: usize,
599 ) -> Result<EnhancedProfilingReport, QuantRS2Error> {
600 let start_time = Instant::now();
601
602 self.initialize_profiling(num_qubits)?;
604
605 let mut gate_results = Vec::new();
607 for (idx, gate) in circuit.iter().enumerate() {
608 let gate_result = self.profile_gate(gate, idx, num_qubits)?;
609 gate_results.push(gate_result);
610 }
611
612 let performance_metrics = self.collect_performance_metrics()?;
614
615 let bottleneck_analysis = if self.config.enable_deep_analysis {
617 Some(self.analyze_bottlenecks(&gate_results, num_qubits)?)
618 } else {
619 None
620 };
621
622 let optimizations = if self.config.generate_optimizations {
624 self.generate_optimization_recommendations(&gate_results, &bottleneck_analysis)?
625 } else {
626 Vec::new()
627 };
628
629 let performance_predictions = if self.config.enable_performance_prediction {
631 Some(self.predict_performance(&gate_results, num_qubits)?)
632 } else {
633 None
634 };
635
636 let total_time = start_time.elapsed();
638
639 let export_data = self.prepare_export_data(&gate_results)?;
641
642 Ok(EnhancedProfilingReport {
643 summary: ProfilingSummary {
644 total_execution_time: total_time,
645 num_gates: circuit.len(),
646 num_qubits,
647 platform_info: PlatformCapabilities::detect(),
648 profiling_config: self.config.clone(),
649 },
650 gate_results,
651 performance_metrics,
652 bottleneck_analysis,
653 optimizations,
654 performance_predictions,
655 export_data,
656 })
657 }
658
659 fn initialize_profiling(&self, num_qubits: usize) -> Result<(), QuantRS2Error> {
661 let mut state = self
662 .profiling_state
663 .lock()
664 .map_err(|e| QuantRS2Error::RuntimeError(format!("Lock poisoned: {e}")))?;
665 state.current_depth = 0;
666 state.call_stack.clear();
667 state.gate_timings.clear();
668 state.memory_snapshots.clear();
669
670 let initial_snapshot = MemorySnapshot {
672 timestamp: Instant::now(),
673 total_memory: self.estimate_memory_usage(num_qubits),
674 heap_memory: 0,
675 stack_memory: 0,
676 buffer_pool_memory: 0,
677 };
678 state.memory_snapshots.push_back(initial_snapshot);
679
680 Ok(())
681 }
682
683 fn profile_gate(
685 &self,
686 gate: &QuantumGate,
687 gate_index: usize,
688 num_qubits: usize,
689 ) -> Result<EnhancedGateProfilingResult, QuantRS2Error> {
690 let start_time = Instant::now();
691 let memory_before = self.estimate_memory_usage(num_qubits);
692
693 {
695 let mut state = self
696 .profiling_state
697 .lock()
698 .map_err(|e| QuantRS2Error::RuntimeError(format!("Lock poisoned: {e}")))?;
699 state.gate_timings.insert(
700 gate_index,
701 GateTimingInfo {
702 gate_type: gate.gate_type().clone(),
703 start_time,
704 end_time: None,
705 memory_before,
706 memory_after: None,
707 simd_ops: 0,
708 parallel_ops: 0,
709 },
710 );
711 }
712
713 self.simulate_gate_execution(gate, num_qubits)?;
715
716 let end_time = Instant::now();
717 let memory_after = self.estimate_memory_usage(num_qubits);
718 let execution_time = end_time - start_time;
719
720 {
722 let mut state = self
723 .profiling_state
724 .lock()
725 .map_err(|e| QuantRS2Error::RuntimeError(format!("Lock poisoned: {e}")))?;
726 if let Some(timing_info) = state.gate_timings.get_mut(&gate_index) {
727 timing_info.end_time = Some(end_time);
728 timing_info.memory_after = Some(memory_after);
729 timing_info.simd_ops = self
730 .metrics_collector
731 .simd_ops_count
732 .load(Ordering::Relaxed);
733 timing_info.parallel_ops = self
734 .metrics_collector
735 .parallel_ops_count
736 .load(Ordering::Relaxed);
737 }
738 }
739
740 self.metrics_collector
742 .record_execution(&format!("{:?}", gate.gate_type()), execution_time);
743 self.metrics_collector
744 .record_memory(memory_after.saturating_sub(memory_before));
745
746 let mut anomalies = Vec::new();
748 {
749 let mut state = self
750 .profiling_state
751 .lock()
752 .map_err(|e| QuantRS2Error::RuntimeError(format!("Lock poisoned: {e}")))?;
753 if let Some(anomaly) = state
754 .anomaly_detector
755 .update_metric(MetricType::ExecutionTime, execution_time.as_secs_f64())
756 {
757 anomalies.push(anomaly);
758 }
759 }
760
761 Ok(EnhancedGateProfilingResult {
762 gate_index,
763 gate_type: gate.gate_type().clone(),
764 execution_time,
765 memory_delta: memory_after as i64 - memory_before as i64,
766 simd_operations: self
767 .metrics_collector
768 .simd_ops_count
769 .load(Ordering::Relaxed),
770 parallel_operations: self
771 .metrics_collector
772 .parallel_ops_count
773 .load(Ordering::Relaxed),
774 cache_efficiency: self.calculate_cache_efficiency(),
775 bandwidth_usage: self.calculate_bandwidth_usage(execution_time),
776 anomalies,
777 detailed_metrics: self.collect_detailed_gate_metrics(gate, execution_time)?,
778 })
779 }
780
781 fn simulate_gate_execution(
783 &self,
784 gate: &QuantumGate,
785 num_qubits: usize,
786 ) -> Result<(), QuantRS2Error> {
787 match gate.gate_type() {
789 GateType::H | GateType::X | GateType::Y | GateType::Z => {
790 if self.platform_caps.simd_available() {
792 self.metrics_collector.record_simd_op();
793 }
794 self.metrics_collector
795 .record_bandwidth(16 * (1 << num_qubits)); }
797 GateType::CNOT | GateType::CZ => {
798 if num_qubits > 10 {
800 self.metrics_collector.record_parallel_op();
801 }
802 self.metrics_collector
803 .record_bandwidth(32 * (1 << num_qubits));
804 }
805 _ => {
806 self.metrics_collector.record_parallel_op();
808 self.metrics_collector
809 .record_bandwidth(64 * (1 << num_qubits));
810 }
811 }
812
813 use scirs2_core::random::prelude::*;
815 let cache_hit = thread_rng().random::<f64>() > 0.2; self.metrics_collector.record_cache_access(cache_hit);
817
818 Ok(())
819 }
820
821 const fn estimate_memory_usage(&self, num_qubits: usize) -> usize {
823 let state_vector_size = (1 << num_qubits) * std::mem::size_of::<Complex64>();
824 let overhead = state_vector_size / 10; state_vector_size + overhead
826 }
827
828 fn calculate_cache_efficiency(&self) -> f64 {
830 let hits = self.metrics_collector.cache_hits.load(Ordering::Relaxed) as f64;
831 let misses = self.metrics_collector.cache_misses.load(Ordering::Relaxed) as f64;
832 let total = hits + misses;
833
834 if total > 0.0 {
835 hits / total
836 } else {
837 1.0 }
839 }
840
841 fn calculate_bandwidth_usage(&self, duration: Duration) -> f64 {
843 let bytes = self
844 .metrics_collector
845 .bandwidth_bytes
846 .load(Ordering::Relaxed) as f64;
847 let seconds = duration.as_secs_f64();
848
849 if seconds > 0.0 {
850 bytes / seconds
851 } else {
852 0.0
853 }
854 }
855
856 fn collect_detailed_gate_metrics(
858 &self,
859 gate: &QuantumGate,
860 execution_time: Duration,
861 ) -> Result<HashMap<String, f64>, QuantRS2Error> {
862 let mut metrics = HashMap::new();
863
864 metrics.insert(
865 "execution_time_us".to_string(),
866 execution_time.as_micros() as f64,
867 );
868 metrics.insert(
869 "cache_efficiency".to_string(),
870 self.calculate_cache_efficiency(),
871 );
872 metrics.insert(
873 "bandwidth_mbps".to_string(),
874 self.calculate_bandwidth_usage(execution_time) / 1e6,
875 );
876
877 if let Some(ref hw_model) = self.hardware_model {
878 metrics.insert(
879 "theoretical_flops".to_string(),
880 self.estimate_flops(gate, &hw_model.characteristics),
881 );
882 }
883
884 Ok(metrics)
885 }
886
887 fn estimate_flops(&self, gate: &QuantumGate, hw_chars: &HardwareCharacteristics) -> f64 {
889 let base_flops = match gate.gate_type() {
890 GateType::H => 8.0, GateType::X | GateType::Y | GateType::Z => 4.0,
892 GateType::CNOT | GateType::CZ => 16.0,
893 _ => 32.0, };
895
896 base_flops * hw_chars.cpu_frequency
897 }
898
899 fn collect_performance_metrics(&self) -> Result<PerformanceMetrics, QuantRS2Error> {
901 let mut values = HashMap::new();
902 let elapsed = self.metrics_collector.get_elapsed();
903
904 values.insert(MetricType::ExecutionTime, elapsed.as_secs_f64());
905 values.insert(
906 MetricType::MemoryUsage,
907 self.metrics_collector.memory_usage.load(Ordering::Relaxed) as f64,
908 );
909 values.insert(
910 MetricType::SimdUtilization,
911 self.metrics_collector
912 .simd_ops_count
913 .load(Ordering::Relaxed) as f64,
914 );
915 values.insert(
916 MetricType::ParallelEfficiency,
917 self.metrics_collector
918 .parallel_ops_count
919 .load(Ordering::Relaxed) as f64,
920 );
921 values.insert(MetricType::CacheHitRate, self.calculate_cache_efficiency());
922 values.insert(
923 MetricType::MemoryBandwidth,
924 self.calculate_bandwidth_usage(elapsed),
925 );
926
927 let statistics = self.calculate_metric_statistics(&values)?;
929
930 let mut time_series = HashMap::new();
932 for (metric, value) in &values {
933 time_series.insert(*metric, vec![(0.0, 0.0), (elapsed.as_secs_f64(), *value)]);
934 }
935
936 Ok(PerformanceMetrics {
937 values,
938 time_series,
939 statistics,
940 correlations: HashMap::new(), anomalies: Vec::new(), })
943 }
944
945 fn calculate_metric_statistics(
947 &self,
948 values: &HashMap<MetricType, f64>,
949 ) -> Result<MetricStatistics, QuantRS2Error> {
950 let mut mean = HashMap::new();
951 let mut std_dev = HashMap::new();
952 let mut min = HashMap::new();
953 let mut max = HashMap::new();
954 let mut percentiles = HashMap::new();
955
956 for (metric, value) in values {
957 mean.insert(*metric, *value);
958 std_dev.insert(*metric, 0.0); min.insert(*metric, *value);
960 max.insert(*metric, *value);
961
962 let mut percs = BTreeMap::new();
963 percs.insert(50, *value); percs.insert(95, *value * 1.1); percs.insert(99, *value * 1.2); percentiles.insert(*metric, percs);
967 }
968
969 Ok(MetricStatistics {
970 mean,
971 std_dev,
972 min,
973 max,
974 percentiles,
975 })
976 }
977
978 fn analyze_bottlenecks(
980 &self,
981 gate_results: &[EnhancedGateProfilingResult],
982 num_qubits: usize,
983 ) -> Result<BottleneckAnalysis, QuantRS2Error> {
984 let mut bottlenecks = Vec::new();
985 let mut impact_analysis = HashMap::new();
986 let mut opportunities = Vec::new();
987
988 let total_time: Duration = gate_results.iter().map(|r| r.execution_time).sum();
990 let avg_time = total_time / gate_results.len() as u32;
991
992 for (idx, result) in gate_results.iter().enumerate() {
993 if result.execution_time > avg_time * 2 {
994 let impact = result.execution_time.as_secs_f64() / total_time.as_secs_f64();
995
996 bottlenecks.push(Bottleneck {
997 location: CircuitLocation {
998 gate_index: idx,
999 layer: idx / num_qubits, qubits: vec![idx % num_qubits], context: format!("Gate {:?} at index {}", result.gate_type, idx),
1002 },
1003 bottleneck_type: BottleneckType::ComputeIntensive,
1004 severity: impact * 100.0,
1005 impact_percentage: impact * 100.0,
1006 suggested_fixes: vec![
1007 "Consider gate decomposition".to_string(),
1008 "Explore parallel execution".to_string(),
1009 ],
1010 });
1011
1012 impact_analysis.insert(format!("gate_{idx}"), impact);
1013 }
1014
1015 if result.cache_efficiency < 0.5 {
1017 bottlenecks.push(Bottleneck {
1018 location: CircuitLocation {
1019 gate_index: idx,
1020 layer: idx / num_qubits,
1021 qubits: vec![idx % num_qubits],
1022 context: format!("Poor cache efficiency at gate {idx}"),
1023 },
1024 bottleneck_type: BottleneckType::CacheMiss,
1025 severity: (1.0 - result.cache_efficiency) * 50.0,
1026 impact_percentage: 10.0, suggested_fixes: vec![
1028 "Reorder operations for better locality".to_string(),
1029 "Consider data prefetching".to_string(),
1030 ],
1031 });
1032 }
1033 }
1034
1035 if self.platform_caps.simd_available() {
1037 let simd_utilization = gate_results
1038 .iter()
1039 .filter(|r| r.simd_operations > 0)
1040 .count() as f64
1041 / gate_results.len() as f64;
1042
1043 if simd_utilization < 0.5 {
1044 opportunities.push(OptimizationOpportunity {
1045 opportunity_type: OpportunityType::SimdOptimization,
1046 estimated_improvement: (1.0 - simd_utilization) * 2.0,
1047 difficulty: Difficulty::Medium,
1048 implementation: "Vectorize gate operations using AVX2".to_string(),
1049 trade_offs: vec!["Increased code complexity".to_string()],
1050 });
1051 }
1052 }
1053
1054 let resource_heatmap = Array2::zeros((gate_results.len(), 4)); Ok(BottleneckAnalysis {
1058 bottlenecks,
1059 impact_analysis,
1060 opportunities,
1061 resource_heatmap,
1062 })
1063 }
1064
1065 fn generate_optimization_recommendations(
1067 &self,
1068 gate_results: &[EnhancedGateProfilingResult],
1069 bottleneck_analysis: &Option<BottleneckAnalysis>,
1070 ) -> Result<Vec<EnhancedOptimizationRecommendation>, QuantRS2Error> {
1071 let mut recommendations = Vec::new();
1072
1073 for window in gate_results.windows(2) {
1075 if Self::can_fuse_gates(&window[0].gate_type, &window[1].gate_type) {
1076 recommendations.push(EnhancedOptimizationRecommendation {
1077 recommendation_type: RecommendationType::GateFusion,
1078 priority: Priority::High,
1079 estimated_speedup: 1.5,
1080 implementation_difficulty: Difficulty::Easy,
1081 description: format!(
1082 "Fuse {:?} and {:?} gates",
1083 window[0].gate_type, window[1].gate_type
1084 ),
1085 code_example: Some(
1086 self.generate_fusion_code(&window[0].gate_type, &window[1].gate_type),
1087 ),
1088 prerequisites: vec!["Adjacent gates must commute".to_string()],
1089 risks: vec!["May increase numerical error".to_string()],
1090 });
1091 }
1092 }
1093
1094 if let Some(ref hw_model) = self.hardware_model {
1096 for strategy in &hw_model.optimization_strategies {
1097 if strategy.expected_speedup > 1.5 {
1098 recommendations.push(EnhancedOptimizationRecommendation {
1099 recommendation_type: RecommendationType::HardwareSpecific,
1100 priority: Priority::Medium,
1101 estimated_speedup: strategy.expected_speedup,
1102 implementation_difficulty: Difficulty::Hard,
1103 description: strategy.strategy_name.clone(),
1104 code_example: None,
1105 prerequisites: strategy.applicable_conditions.clone(),
1106 risks: vec!["Platform-specific code".to_string()],
1107 });
1108 }
1109 }
1110 }
1111
1112 if let Some(bottleneck_analysis) = bottleneck_analysis {
1114 for opportunity in &bottleneck_analysis.opportunities {
1115 recommendations.push(EnhancedOptimizationRecommendation {
1116 recommendation_type: match opportunity.opportunity_type {
1117 OpportunityType::GateFusion => RecommendationType::GateFusion,
1118 OpportunityType::Parallelization => RecommendationType::Parallelization,
1119 OpportunityType::SimdOptimization => RecommendationType::SimdVectorization,
1120 OpportunityType::MemoryReordering => RecommendationType::MemoryOptimization,
1121 OpportunityType::CacheOptimization => RecommendationType::CacheOptimization,
1122 OpportunityType::AlgorithmicImprovement => {
1123 RecommendationType::AlgorithmicChange
1124 }
1125 OpportunityType::HardwareSpecific => RecommendationType::HardwareSpecific,
1126 },
1127 priority: match opportunity.difficulty {
1128 Difficulty::Trivial | Difficulty::Easy => Priority::High,
1129 Difficulty::Medium => Priority::Medium,
1130 Difficulty::Hard | Difficulty::Expert => Priority::Low,
1131 },
1132 estimated_speedup: opportunity.estimated_improvement,
1133 implementation_difficulty: opportunity.difficulty,
1134 description: opportunity.implementation.clone(),
1135 code_example: None,
1136 prerequisites: Vec::new(),
1137 risks: opportunity.trade_offs.clone(),
1138 });
1139 }
1140 }
1141
1142 Ok(recommendations)
1143 }
1144
1145 const fn can_fuse_gates(gate1: &GateType, gate2: &GateType) -> bool {
1147 use GateType::{Rx, Ry, Rz, H, X, Y, Z};
1148 matches!(
1149 (gate1, gate2),
1150 (H, H) | (X, X) | (Y, Y) | (Z, Z) | (Rz(_), Rz(_)) | (Rx(_), Rx(_)) | (Ry(_), Ry(_)) )
1153 }
1154
1155 fn generate_fusion_code(&self, gate1: &GateType, gate2: &GateType) -> String {
1157 format!(
1158 "// Fused {gate1:?} and {gate2:?}\nlet fused_gate = FusedGate::new({gate1:?}, {gate2:?});\nfused_gate.apply(state);"
1159 )
1160 }
1161
1162 fn predict_performance(
1164 &self,
1165 gate_results: &[EnhancedGateProfilingResult],
1166 num_qubits: usize,
1167 ) -> Result<PerformancePredictions, QuantRS2Error> {
1168 let mut predictions = HashMap::new();
1169
1170 let current_time: Duration = gate_results.iter().map(|r| r.execution_time).sum();
1172
1173 predictions.insert(
1174 "current".to_string(),
1175 PredictedPerformance {
1176 hardware_description: "Current Platform".to_string(),
1177 estimated_time: current_time,
1178 confidence: 1.0,
1179 limiting_factors: vec!["Actual measurement".to_string()],
1180 },
1181 );
1182
1183 if self.platform_caps.gpu_available() {
1185 let gpu_speedup = ((num_qubits as f64).ln() * 2.0).max(1.0);
1189 predictions.insert(
1190 "gpu".to_string(),
1191 PredictedPerformance {
1192 hardware_description: "GPU Acceleration".to_string(),
1193 estimated_time: current_time.div_f64(gpu_speedup),
1194 confidence: 0.8,
1195 limiting_factors: vec!["Memory transfer overhead".to_string()],
1196 },
1197 );
1198 }
1199
1200 predictions.insert(
1202 "quantum_hw".to_string(),
1203 PredictedPerformance {
1204 hardware_description: "Quantum Hardware (NISQ)".to_string(),
1205 estimated_time: Duration::from_millis(gate_results.len() as u64 * 10), confidence: 0.5,
1207 limiting_factors: vec![
1208 "Gate fidelity".to_string(),
1209 "Connectivity constraints".to_string(),
1210 "Decoherence".to_string(),
1211 ],
1212 },
1213 );
1214
1215 predictions.insert(
1217 "cloud_qpu".to_string(),
1218 PredictedPerformance {
1219 hardware_description: "Cloud Quantum Processor".to_string(),
1220 estimated_time: Duration::from_secs(1)
1221 + Duration::from_millis(gate_results.len() as u64),
1222 confidence: 0.6,
1223 limiting_factors: vec!["Network latency".to_string(), "Queue time".to_string()],
1224 },
1225 );
1226
1227 let hardware_recommendations =
1229 self.generate_hardware_recommendations(num_qubits, &predictions);
1230
1231 Ok(PerformancePredictions {
1232 predictions,
1233 scaling_analysis: self.analyze_scaling(num_qubits)?,
1234 hardware_recommendations,
1235 })
1236 }
1237
1238 fn analyze_scaling(&self, num_qubits: usize) -> Result<ScalingAnalysis, QuantRS2Error> {
1240 Ok(ScalingAnalysis {
1241 qubit_scaling: ScalingType::Exponential,
1242 gate_scaling: ScalingType::Linear,
1243 memory_scaling: ScalingType::Exponential,
1244 predicted_limits: HashMap::from([
1245 ("max_qubits_cpu".to_string(), 30.0),
1246 ("max_qubits_gpu".to_string(), 35.0),
1247 ("max_gates_per_second".to_string(), 1e6),
1248 ]),
1249 })
1250 }
1251
1252 fn generate_hardware_recommendations(
1254 &self,
1255 num_qubits: usize,
1256 predictions: &HashMap<String, PredictedPerformance>,
1257 ) -> Vec<String> {
1258 let mut recommendations = Vec::new();
1259
1260 if num_qubits > 20 {
1261 recommendations.push("Consider GPU acceleration for large circuits".to_string());
1262 }
1263
1264 if num_qubits > 30 {
1265 recommendations.push("Tensor network methods recommended".to_string());
1266 }
1267
1268 if let Some(gpu_pred) = predictions.get("gpu") {
1269 if gpu_pred.confidence > 0.7 {
1270 recommendations.push("GPU acceleration shows promising speedup".to_string());
1271 }
1272 }
1273
1274 recommendations
1275 }
1276
1277 fn prepare_export_data(
1279 &self,
1280 gate_results: &[EnhancedGateProfilingResult],
1281 ) -> Result<HashMap<ExportFormat, Vec<u8>>, QuantRS2Error> {
1282 let mut export_data = HashMap::new();
1283
1284 for format in &self.config.export_formats {
1285 let data = match format {
1286 ExportFormat::JSON => self.export_to_json(gate_results)?,
1287 ExportFormat::CSV => self.export_to_csv(gate_results)?,
1288 ExportFormat::HTML => self.export_to_html(gate_results)?,
1289 _ => Vec::new(), };
1291 export_data.insert(*format, data);
1292 }
1293
1294 Ok(export_data)
1295 }
1296
1297 fn export_to_json(
1299 &self,
1300 gate_results: &[EnhancedGateProfilingResult],
1301 ) -> Result<Vec<u8>, QuantRS2Error> {
1302 let json = serde_json::to_vec_pretty(gate_results)
1303 .map_err(|e| QuantRS2Error::ComputationError(format!("CSV generation failed: {e}")))?;
1304 Ok(json)
1305 }
1306
1307 fn export_to_csv(
1309 &self,
1310 gate_results: &[EnhancedGateProfilingResult],
1311 ) -> Result<Vec<u8>, QuantRS2Error> {
1312 let mut csv = Vec::new();
1313 writeln!(csv, "gate_index,gate_type,execution_time_us,memory_delta,simd_ops,parallel_ops,cache_efficiency")
1314 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1315
1316 for result in gate_results {
1317 writeln!(
1318 csv,
1319 "{},{:?},{},{},{},{},{:.2}",
1320 result.gate_index,
1321 result.gate_type,
1322 result.execution_time.as_micros(),
1323 result.memory_delta,
1324 result.simd_operations,
1325 result.parallel_operations,
1326 result.cache_efficiency
1327 )
1328 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1329 }
1330
1331 Ok(csv)
1332 }
1333
1334 fn export_to_html(
1336 &self,
1337 gate_results: &[EnhancedGateProfilingResult],
1338 ) -> Result<Vec<u8>, QuantRS2Error> {
1339 let mut html = Vec::new();
1340 writeln!(
1341 html,
1342 "<html><head><title>Quantum Circuit Profiling Report</title>"
1343 )
1344 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1345 writeln!(html, "<style>table {{ border-collapse: collapse; }} th, td {{ border: 1px solid black; padding: 8px; }}</style>")
1346 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1347 writeln!(html, "</head><body><h1>Profiling Results</h1><table>")
1348 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1349 writeln!(html, "<tr><th>Gate</th><th>Type</th><th>Time (μs)</th><th>Memory</th><th>SIMD</th><th>Parallel</th><th>Cache</th></tr>")
1350 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1351
1352 for result in gate_results {
1353 writeln!(html, "<tr><td>{}</td><td>{:?}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{:.1}%</td></tr>",
1354 result.gate_index,
1355 result.gate_type,
1356 result.execution_time.as_micros(),
1357 result.memory_delta,
1358 result.simd_operations,
1359 result.parallel_operations,
1360 result.cache_efficiency * 100.0
1361 ).map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1362 }
1363
1364 writeln!(html, "</table></body></html>")
1365 .map_err(|e| QuantRS2Error::ComputationError(format!("IO error: {e}")))?;
1366
1367 Ok(html)
1368 }
1369}
1370
1371#[derive(Debug, Clone, Serialize, Deserialize)]
1373pub struct EnhancedGateProfilingResult {
1374 pub gate_index: usize,
1375 pub gate_type: GateType,
1376 pub execution_time: Duration,
1377 pub memory_delta: i64,
1378 pub simd_operations: u64,
1379 pub parallel_operations: u64,
1380 pub cache_efficiency: f64,
1381 pub bandwidth_usage: f64,
1382 pub anomalies: Vec<AnomalyEvent>,
1383 pub detailed_metrics: HashMap<String, f64>,
1384}
1385
1386#[derive(Debug, Clone, Serialize, Deserialize)]
1388pub struct EnhancedOptimizationRecommendation {
1389 pub recommendation_type: RecommendationType,
1390 pub priority: Priority,
1391 pub estimated_speedup: f64,
1392 pub implementation_difficulty: Difficulty,
1393 pub description: String,
1394 pub code_example: Option<String>,
1395 pub prerequisites: Vec<String>,
1396 pub risks: Vec<String>,
1397}
1398
1399#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1400pub enum RecommendationType {
1401 GateFusion,
1402 Parallelization,
1403 SimdVectorization,
1404 MemoryOptimization,
1405 CacheOptimization,
1406 AlgorithmicChange,
1407 HardwareSpecific,
1408}
1409
1410#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1411pub enum Priority {
1412 Low,
1413 Medium,
1414 High,
1415 Critical,
1416}
1417
1418#[derive(Debug, Clone, Serialize, Deserialize)]
1420pub struct PerformancePredictions {
1421 pub predictions: HashMap<String, PredictedPerformance>,
1422 pub scaling_analysis: ScalingAnalysis,
1423 pub hardware_recommendations: Vec<String>,
1424}
1425
1426#[derive(Debug, Clone, Serialize, Deserialize)]
1427pub struct PredictedPerformance {
1428 pub hardware_description: String,
1429 pub estimated_time: Duration,
1430 pub confidence: f64,
1431 pub limiting_factors: Vec<String>,
1432}
1433
1434#[derive(Debug, Clone, Serialize, Deserialize)]
1435pub struct ScalingAnalysis {
1436 pub qubit_scaling: ScalingType,
1437 pub gate_scaling: ScalingType,
1438 pub memory_scaling: ScalingType,
1439 pub predicted_limits: HashMap<String, f64>,
1440}
1441
1442#[derive(Serialize, Deserialize)]
1444pub struct EnhancedProfilingReport {
1445 pub summary: ProfilingSummary,
1446 pub gate_results: Vec<EnhancedGateProfilingResult>,
1447 pub performance_metrics: PerformanceMetrics,
1448 pub bottleneck_analysis: Option<BottleneckAnalysis>,
1449 pub optimizations: Vec<EnhancedOptimizationRecommendation>,
1450 pub performance_predictions: Option<PerformancePredictions>,
1451 pub export_data: HashMap<ExportFormat, Vec<u8>>,
1452}
1453
1454#[derive(Serialize, Deserialize)]
1455pub struct ProfilingSummary {
1456 pub total_execution_time: Duration,
1457 pub num_gates: usize,
1458 pub num_qubits: usize,
1459 #[serde(skip, default = "PlatformCapabilities::detect")]
1460 pub platform_info: PlatformCapabilities,
1461 pub profiling_config: EnhancedProfilingConfig,
1462}
1463
1464#[cfg(test)]
1465mod tests {
1466 use super::*;
1467
1468 #[test]
1469 fn test_enhanced_profiler_creation() {
1470 let profiler = EnhancedQuantumProfiler::new();
1471 assert!(profiler.platform_caps.simd_available());
1472 }
1473
1474 #[test]
1475 fn test_gpu_memory_reflects_real_hardware_not_hardcoded() {
1476 let caps = PlatformCapabilities::detect();
1479 let reported = EnhancedQuantumProfiler::gpu_total_memory_bytes(&caps);
1480
1481 if caps.gpu.available {
1482 let primary = caps.gpu.primary_device.unwrap_or(0);
1485 let expected = caps
1486 .gpu
1487 .devices
1488 .get(primary)
1489 .or_else(|| caps.gpu.devices.first())
1490 .map(|d| d.memory_bytes)
1491 .filter(|&b| b > 0);
1492 assert_eq!(
1493 reported, expected,
1494 "GPU memory must match the detector's real device query"
1495 );
1496 } else {
1497 assert_eq!(
1499 reported, None,
1500 "with no GPU present, gpu_memory must be None, not a fabricated constant"
1501 );
1502 }
1503 }
1504
1505 #[test]
1506 fn test_basic_profiling() {
1507 let profiler = EnhancedQuantumProfiler::new();
1508 let gates = vec![
1509 QuantumGate::new(GateType::H, vec![0], None),
1510 QuantumGate::new(GateType::CNOT, vec![0, 1], None),
1511 QuantumGate::new(GateType::H, vec![1], None),
1512 ];
1513
1514 let result = profiler
1515 .profile_circuit(&gates, 2)
1516 .expect("Failed to profile circuit");
1517 assert_eq!(result.gate_results.len(), 3);
1518 assert!(result.summary.total_execution_time.as_nanos() > 0);
1519 }
1520
1521 #[test]
1522 fn test_bottleneck_detection() {
1523 let config = EnhancedProfilingConfig {
1524 enable_deep_analysis: true,
1525 ..Default::default()
1526 };
1527 let profiler = EnhancedQuantumProfiler::with_config(config);
1528
1529 let gates = vec![
1530 QuantumGate::new(GateType::H, vec![0], None),
1531 QuantumGate::new(GateType::T, vec![0], None),
1532 QuantumGate::new(GateType::H, vec![0], None),
1533 ];
1534
1535 let result = profiler
1536 .profile_circuit(&gates, 1)
1537 .expect("Failed to profile circuit");
1538 assert!(result.bottleneck_analysis.is_some());
1539 }
1540
1541 #[test]
1542 fn test_optimization_recommendations() {
1543 let config = EnhancedProfilingConfig {
1544 generate_optimizations: true,
1545 ..Default::default()
1546 };
1547 let profiler = EnhancedQuantumProfiler::with_config(config);
1548
1549 let gates = vec![
1550 QuantumGate::new(GateType::H, vec![0], None),
1551 QuantumGate::new(GateType::H, vec![0], None), ];
1553
1554 let result = profiler
1555 .profile_circuit(&gates, 1)
1556 .expect("Failed to profile circuit");
1557 assert!(!result.optimizations.is_empty());
1558 assert!(result
1559 .optimizations
1560 .iter()
1561 .any(|opt| opt.recommendation_type == RecommendationType::GateFusion));
1562 }
1563
1564 #[test]
1565 fn test_performance_prediction() {
1566 let config = EnhancedProfilingConfig {
1567 enable_performance_prediction: true,
1568 ..Default::default()
1569 };
1570 let profiler = EnhancedQuantumProfiler::with_config(config);
1571
1572 let gates = vec![
1573 QuantumGate::new(GateType::X, vec![0], None),
1574 QuantumGate::new(GateType::Y, vec![1], None),
1575 QuantumGate::new(GateType::Z, vec![2], None),
1576 ];
1577
1578 let result = profiler
1579 .profile_circuit(&gates, 3)
1580 .expect("Failed to profile circuit");
1581 assert!(result.performance_predictions.is_some());
1582
1583 let predictions = result
1584 .performance_predictions
1585 .expect("Missing performance predictions");
1586 assert!(predictions.predictions.contains_key("current"));
1587 assert!(predictions.predictions.contains_key("quantum_hw"));
1588 }
1589
1590 #[test]
1591 fn test_export_formats() {
1592 let config = EnhancedProfilingConfig {
1593 export_formats: vec![ExportFormat::JSON, ExportFormat::CSV, ExportFormat::HTML],
1594 ..Default::default()
1595 };
1596 let profiler = EnhancedQuantumProfiler::with_config(config);
1597
1598 let gates = vec![QuantumGate::new(GateType::H, vec![0], None)];
1599
1600 let result = profiler
1601 .profile_circuit(&gates, 1)
1602 .expect("Failed to profile circuit");
1603 assert_eq!(result.export_data.len(), 3);
1604 assert!(result.export_data.contains_key(&ExportFormat::JSON));
1605 assert!(result.export_data.contains_key(&ExportFormat::CSV));
1606 assert!(result.export_data.contains_key(&ExportFormat::HTML));
1607 }
1608}