quantrs2_circuit/
resource_estimator.rs

1//! Resource estimator using `SciRS2` complexity analysis
2//!
3//! This module provides comprehensive resource estimation for quantum circuits,
4//! including gate counts, circuit depth, memory requirements, and execution time
5//! estimation using `SciRS2`'s advanced complexity analysis capabilities.
6
7use crate::builder::Circuit;
8use crate::scirs2_integration::{AnalyzerConfig, GraphMetrics, SciRS2CircuitAnalyzer};
9use quantrs2_core::{
10    error::{QuantRS2Error, QuantRS2Result},
11    gate::GateOp,
12    qubit::QubitId,
13};
14use scirs2_core::ndarray::Array2;
15use scirs2_core::Complex64;
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18use std::time::Duration;
19
20/// Comprehensive resource estimation result
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct ResourceEstimate {
23    /// Circuit-level resource metrics
24    pub circuit_metrics: CircuitMetrics,
25    /// Computational complexity analysis
26    pub complexity_analysis: ComplexityAnalysis,
27    /// Memory requirements estimation
28    pub memory_requirements: MemoryRequirements,
29    /// Execution time estimation
30    pub execution_time: ExecutionTimeEstimate,
31    /// Hardware-specific requirements
32    pub hardware_requirements: HardwareRequirements,
33    /// `SciRS2` graph analysis metrics
34    pub graph_metrics: Option<GraphMetrics>,
35    /// Scalability analysis
36    pub scalability_analysis: ScalabilityAnalysis,
37    /// Optimization suggestions
38    pub optimization_suggestions: Vec<OptimizationSuggestion>,
39}
40
41/// Basic circuit metrics
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct CircuitMetrics {
44    /// Total number of gates
45    pub total_gates: usize,
46    /// Gate count by type
47    pub gate_counts: HashMap<String, usize>,
48    /// Circuit depth (critical path length)
49    pub circuit_depth: usize,
50    /// Number of qubits used
51    pub qubit_count: usize,
52    /// Number of two-qubit gates
53    pub two_qubit_gates: usize,
54    /// Number of single-qubit gates
55    pub single_qubit_gates: usize,
56    /// Number of multi-qubit gates (3+ qubits)
57    pub multi_qubit_gates: usize,
58    /// Quantum volume estimate
59    pub quantum_volume: f64,
60    /// Circuit fidelity estimate
61    pub fidelity_estimate: f64,
62}
63
64/// Computational complexity analysis
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct ComplexityAnalysis {
67    /// Time complexity class
68    pub time_complexity: ComplexityClass,
69    /// Space complexity class
70    pub space_complexity: ComplexityClass,
71    /// Gate complexity (product of gates and qubits)
72    pub gate_complexity: f64,
73    /// Entanglement complexity
74    pub entanglement_complexity: f64,
75    /// Classical simulation complexity
76    pub classical_simulation_complexity: f64,
77    /// Quantum advantage factor
78    pub quantum_advantage_factor: Option<f64>,
79    /// Algorithm classification
80    pub algorithm_classification: AlgorithmClass,
81    /// Scaling behavior
82    pub scaling_behavior: ScalingBehavior,
83}
84
85/// Complexity classes for quantum algorithms
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub enum ComplexityClass {
88    /// Constant complexity O(1)
89    Constant,
90    /// Logarithmic complexity O(log n)
91    Logarithmic,
92    /// Linear complexity O(n)
93    Linear,
94    /// Polynomial complexity O(n^k)
95    Polynomial { degree: f64 },
96    /// Exponential complexity O(2^n)
97    Exponential,
98    /// Super-exponential complexity
99    SuperExponential,
100    /// Unknown or custom complexity
101    Custom { description: String },
102}
103
104/// Algorithm classification
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub enum AlgorithmClass {
107    /// Quantum Fourier Transform based
108    QftBased,
109    /// Amplitude amplification based
110    AmplitudeAmplification,
111    /// Variational quantum algorithm
112    Variational,
113    /// Quantum walk based
114    QuantumWalk,
115    /// Adiabatic quantum computation
116    Adiabatic,
117    /// Quantum error correction
118    ErrorCorrection,
119    /// Quantum machine learning
120    QuantumML,
121    /// Quantum simulation
122    QuantumSimulation,
123    /// Quantum cryptography
124    Cryptography,
125    /// Quantum optimization
126    Optimization,
127    /// General quantum circuit
128    General,
129}
130
131/// Scaling behavior analysis
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct ScalingBehavior {
134    /// How gates scale with problem size
135    pub gate_scaling: ScalingFunction,
136    /// How depth scales with problem size
137    pub depth_scaling: ScalingFunction,
138    /// How qubits scale with problem size
139    pub qubit_scaling: ScalingFunction,
140    /// How execution time scales
141    pub time_scaling: ScalingFunction,
142}
143
144/// Mathematical scaling function
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub enum ScalingFunction {
147    /// Constant scaling
148    Constant { value: f64 },
149    /// Linear scaling
150    Linear { coefficient: f64 },
151    /// Polynomial scaling
152    Polynomial { coefficient: f64, exponent: f64 },
153    /// Exponential scaling
154    Exponential { base: f64, coefficient: f64 },
155    /// Logarithmic scaling
156    Logarithmic { coefficient: f64 },
157    /// Custom function
158    Custom {
159        description: String,
160        complexity: f64,
161    },
162}
163
164/// Memory requirements estimation
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct MemoryRequirements {
167    /// Classical memory for state vector (bytes)
168    pub state_vector_memory: u64,
169    /// Classical memory for gate matrices (bytes)
170    pub gate_matrix_memory: u64,
171    /// Auxiliary memory for computation (bytes)
172    pub auxiliary_memory: u64,
173    /// Total classical memory required (bytes)
174    pub total_classical_memory: u64,
175    /// Quantum memory (number of qubits)
176    pub quantum_memory: usize,
177    /// Memory complexity scaling
178    pub memory_scaling: ScalingFunction,
179    /// Memory optimization suggestions
180    pub memory_optimizations: Vec<String>,
181}
182
183/// Execution time estimation
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct ExecutionTimeEstimate {
186    /// Estimated execution time
187    pub estimated_time: Duration,
188    /// Gate execution time breakdown
189    pub gate_time_breakdown: HashMap<String, Duration>,
190    /// Critical path execution time
191    pub critical_path_time: Duration,
192    /// Parallelization factor
193    pub parallelization_factor: f64,
194    /// Hardware-dependent timing factors
195    pub hardware_timing_factors: HashMap<String, f64>,
196    /// Confidence interval
197    pub confidence_interval: (Duration, Duration),
198    /// Timing model used
199    pub timing_model: TimingModel,
200}
201
202/// Timing models for execution estimation
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub enum TimingModel {
205    /// Simple gate counting model
206    GateCounting { gates_per_second: f64 },
207    /// Physics-based model with T1/T2 times
208    PhysicsBased {
209        t1_time: Duration,
210        t2_time: Duration,
211        gate_times: HashMap<String, Duration>,
212    },
213    /// Machine learning predicted times
214    MachineLearning { model_id: String, accuracy: f64 },
215    /// Benchmark-based empirical model
216    Empirical { benchmark_data: String },
217}
218
219/// Hardware-specific requirements
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct HardwareRequirements {
222    /// Minimum number of physical qubits
223    pub min_physical_qubits: usize,
224    /// Connectivity requirements
225    pub connectivity_requirements: ConnectivityRequirement,
226    /// Gate fidelity requirements
227    pub fidelity_requirements: HashMap<String, f64>,
228    /// Coherence time requirements
229    pub coherence_requirements: CoherenceRequirement,
230    /// Hardware platform recommendations
231    pub platform_recommendations: Vec<PlatformRecommendation>,
232    /// Error correction overhead
233    pub error_correction_overhead: ErrorCorrectionOverhead,
234}
235
236/// Connectivity requirements for quantum hardware
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub enum ConnectivityRequirement {
239    /// All-to-all connectivity required
240    AllToAll,
241    /// Linear nearest-neighbor connectivity
242    Linear,
243    /// Grid connectivity
244    Grid { dimensions: (usize, usize) },
245    /// Specific connectivity graph
246    Custom { adjacency_matrix: Vec<Vec<bool>> },
247    /// Minimum connectivity degree
248    MinimumDegree { degree: usize },
249}
250
251/// Coherence time requirements
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct CoherenceRequirement {
254    /// Minimum T1 time required
255    pub min_t1: Duration,
256    /// Minimum T2 time required
257    pub min_t2: Duration,
258    /// Required gate time to coherence time ratio
259    pub gate_to_coherence_ratio: f64,
260}
261
262/// Platform recommendation
263#[derive(Debug, Clone, Serialize, Deserialize)]
264pub struct PlatformRecommendation {
265    /// Platform name
266    pub platform: String,
267    /// Suitability score (0.0 to 1.0)
268    pub suitability_score: f64,
269    /// Reasoning for recommendation
270    pub reasoning: String,
271    /// Estimated success probability
272    pub success_probability: f64,
273    /// Required modifications
274    pub required_modifications: Vec<String>,
275}
276
277/// Error correction overhead analysis
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct ErrorCorrectionOverhead {
280    /// Physical to logical qubit ratio
281    pub physical_to_logical_ratio: f64,
282    /// Gate count overhead factor
283    pub gate_overhead_factor: f64,
284    /// Time overhead factor
285    pub time_overhead_factor: f64,
286    /// Recommended error correction code
287    pub recommended_code: String,
288    /// Threshold error rate required
289    pub threshold_error_rate: f64,
290}
291
292/// Scalability analysis
293#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct ScalabilityAnalysis {
295    /// Scalability score (0.0 to 1.0)
296    pub scalability_score: f64,
297    /// Bottleneck identification
298    pub bottlenecks: Vec<ScalabilityBottleneck>,
299    /// Scaling predictions
300    pub scaling_predictions: HashMap<String, ScalingPrediction>,
301    /// Resource limits
302    pub resource_limits: ResourceLimits,
303}
304
305/// Scalability bottleneck
306#[derive(Debug, Clone, Serialize, Deserialize)]
307pub struct ScalabilityBottleneck {
308    /// Bottleneck type
309    pub bottleneck_type: BottleneckType,
310    /// Severity (0.0 to 1.0)
311    pub severity: f64,
312    /// Description
313    pub description: String,
314    /// Mitigation suggestions
315    pub mitigation_suggestions: Vec<String>,
316}
317
318/// Types of scalability bottlenecks
319#[derive(Debug, Clone, Serialize, Deserialize)]
320pub enum BottleneckType {
321    /// Memory bottleneck
322    Memory,
323    /// Computation time bottleneck
324    ComputationTime,
325    /// Quantum coherence bottleneck
326    QuantumCoherence,
327    /// Hardware connectivity bottleneck
328    Connectivity,
329    /// Error rate bottleneck
330    ErrorRate,
331    /// Classical processing bottleneck
332    ClassicalProcessing,
333}
334
335/// Scaling prediction for different problem sizes
336#[derive(Debug, Clone, Serialize, Deserialize)]
337pub struct ScalingPrediction {
338    /// Problem sizes to predict for
339    pub problem_sizes: Vec<usize>,
340    /// Predicted resource values
341    pub predicted_values: Vec<f64>,
342    /// Confidence intervals
343    pub confidence_intervals: Vec<(f64, f64)>,
344    /// Prediction model used
345    pub model: String,
346}
347
348/// Resource limits for different scales
349#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct ResourceLimits {
351    /// Maximum feasible problem size with current technology
352    pub max_current_technology: usize,
353    /// Maximum feasible with near-term improvements
354    pub max_near_term: usize,
355    /// Maximum theoretical limit
356    pub max_theoretical: Option<usize>,
357    /// Limiting factors
358    pub limiting_factors: Vec<String>,
359}
360
361/// Optimization suggestion
362#[derive(Debug, Clone, Serialize, Deserialize)]
363pub struct OptimizationSuggestion {
364    /// Suggestion type
365    pub suggestion_type: OptimizationType,
366    /// Expected improvement
367    pub expected_improvement: f64,
368    /// Implementation complexity
369    pub implementation_complexity: ComplexityLevel,
370    /// Description
371    pub description: String,
372    /// Code impact areas
373    pub impact_areas: Vec<String>,
374}
375
376/// Types of optimization suggestions
377#[derive(Debug, Clone, Serialize, Deserialize)]
378pub enum OptimizationType {
379    /// Gate count reduction
380    GateCountReduction,
381    /// Depth reduction
382    DepthReduction,
383    /// Memory optimization
384    MemoryOptimization,
385    /// Parallelization opportunity
386    Parallelization,
387    /// Algorithm substitution
388    AlgorithmSubstitution,
389    /// Hardware-specific optimization
390    HardwareOptimization,
391    /// Error mitigation
392    ErrorMitigation,
393}
394
395/// Implementation complexity levels
396#[derive(Debug, Clone, Serialize, Deserialize)]
397pub enum ComplexityLevel {
398    /// Low complexity (easy to implement)
399    Low,
400    /// Medium complexity (moderate effort)
401    Medium,
402    /// High complexity (significant effort)
403    High,
404    /// Research required
405    Research,
406}
407
408/// Resource estimation configuration
409#[derive(Debug, Clone, Serialize, Deserialize)]
410pub struct ResourceEstimatorConfig {
411    /// Enable detailed analysis
412    pub enable_detailed_analysis: bool,
413    /// Enable `SciRS2` graph analysis
414    pub enable_graph_analysis: bool,
415    /// Enable scalability analysis
416    pub enable_scalability_analysis: bool,
417    /// Enable hardware-specific analysis
418    pub enable_hardware_analysis: bool,
419    /// Target hardware platforms
420    pub target_platforms: Vec<String>,
421    /// Analysis depth level
422    pub analysis_depth: AnalysisDepth,
423    /// Include optimization suggestions
424    pub include_optimizations: bool,
425    /// `SciRS2` analyzer configuration
426    pub scirs2_config: Option<AnalyzerConfig>,
427}
428
429/// Analysis depth levels
430#[derive(Debug, Clone, Serialize, Deserialize)]
431pub enum AnalysisDepth {
432    /// Basic gate counting only
433    Basic,
434    /// Standard complexity analysis
435    Standard,
436    /// Comprehensive analysis
437    Comprehensive,
438    /// Research-grade analysis
439    Research,
440}
441
442impl Default for ResourceEstimatorConfig {
443    fn default() -> Self {
444        Self {
445            enable_detailed_analysis: true,
446            enable_graph_analysis: true,
447            enable_scalability_analysis: true,
448            enable_hardware_analysis: true,
449            target_platforms: vec![
450                "IBM Quantum".to_string(),
451                "Google Quantum AI".to_string(),
452                "IonQ".to_string(),
453                "Rigetti".to_string(),
454            ],
455            analysis_depth: AnalysisDepth::Standard,
456            include_optimizations: true,
457            scirs2_config: None,
458        }
459    }
460}
461
462/// SciRS2-powered resource estimator
463pub struct ResourceEstimator {
464    config: ResourceEstimatorConfig,
465    scirs2_analyzer: Option<SciRS2CircuitAnalyzer>,
466    gate_cost_database: HashMap<String, GateCost>,
467    platform_database: HashMap<String, PlatformCharacteristics>,
468}
469
470/// Cost characteristics for different gates
471#[derive(Debug, Clone)]
472pub struct GateCost {
473    /// Execution time
474    pub execution_time: Duration,
475    /// Error rate
476    pub error_rate: f64,
477    /// Energy consumption
478    pub energy_cost: f64,
479    /// Resource overhead
480    pub resource_overhead: f64,
481}
482
483/// Platform characteristics database
484#[derive(Debug, Clone)]
485pub struct PlatformCharacteristics {
486    /// Platform name
487    pub name: String,
488    /// Qubit count
489    pub qubit_count: usize,
490    /// Connectivity topology
491    pub connectivity: ConnectivityRequirement,
492    /// Gate fidelities
493    pub gate_fidelities: HashMap<String, f64>,
494    /// Coherence times
495    pub coherence_times: CoherenceRequirement,
496    /// Gate set supported
497    pub native_gates: Vec<String>,
498    /// Measurement fidelity
499    pub measurement_fidelity: f64,
500}
501
502impl ResourceEstimator {
503    /// Create a new resource estimator
504    #[must_use]
505    pub fn new(config: ResourceEstimatorConfig) -> Self {
506        let scirs2_analyzer = if config.enable_graph_analysis {
507            Some(SciRS2CircuitAnalyzer::new())
508        } else {
509            None
510        };
511
512        let mut estimator = Self {
513            config,
514            scirs2_analyzer,
515            gate_cost_database: HashMap::new(),
516            platform_database: HashMap::new(),
517        };
518
519        estimator.initialize_databases();
520        estimator
521    }
522
523    /// Create resource estimator with custom `SciRS2` configuration
524    #[must_use]
525    pub fn with_scirs2_config(
526        config: ResourceEstimatorConfig,
527        scirs2_config: AnalyzerConfig,
528    ) -> Self {
529        let scirs2_analyzer = Some(SciRS2CircuitAnalyzer::with_config(scirs2_config));
530
531        let mut estimator = Self {
532            config,
533            scirs2_analyzer,
534            gate_cost_database: HashMap::new(),
535            platform_database: HashMap::new(),
536        };
537
538        estimator.initialize_databases();
539        estimator
540    }
541
542    /// Estimate resources for a quantum circuit
543    pub fn estimate_resources<const N: usize>(
544        &mut self,
545        circuit: &Circuit<N>,
546    ) -> QuantRS2Result<ResourceEstimate> {
547        // Calculate basic circuit metrics
548        let circuit_metrics = self.calculate_circuit_metrics(circuit)?;
549
550        // Perform complexity analysis
551        let complexity_analysis = self.analyze_complexity(circuit, &circuit_metrics)?;
552
553        // Estimate memory requirements
554        let memory_requirements = self.estimate_memory_requirements(circuit, &circuit_metrics)?;
555
556        // Estimate execution time
557        let execution_time = self.estimate_execution_time(circuit, &circuit_metrics)?;
558
559        // Analyze hardware requirements
560        let hardware_requirements = if self.config.enable_hardware_analysis {
561            self.analyze_hardware_requirements(circuit, &circuit_metrics)?
562        } else {
563            self.default_hardware_requirements()
564        };
565
566        // Get SciRS2 graph metrics if enabled
567        let graph_metrics = if self.config.enable_graph_analysis {
568            self.get_graph_metrics(circuit)?
569        } else {
570            None
571        };
572
573        // Perform scalability analysis
574        let scalability_analysis = if self.config.enable_scalability_analysis {
575            self.analyze_scalability(circuit, &circuit_metrics, &complexity_analysis)?
576        } else {
577            self.default_scalability_analysis()
578        };
579
580        // Generate optimization suggestions
581        let optimization_suggestions = if self.config.include_optimizations {
582            self.generate_optimization_suggestions(
583                circuit,
584                &circuit_metrics,
585                &complexity_analysis,
586                &memory_requirements,
587            )?
588        } else {
589            Vec::new()
590        };
591
592        Ok(ResourceEstimate {
593            circuit_metrics,
594            complexity_analysis,
595            memory_requirements,
596            execution_time,
597            hardware_requirements,
598            graph_metrics,
599            scalability_analysis,
600            optimization_suggestions,
601        })
602    }
603
604    /// Initialize gate cost and platform databases
605    fn initialize_databases(&mut self) {
606        // Initialize gate cost database
607        self.gate_cost_database.insert(
608            "H".to_string(),
609            GateCost {
610                execution_time: Duration::from_nanos(20),
611                error_rate: 0.001,
612                energy_cost: 1.0,
613                resource_overhead: 1.0,
614            },
615        );
616
617        self.gate_cost_database.insert(
618            "X".to_string(),
619            GateCost {
620                execution_time: Duration::from_nanos(20),
621                error_rate: 0.001,
622                energy_cost: 1.0,
623                resource_overhead: 1.0,
624            },
625        );
626
627        self.gate_cost_database.insert(
628            "CNOT".to_string(),
629            GateCost {
630                execution_time: Duration::from_nanos(200),
631                error_rate: 0.01,
632                energy_cost: 5.0,
633                resource_overhead: 2.0,
634            },
635        );
636
637        // Initialize platform database
638        self.platform_database.insert(
639            "IBM Quantum".to_string(),
640            PlatformCharacteristics {
641                name: "IBM Quantum".to_string(),
642                qubit_count: 127,
643                connectivity: ConnectivityRequirement::Custom {
644                    adjacency_matrix: Vec::new(), // Would contain actual IBM topology
645                },
646                gate_fidelities: [
647                    ("H".to_string(), 0.999),
648                    ("X".to_string(), 0.999),
649                    ("CNOT".to_string(), 0.99),
650                ]
651                .iter()
652                .cloned()
653                .collect(),
654                coherence_times: CoherenceRequirement {
655                    min_t1: Duration::from_micros(100),
656                    min_t2: Duration::from_micros(50),
657                    gate_to_coherence_ratio: 0.01,
658                },
659                native_gates: vec![
660                    "RZ".to_string(),
661                    "SX".to_string(),
662                    "X".to_string(),
663                    "CNOT".to_string(),
664                ],
665                measurement_fidelity: 0.98,
666            },
667        );
668
669        // Add more platforms...
670    }
671
672    /// Calculate basic circuit metrics
673    fn calculate_circuit_metrics<const N: usize>(
674        &self,
675        circuit: &Circuit<N>,
676    ) -> QuantRS2Result<CircuitMetrics> {
677        let gates = circuit.gates();
678        let total_gates = gates.len();
679
680        let mut gate_counts = HashMap::new();
681        let mut single_qubit_gates = 0;
682        let mut two_qubit_gates = 0;
683        let mut multi_qubit_gates = 0;
684
685        for gate in gates {
686            let gate_name = gate.name();
687            *gate_counts.entry(gate_name.to_string()).or_insert(0) += 1;
688
689            match gate.qubits().len() {
690                1 => single_qubit_gates += 1,
691                2 => two_qubit_gates += 1,
692                n if n > 2 => multi_qubit_gates += 1,
693                _ => {}
694            }
695        }
696
697        // Calculate circuit depth (simplified)
698        let circuit_depth = self.calculate_circuit_depth(circuit)?;
699
700        // Estimate quantum volume
701        let quantum_volume = (N as f64).min(circuit_depth as f64).powi(2);
702
703        // Estimate fidelity
704        let fidelity_estimate = self.estimate_circuit_fidelity(circuit, &gate_counts)?;
705
706        Ok(CircuitMetrics {
707            total_gates,
708            gate_counts,
709            circuit_depth,
710            qubit_count: N,
711            two_qubit_gates,
712            single_qubit_gates,
713            multi_qubit_gates,
714            quantum_volume,
715            fidelity_estimate,
716        })
717    }
718
719    /// Calculate circuit depth using topological analysis
720    fn calculate_circuit_depth<const N: usize>(
721        &self,
722        circuit: &Circuit<N>,
723    ) -> QuantRS2Result<usize> {
724        // Simplified depth calculation - would use proper DAG analysis in practice
725        let gates = circuit.gates();
726        if gates.is_empty() {
727            return Ok(0);
728        }
729
730        // For now, return a rough estimate based on gate dependencies
731        // In a full implementation, this would use proper topological sorting
732        let mut depth_per_qubit = vec![0; N];
733
734        for gate in gates {
735            let qubits = gate.qubits();
736            let max_current_depth = qubits
737                .iter()
738                .map(|q| depth_per_qubit[q.id() as usize])
739                .max()
740                .unwrap_or(0);
741
742            for qubit in qubits {
743                depth_per_qubit[qubit.id() as usize] = max_current_depth + 1;
744            }
745        }
746
747        Ok(depth_per_qubit.into_iter().max().unwrap_or(0))
748    }
749
750    /// Estimate circuit fidelity based on gate error rates
751    fn estimate_circuit_fidelity<const N: usize>(
752        &self,
753        circuit: &Circuit<N>,
754        gate_counts: &HashMap<String, usize>,
755    ) -> QuantRS2Result<f64> {
756        let mut total_error_rate = 0.0;
757
758        for (gate_name, count) in gate_counts {
759            if let Some(gate_cost) = self.gate_cost_database.get(gate_name) {
760                total_error_rate += gate_cost.error_rate * (*count as f64);
761            } else {
762                // Default error rate for unknown gates
763                total_error_rate += 0.01 * (*count as f64);
764            }
765        }
766
767        let fidelity = (1.0 - total_error_rate).clamp(0.0, 1.0);
768        Ok(fidelity)
769    }
770
771    /// Analyze computational complexity
772    fn analyze_complexity<const N: usize>(
773        &self,
774        circuit: &Circuit<N>,
775        metrics: &CircuitMetrics,
776    ) -> QuantRS2Result<ComplexityAnalysis> {
777        // Analyze time complexity based on gate count and circuit structure
778        let time_complexity = if metrics.total_gates <= 100 {
779            ComplexityClass::Constant
780        } else if metrics.total_gates < 1000 {
781            ComplexityClass::Linear
782        } else {
783            ComplexityClass::Polynomial { degree: 2.0 }
784        };
785
786        // Analyze space complexity (exponential in qubit count for classical simulation)
787        let space_complexity = ComplexityClass::Exponential;
788
789        // Calculate gate complexity
790        let gate_complexity = (metrics.total_gates as f64) * (N as f64);
791
792        // Estimate entanglement complexity (simplified)
793        let entanglement_complexity =
794            (metrics.two_qubit_gates as f64) / (metrics.total_gates as f64).max(1.0);
795
796        // Classical simulation complexity
797        let classical_simulation_complexity = (N as f64).exp2();
798
799        // Quantum advantage factor (simplified estimation)
800        let quantum_advantage_factor = if classical_simulation_complexity > 1e6 {
801            Some(classical_simulation_complexity / (metrics.total_gates as f64))
802        } else {
803            None
804        };
805
806        // Algorithm classification (simplified heuristic)
807        let algorithm_classification = self.classify_algorithm(circuit, metrics)?;
808
809        // Scaling behavior analysis
810        let scaling_behavior = self.analyze_scaling_behavior(metrics)?;
811
812        Ok(ComplexityAnalysis {
813            time_complexity,
814            space_complexity,
815            gate_complexity,
816            entanglement_complexity,
817            classical_simulation_complexity,
818            quantum_advantage_factor,
819            algorithm_classification,
820            scaling_behavior,
821        })
822    }
823
824    /// Classify the quantum algorithm based on circuit structure
825    fn classify_algorithm<const N: usize>(
826        &self,
827        circuit: &Circuit<N>,
828        metrics: &CircuitMetrics,
829    ) -> QuantRS2Result<AlgorithmClass> {
830        // Simplified algorithm classification based on gate patterns
831        let gates = circuit.gates();
832
833        // Check for QFT patterns (many H gates)
834        if let Some(&h_count) = metrics.gate_counts.get("H") {
835            if h_count > N / 2 {
836                return Ok(AlgorithmClass::QftBased);
837            }
838        }
839
840        // Check for amplitude amplification (controlled gates + H gates)
841        if metrics.two_qubit_gates > metrics.single_qubit_gates {
842            return Ok(AlgorithmClass::AmplitudeAmplification);
843        }
844
845        // Check for variational patterns (parameterized gates)
846        // This would require checking for RX, RY, RZ gates in practice
847        if metrics.circuit_depth > metrics.total_gates / 4 {
848            return Ok(AlgorithmClass::Variational);
849        }
850
851        Ok(AlgorithmClass::General)
852    }
853
854    /// Analyze scaling behavior
855    fn analyze_scaling_behavior(
856        &self,
857        metrics: &CircuitMetrics,
858    ) -> QuantRS2Result<ScalingBehavior> {
859        Ok(ScalingBehavior {
860            gate_scaling: ScalingFunction::Linear {
861                coefficient: metrics.total_gates as f64 / metrics.qubit_count as f64,
862            },
863            depth_scaling: ScalingFunction::Linear {
864                coefficient: metrics.circuit_depth as f64 / metrics.qubit_count as f64,
865            },
866            qubit_scaling: ScalingFunction::Linear { coefficient: 1.0 },
867            time_scaling: ScalingFunction::Polynomial {
868                coefficient: 1.0,
869                exponent: 2.0,
870            },
871        })
872    }
873
874    /// Estimate memory requirements
875    fn estimate_memory_requirements<const N: usize>(
876        &self,
877        circuit: &Circuit<N>,
878        metrics: &CircuitMetrics,
879    ) -> QuantRS2Result<MemoryRequirements> {
880        // State vector memory: 2^N complex numbers, each 16 bytes
881        let state_vector_memory = (1u64 << N) * 16;
882
883        // Gate matrix memory: approximate based on gate count
884        let gate_matrix_memory = (metrics.total_gates as u64) * 64; // 4x4 complex matrices
885
886        // Auxiliary memory for computation (buffers, temporaries)
887        let auxiliary_memory = state_vector_memory / 4;
888
889        let total_classical_memory = state_vector_memory + gate_matrix_memory + auxiliary_memory;
890
891        let memory_scaling = ScalingFunction::Exponential {
892            base: 2.0,
893            coefficient: 16.0,
894        };
895
896        let memory_optimizations = vec![
897            "Use sparse state representations for low-entanglement circuits".to_string(),
898            "Implement tensor network simulation for large qubit counts".to_string(),
899            "Use GPU memory for state vector storage".to_string(),
900        ];
901
902        Ok(MemoryRequirements {
903            state_vector_memory,
904            gate_matrix_memory,
905            auxiliary_memory,
906            total_classical_memory,
907            quantum_memory: N,
908            memory_scaling,
909            memory_optimizations,
910        })
911    }
912
913    /// Estimate execution time
914    fn estimate_execution_time<const N: usize>(
915        &self,
916        circuit: &Circuit<N>,
917        metrics: &CircuitMetrics,
918    ) -> QuantRS2Result<ExecutionTimeEstimate> {
919        let mut total_time = Duration::from_nanos(0);
920        let mut gate_time_breakdown = HashMap::new();
921
922        // Calculate time for each gate type
923        for (gate_name, count) in &metrics.gate_counts {
924            let gate_time = if let Some(gate_cost) = self.gate_cost_database.get(gate_name) {
925                gate_cost.execution_time
926            } else {
927                Duration::from_nanos(100) // Default gate time
928            };
929
930            let total_gate_time = gate_time * (*count as u32);
931            gate_time_breakdown.insert(gate_name.clone(), total_gate_time);
932            total_time += total_gate_time;
933        }
934
935        // Critical path time (simplified - would use proper scheduling analysis)
936        let critical_path_time = total_time / 2; // Rough estimate
937
938        // Parallelization factor
939        let parallelization_factor = if metrics.circuit_depth > 0 {
940            (metrics.total_gates as f64) / (metrics.circuit_depth as f64)
941        } else {
942            1.0
943        };
944
945        // Hardware timing factors
946        let hardware_timing_factors = [
947            ("decoherence_overhead".to_string(), 1.1),
948            ("measurement_overhead".to_string(), 1.05),
949            ("classical_processing".to_string(), 1.2),
950        ]
951        .iter()
952        .cloned()
953        .collect();
954
955        // Confidence interval (±20%)
956        let lower_bound = total_time * 80 / 100;
957        let upper_bound = total_time * 120 / 100;
958
959        let timing_model = TimingModel::GateCounting {
960            gates_per_second: 1e6,
961        };
962
963        Ok(ExecutionTimeEstimate {
964            estimated_time: total_time,
965            gate_time_breakdown,
966            critical_path_time,
967            parallelization_factor,
968            hardware_timing_factors,
969            confidence_interval: (lower_bound, upper_bound),
970            timing_model,
971        })
972    }
973
974    /// Analyze hardware requirements
975    fn analyze_hardware_requirements<const N: usize>(
976        &self,
977        circuit: &Circuit<N>,
978        metrics: &CircuitMetrics,
979    ) -> QuantRS2Result<HardwareRequirements> {
980        // Minimum physical qubits (with error correction overhead)
981        let min_physical_qubits = N * 50; // Rough estimate for logical qubits
982
983        // Connectivity requirements based on circuit structure
984        let connectivity_requirements = if metrics.two_qubit_gates > N {
985            ConnectivityRequirement::AllToAll
986        } else {
987            ConnectivityRequirement::Linear
988        };
989
990        // Fidelity requirements
991        let fidelity_requirements = [
992            ("single_qubit".to_string(), 0.999),
993            ("two_qubit".to_string(), 0.99),
994            ("measurement".to_string(), 0.98),
995        ]
996        .iter()
997        .cloned()
998        .collect();
999
1000        // Coherence requirements
1001        let coherence_requirements = CoherenceRequirement {
1002            min_t1: Duration::from_micros((metrics.circuit_depth as u64) * 10),
1003            min_t2: Duration::from_micros((metrics.circuit_depth as u64) * 5),
1004            gate_to_coherence_ratio: 0.01,
1005        };
1006
1007        // Platform recommendations
1008        let platform_recommendations = self.recommend_platforms(metrics)?;
1009
1010        // Error correction overhead
1011        let error_correction_overhead = ErrorCorrectionOverhead {
1012            physical_to_logical_ratio: 50.0,
1013            gate_overhead_factor: 10.0,
1014            time_overhead_factor: 100.0,
1015            recommended_code: "Surface Code".to_string(),
1016            threshold_error_rate: 0.001,
1017        };
1018
1019        Ok(HardwareRequirements {
1020            min_physical_qubits,
1021            connectivity_requirements,
1022            fidelity_requirements,
1023            coherence_requirements,
1024            platform_recommendations,
1025            error_correction_overhead,
1026        })
1027    }
1028
1029    /// Recommend suitable hardware platforms
1030    fn recommend_platforms(
1031        &self,
1032        metrics: &CircuitMetrics,
1033    ) -> QuantRS2Result<Vec<PlatformRecommendation>> {
1034        let mut recommendations = Vec::new();
1035
1036        for platform_name in &self.config.target_platforms {
1037            if let Some(platform) = self.platform_database.get(platform_name) {
1038                let suitability_score = self.calculate_platform_suitability(platform, metrics);
1039
1040                recommendations.push(PlatformRecommendation {
1041                    platform: platform_name.clone(),
1042                    suitability_score,
1043                    reasoning: self.generate_platform_reasoning(
1044                        platform,
1045                        metrics,
1046                        suitability_score,
1047                    ),
1048                    success_probability: suitability_score * 0.8,
1049                    required_modifications: self.suggest_platform_modifications(platform, metrics),
1050                });
1051            }
1052        }
1053
1054        recommendations.sort_by(|a, b| {
1055            b.suitability_score
1056                .partial_cmp(&a.suitability_score)
1057                .unwrap_or(std::cmp::Ordering::Equal)
1058        });
1059        Ok(recommendations)
1060    }
1061
1062    /// Calculate platform suitability score
1063    fn calculate_platform_suitability(
1064        &self,
1065        platform: &PlatformCharacteristics,
1066        metrics: &CircuitMetrics,
1067    ) -> f64 {
1068        let mut score = 1.0;
1069
1070        // Qubit count factor
1071        if platform.qubit_count < metrics.qubit_count {
1072            score *= 0.1; // Severely penalize insufficient qubits
1073        }
1074
1075        // Gate fidelity factor
1076        let avg_fidelity: f64 =
1077            platform.gate_fidelities.values().sum::<f64>() / platform.gate_fidelities.len() as f64;
1078        score *= avg_fidelity;
1079
1080        // Two-qubit gate factor
1081        if metrics.two_qubit_gates > metrics.qubit_count * 2 {
1082            score *= 0.8; // Penalize for high two-qubit gate requirements
1083        }
1084
1085        score.clamp(0.0, 1.0)
1086    }
1087
1088    /// Generate reasoning for platform recommendation
1089    fn generate_platform_reasoning(
1090        &self,
1091        platform: &PlatformCharacteristics,
1092        metrics: &CircuitMetrics,
1093        score: f64,
1094    ) -> String {
1095        if score > 0.8 {
1096            format!(
1097                "Excellent match: {} has sufficient qubits ({}) and high fidelity gates",
1098                platform.name, platform.qubit_count
1099            )
1100        } else if score > 0.6 {
1101            format!(
1102                "Good match: {} meets most requirements but may need optimization",
1103                platform.name
1104            )
1105        } else if score > 0.4 {
1106            format!(
1107                "Marginal match: {} has limitations for this circuit",
1108                platform.name
1109            )
1110        } else {
1111            format!(
1112                "Poor match: {} is not well-suited for this circuit",
1113                platform.name
1114            )
1115        }
1116    }
1117
1118    /// Suggest platform modifications
1119    fn suggest_platform_modifications(
1120        &self,
1121        platform: &PlatformCharacteristics,
1122        metrics: &CircuitMetrics,
1123    ) -> Vec<String> {
1124        let mut modifications = Vec::new();
1125
1126        if platform.qubit_count < metrics.qubit_count {
1127            modifications.push("Increase qubit count or decompose circuit".to_string());
1128        }
1129
1130        if metrics.two_qubit_gates > platform.qubit_count {
1131            modifications.push("Optimize circuit connectivity".to_string());
1132        }
1133
1134        modifications
1135    }
1136
1137    /// Get `SciRS2` graph metrics
1138    fn get_graph_metrics<const N: usize>(
1139        &mut self,
1140        circuit: &Circuit<N>,
1141    ) -> QuantRS2Result<Option<GraphMetrics>> {
1142        if let Some(analyzer) = &mut self.scirs2_analyzer {
1143            let analysis = analyzer.analyze_circuit(circuit)?;
1144            Ok(Some(analysis.metrics))
1145        } else {
1146            Ok(None)
1147        }
1148    }
1149
1150    /// Analyze scalability
1151    fn analyze_scalability<const N: usize>(
1152        &self,
1153        circuit: &Circuit<N>,
1154        metrics: &CircuitMetrics,
1155        complexity: &ComplexityAnalysis,
1156    ) -> QuantRS2Result<ScalabilityAnalysis> {
1157        let scalability_score = self.calculate_scalability_score(metrics, complexity);
1158        let bottlenecks = self.identify_bottlenecks(metrics, complexity);
1159        let scaling_predictions = self.predict_scaling(metrics)?;
1160        let resource_limits = self.calculate_resource_limits(metrics);
1161
1162        Ok(ScalabilityAnalysis {
1163            scalability_score,
1164            bottlenecks,
1165            scaling_predictions,
1166            resource_limits,
1167        })
1168    }
1169
1170    /// Calculate overall scalability score
1171    fn calculate_scalability_score(
1172        &self,
1173        metrics: &CircuitMetrics,
1174        complexity: &ComplexityAnalysis,
1175    ) -> f64 {
1176        let mut score: f64 = 1.0;
1177
1178        // Penalize exponential classical simulation complexity
1179        if complexity.classical_simulation_complexity > 1e12 {
1180            score *= 0.5;
1181        }
1182
1183        // Penalize high gate complexity
1184        if complexity.gate_complexity > 1e6 {
1185            score *= 0.7;
1186        }
1187
1188        // Reward quantum advantage
1189        if complexity.quantum_advantage_factor.is_some() {
1190            score *= 1.2;
1191        }
1192
1193        score.clamp(0.0, 1.0)
1194    }
1195
1196    /// Identify scalability bottlenecks
1197    fn identify_bottlenecks(
1198        &self,
1199        metrics: &CircuitMetrics,
1200        complexity: &ComplexityAnalysis,
1201    ) -> Vec<ScalabilityBottleneck> {
1202        let mut bottlenecks = Vec::new();
1203
1204        // Memory bottleneck
1205        if complexity.classical_simulation_complexity > 1e15 {
1206            bottlenecks.push(ScalabilityBottleneck {
1207                bottleneck_type: BottleneckType::Memory,
1208                severity: 0.9,
1209                description: "Exponential memory growth limits classical simulation".to_string(),
1210                mitigation_suggestions: vec![
1211                    "Use tensor network simulation".to_string(),
1212                    "Implement approximate methods".to_string(),
1213                ],
1214            });
1215        }
1216
1217        // Coherence bottleneck
1218        if metrics.circuit_depth > 100 {
1219            bottlenecks.push(ScalabilityBottleneck {
1220                bottleneck_type: BottleneckType::QuantumCoherence,
1221                severity: 0.7,
1222                description: "Deep circuits may exceed coherence times".to_string(),
1223                mitigation_suggestions: vec![
1224                    "Reduce circuit depth".to_string(),
1225                    "Use error correction".to_string(),
1226                ],
1227            });
1228        }
1229
1230        bottlenecks
1231    }
1232
1233    /// Predict scaling for different problem sizes
1234    fn predict_scaling(
1235        &self,
1236        metrics: &CircuitMetrics,
1237    ) -> QuantRS2Result<HashMap<String, ScalingPrediction>> {
1238        let mut predictions = HashMap::new();
1239
1240        // Gate count scaling
1241        let problem_sizes = vec![10, 20, 30, 40, 50];
1242        let gate_predictions: Vec<f64> = problem_sizes
1243            .iter()
1244            .map(|&size| {
1245                (size as f64) * (metrics.total_gates as f64) / (metrics.qubit_count as f64)
1246            })
1247            .collect();
1248        let gate_confidence: Vec<(f64, f64)> = gate_predictions
1249            .iter()
1250            .map(|&pred| (pred * 0.8, pred * 1.2))
1251            .collect();
1252
1253        predictions.insert(
1254            "gates".to_string(),
1255            ScalingPrediction {
1256                problem_sizes,
1257                predicted_values: gate_predictions,
1258                confidence_intervals: gate_confidence,
1259                model: "Linear scaling".to_string(),
1260            },
1261        );
1262
1263        Ok(predictions)
1264    }
1265
1266    /// Calculate resource limits
1267    fn calculate_resource_limits(&self, metrics: &CircuitMetrics) -> ResourceLimits {
1268        ResourceLimits {
1269            max_current_technology: 50,   // Current NISQ limit
1270            max_near_term: 1000,          // Near-term with error correction
1271            max_theoretical: Some(10000), // Theoretical limit
1272            limiting_factors: vec![
1273                "Quantum error rates".to_string(),
1274                "Coherence times".to_string(),
1275                "Classical simulation complexity".to_string(),
1276            ],
1277        }
1278    }
1279
1280    /// Generate optimization suggestions
1281    fn generate_optimization_suggestions<const N: usize>(
1282        &self,
1283        circuit: &Circuit<N>,
1284        metrics: &CircuitMetrics,
1285        complexity: &ComplexityAnalysis,
1286        memory: &MemoryRequirements,
1287    ) -> QuantRS2Result<Vec<OptimizationSuggestion>> {
1288        let mut suggestions = Vec::new();
1289
1290        // Gate count reduction
1291        if metrics.total_gates > 100 {
1292            suggestions.push(OptimizationSuggestion {
1293                suggestion_type: OptimizationType::GateCountReduction,
1294                expected_improvement: 0.2,
1295                implementation_complexity: ComplexityLevel::Medium,
1296                description: "Apply gate fusion and redundancy elimination".to_string(),
1297                impact_areas: vec!["circuit_depth".to_string(), "execution_time".to_string()],
1298            });
1299        }
1300
1301        // Memory optimization
1302        if memory.total_classical_memory > 1e9 as u64 {
1303            suggestions.push(OptimizationSuggestion {
1304                suggestion_type: OptimizationType::MemoryOptimization,
1305                expected_improvement: 0.5,
1306                implementation_complexity: ComplexityLevel::High,
1307                description: "Use tensor network or sparse representations".to_string(),
1308                impact_areas: vec![
1309                    "memory_usage".to_string(),
1310                    "simulation_feasibility".to_string(),
1311                ],
1312            });
1313        }
1314
1315        // Parallelization
1316        if metrics.circuit_depth < metrics.total_gates / 2 {
1317            suggestions.push(OptimizationSuggestion {
1318                suggestion_type: OptimizationType::Parallelization,
1319                expected_improvement: 0.3,
1320                implementation_complexity: ComplexityLevel::Low,
1321                description: "Increase gate-level parallelism".to_string(),
1322                impact_areas: vec!["execution_time".to_string()],
1323            });
1324        }
1325
1326        Ok(suggestions)
1327    }
1328
1329    /// Default hardware requirements for simplified analysis
1330    fn default_hardware_requirements(&self) -> HardwareRequirements {
1331        HardwareRequirements {
1332            min_physical_qubits: 0,
1333            connectivity_requirements: ConnectivityRequirement::Linear,
1334            fidelity_requirements: HashMap::new(),
1335            coherence_requirements: CoherenceRequirement {
1336                min_t1: Duration::from_micros(100),
1337                min_t2: Duration::from_micros(50),
1338                gate_to_coherence_ratio: 0.01,
1339            },
1340            platform_recommendations: Vec::new(),
1341            error_correction_overhead: ErrorCorrectionOverhead {
1342                physical_to_logical_ratio: 1.0,
1343                gate_overhead_factor: 1.0,
1344                time_overhead_factor: 1.0,
1345                recommended_code: "None".to_string(),
1346                threshold_error_rate: 1.0,
1347            },
1348        }
1349    }
1350
1351    /// Default scalability analysis for simplified analysis
1352    fn default_scalability_analysis(&self) -> ScalabilityAnalysis {
1353        ScalabilityAnalysis {
1354            scalability_score: 0.5,
1355            bottlenecks: Vec::new(),
1356            scaling_predictions: HashMap::new(),
1357            resource_limits: ResourceLimits {
1358                max_current_technology: 50,
1359                max_near_term: 100,
1360                max_theoretical: None,
1361                limiting_factors: Vec::new(),
1362            },
1363        }
1364    }
1365}
1366
1367/// Quick resource estimation with default options
1368pub fn estimate_circuit_resources<const N: usize>(
1369    circuit: &Circuit<N>,
1370) -> QuantRS2Result<ResourceEstimate> {
1371    let mut estimator = ResourceEstimator::new(ResourceEstimatorConfig::default());
1372    estimator.estimate_resources(circuit)
1373}
1374
1375/// Resource estimation with custom configuration
1376pub fn estimate_circuit_resources_with_config<const N: usize>(
1377    circuit: &Circuit<N>,
1378    config: ResourceEstimatorConfig,
1379) -> QuantRS2Result<ResourceEstimate> {
1380    let mut estimator = ResourceEstimator::new(config);
1381    estimator.estimate_resources(circuit)
1382}
1383
1384#[cfg(test)]
1385mod tests {
1386    use super::*;
1387    use quantrs2_core::gate::multi::CNOT;
1388    use quantrs2_core::gate::single::Hadamard;
1389
1390    #[test]
1391    fn test_basic_resource_estimation() {
1392        let mut circuit = Circuit::<3>::new();
1393        circuit
1394            .add_gate(Hadamard { target: QubitId(0) })
1395            .expect("Failed to add Hadamard gate to qubit 0");
1396        circuit
1397            .add_gate(CNOT {
1398                control: QubitId(0),
1399                target: QubitId(1),
1400            })
1401            .expect("Failed to add CNOT gate");
1402        circuit
1403            .add_gate(Hadamard { target: QubitId(2) })
1404            .expect("Failed to add Hadamard gate to qubit 2");
1405
1406        let estimate =
1407            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1408
1409        assert_eq!(estimate.circuit_metrics.total_gates, 3);
1410        assert_eq!(estimate.circuit_metrics.qubit_count, 3);
1411        assert!(estimate.circuit_metrics.single_qubit_gates > 0);
1412        assert!(estimate.circuit_metrics.two_qubit_gates > 0);
1413    }
1414
1415    #[test]
1416    fn test_complexity_analysis() {
1417        let mut circuit = Circuit::<2>::new();
1418        circuit
1419            .add_gate(Hadamard { target: QubitId(0) })
1420            .expect("Failed to add Hadamard gate");
1421        circuit
1422            .add_gate(CNOT {
1423                control: QubitId(0),
1424                target: QubitId(1),
1425            })
1426            .expect("Failed to add CNOT gate");
1427
1428        let estimate =
1429            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1430
1431        // Should classify as constant time complexity for small circuits
1432        match estimate.complexity_analysis.time_complexity {
1433            ComplexityClass::Constant | ComplexityClass::Linear => {}
1434            _ => panic!("Unexpected time complexity for small circuit"),
1435        }
1436
1437        // Space complexity should be exponential for classical simulation
1438        match estimate.complexity_analysis.space_complexity {
1439            ComplexityClass::Exponential => {}
1440            _ => panic!("Expected exponential space complexity"),
1441        }
1442    }
1443
1444    #[test]
1445    fn test_memory_estimation() {
1446        let mut circuit = Circuit::<4>::new();
1447        for i in 0..4 {
1448            circuit
1449                .add_gate(Hadamard { target: QubitId(i) })
1450                .expect("Failed to add Hadamard gate");
1451        }
1452
1453        let estimate =
1454            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1455
1456        // 4 qubits should require 2^4 * 16 = 256 bytes for state vector
1457        assert_eq!(estimate.memory_requirements.state_vector_memory, 256);
1458        assert!(estimate.memory_requirements.total_classical_memory > 256);
1459    }
1460
1461    #[test]
1462    fn test_execution_time_estimation() {
1463        let mut circuit = Circuit::<2>::new();
1464        circuit
1465            .add_gate(Hadamard { target: QubitId(0) })
1466            .expect("Failed to add Hadamard gate");
1467        circuit
1468            .add_gate(CNOT {
1469                control: QubitId(0),
1470                target: QubitId(1),
1471            })
1472            .expect("Failed to add CNOT gate");
1473
1474        let estimate =
1475            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1476
1477        assert!(estimate.execution_time.estimated_time > Duration::from_nanos(0));
1478        assert!(!estimate.execution_time.gate_time_breakdown.is_empty());
1479        assert!(estimate.execution_time.parallelization_factor > 0.0);
1480    }
1481
1482    #[test]
1483    fn test_hardware_requirements() {
1484        let mut circuit = Circuit::<10>::new();
1485        for i in 0..9 {
1486            circuit
1487                .add_gate(CNOT {
1488                    control: QubitId(i),
1489                    target: QubitId(i + 1),
1490                })
1491                .expect("Failed to add CNOT gate");
1492        }
1493
1494        let estimate =
1495            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1496
1497        assert!(estimate.hardware_requirements.min_physical_qubits >= 10);
1498        assert!(!estimate
1499            .hardware_requirements
1500            .platform_recommendations
1501            .is_empty());
1502    }
1503
1504    #[test]
1505    fn test_optimization_suggestions() {
1506        let mut circuit = Circuit::<5>::new();
1507        // Create a circuit with just enough gates to trigger optimization suggestions (>100)
1508        // Use 105 gates instead of 200 to avoid slow graph analysis with O(n^2) complexity
1509        for _ in 0..105 {
1510            circuit
1511                .add_gate(Hadamard { target: QubitId(0) })
1512                .expect("Failed to add Hadamard gate");
1513        }
1514
1515        // Use lightweight config without expensive graph analysis
1516        let config = ResourceEstimatorConfig {
1517            enable_graph_analysis: false, // Skip O(n^2) graph analysis
1518            enable_hardware_analysis: false,
1519            enable_scalability_analysis: false,
1520            include_optimizations: true, // This is what we're testing
1521            ..Default::default()
1522        };
1523
1524        let estimate = estimate_circuit_resources_with_config(&circuit, config)
1525            .expect("Failed to estimate circuit resources");
1526
1527        assert!(!estimate.optimization_suggestions.is_empty());
1528
1529        let has_gate_reduction = estimate
1530            .optimization_suggestions
1531            .iter()
1532            .any(|s| matches!(s.suggestion_type, OptimizationType::GateCountReduction));
1533        assert!(has_gate_reduction);
1534    }
1535
1536    #[test]
1537    fn test_custom_configuration() {
1538        let config = ResourceEstimatorConfig {
1539            analysis_depth: AnalysisDepth::Comprehensive,
1540            enable_scalability_analysis: true,
1541            ..Default::default()
1542        };
1543
1544        let mut circuit = Circuit::<3>::new();
1545        circuit
1546            .add_gate(Hadamard { target: QubitId(0) })
1547            .expect("Failed to add Hadamard gate");
1548
1549        let estimate = estimate_circuit_resources_with_config(&circuit, config)
1550            .expect("Failed to estimate circuit resources with config");
1551
1552        assert!(estimate.scalability_analysis.scalability_score >= 0.0);
1553        assert!(estimate.scalability_analysis.scalability_score <= 1.0);
1554    }
1555
1556    #[test]
1557    fn test_algorithm_classification() {
1558        // Test QFT-like circuit (many H gates)
1559        let mut qft_circuit = Circuit::<4>::new();
1560        for i in 0..4 {
1561            qft_circuit
1562                .add_gate(Hadamard { target: QubitId(i) })
1563                .expect("Failed to add Hadamard gate");
1564        }
1565
1566        let estimate =
1567            estimate_circuit_resources(&qft_circuit).expect("Failed to estimate circuit resources");
1568        match estimate.complexity_analysis.algorithm_classification {
1569            AlgorithmClass::QftBased | AlgorithmClass::General => {}
1570            _ => panic!("Unexpected algorithm classification"),
1571        }
1572    }
1573}