Skip to main content

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 the exact circuit depth via ASAP (as-soon-as-possible)
720    /// scheduling for the circuit's gate order.
721    ///
722    /// Each gate is placed one level after the maximum depth of the qubits it
723    /// touches, and every touched qubit is advanced to that level. The returned
724    /// value is the critical-path length (longest chain of data-dependent gates)
725    /// for the given gate sequence, which is the standard definition of circuit
726    /// depth. This is exact for the gate order as written; it does not attempt
727    /// commutation-based reordering to shorten the schedule further.
728    fn calculate_circuit_depth<const N: usize>(
729        &self,
730        circuit: &Circuit<N>,
731    ) -> QuantRS2Result<usize> {
732        let gates = circuit.gates();
733        if gates.is_empty() {
734            return Ok(0);
735        }
736
737        // Per-qubit "next free level". A gate on qubits Q starts at
738        // max(depth_per_qubit[q] for q in Q) and advances each q to that + 1.
739        let mut depth_per_qubit = vec![0usize; N];
740
741        for gate in gates {
742            let qubits = gate.qubits();
743            let max_current_depth = qubits
744                .iter()
745                .map(|q| depth_per_qubit[q.id() as usize])
746                .max()
747                .unwrap_or(0);
748
749            for qubit in qubits {
750                depth_per_qubit[qubit.id() as usize] = max_current_depth + 1;
751            }
752        }
753
754        Ok(depth_per_qubit.into_iter().max().unwrap_or(0))
755    }
756
757    /// Estimate circuit fidelity based on gate error rates
758    fn estimate_circuit_fidelity<const N: usize>(
759        &self,
760        circuit: &Circuit<N>,
761        gate_counts: &HashMap<String, usize>,
762    ) -> QuantRS2Result<f64> {
763        let mut total_error_rate = 0.0;
764
765        for (gate_name, count) in gate_counts {
766            if let Some(gate_cost) = self.gate_cost_database.get(gate_name) {
767                total_error_rate += gate_cost.error_rate * (*count as f64);
768            } else {
769                // Default error rate for unknown gates
770                total_error_rate += 0.01 * (*count as f64);
771            }
772        }
773
774        let fidelity = (1.0 - total_error_rate).clamp(0.0, 1.0);
775        Ok(fidelity)
776    }
777
778    /// Analyze computational complexity
779    fn analyze_complexity<const N: usize>(
780        &self,
781        circuit: &Circuit<N>,
782        metrics: &CircuitMetrics,
783    ) -> QuantRS2Result<ComplexityAnalysis> {
784        // Analyze time complexity based on gate count and circuit structure
785        let time_complexity = if metrics.total_gates <= 100 {
786            ComplexityClass::Constant
787        } else if metrics.total_gates < 1000 {
788            ComplexityClass::Linear
789        } else {
790            ComplexityClass::Polynomial { degree: 2.0 }
791        };
792
793        // Analyze space complexity (exponential in qubit count for classical simulation)
794        let space_complexity = ComplexityClass::Exponential;
795
796        // Calculate gate complexity
797        let gate_complexity = (metrics.total_gates as f64) * (N as f64);
798
799        // Estimate entanglement complexity (simplified)
800        let entanglement_complexity =
801            (metrics.two_qubit_gates as f64) / (metrics.total_gates as f64).max(1.0);
802
803        // Classical simulation complexity
804        let classical_simulation_complexity = (N as f64).exp2();
805
806        // Quantum advantage factor (simplified estimation)
807        let quantum_advantage_factor = if classical_simulation_complexity > 1e6 {
808            Some(classical_simulation_complexity / (metrics.total_gates as f64))
809        } else {
810            None
811        };
812
813        // Algorithm classification (simplified heuristic)
814        let algorithm_classification = self.classify_algorithm(circuit, metrics)?;
815
816        // Scaling behavior analysis
817        let scaling_behavior = self.analyze_scaling_behavior(metrics)?;
818
819        Ok(ComplexityAnalysis {
820            time_complexity,
821            space_complexity,
822            gate_complexity,
823            entanglement_complexity,
824            classical_simulation_complexity,
825            quantum_advantage_factor,
826            algorithm_classification,
827            scaling_behavior,
828        })
829    }
830
831    /// Classify the quantum algorithm based on circuit structure
832    fn classify_algorithm<const N: usize>(
833        &self,
834        circuit: &Circuit<N>,
835        metrics: &CircuitMetrics,
836    ) -> QuantRS2Result<AlgorithmClass> {
837        // Simplified algorithm classification based on gate patterns
838        let gates = circuit.gates();
839
840        // Check for QFT patterns (many H gates)
841        if let Some(&h_count) = metrics.gate_counts.get("H") {
842            if h_count > N / 2 {
843                return Ok(AlgorithmClass::QftBased);
844            }
845        }
846
847        // Check for amplitude amplification (controlled gates + H gates)
848        if metrics.two_qubit_gates > metrics.single_qubit_gates {
849            return Ok(AlgorithmClass::AmplitudeAmplification);
850        }
851
852        // Check for variational patterns (parameterized gates)
853        // This would require checking for RX, RY, RZ gates in practice
854        if metrics.circuit_depth > metrics.total_gates / 4 {
855            return Ok(AlgorithmClass::Variational);
856        }
857
858        Ok(AlgorithmClass::General)
859    }
860
861    /// Analyze scaling behavior
862    fn analyze_scaling_behavior(
863        &self,
864        metrics: &CircuitMetrics,
865    ) -> QuantRS2Result<ScalingBehavior> {
866        Ok(ScalingBehavior {
867            gate_scaling: ScalingFunction::Linear {
868                coefficient: metrics.total_gates as f64 / metrics.qubit_count as f64,
869            },
870            depth_scaling: ScalingFunction::Linear {
871                coefficient: metrics.circuit_depth as f64 / metrics.qubit_count as f64,
872            },
873            qubit_scaling: ScalingFunction::Linear { coefficient: 1.0 },
874            time_scaling: ScalingFunction::Polynomial {
875                coefficient: 1.0,
876                exponent: 2.0,
877            },
878        })
879    }
880
881    /// Estimate memory requirements
882    fn estimate_memory_requirements<const N: usize>(
883        &self,
884        circuit: &Circuit<N>,
885        metrics: &CircuitMetrics,
886    ) -> QuantRS2Result<MemoryRequirements> {
887        // State vector memory: 2^N complex numbers, each 16 bytes
888        let state_vector_memory = (1u64 << N) * 16;
889
890        // Gate matrix memory: approximate based on gate count
891        let gate_matrix_memory = (metrics.total_gates as u64) * 64; // 4x4 complex matrices
892
893        // Auxiliary memory for computation (buffers, temporaries)
894        let auxiliary_memory = state_vector_memory / 4;
895
896        let total_classical_memory = state_vector_memory + gate_matrix_memory + auxiliary_memory;
897
898        let memory_scaling = ScalingFunction::Exponential {
899            base: 2.0,
900            coefficient: 16.0,
901        };
902
903        let memory_optimizations = vec![
904            "Use sparse state representations for low-entanglement circuits".to_string(),
905            "Implement tensor network simulation for large qubit counts".to_string(),
906            "Use GPU memory for state vector storage".to_string(),
907        ];
908
909        Ok(MemoryRequirements {
910            state_vector_memory,
911            gate_matrix_memory,
912            auxiliary_memory,
913            total_classical_memory,
914            quantum_memory: N,
915            memory_scaling,
916            memory_optimizations,
917        })
918    }
919
920    /// Estimate execution time
921    fn estimate_execution_time<const N: usize>(
922        &self,
923        circuit: &Circuit<N>,
924        metrics: &CircuitMetrics,
925    ) -> QuantRS2Result<ExecutionTimeEstimate> {
926        let mut total_time = Duration::from_nanos(0);
927        let mut gate_time_breakdown = HashMap::new();
928
929        // Calculate time for each gate type
930        for (gate_name, count) in &metrics.gate_counts {
931            let gate_time = if let Some(gate_cost) = self.gate_cost_database.get(gate_name) {
932                gate_cost.execution_time
933            } else {
934                Duration::from_nanos(100) // Default gate time
935            };
936
937            let total_gate_time = gate_time * (*count as u32);
938            gate_time_breakdown.insert(gate_name.clone(), total_gate_time);
939            total_time += total_gate_time;
940        }
941
942        // Critical path time (simplified - would use proper scheduling analysis)
943        let critical_path_time = total_time / 2; // Rough estimate
944
945        // Parallelization factor
946        let parallelization_factor = if metrics.circuit_depth > 0 {
947            (metrics.total_gates as f64) / (metrics.circuit_depth as f64)
948        } else {
949            1.0
950        };
951
952        // Hardware timing factors
953        let hardware_timing_factors = [
954            ("decoherence_overhead".to_string(), 1.1),
955            ("measurement_overhead".to_string(), 1.05),
956            ("classical_processing".to_string(), 1.2),
957        ]
958        .iter()
959        .cloned()
960        .collect();
961
962        // Confidence interval (±20%)
963        let lower_bound = total_time * 80 / 100;
964        let upper_bound = total_time * 120 / 100;
965
966        let timing_model = TimingModel::GateCounting {
967            gates_per_second: 1e6,
968        };
969
970        Ok(ExecutionTimeEstimate {
971            estimated_time: total_time,
972            gate_time_breakdown,
973            critical_path_time,
974            parallelization_factor,
975            hardware_timing_factors,
976            confidence_interval: (lower_bound, upper_bound),
977            timing_model,
978        })
979    }
980
981    /// Analyze hardware requirements
982    fn analyze_hardware_requirements<const N: usize>(
983        &self,
984        circuit: &Circuit<N>,
985        metrics: &CircuitMetrics,
986    ) -> QuantRS2Result<HardwareRequirements> {
987        // Minimum physical qubits (with error correction overhead)
988        let min_physical_qubits = N * 50; // Rough estimate for logical qubits
989
990        // Connectivity requirements based on circuit structure
991        let connectivity_requirements = if metrics.two_qubit_gates > N {
992            ConnectivityRequirement::AllToAll
993        } else {
994            ConnectivityRequirement::Linear
995        };
996
997        // Fidelity requirements
998        let fidelity_requirements = [
999            ("single_qubit".to_string(), 0.999),
1000            ("two_qubit".to_string(), 0.99),
1001            ("measurement".to_string(), 0.98),
1002        ]
1003        .iter()
1004        .cloned()
1005        .collect();
1006
1007        // Coherence requirements
1008        let coherence_requirements = CoherenceRequirement {
1009            min_t1: Duration::from_micros((metrics.circuit_depth as u64) * 10),
1010            min_t2: Duration::from_micros((metrics.circuit_depth as u64) * 5),
1011            gate_to_coherence_ratio: 0.01,
1012        };
1013
1014        // Platform recommendations
1015        let platform_recommendations = self.recommend_platforms(metrics)?;
1016
1017        // Error correction overhead
1018        let error_correction_overhead = ErrorCorrectionOverhead {
1019            physical_to_logical_ratio: 50.0,
1020            gate_overhead_factor: 10.0,
1021            time_overhead_factor: 100.0,
1022            recommended_code: "Surface Code".to_string(),
1023            threshold_error_rate: 0.001,
1024        };
1025
1026        Ok(HardwareRequirements {
1027            min_physical_qubits,
1028            connectivity_requirements,
1029            fidelity_requirements,
1030            coherence_requirements,
1031            platform_recommendations,
1032            error_correction_overhead,
1033        })
1034    }
1035
1036    /// Recommend suitable hardware platforms
1037    fn recommend_platforms(
1038        &self,
1039        metrics: &CircuitMetrics,
1040    ) -> QuantRS2Result<Vec<PlatformRecommendation>> {
1041        let mut recommendations = Vec::new();
1042
1043        for platform_name in &self.config.target_platforms {
1044            if let Some(platform) = self.platform_database.get(platform_name) {
1045                let suitability_score = self.calculate_platform_suitability(platform, metrics);
1046
1047                recommendations.push(PlatformRecommendation {
1048                    platform: platform_name.clone(),
1049                    suitability_score,
1050                    reasoning: self.generate_platform_reasoning(
1051                        platform,
1052                        metrics,
1053                        suitability_score,
1054                    ),
1055                    success_probability: suitability_score * 0.8,
1056                    required_modifications: self.suggest_platform_modifications(platform, metrics),
1057                });
1058            }
1059        }
1060
1061        recommendations.sort_by(|a, b| {
1062            b.suitability_score
1063                .partial_cmp(&a.suitability_score)
1064                .unwrap_or(std::cmp::Ordering::Equal)
1065        });
1066        Ok(recommendations)
1067    }
1068
1069    /// Calculate platform suitability score
1070    fn calculate_platform_suitability(
1071        &self,
1072        platform: &PlatformCharacteristics,
1073        metrics: &CircuitMetrics,
1074    ) -> f64 {
1075        let mut score = 1.0;
1076
1077        // Qubit count factor
1078        if platform.qubit_count < metrics.qubit_count {
1079            score *= 0.1; // Severely penalize insufficient qubits
1080        }
1081
1082        // Gate fidelity factor
1083        let avg_fidelity: f64 =
1084            platform.gate_fidelities.values().sum::<f64>() / platform.gate_fidelities.len() as f64;
1085        score *= avg_fidelity;
1086
1087        // Two-qubit gate factor
1088        if metrics.two_qubit_gates > metrics.qubit_count * 2 {
1089            score *= 0.8; // Penalize for high two-qubit gate requirements
1090        }
1091
1092        score.clamp(0.0, 1.0)
1093    }
1094
1095    /// Generate reasoning for platform recommendation
1096    fn generate_platform_reasoning(
1097        &self,
1098        platform: &PlatformCharacteristics,
1099        metrics: &CircuitMetrics,
1100        score: f64,
1101    ) -> String {
1102        if score > 0.8 {
1103            format!(
1104                "Excellent match: {} has sufficient qubits ({}) and high fidelity gates",
1105                platform.name, platform.qubit_count
1106            )
1107        } else if score > 0.6 {
1108            format!(
1109                "Good match: {} meets most requirements but may need optimization",
1110                platform.name
1111            )
1112        } else if score > 0.4 {
1113            format!(
1114                "Marginal match: {} has limitations for this circuit",
1115                platform.name
1116            )
1117        } else {
1118            format!(
1119                "Poor match: {} is not well-suited for this circuit",
1120                platform.name
1121            )
1122        }
1123    }
1124
1125    /// Suggest platform modifications
1126    fn suggest_platform_modifications(
1127        &self,
1128        platform: &PlatformCharacteristics,
1129        metrics: &CircuitMetrics,
1130    ) -> Vec<String> {
1131        let mut modifications = Vec::new();
1132
1133        if platform.qubit_count < metrics.qubit_count {
1134            modifications.push("Increase qubit count or decompose circuit".to_string());
1135        }
1136
1137        if metrics.two_qubit_gates > platform.qubit_count {
1138            modifications.push("Optimize circuit connectivity".to_string());
1139        }
1140
1141        modifications
1142    }
1143
1144    /// Get `SciRS2` graph metrics
1145    fn get_graph_metrics<const N: usize>(
1146        &mut self,
1147        circuit: &Circuit<N>,
1148    ) -> QuantRS2Result<Option<GraphMetrics>> {
1149        if let Some(analyzer) = &mut self.scirs2_analyzer {
1150            let analysis = analyzer.analyze_circuit(circuit)?;
1151            Ok(Some(analysis.metrics))
1152        } else {
1153            Ok(None)
1154        }
1155    }
1156
1157    /// Analyze scalability
1158    fn analyze_scalability<const N: usize>(
1159        &self,
1160        circuit: &Circuit<N>,
1161        metrics: &CircuitMetrics,
1162        complexity: &ComplexityAnalysis,
1163    ) -> QuantRS2Result<ScalabilityAnalysis> {
1164        let scalability_score = self.calculate_scalability_score(metrics, complexity);
1165        let bottlenecks = self.identify_bottlenecks(metrics, complexity);
1166        let scaling_predictions = self.predict_scaling(metrics)?;
1167        let resource_limits = self.calculate_resource_limits(metrics);
1168
1169        Ok(ScalabilityAnalysis {
1170            scalability_score,
1171            bottlenecks,
1172            scaling_predictions,
1173            resource_limits,
1174        })
1175    }
1176
1177    /// Calculate overall scalability score
1178    fn calculate_scalability_score(
1179        &self,
1180        metrics: &CircuitMetrics,
1181        complexity: &ComplexityAnalysis,
1182    ) -> f64 {
1183        let mut score: f64 = 1.0;
1184
1185        // Penalize exponential classical simulation complexity
1186        if complexity.classical_simulation_complexity > 1e12 {
1187            score *= 0.5;
1188        }
1189
1190        // Penalize high gate complexity
1191        if complexity.gate_complexity > 1e6 {
1192            score *= 0.7;
1193        }
1194
1195        // Reward quantum advantage
1196        if complexity.quantum_advantage_factor.is_some() {
1197            score *= 1.2;
1198        }
1199
1200        score.clamp(0.0, 1.0)
1201    }
1202
1203    /// Identify scalability bottlenecks
1204    fn identify_bottlenecks(
1205        &self,
1206        metrics: &CircuitMetrics,
1207        complexity: &ComplexityAnalysis,
1208    ) -> Vec<ScalabilityBottleneck> {
1209        let mut bottlenecks = Vec::new();
1210
1211        // Memory bottleneck
1212        if complexity.classical_simulation_complexity > 1e15 {
1213            bottlenecks.push(ScalabilityBottleneck {
1214                bottleneck_type: BottleneckType::Memory,
1215                severity: 0.9,
1216                description: "Exponential memory growth limits classical simulation".to_string(),
1217                mitigation_suggestions: vec![
1218                    "Use tensor network simulation".to_string(),
1219                    "Implement approximate methods".to_string(),
1220                ],
1221            });
1222        }
1223
1224        // Coherence bottleneck
1225        if metrics.circuit_depth > 100 {
1226            bottlenecks.push(ScalabilityBottleneck {
1227                bottleneck_type: BottleneckType::QuantumCoherence,
1228                severity: 0.7,
1229                description: "Deep circuits may exceed coherence times".to_string(),
1230                mitigation_suggestions: vec![
1231                    "Reduce circuit depth".to_string(),
1232                    "Use error correction".to_string(),
1233                ],
1234            });
1235        }
1236
1237        bottlenecks
1238    }
1239
1240    /// Predict scaling for different problem sizes
1241    fn predict_scaling(
1242        &self,
1243        metrics: &CircuitMetrics,
1244    ) -> QuantRS2Result<HashMap<String, ScalingPrediction>> {
1245        let mut predictions = HashMap::new();
1246
1247        // Gate count scaling
1248        let problem_sizes = vec![10, 20, 30, 40, 50];
1249        let gate_predictions: Vec<f64> = problem_sizes
1250            .iter()
1251            .map(|&size| {
1252                (size as f64) * (metrics.total_gates as f64) / (metrics.qubit_count as f64)
1253            })
1254            .collect();
1255        let gate_confidence: Vec<(f64, f64)> = gate_predictions
1256            .iter()
1257            .map(|&pred| (pred * 0.8, pred * 1.2))
1258            .collect();
1259
1260        predictions.insert(
1261            "gates".to_string(),
1262            ScalingPrediction {
1263                problem_sizes,
1264                predicted_values: gate_predictions,
1265                confidence_intervals: gate_confidence,
1266                model: "Linear scaling".to_string(),
1267            },
1268        );
1269
1270        Ok(predictions)
1271    }
1272
1273    /// Calculate resource limits
1274    fn calculate_resource_limits(&self, metrics: &CircuitMetrics) -> ResourceLimits {
1275        ResourceLimits {
1276            max_current_technology: 50,   // Current NISQ limit
1277            max_near_term: 1000,          // Near-term with error correction
1278            max_theoretical: Some(10000), // Theoretical limit
1279            limiting_factors: vec![
1280                "Quantum error rates".to_string(),
1281                "Coherence times".to_string(),
1282                "Classical simulation complexity".to_string(),
1283            ],
1284        }
1285    }
1286
1287    /// Generate optimization suggestions
1288    fn generate_optimization_suggestions<const N: usize>(
1289        &self,
1290        circuit: &Circuit<N>,
1291        metrics: &CircuitMetrics,
1292        complexity: &ComplexityAnalysis,
1293        memory: &MemoryRequirements,
1294    ) -> QuantRS2Result<Vec<OptimizationSuggestion>> {
1295        let mut suggestions = Vec::new();
1296
1297        // Gate count reduction
1298        if metrics.total_gates > 100 {
1299            suggestions.push(OptimizationSuggestion {
1300                suggestion_type: OptimizationType::GateCountReduction,
1301                expected_improvement: 0.2,
1302                implementation_complexity: ComplexityLevel::Medium,
1303                description: "Apply gate fusion and redundancy elimination".to_string(),
1304                impact_areas: vec!["circuit_depth".to_string(), "execution_time".to_string()],
1305            });
1306        }
1307
1308        // Memory optimization
1309        if memory.total_classical_memory > 1e9 as u64 {
1310            suggestions.push(OptimizationSuggestion {
1311                suggestion_type: OptimizationType::MemoryOptimization,
1312                expected_improvement: 0.5,
1313                implementation_complexity: ComplexityLevel::High,
1314                description: "Use tensor network or sparse representations".to_string(),
1315                impact_areas: vec![
1316                    "memory_usage".to_string(),
1317                    "simulation_feasibility".to_string(),
1318                ],
1319            });
1320        }
1321
1322        // Parallelization
1323        if metrics.circuit_depth < metrics.total_gates / 2 {
1324            suggestions.push(OptimizationSuggestion {
1325                suggestion_type: OptimizationType::Parallelization,
1326                expected_improvement: 0.3,
1327                implementation_complexity: ComplexityLevel::Low,
1328                description: "Increase gate-level parallelism".to_string(),
1329                impact_areas: vec!["execution_time".to_string()],
1330            });
1331        }
1332
1333        Ok(suggestions)
1334    }
1335
1336    /// Default hardware requirements for simplified analysis
1337    fn default_hardware_requirements(&self) -> HardwareRequirements {
1338        HardwareRequirements {
1339            min_physical_qubits: 0,
1340            connectivity_requirements: ConnectivityRequirement::Linear,
1341            fidelity_requirements: HashMap::new(),
1342            coherence_requirements: CoherenceRequirement {
1343                min_t1: Duration::from_micros(100),
1344                min_t2: Duration::from_micros(50),
1345                gate_to_coherence_ratio: 0.01,
1346            },
1347            platform_recommendations: Vec::new(),
1348            error_correction_overhead: ErrorCorrectionOverhead {
1349                physical_to_logical_ratio: 1.0,
1350                gate_overhead_factor: 1.0,
1351                time_overhead_factor: 1.0,
1352                recommended_code: "None".to_string(),
1353                threshold_error_rate: 1.0,
1354            },
1355        }
1356    }
1357
1358    /// Default scalability analysis for simplified analysis
1359    fn default_scalability_analysis(&self) -> ScalabilityAnalysis {
1360        ScalabilityAnalysis {
1361            scalability_score: 0.5,
1362            bottlenecks: Vec::new(),
1363            scaling_predictions: HashMap::new(),
1364            resource_limits: ResourceLimits {
1365                max_current_technology: 50,
1366                max_near_term: 100,
1367                max_theoretical: None,
1368                limiting_factors: Vec::new(),
1369            },
1370        }
1371    }
1372}
1373
1374/// Quick resource estimation with default options
1375pub fn estimate_circuit_resources<const N: usize>(
1376    circuit: &Circuit<N>,
1377) -> QuantRS2Result<ResourceEstimate> {
1378    let mut estimator = ResourceEstimator::new(ResourceEstimatorConfig::default());
1379    estimator.estimate_resources(circuit)
1380}
1381
1382/// Resource estimation with custom configuration
1383pub fn estimate_circuit_resources_with_config<const N: usize>(
1384    circuit: &Circuit<N>,
1385    config: ResourceEstimatorConfig,
1386) -> QuantRS2Result<ResourceEstimate> {
1387    let mut estimator = ResourceEstimator::new(config);
1388    estimator.estimate_resources(circuit)
1389}
1390
1391#[cfg(test)]
1392mod tests {
1393    use super::*;
1394    use quantrs2_core::gate::multi::CNOT;
1395    use quantrs2_core::gate::single::Hadamard;
1396
1397    #[test]
1398    fn test_basic_resource_estimation() {
1399        let mut circuit = Circuit::<3>::new();
1400        circuit
1401            .add_gate(Hadamard { target: QubitId(0) })
1402            .expect("Failed to add Hadamard gate to qubit 0");
1403        circuit
1404            .add_gate(CNOT {
1405                control: QubitId(0),
1406                target: QubitId(1),
1407            })
1408            .expect("Failed to add CNOT gate");
1409        circuit
1410            .add_gate(Hadamard { target: QubitId(2) })
1411            .expect("Failed to add Hadamard gate to qubit 2");
1412
1413        let estimate =
1414            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1415
1416        assert_eq!(estimate.circuit_metrics.total_gates, 3);
1417        assert_eq!(estimate.circuit_metrics.qubit_count, 3);
1418        assert!(estimate.circuit_metrics.single_qubit_gates > 0);
1419        assert!(estimate.circuit_metrics.two_qubit_gates > 0);
1420    }
1421
1422    #[test]
1423    fn test_complexity_analysis() {
1424        let mut circuit = Circuit::<2>::new();
1425        circuit
1426            .add_gate(Hadamard { target: QubitId(0) })
1427            .expect("Failed to add Hadamard gate");
1428        circuit
1429            .add_gate(CNOT {
1430                control: QubitId(0),
1431                target: QubitId(1),
1432            })
1433            .expect("Failed to add CNOT gate");
1434
1435        let estimate =
1436            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1437
1438        // Should classify as constant time complexity for small circuits
1439        match estimate.complexity_analysis.time_complexity {
1440            ComplexityClass::Constant | ComplexityClass::Linear => {}
1441            _ => panic!("Unexpected time complexity for small circuit"),
1442        }
1443
1444        // Space complexity should be exponential for classical simulation
1445        match estimate.complexity_analysis.space_complexity {
1446            ComplexityClass::Exponential => {}
1447            _ => panic!("Expected exponential space complexity"),
1448        }
1449    }
1450
1451    #[test]
1452    fn test_memory_estimation() {
1453        let mut circuit = Circuit::<4>::new();
1454        for i in 0..4 {
1455            circuit
1456                .add_gate(Hadamard { target: QubitId(i) })
1457                .expect("Failed to add Hadamard gate");
1458        }
1459
1460        let estimate =
1461            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1462
1463        // 4 qubits should require 2^4 * 16 = 256 bytes for state vector
1464        assert_eq!(estimate.memory_requirements.state_vector_memory, 256);
1465        assert!(estimate.memory_requirements.total_classical_memory > 256);
1466    }
1467
1468    #[test]
1469    fn test_execution_time_estimation() {
1470        let mut circuit = Circuit::<2>::new();
1471        circuit
1472            .add_gate(Hadamard { target: QubitId(0) })
1473            .expect("Failed to add Hadamard gate");
1474        circuit
1475            .add_gate(CNOT {
1476                control: QubitId(0),
1477                target: QubitId(1),
1478            })
1479            .expect("Failed to add CNOT gate");
1480
1481        let estimate =
1482            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1483
1484        assert!(estimate.execution_time.estimated_time > Duration::from_nanos(0));
1485        assert!(!estimate.execution_time.gate_time_breakdown.is_empty());
1486        assert!(estimate.execution_time.parallelization_factor > 0.0);
1487    }
1488
1489    #[test]
1490    fn test_hardware_requirements() {
1491        let mut circuit = Circuit::<10>::new();
1492        for i in 0..9 {
1493            circuit
1494                .add_gate(CNOT {
1495                    control: QubitId(i),
1496                    target: QubitId(i + 1),
1497                })
1498                .expect("Failed to add CNOT gate");
1499        }
1500
1501        let estimate =
1502            estimate_circuit_resources(&circuit).expect("Failed to estimate circuit resources");
1503
1504        assert!(estimate.hardware_requirements.min_physical_qubits >= 10);
1505        assert!(!estimate
1506            .hardware_requirements
1507            .platform_recommendations
1508            .is_empty());
1509    }
1510
1511    #[test]
1512    fn test_optimization_suggestions() {
1513        let mut circuit = Circuit::<5>::new();
1514        // Create a circuit with just enough gates to trigger optimization suggestions (>100)
1515        // Use 105 gates instead of 200 to avoid slow graph analysis with O(n^2) complexity
1516        for _ in 0..105 {
1517            circuit
1518                .add_gate(Hadamard { target: QubitId(0) })
1519                .expect("Failed to add Hadamard gate");
1520        }
1521
1522        // Use lightweight config without expensive graph analysis
1523        let config = ResourceEstimatorConfig {
1524            enable_graph_analysis: false, // Skip O(n^2) graph analysis
1525            enable_hardware_analysis: false,
1526            enable_scalability_analysis: false,
1527            include_optimizations: true, // This is what we're testing
1528            ..Default::default()
1529        };
1530
1531        let estimate = estimate_circuit_resources_with_config(&circuit, config)
1532            .expect("Failed to estimate circuit resources");
1533
1534        assert!(!estimate.optimization_suggestions.is_empty());
1535
1536        let has_gate_reduction = estimate
1537            .optimization_suggestions
1538            .iter()
1539            .any(|s| matches!(s.suggestion_type, OptimizationType::GateCountReduction));
1540        assert!(has_gate_reduction);
1541    }
1542
1543    #[test]
1544    fn test_custom_configuration() {
1545        let config = ResourceEstimatorConfig {
1546            analysis_depth: AnalysisDepth::Comprehensive,
1547            enable_scalability_analysis: true,
1548            ..Default::default()
1549        };
1550
1551        let mut circuit = Circuit::<3>::new();
1552        circuit
1553            .add_gate(Hadamard { target: QubitId(0) })
1554            .expect("Failed to add Hadamard gate");
1555
1556        let estimate = estimate_circuit_resources_with_config(&circuit, config)
1557            .expect("Failed to estimate circuit resources with config");
1558
1559        assert!(estimate.scalability_analysis.scalability_score >= 0.0);
1560        assert!(estimate.scalability_analysis.scalability_score <= 1.0);
1561    }
1562
1563    #[test]
1564    fn test_algorithm_classification() {
1565        // Test QFT-like circuit (many H gates)
1566        let mut qft_circuit = Circuit::<4>::new();
1567        for i in 0..4 {
1568            qft_circuit
1569                .add_gate(Hadamard { target: QubitId(i) })
1570                .expect("Failed to add Hadamard gate");
1571        }
1572
1573        let estimate =
1574            estimate_circuit_resources(&qft_circuit).expect("Failed to estimate circuit resources");
1575        match estimate.complexity_analysis.algorithm_classification {
1576            AlgorithmClass::QftBased | AlgorithmClass::General => {}
1577            _ => panic!("Unexpected algorithm classification"),
1578        }
1579    }
1580}