quantrs2_sim/
circuit_interfaces.rs

1//! Efficient interfaces with circuit module for seamless integration.
2//!
3//! This module provides comprehensive bridge functionality between quantum circuit
4//! representations from the circuit module and various simulation backends in the
5//! sim module. It includes optimized gate translation, circuit analysis, and
6//! execution pipelines for maximum performance.
7
8use scirs2_core::ndarray::{Array1, Array2};
9use scirs2_core::Complex64;
10use serde::{Deserialize, Serialize};
11use std::collections::hash_map::DefaultHasher;
12use std::collections::HashMap;
13use std::hash::{Hash, Hasher};
14use std::sync::{Arc, Mutex};
15
16use crate::error::{Result, SimulatorError};
17use crate::scirs2_integration::SciRS2Backend;
18use crate::sparse::CSRMatrix;
19use crate::statevector::StateVectorSimulator;
20#[cfg(feature = "advanced_math")]
21#[allow(unused_imports)]
22use crate::tensor_network::TensorNetwork;
23
24/// Circuit interface configuration
25#[derive(Debug, Clone)]
26pub struct CircuitInterfaceConfig {
27    /// Enable automatic backend selection
28    pub auto_backend_selection: bool,
29    /// Enable circuit optimization during translation
30    pub enable_optimization: bool,
31    /// Maximum qubits for state vector simulation
32    pub max_statevector_qubits: usize,
33    /// Maximum bond dimension for MPS simulation
34    pub max_mps_bond_dim: usize,
35    /// Enable parallel gate compilation
36    pub parallel_compilation: bool,
37    /// Cache compiled circuits
38    pub enable_circuit_cache: bool,
39    /// Maximum cache size
40    pub max_cache_size: usize,
41    /// Enable circuit analysis and profiling
42    pub enable_profiling: bool,
43}
44
45impl Default for CircuitInterfaceConfig {
46    fn default() -> Self {
47        Self {
48            auto_backend_selection: true,
49            enable_optimization: true,
50            max_statevector_qubits: 25,
51            max_mps_bond_dim: 1024,
52            parallel_compilation: true,
53            enable_circuit_cache: true,
54            max_cache_size: 10000,
55            enable_profiling: true,
56        }
57    }
58}
59
60/// Quantum gate types for circuit interface
61#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
62pub enum InterfaceGateType {
63    // Single-qubit gates
64    Identity,
65    PauliX,
66    X, // Alias for PauliX
67    PauliY,
68    PauliZ,
69    Hadamard,
70    H, // Alias for Hadamard
71    S,
72    T,
73    Phase(f64),
74    RX(f64),
75    RY(f64),
76    RZ(f64),
77    U1(f64),
78    U2(f64, f64),
79    U3(f64, f64, f64),
80    // Two-qubit gates
81    CNOT,
82    CZ,
83    CY,
84    SWAP,
85    ISwap,
86    CRX(f64),
87    CRY(f64),
88    CRZ(f64),
89    CPhase(f64),
90    // Three-qubit gates
91    Toffoli,
92    Fredkin,
93    // Multi-qubit gates
94    MultiControlledX(usize), // Number of control qubits
95    MultiControlledZ(usize),
96    // Custom gates
97    Custom(String, Array2<Complex64>),
98    // Measurement
99    Measure,
100    Reset,
101}
102
103// Custom Hash implementation since f64 doesn't implement Hash
104impl std::hash::Hash for InterfaceGateType {
105    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
106        use std::mem;
107        match self {
108            InterfaceGateType::Identity => 0u8.hash(state),
109            InterfaceGateType::PauliX => 1u8.hash(state),
110            InterfaceGateType::X => 2u8.hash(state),
111            InterfaceGateType::PauliY => 3u8.hash(state),
112            InterfaceGateType::PauliZ => 4u8.hash(state),
113            InterfaceGateType::Hadamard => 5u8.hash(state),
114            InterfaceGateType::H => 6u8.hash(state),
115            InterfaceGateType::S => 7u8.hash(state),
116            InterfaceGateType::T => 8u8.hash(state),
117            InterfaceGateType::Phase(angle) => {
118                9u8.hash(state);
119                angle.to_bits().hash(state);
120            }
121            InterfaceGateType::RX(angle) => {
122                10u8.hash(state);
123                angle.to_bits().hash(state);
124            }
125            InterfaceGateType::RY(angle) => {
126                11u8.hash(state);
127                angle.to_bits().hash(state);
128            }
129            InterfaceGateType::RZ(angle) => {
130                12u8.hash(state);
131                angle.to_bits().hash(state);
132            }
133            InterfaceGateType::U1(angle) => {
134                13u8.hash(state);
135                angle.to_bits().hash(state);
136            }
137            InterfaceGateType::U2(theta, phi) => {
138                14u8.hash(state);
139                theta.to_bits().hash(state);
140                phi.to_bits().hash(state);
141            }
142            InterfaceGateType::U3(theta, phi, lambda) => {
143                15u8.hash(state);
144                theta.to_bits().hash(state);
145                phi.to_bits().hash(state);
146                lambda.to_bits().hash(state);
147            }
148            InterfaceGateType::CNOT => 16u8.hash(state),
149            InterfaceGateType::CZ => 17u8.hash(state),
150            InterfaceGateType::CY => 18u8.hash(state),
151            InterfaceGateType::SWAP => 19u8.hash(state),
152            InterfaceGateType::ISwap => 20u8.hash(state),
153            InterfaceGateType::CRX(angle) => {
154                21u8.hash(state);
155                angle.to_bits().hash(state);
156            }
157            InterfaceGateType::CRY(angle) => {
158                22u8.hash(state);
159                angle.to_bits().hash(state);
160            }
161            InterfaceGateType::CRZ(angle) => {
162                23u8.hash(state);
163                angle.to_bits().hash(state);
164            }
165            InterfaceGateType::CPhase(angle) => {
166                24u8.hash(state);
167                angle.to_bits().hash(state);
168            }
169            InterfaceGateType::Toffoli => 25u8.hash(state),
170            InterfaceGateType::Fredkin => 26u8.hash(state),
171            InterfaceGateType::MultiControlledX(n) => {
172                27u8.hash(state);
173                n.hash(state);
174            }
175            InterfaceGateType::MultiControlledZ(n) => {
176                28u8.hash(state);
177                n.hash(state);
178            }
179            InterfaceGateType::Custom(name, matrix) => {
180                29u8.hash(state);
181                name.hash(state);
182                // Hash matrix shape instead of all elements
183                matrix.shape().hash(state);
184            }
185            InterfaceGateType::Measure => 30u8.hash(state),
186            InterfaceGateType::Reset => 31u8.hash(state),
187        }
188    }
189}
190
191// Custom Eq implementation since f64 doesn't implement Eq
192impl Eq for InterfaceGateType {}
193
194/// Quantum gate representation for circuit interface
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct InterfaceGate {
197    /// Gate type and parameters
198    pub gate_type: InterfaceGateType,
199    /// Qubits this gate acts on
200    pub qubits: Vec<usize>,
201    /// Classical register targets (for measurements)
202    pub classical_targets: Vec<usize>,
203    /// Gate position in the circuit
204    pub position: usize,
205    /// Conditional execution (if classical bit is 1)
206    pub condition: Option<usize>,
207    /// Gate label for debugging
208    pub label: Option<String>,
209}
210
211impl InterfaceGate {
212    /// Create a new interface gate
213    pub fn new(gate_type: InterfaceGateType, qubits: Vec<usize>) -> Self {
214        Self {
215            gate_type,
216            qubits,
217            classical_targets: Vec::new(),
218            position: 0,
219            condition: None,
220            label: None,
221        }
222    }
223
224    /// Create a measurement gate
225    pub fn measurement(qubit: usize, classical_bit: usize) -> Self {
226        Self {
227            gate_type: InterfaceGateType::Measure,
228            qubits: vec![qubit],
229            classical_targets: vec![classical_bit],
230            position: 0,
231            condition: None,
232            label: None,
233        }
234    }
235
236    /// Create a conditional gate
237    pub fn conditional(mut self, condition: usize) -> Self {
238        self.condition = Some(condition);
239        self
240    }
241
242    /// Add a label to the gate
243    pub fn with_label(mut self, label: String) -> Self {
244        self.label = Some(label);
245        self
246    }
247
248    /// Get the unitary matrix for this gate
249    pub fn unitary_matrix(&self) -> Result<Array2<Complex64>> {
250        match &self.gate_type {
251            InterfaceGateType::Identity => Ok(Array2::eye(2)),
252            InterfaceGateType::PauliX => Ok(Array2::from_shape_vec(
253                (2, 2),
254                vec![
255                    Complex64::new(0.0, 0.0),
256                    Complex64::new(1.0, 0.0),
257                    Complex64::new(1.0, 0.0),
258                    Complex64::new(0.0, 0.0),
259                ],
260            )
261            .unwrap()),
262            InterfaceGateType::PauliY => Ok(Array2::from_shape_vec(
263                (2, 2),
264                vec![
265                    Complex64::new(0.0, 0.0),
266                    Complex64::new(0.0, -1.0),
267                    Complex64::new(0.0, 1.0),
268                    Complex64::new(0.0, 0.0),
269                ],
270            )
271            .unwrap()),
272            InterfaceGateType::PauliZ => Ok(Array2::from_shape_vec(
273                (2, 2),
274                vec![
275                    Complex64::new(1.0, 0.0),
276                    Complex64::new(0.0, 0.0),
277                    Complex64::new(0.0, 0.0),
278                    Complex64::new(-1.0, 0.0),
279                ],
280            )
281            .unwrap()),
282            InterfaceGateType::Hadamard => {
283                let inv_sqrt2 = 1.0 / (2.0_f64).sqrt();
284                Ok(Array2::from_shape_vec(
285                    (2, 2),
286                    vec![
287                        Complex64::new(inv_sqrt2, 0.0),
288                        Complex64::new(inv_sqrt2, 0.0),
289                        Complex64::new(inv_sqrt2, 0.0),
290                        Complex64::new(-inv_sqrt2, 0.0),
291                    ],
292                )
293                .unwrap())
294            }
295            InterfaceGateType::S => Ok(Array2::from_shape_vec(
296                (2, 2),
297                vec![
298                    Complex64::new(1.0, 0.0),
299                    Complex64::new(0.0, 0.0),
300                    Complex64::new(0.0, 0.0),
301                    Complex64::new(0.0, 1.0),
302                ],
303            )
304            .unwrap()),
305            InterfaceGateType::T => {
306                let phase = Complex64::new(0.0, std::f64::consts::PI / 4.0).exp();
307                Ok(Array2::from_shape_vec(
308                    (2, 2),
309                    vec![
310                        Complex64::new(1.0, 0.0),
311                        Complex64::new(0.0, 0.0),
312                        Complex64::new(0.0, 0.0),
313                        phase,
314                    ],
315                )
316                .unwrap())
317            }
318            InterfaceGateType::Phase(theta) => {
319                let phase = Complex64::new(0.0, *theta).exp();
320                Ok(Array2::from_shape_vec(
321                    (2, 2),
322                    vec![
323                        Complex64::new(1.0, 0.0),
324                        Complex64::new(0.0, 0.0),
325                        Complex64::new(0.0, 0.0),
326                        phase,
327                    ],
328                )
329                .unwrap())
330            }
331            InterfaceGateType::RX(theta) => {
332                let cos_half = (theta / 2.0).cos();
333                let sin_half = (theta / 2.0).sin();
334                Ok(Array2::from_shape_vec(
335                    (2, 2),
336                    vec![
337                        Complex64::new(cos_half, 0.0),
338                        Complex64::new(0.0, -sin_half),
339                        Complex64::new(0.0, -sin_half),
340                        Complex64::new(cos_half, 0.0),
341                    ],
342                )
343                .unwrap())
344            }
345            InterfaceGateType::RY(theta) => {
346                let cos_half = (theta / 2.0).cos();
347                let sin_half = (theta / 2.0).sin();
348                Ok(Array2::from_shape_vec(
349                    (2, 2),
350                    vec![
351                        Complex64::new(cos_half, 0.0),
352                        Complex64::new(-sin_half, 0.0),
353                        Complex64::new(sin_half, 0.0),
354                        Complex64::new(cos_half, 0.0),
355                    ],
356                )
357                .unwrap())
358            }
359            InterfaceGateType::RZ(theta) => {
360                let exp_neg = Complex64::new(0.0, -theta / 2.0).exp();
361                let exp_pos = Complex64::new(0.0, theta / 2.0).exp();
362                Ok(Array2::from_shape_vec(
363                    (2, 2),
364                    vec![
365                        exp_neg,
366                        Complex64::new(0.0, 0.0),
367                        Complex64::new(0.0, 0.0),
368                        exp_pos,
369                    ],
370                )
371                .unwrap())
372            }
373            InterfaceGateType::CNOT => Ok(Array2::from_shape_vec(
374                (4, 4),
375                vec![
376                    Complex64::new(1.0, 0.0),
377                    Complex64::new(0.0, 0.0),
378                    Complex64::new(0.0, 0.0),
379                    Complex64::new(0.0, 0.0),
380                    Complex64::new(0.0, 0.0),
381                    Complex64::new(1.0, 0.0),
382                    Complex64::new(0.0, 0.0),
383                    Complex64::new(0.0, 0.0),
384                    Complex64::new(0.0, 0.0),
385                    Complex64::new(0.0, 0.0),
386                    Complex64::new(0.0, 0.0),
387                    Complex64::new(1.0, 0.0),
388                    Complex64::new(0.0, 0.0),
389                    Complex64::new(0.0, 0.0),
390                    Complex64::new(1.0, 0.0),
391                    Complex64::new(0.0, 0.0),
392                ],
393            )
394            .unwrap()),
395            InterfaceGateType::CZ => Ok(Array2::from_shape_vec(
396                (4, 4),
397                vec![
398                    Complex64::new(1.0, 0.0),
399                    Complex64::new(0.0, 0.0),
400                    Complex64::new(0.0, 0.0),
401                    Complex64::new(0.0, 0.0),
402                    Complex64::new(0.0, 0.0),
403                    Complex64::new(1.0, 0.0),
404                    Complex64::new(0.0, 0.0),
405                    Complex64::new(0.0, 0.0),
406                    Complex64::new(0.0, 0.0),
407                    Complex64::new(0.0, 0.0),
408                    Complex64::new(1.0, 0.0),
409                    Complex64::new(0.0, 0.0),
410                    Complex64::new(0.0, 0.0),
411                    Complex64::new(0.0, 0.0),
412                    Complex64::new(0.0, 0.0),
413                    Complex64::new(-1.0, 0.0),
414                ],
415            )
416            .unwrap()),
417            InterfaceGateType::SWAP => Ok(Array2::from_shape_vec(
418                (4, 4),
419                vec![
420                    Complex64::new(1.0, 0.0),
421                    Complex64::new(0.0, 0.0),
422                    Complex64::new(0.0, 0.0),
423                    Complex64::new(0.0, 0.0),
424                    Complex64::new(0.0, 0.0),
425                    Complex64::new(0.0, 0.0),
426                    Complex64::new(1.0, 0.0),
427                    Complex64::new(0.0, 0.0),
428                    Complex64::new(0.0, 0.0),
429                    Complex64::new(1.0, 0.0),
430                    Complex64::new(0.0, 0.0),
431                    Complex64::new(0.0, 0.0),
432                    Complex64::new(0.0, 0.0),
433                    Complex64::new(0.0, 0.0),
434                    Complex64::new(0.0, 0.0),
435                    Complex64::new(1.0, 0.0),
436                ],
437            )
438            .unwrap()),
439            InterfaceGateType::MultiControlledZ(num_controls) => {
440                let total_qubits = num_controls + 1;
441                let dim = 1 << total_qubits;
442                let mut matrix = Array2::eye(dim);
443
444                // Apply Z to the target when all control qubits are |1⟩
445                let target_state = (1 << total_qubits) - 1; // All qubits in |1⟩ state
446                matrix[(target_state, target_state)] = Complex64::new(-1.0, 0.0);
447
448                Ok(matrix)
449            }
450            InterfaceGateType::MultiControlledX(num_controls) => {
451                let total_qubits = num_controls + 1;
452                let dim = 1 << total_qubits;
453                let mut matrix = Array2::eye(dim);
454
455                // Apply X to the target when all control qubits are |1⟩
456                let control_pattern = (1 << *num_controls) - 1; // All control qubits in |1⟩
457                let target_bit = 1 << num_controls;
458
459                // Swap the two states where only the target bit differs
460                let state0 = control_pattern; // Target qubit is |0⟩
461                let state1 = control_pattern | target_bit; // Target qubit is |1⟩
462
463                matrix[(state0, state0)] = Complex64::new(0.0, 0.0);
464                matrix[(state1, state1)] = Complex64::new(0.0, 0.0);
465                matrix[(state0, state1)] = Complex64::new(1.0, 0.0);
466                matrix[(state1, state0)] = Complex64::new(1.0, 0.0);
467
468                Ok(matrix)
469            }
470            InterfaceGateType::CPhase(phase) => {
471                let phase_factor = Complex64::new(0.0, *phase).exp();
472                Ok(Array2::from_shape_vec(
473                    (4, 4),
474                    vec![
475                        Complex64::new(1.0, 0.0),
476                        Complex64::new(0.0, 0.0),
477                        Complex64::new(0.0, 0.0),
478                        Complex64::new(0.0, 0.0),
479                        Complex64::new(0.0, 0.0),
480                        Complex64::new(1.0, 0.0),
481                        Complex64::new(0.0, 0.0),
482                        Complex64::new(0.0, 0.0),
483                        Complex64::new(0.0, 0.0),
484                        Complex64::new(0.0, 0.0),
485                        Complex64::new(1.0, 0.0),
486                        Complex64::new(0.0, 0.0),
487                        Complex64::new(0.0, 0.0),
488                        Complex64::new(0.0, 0.0),
489                        Complex64::new(0.0, 0.0),
490                        phase_factor,
491                    ],
492                )
493                .unwrap())
494            }
495            InterfaceGateType::Custom(_, matrix) => Ok(matrix.clone()),
496            _ => Err(SimulatorError::UnsupportedOperation(format!(
497                "Unitary matrix not available for gate type: {:?}",
498                self.gate_type
499            ))),
500        }
501    }
502
503    /// Check if this gate is a measurement
504    pub fn is_measurement(&self) -> bool {
505        matches!(self.gate_type, InterfaceGateType::Measure)
506    }
507
508    /// Check if this gate is unitary
509    pub fn is_unitary(&self) -> bool {
510        !matches!(
511            self.gate_type,
512            InterfaceGateType::Measure | InterfaceGateType::Reset
513        )
514    }
515
516    /// Get the number of qubits this gate acts on
517    pub fn num_qubits(&self) -> usize {
518        match &self.gate_type {
519            InterfaceGateType::MultiControlledX(n) | InterfaceGateType::MultiControlledZ(n) => {
520                n + 1
521            }
522            _ => self.qubits.len(),
523        }
524    }
525}
526
527/// Quantum circuit representation for interface
528#[derive(Debug, Clone, Serialize, Deserialize)]
529pub struct InterfaceCircuit {
530    /// Number of qubits
531    pub num_qubits: usize,
532    /// Number of classical bits
533    pub num_classical: usize,
534    /// Gates in the circuit
535    pub gates: Vec<InterfaceGate>,
536    /// Circuit metadata
537    pub metadata: CircuitMetadata,
538}
539
540/// Circuit metadata
541#[derive(Debug, Clone, Default, Serialize, Deserialize)]
542pub struct CircuitMetadata {
543    /// Circuit name
544    pub name: Option<String>,
545    /// Circuit description
546    pub description: Option<String>,
547    /// Creation timestamp
548    #[serde(skip)]
549    pub created_at: Option<std::time::SystemTime>,
550    /// Circuit depth
551    pub depth: usize,
552    /// Number of two-qubit gates
553    pub two_qubit_gates: usize,
554    /// Circuit complexity score
555    pub complexity_score: f64,
556    /// Estimated classical simulation complexity
557    pub classical_complexity: Option<f64>,
558}
559
560impl InterfaceCircuit {
561    /// Create a new circuit
562    pub fn new(num_qubits: usize, num_classical: usize) -> Self {
563        Self {
564            num_qubits,
565            num_classical,
566            gates: Vec::new(),
567            metadata: CircuitMetadata::default(),
568        }
569    }
570
571    /// Add a gate to the circuit
572    pub fn add_gate(&mut self, mut gate: InterfaceGate) {
573        gate.position = self.gates.len();
574        self.gates.push(gate);
575        self.update_metadata();
576    }
577
578    /// Add multiple gates to the circuit
579    pub fn add_gates(&mut self, gates: Vec<InterfaceGate>) {
580        for gate in gates {
581            self.add_gate(gate);
582        }
583    }
584
585    /// Update circuit metadata
586    fn update_metadata(&mut self) {
587        let depth = self.calculate_depth();
588        let two_qubit_gates = self.gates.iter().filter(|g| g.num_qubits() == 2).count();
589
590        let complexity_score = self.calculate_complexity_score();
591
592        self.metadata.depth = depth;
593        self.metadata.two_qubit_gates = two_qubit_gates;
594        self.metadata.complexity_score = complexity_score;
595    }
596
597    /// Calculate circuit depth
598    pub fn calculate_depth(&self) -> usize {
599        if self.gates.is_empty() {
600            return 0;
601        }
602
603        let mut qubit_depths = vec![0; self.num_qubits];
604
605        for gate in &self.gates {
606            // Skip gates with invalid qubit indices
607            let valid_qubits: Vec<usize> = gate
608                .qubits
609                .iter()
610                .filter(|&&q| q < self.num_qubits)
611                .copied()
612                .collect();
613
614            if valid_qubits.is_empty() {
615                continue;
616            }
617
618            let max_depth = valid_qubits
619                .iter()
620                .map(|&q| qubit_depths[q])
621                .max()
622                .unwrap_or(0);
623
624            for &qubit in &valid_qubits {
625                qubit_depths[qubit] = max_depth + 1;
626            }
627        }
628
629        qubit_depths.into_iter().max().unwrap_or(0)
630    }
631
632    /// Calculate complexity score
633    fn calculate_complexity_score(&self) -> f64 {
634        let mut score = 0.0;
635
636        for gate in &self.gates {
637            let gate_score = match gate.num_qubits() {
638                1 => 1.0,
639                2 => 5.0,
640                3 => 25.0,
641                n => (5.0_f64).powi(n as i32 - 1),
642            };
643            score += gate_score;
644        }
645
646        score
647    }
648
649    /// Extract subcircuit
650    pub fn subcircuit(&self, start: usize, end: usize) -> Result<InterfaceCircuit> {
651        if start >= end || end > self.gates.len() {
652            return Err(SimulatorError::InvalidInput(
653                "Invalid subcircuit range".to_string(),
654            ));
655        }
656
657        let mut subcircuit = InterfaceCircuit::new(self.num_qubits, self.num_classical);
658        subcircuit.gates = self.gates[start..end].to_vec();
659        subcircuit.update_metadata();
660
661        Ok(subcircuit)
662    }
663
664    /// Optimize the circuit
665    pub fn optimize(&mut self) -> CircuitOptimizationResult {
666        let original_gates = self.gates.len();
667        let original_depth = self.metadata.depth;
668
669        // Apply various optimization passes
670        self.remove_identity_gates();
671        self.cancel_adjacent_gates();
672        self.merge_rotation_gates();
673        self.optimize_cnot_patterns();
674
675        self.update_metadata();
676
677        CircuitOptimizationResult {
678            original_gates,
679            optimized_gates: self.gates.len(),
680            original_depth,
681            optimized_depth: self.metadata.depth,
682            gates_eliminated: original_gates.saturating_sub(self.gates.len()),
683            depth_reduction: original_depth.saturating_sub(self.metadata.depth),
684        }
685    }
686
687    /// Remove identity gates
688    fn remove_identity_gates(&mut self) {
689        self.gates
690            .retain(|gate| !matches!(gate.gate_type, InterfaceGateType::Identity));
691    }
692
693    /// Cancel adjacent gates
694    fn cancel_adjacent_gates(&mut self) {
695        let mut i = 0;
696        while i + 1 < self.gates.len() {
697            if self.gates_cancel(&self.gates[i], &self.gates[i + 1]) {
698                self.gates.remove(i);
699                self.gates.remove(i);
700                if i > 0 {
701                    i = i.saturating_sub(1);
702                }
703            } else {
704                i += 1;
705            }
706        }
707    }
708
709    /// Check if two gates cancel each other
710    fn gates_cancel(&self, gate1: &InterfaceGate, gate2: &InterfaceGate) -> bool {
711        if gate1.qubits != gate2.qubits {
712            return false;
713        }
714
715        match (&gate1.gate_type, &gate2.gate_type) {
716            (InterfaceGateType::PauliX, InterfaceGateType::PauliX)
717            | (InterfaceGateType::PauliY, InterfaceGateType::PauliY)
718            | (InterfaceGateType::PauliZ, InterfaceGateType::PauliZ)
719            | (InterfaceGateType::Hadamard, InterfaceGateType::Hadamard)
720            | (InterfaceGateType::S, InterfaceGateType::S)
721            | (InterfaceGateType::CNOT, InterfaceGateType::CNOT)
722            | (InterfaceGateType::CZ, InterfaceGateType::CZ)
723            | (InterfaceGateType::SWAP, InterfaceGateType::SWAP) => true,
724            _ => false,
725        }
726    }
727
728    /// Merge rotation gates
729    fn merge_rotation_gates(&mut self) {
730        let mut i = 0;
731        while i + 1 < self.gates.len() {
732            if let Some(merged) = self.try_merge_rotations(&self.gates[i], &self.gates[i + 1]) {
733                self.gates[i] = merged;
734                self.gates.remove(i + 1);
735            } else {
736                i += 1;
737            }
738        }
739    }
740
741    /// Try to merge two rotation gates
742    fn try_merge_rotations(
743        &self,
744        gate1: &InterfaceGate,
745        gate2: &InterfaceGate,
746    ) -> Option<InterfaceGate> {
747        if gate1.qubits != gate2.qubits {
748            return None;
749        }
750
751        match (&gate1.gate_type, &gate2.gate_type) {
752            (InterfaceGateType::RX(angle1), InterfaceGateType::RX(angle2)) => Some(
753                InterfaceGate::new(InterfaceGateType::RX(angle1 + angle2), gate1.qubits.clone()),
754            ),
755            (InterfaceGateType::RY(angle1), InterfaceGateType::RY(angle2)) => Some(
756                InterfaceGate::new(InterfaceGateType::RY(angle1 + angle2), gate1.qubits.clone()),
757            ),
758            (InterfaceGateType::RZ(angle1), InterfaceGateType::RZ(angle2)) => Some(
759                InterfaceGate::new(InterfaceGateType::RZ(angle1 + angle2), gate1.qubits.clone()),
760            ),
761            _ => None,
762        }
763    }
764
765    /// Optimize CNOT patterns
766    fn optimize_cnot_patterns(&mut self) {
767        // Look for CNOT chains and optimize them
768        let mut i = 0;
769        while i + 2 < self.gates.len() {
770            if self.is_cnot_chain(i) {
771                self.optimize_cnot_chain(i);
772            }
773            i += 1;
774        }
775    }
776
777    /// Check if there's a CNOT chain starting at position i
778    fn is_cnot_chain(&self, start: usize) -> bool {
779        if start + 2 >= self.gates.len() {
780            return false;
781        }
782
783        for i in start..start + 3 {
784            if !matches!(self.gates[i].gate_type, InterfaceGateType::CNOT) {
785                return false;
786            }
787        }
788
789        true
790    }
791
792    /// Optimize a CNOT chain
793    fn optimize_cnot_chain(&mut self, start: usize) {
794        // Simple optimization: remove triple CNOTs with same control/target
795        if start + 2 < self.gates.len() {
796            let gate1 = &self.gates[start];
797            let gate2 = &self.gates[start + 1];
798            let gate3 = &self.gates[start + 2];
799
800            if gate1.qubits == gate2.qubits && gate2.qubits == gate3.qubits {
801                // Three identical CNOTs = one CNOT
802                self.gates.drain(start + 1..start + 3);
803            }
804        }
805    }
806}
807
808/// Circuit optimization result
809#[derive(Debug, Clone)]
810pub struct CircuitOptimizationResult {
811    /// Original number of gates
812    pub original_gates: usize,
813    /// Optimized number of gates
814    pub optimized_gates: usize,
815    /// Original circuit depth
816    pub original_depth: usize,
817    /// Optimized circuit depth
818    pub optimized_depth: usize,
819    /// Number of gates eliminated
820    pub gates_eliminated: usize,
821    /// Depth reduction achieved
822    pub depth_reduction: usize,
823}
824
825/// Circuit execution backend
826#[derive(Debug, Clone, Copy, PartialEq, Eq)]
827pub enum SimulationBackend {
828    /// State vector simulation
829    StateVector,
830    /// Matrix Product State simulation
831    MPS,
832    /// Stabilizer simulation (for Clifford circuits)
833    Stabilizer,
834    /// Sparse matrix simulation
835    Sparse,
836    /// Tensor network simulation
837    TensorNetwork,
838    /// Automatic backend selection
839    Auto,
840}
841
842/// Circuit interface for simulation backends
843pub struct CircuitInterface {
844    /// Configuration
845    config: CircuitInterfaceConfig,
846    /// SciRS2 backend for optimization
847    backend: Option<SciRS2Backend>,
848    /// Circuit cache
849    circuit_cache: Arc<Mutex<HashMap<u64, CompiledCircuit>>>,
850    /// Performance statistics
851    stats: CircuitInterfaceStats,
852}
853
854/// Compiled circuit representation
855#[derive(Debug, Clone)]
856pub struct CompiledCircuit {
857    /// Original circuit
858    pub original: InterfaceCircuit,
859    /// Optimized gate sequence
860    pub optimized_gates: Vec<InterfaceGate>,
861    /// Backend-specific compiled representation
862    pub backend_data: BackendCompiledData,
863    /// Compilation metadata
864    pub metadata: CompilationMetadata,
865}
866
867/// Backend-specific compiled data
868#[derive(Debug, Clone)]
869pub enum BackendCompiledData {
870    StateVector {
871        unitary_matrices: Vec<Array2<Complex64>>,
872        gate_indices: Vec<Vec<usize>>,
873    },
874    MPS {
875        bond_dimensions: Vec<usize>,
876        truncation_thresholds: Vec<f64>,
877    },
878    Stabilizer {
879        clifford_sequence: Vec<StabilizerOp>,
880    },
881    Sparse {
882        sparse_matrices: Vec<CSRMatrix>,
883    },
884}
885
886/// Stabilizer operation for Clifford circuits
887#[derive(Debug, Clone)]
888pub enum StabilizerOp {
889    H(usize),
890    S(usize),
891    CNOT(usize, usize),
892    X(usize),
893    Y(usize),
894    Z(usize),
895}
896
897/// Compilation metadata
898#[derive(Debug, Clone)]
899pub struct CompilationMetadata {
900    /// Compilation time in milliseconds
901    pub compilation_time_ms: f64,
902    /// Backend used for compilation
903    pub backend: SimulationBackend,
904    /// Optimization passes applied
905    pub optimization_passes: Vec<String>,
906    /// Estimated execution time
907    pub estimated_execution_time_ms: f64,
908    /// Memory requirements estimate
909    pub estimated_memory_bytes: usize,
910}
911
912/// Circuit interface performance statistics
913#[derive(Debug, Clone, Default, Serialize, Deserialize)]
914pub struct CircuitInterfaceStats {
915    /// Total circuits compiled
916    pub circuits_compiled: usize,
917    /// Total compilation time
918    pub total_compilation_time_ms: f64,
919    /// Cache hit rate
920    pub cache_hit_rate: f64,
921    /// Backend selection counts
922    pub backend_selections: HashMap<String, usize>,
923    /// Optimization statistics
924    pub optimization_stats: OptimizationStats,
925}
926
927/// Optimization statistics
928#[derive(Debug, Clone, Default, Serialize, Deserialize)]
929pub struct OptimizationStats {
930    /// Total gates eliminated
931    pub total_gates_eliminated: usize,
932    /// Total depth reduction
933    pub total_depth_reduction: usize,
934    /// Average optimization ratio
935    pub average_optimization_ratio: f64,
936}
937
938impl CircuitInterface {
939    /// Create new circuit interface
940    pub fn new(config: CircuitInterfaceConfig) -> Result<Self> {
941        Ok(Self {
942            config,
943            backend: None,
944            circuit_cache: Arc::new(Mutex::new(HashMap::new())),
945            stats: CircuitInterfaceStats::default(),
946        })
947    }
948
949    /// Initialize with SciRS2 backend
950    pub fn with_backend(mut self) -> Result<Self> {
951        self.backend = Some(SciRS2Backend::new());
952        Ok(self)
953    }
954
955    /// Compile circuit for execution
956    pub fn compile_circuit(
957        &mut self,
958        circuit: &InterfaceCircuit,
959        backend: SimulationBackend,
960    ) -> Result<CompiledCircuit> {
961        let start_time = std::time::Instant::now();
962
963        // Check cache first
964        let circuit_hash = self.calculate_circuit_hash(circuit);
965        if self.config.enable_circuit_cache {
966            let cache = self.circuit_cache.lock().unwrap();
967            if let Some(compiled) = cache.get(&circuit_hash) {
968                self.stats.cache_hit_rate =
969                    (self.stats.cache_hit_rate * self.stats.circuits_compiled as f64 + 1.0)
970                        / (self.stats.circuits_compiled + 1) as f64;
971                return Ok(compiled.clone());
972            }
973        }
974
975        // Select backend automatically if needed
976        let selected_backend = if backend == SimulationBackend::Auto {
977            self.select_optimal_backend(circuit)?
978        } else {
979            backend
980        };
981
982        // Optimize circuit if enabled
983        let mut optimized_circuit = circuit.clone();
984        let mut optimization_passes = Vec::new();
985
986        if self.config.enable_optimization {
987            let opt_result = optimized_circuit.optimize();
988            optimization_passes.push("basic_optimization".to_string());
989
990            self.stats.optimization_stats.total_gates_eliminated += opt_result.gates_eliminated;
991            self.stats.optimization_stats.total_depth_reduction += opt_result.depth_reduction;
992        }
993
994        // Compile for specific backend
995        let backend_data = self.compile_for_backend(&optimized_circuit, selected_backend)?;
996
997        // Estimate execution time and memory
998        let estimated_execution_time_ms =
999            self.estimate_execution_time(&optimized_circuit, selected_backend);
1000        let estimated_memory_bytes =
1001            self.estimate_memory_requirements(&optimized_circuit, selected_backend);
1002
1003        let compilation_time_ms = start_time.elapsed().as_secs_f64() * 1000.0;
1004
1005        let compiled = CompiledCircuit {
1006            original: circuit.clone(),
1007            optimized_gates: optimized_circuit.gates,
1008            backend_data,
1009            metadata: CompilationMetadata {
1010                compilation_time_ms,
1011                backend: selected_backend,
1012                optimization_passes,
1013                estimated_execution_time_ms,
1014                estimated_memory_bytes,
1015            },
1016        };
1017
1018        // Update cache
1019        if self.config.enable_circuit_cache {
1020            let mut cache = self.circuit_cache.lock().unwrap();
1021            if cache.len() >= self.config.max_cache_size {
1022                // Simple LRU: remove oldest entry
1023                if let Some(oldest_key) = cache.keys().next().copied() {
1024                    cache.remove(&oldest_key);
1025                }
1026            }
1027            cache.insert(circuit_hash, compiled.clone());
1028        }
1029
1030        // Update statistics
1031        self.stats.circuits_compiled += 1;
1032        self.stats.total_compilation_time_ms += compilation_time_ms;
1033        *self
1034            .stats
1035            .backend_selections
1036            .entry(format!("{:?}", selected_backend))
1037            .or_insert(0) += 1;
1038
1039        Ok(compiled)
1040    }
1041
1042    /// Execute compiled circuit
1043    pub fn execute_circuit(
1044        &mut self,
1045        compiled: &CompiledCircuit,
1046        initial_state: Option<Array1<Complex64>>,
1047    ) -> Result<CircuitExecutionResult> {
1048        let start_time = std::time::Instant::now();
1049
1050        let result = match compiled.metadata.backend {
1051            SimulationBackend::StateVector => self.execute_statevector(compiled, initial_state)?,
1052            SimulationBackend::MPS => self.execute_mps(compiled, initial_state)?,
1053            SimulationBackend::Stabilizer => self.execute_stabilizer(compiled)?,
1054            SimulationBackend::Sparse => self.execute_sparse(compiled, initial_state)?,
1055            #[cfg(feature = "advanced_math")]
1056            SimulationBackend::TensorNetwork => {
1057                self.execute_tensor_network(compiled, initial_state)?
1058            }
1059            #[cfg(not(feature = "advanced_math"))]
1060            SimulationBackend::TensorNetwork => {
1061                return Err(SimulatorError::UnsupportedOperation(
1062                    "Tensor network simulation requires advanced_math feature".to_string(),
1063                ))
1064            }
1065            SimulationBackend::Auto => {
1066                unreachable!("Auto backend should be resolved during compilation")
1067            }
1068        };
1069
1070        let execution_time_ms = start_time.elapsed().as_secs_f64() * 1000.0;
1071
1072        Ok(CircuitExecutionResult {
1073            final_state: result.final_state,
1074            measurement_results: result.measurement_results,
1075            classical_bits: result.classical_bits,
1076            execution_time_ms,
1077            backend_used: compiled.metadata.backend,
1078            memory_used_bytes: result.memory_used_bytes,
1079        })
1080    }
1081
1082    /// Select optimal backend for circuit
1083    fn select_optimal_backend(&self, circuit: &InterfaceCircuit) -> Result<SimulationBackend> {
1084        let num_qubits = circuit.num_qubits;
1085        let two_qubit_gates = circuit.metadata.two_qubit_gates;
1086        let total_gates = circuit.gates.len();
1087
1088        // Check if circuit is Clifford (can use stabilizer simulation)
1089        if self.is_clifford_circuit(circuit) {
1090            return Ok(SimulationBackend::Stabilizer);
1091        }
1092
1093        // For small circuits, use state vector
1094        if num_qubits <= self.config.max_statevector_qubits {
1095            return Ok(SimulationBackend::StateVector);
1096        }
1097
1098        // For circuits with low entanglement, use MPS
1099        let entanglement_score = two_qubit_gates as f64 / total_gates as f64;
1100        if entanglement_score < 0.3 {
1101            return Ok(SimulationBackend::MPS);
1102        }
1103
1104        // For very sparse circuits, use sparse simulation
1105        let sparsity_score = self.estimate_sparsity(circuit);
1106        if sparsity_score > 0.8 {
1107            return Ok(SimulationBackend::Sparse);
1108        }
1109
1110        // For highly structured circuits, use tensor networks
1111        if self.has_tensor_network_structure(circuit) {
1112            return Ok(SimulationBackend::TensorNetwork);
1113        }
1114
1115        // Default to MPS for large circuits
1116        Ok(SimulationBackend::MPS)
1117    }
1118
1119    /// Check if circuit is Clifford
1120    fn is_clifford_circuit(&self, circuit: &InterfaceCircuit) -> bool {
1121        circuit.gates.iter().all(|gate| {
1122            matches!(
1123                gate.gate_type,
1124                InterfaceGateType::Identity
1125                    | InterfaceGateType::PauliX
1126                    | InterfaceGateType::PauliY
1127                    | InterfaceGateType::PauliZ
1128                    | InterfaceGateType::Hadamard
1129                    | InterfaceGateType::S
1130                    | InterfaceGateType::CNOT
1131                    | InterfaceGateType::CZ
1132                    | InterfaceGateType::SWAP
1133                    | InterfaceGateType::Measure
1134                    | InterfaceGateType::Reset
1135            )
1136        })
1137    }
1138
1139    /// Estimate circuit sparsity
1140    fn estimate_sparsity(&self, circuit: &InterfaceCircuit) -> f64 {
1141        // Heuristic: circuits with many single-qubit gates are typically sparser
1142        let single_qubit_gates = circuit.gates.iter().filter(|g| g.num_qubits() == 1).count();
1143
1144        single_qubit_gates as f64 / circuit.gates.len() as f64
1145    }
1146
1147    /// Check if circuit has tensor network structure
1148    fn has_tensor_network_structure(&self, circuit: &InterfaceCircuit) -> bool {
1149        // Heuristic: circuits with regular structure and moderate entanglement
1150        let depth = circuit.metadata.depth;
1151        let num_qubits = circuit.num_qubits;
1152
1153        // Look for regular patterns
1154        depth > num_qubits && circuit.metadata.complexity_score > 100.0
1155    }
1156
1157    /// Compile circuit for specific backend
1158    fn compile_for_backend(
1159        &self,
1160        circuit: &InterfaceCircuit,
1161        backend: SimulationBackend,
1162    ) -> Result<BackendCompiledData> {
1163        match backend {
1164            SimulationBackend::StateVector => {
1165                let mut unitary_matrices = Vec::new();
1166                let mut gate_indices = Vec::new();
1167
1168                for gate in &circuit.gates {
1169                    if gate.is_unitary() {
1170                        unitary_matrices.push(gate.unitary_matrix()?);
1171                        gate_indices.push(gate.qubits.clone());
1172                    }
1173                }
1174
1175                Ok(BackendCompiledData::StateVector {
1176                    unitary_matrices,
1177                    gate_indices,
1178                })
1179            }
1180            SimulationBackend::MPS => {
1181                // Analyze circuit to determine optimal bond dimensions
1182                let bond_dimensions = self.calculate_optimal_bond_dimensions(circuit);
1183                let truncation_thresholds = vec![1e-12; circuit.gates.len()];
1184
1185                Ok(BackendCompiledData::MPS {
1186                    bond_dimensions,
1187                    truncation_thresholds,
1188                })
1189            }
1190            SimulationBackend::Stabilizer => {
1191                let mut clifford_sequence = Vec::new();
1192
1193                for gate in &circuit.gates {
1194                    match &gate.gate_type {
1195                        InterfaceGateType::Hadamard => {
1196                            clifford_sequence.push(StabilizerOp::H(gate.qubits[0]))
1197                        }
1198                        InterfaceGateType::S => {
1199                            clifford_sequence.push(StabilizerOp::S(gate.qubits[0]))
1200                        }
1201                        InterfaceGateType::PauliX => {
1202                            clifford_sequence.push(StabilizerOp::X(gate.qubits[0]))
1203                        }
1204                        InterfaceGateType::PauliY => {
1205                            clifford_sequence.push(StabilizerOp::Y(gate.qubits[0]))
1206                        }
1207                        InterfaceGateType::PauliZ => {
1208                            clifford_sequence.push(StabilizerOp::Z(gate.qubits[0]))
1209                        }
1210                        InterfaceGateType::CNOT => clifford_sequence
1211                            .push(StabilizerOp::CNOT(gate.qubits[0], gate.qubits[1])),
1212                        _ => {} // Skip non-Clifford gates
1213                    }
1214                }
1215
1216                Ok(BackendCompiledData::Stabilizer { clifford_sequence })
1217            }
1218            SimulationBackend::Sparse => {
1219                let sparse_matrices = Vec::new(); // Would be implemented with actual sparse matrix compilation
1220                Ok(BackendCompiledData::Sparse { sparse_matrices })
1221            }
1222            SimulationBackend::TensorNetwork => {
1223                // For now, use the same data as state vector
1224                let mut unitary_matrices = Vec::new();
1225                let mut gate_indices = Vec::new();
1226
1227                for gate in &circuit.gates {
1228                    if gate.is_unitary() {
1229                        unitary_matrices.push(gate.unitary_matrix()?);
1230                        gate_indices.push(gate.qubits.clone());
1231                    }
1232                }
1233
1234                Ok(BackendCompiledData::StateVector {
1235                    unitary_matrices,
1236                    gate_indices,
1237                })
1238            }
1239            SimulationBackend::Auto => unreachable!(),
1240        }
1241    }
1242
1243    /// Calculate optimal bond dimensions for MPS
1244    fn calculate_optimal_bond_dimensions(&self, circuit: &InterfaceCircuit) -> Vec<usize> {
1245        let base_bond_dim = self.config.max_mps_bond_dim.min(64);
1246        vec![base_bond_dim; circuit.num_qubits - 1]
1247    }
1248
1249    /// Execute state vector simulation
1250    fn execute_statevector(
1251        &self,
1252        compiled: &CompiledCircuit,
1253        initial_state: Option<Array1<Complex64>>,
1254    ) -> Result<BackendExecutionResult> {
1255        let _simulator = StateVectorSimulator::new();
1256
1257        // For now, use a placeholder implementation
1258        let num_qubits = compiled.original.num_qubits;
1259        let state_size = 1 << num_qubits;
1260
1261        let final_state = initial_state.unwrap_or_else(|| {
1262            let mut state = Array1::zeros(state_size);
1263            state[0] = Complex64::new(1.0, 0.0);
1264            state
1265        });
1266        let memory_used = final_state.len() * std::mem::size_of::<Complex64>();
1267
1268        Ok(BackendExecutionResult {
1269            final_state: Some(final_state),
1270            measurement_results: Vec::new(),
1271            classical_bits: vec![false; compiled.original.num_classical],
1272            memory_used_bytes: memory_used,
1273        })
1274    }
1275
1276    /// Execute MPS simulation
1277    fn execute_mps(
1278        &self,
1279        compiled: &CompiledCircuit,
1280        initial_state: Option<Array1<Complex64>>,
1281    ) -> Result<BackendExecutionResult> {
1282        // Placeholder implementation
1283        Ok(BackendExecutionResult {
1284            final_state: None,
1285            measurement_results: Vec::new(),
1286            classical_bits: vec![false; compiled.original.num_classical],
1287            memory_used_bytes: 0,
1288        })
1289    }
1290
1291    /// Execute stabilizer simulation
1292    fn execute_stabilizer(&self, compiled: &CompiledCircuit) -> Result<BackendExecutionResult> {
1293        // Placeholder implementation
1294        Ok(BackendExecutionResult {
1295            final_state: None,
1296            measurement_results: Vec::new(),
1297            classical_bits: vec![false; compiled.original.num_classical],
1298            memory_used_bytes: 0,
1299        })
1300    }
1301
1302    /// Execute sparse simulation
1303    fn execute_sparse(
1304        &self,
1305        compiled: &CompiledCircuit,
1306        initial_state: Option<Array1<Complex64>>,
1307    ) -> Result<BackendExecutionResult> {
1308        // Placeholder implementation
1309        Ok(BackendExecutionResult {
1310            final_state: None,
1311            measurement_results: Vec::new(),
1312            classical_bits: vec![false; compiled.original.num_classical],
1313            memory_used_bytes: 0,
1314        })
1315    }
1316
1317    /// Execute tensor network simulation
1318    #[cfg(feature = "advanced_math")]
1319    fn execute_tensor_network(
1320        &self,
1321        compiled: &CompiledCircuit,
1322        initial_state: Option<Array1<Complex64>>,
1323    ) -> Result<BackendExecutionResult> {
1324        // Placeholder implementation
1325        Ok(BackendExecutionResult {
1326            final_state: None,
1327            measurement_results: Vec::new(),
1328            classical_bits: vec![false; compiled.original.num_classical],
1329            memory_used_bytes: 0,
1330        })
1331    }
1332
1333    #[cfg(not(feature = "advanced_math"))]
1334    fn execute_tensor_network(
1335        &self,
1336        _compiled: &CompiledCircuit,
1337        _initial_state: Option<Array1<Complex64>>,
1338    ) -> Result<BackendExecutionResult> {
1339        Err(SimulatorError::UnsupportedOperation(
1340            "Tensor network simulation requires advanced_math feature".to_string(),
1341        ))
1342    }
1343
1344    /// Calculate circuit hash for caching
1345    fn calculate_circuit_hash(&self, circuit: &InterfaceCircuit) -> u64 {
1346        let mut hasher = DefaultHasher::new();
1347        circuit.num_qubits.hash(&mut hasher);
1348        circuit.num_classical.hash(&mut hasher);
1349
1350        for gate in &circuit.gates {
1351            // Hash gate type discriminant
1352            std::mem::discriminant(&gate.gate_type).hash(&mut hasher);
1353            // Hash gate parameters separately
1354            match &gate.gate_type {
1355                InterfaceGateType::Phase(angle)
1356                | InterfaceGateType::RX(angle)
1357                | InterfaceGateType::RY(angle)
1358                | InterfaceGateType::RZ(angle) => {
1359                    angle.to_bits().hash(&mut hasher);
1360                }
1361                _ => {}
1362            }
1363            gate.qubits.hash(&mut hasher);
1364        }
1365
1366        hasher.finish()
1367    }
1368
1369    /// Estimate execution time
1370    fn estimate_execution_time(
1371        &self,
1372        circuit: &InterfaceCircuit,
1373        backend: SimulationBackend,
1374    ) -> f64 {
1375        let base_time_per_gate = match backend {
1376            SimulationBackend::StateVector => 0.1, // ms per gate
1377            SimulationBackend::MPS => 1.0,
1378            SimulationBackend::Stabilizer => 0.01,
1379            SimulationBackend::Sparse => 0.5,
1380            SimulationBackend::TensorNetwork => 2.0,
1381            SimulationBackend::Auto => 1.0,
1382        };
1383
1384        circuit.gates.len() as f64 * base_time_per_gate * (1.1_f64).powi(circuit.num_qubits as i32)
1385    }
1386
1387    /// Estimate memory requirements
1388    fn estimate_memory_requirements(
1389        &self,
1390        circuit: &InterfaceCircuit,
1391        backend: SimulationBackend,
1392    ) -> usize {
1393        let base_memory = match backend {
1394            SimulationBackend::StateVector => {
1395                (1_usize << circuit.num_qubits) * std::mem::size_of::<Complex64>()
1396            }
1397            SimulationBackend::MPS => {
1398                circuit.num_qubits
1399                    * self.config.max_mps_bond_dim
1400                    * self.config.max_mps_bond_dim
1401                    * std::mem::size_of::<Complex64>()
1402            }
1403            SimulationBackend::Stabilizer => {
1404                circuit.num_qubits * circuit.num_qubits * 2 // Stabilizer tableau
1405            }
1406            SimulationBackend::Sparse => {
1407                circuit.gates.len() * 1000 * std::mem::size_of::<Complex64>() // Rough estimate
1408            }
1409            SimulationBackend::TensorNetwork => {
1410                circuit.num_qubits * 64 * std::mem::size_of::<Complex64>() // Bond dimension 64
1411            }
1412            SimulationBackend::Auto => 0,
1413        };
1414
1415        base_memory
1416    }
1417
1418    /// Get performance statistics
1419    pub fn get_stats(&self) -> &CircuitInterfaceStats {
1420        &self.stats
1421    }
1422
1423    /// Reset performance statistics
1424    pub fn reset_stats(&mut self) {
1425        self.stats = CircuitInterfaceStats::default();
1426    }
1427}
1428
1429/// Backend execution result
1430#[derive(Debug)]
1431struct BackendExecutionResult {
1432    final_state: Option<Array1<Complex64>>,
1433    measurement_results: Vec<bool>,
1434    classical_bits: Vec<bool>,
1435    memory_used_bytes: usize,
1436}
1437
1438/// Circuit execution result
1439#[derive(Debug)]
1440pub struct CircuitExecutionResult {
1441    /// Final quantum state (if available)
1442    pub final_state: Option<Array1<Complex64>>,
1443    /// Measurement results
1444    pub measurement_results: Vec<bool>,
1445    /// Classical bit values
1446    pub classical_bits: Vec<bool>,
1447    /// Execution time in milliseconds
1448    pub execution_time_ms: f64,
1449    /// Backend used for execution
1450    pub backend_used: SimulationBackend,
1451    /// Memory used in bytes
1452    pub memory_used_bytes: usize,
1453}
1454
1455/// Circuit interface utilities
1456pub struct CircuitInterfaceUtils;
1457
1458impl CircuitInterfaceUtils {
1459    /// Create a test circuit
1460    pub fn create_test_circuit(circuit_type: &str, num_qubits: usize) -> InterfaceCircuit {
1461        let mut circuit = InterfaceCircuit::new(num_qubits, num_qubits);
1462
1463        match circuit_type {
1464            "ghz" => {
1465                // GHZ state preparation
1466                circuit.add_gate(InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]));
1467                for i in 1..num_qubits {
1468                    circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![0, i]));
1469                }
1470            }
1471            "qft" => {
1472                // Quantum Fourier Transform
1473                for i in 0..num_qubits {
1474                    circuit.add_gate(InterfaceGate::new(InterfaceGateType::Hadamard, vec![i]));
1475                    for j in i + 1..num_qubits {
1476                        let angle = std::f64::consts::PI / (1 << (j - i)) as f64;
1477                        circuit.add_gate(InterfaceGate::new(
1478                            InterfaceGateType::CRZ(angle),
1479                            vec![j, i],
1480                        ));
1481                    }
1482                }
1483            }
1484            "random" => {
1485                // Random circuit
1486                for _ in 0..num_qubits * 5 {
1487                    let qubit = fastrand::usize(0..num_qubits);
1488                    let gate_type = match fastrand::usize(0..4) {
1489                        0 => InterfaceGateType::Hadamard,
1490                        1 => InterfaceGateType::RX(fastrand::f64() * 2.0 * std::f64::consts::PI),
1491                        2 => InterfaceGateType::RY(fastrand::f64() * 2.0 * std::f64::consts::PI),
1492                        _ => InterfaceGateType::RZ(fastrand::f64() * 2.0 * std::f64::consts::PI),
1493                    };
1494                    circuit.add_gate(InterfaceGate::new(gate_type, vec![qubit]));
1495                }
1496            }
1497            _ => {
1498                // Identity circuit
1499                for i in 0..num_qubits {
1500                    circuit.add_gate(InterfaceGate::new(InterfaceGateType::Identity, vec![i]));
1501                }
1502            }
1503        }
1504
1505        circuit
1506    }
1507
1508    /// Benchmark circuit interface
1509    pub fn benchmark_interface(
1510        config: CircuitInterfaceConfig,
1511    ) -> Result<InterfaceBenchmarkResults> {
1512        let mut interface = CircuitInterface::new(config)?;
1513        let mut results = InterfaceBenchmarkResults::default();
1514
1515        let circuit_types = vec!["ghz", "qft", "random"];
1516        let qubit_counts = vec![5, 10, 15, 20];
1517
1518        for circuit_type in circuit_types {
1519            for &num_qubits in &qubit_counts {
1520                let circuit = Self::create_test_circuit(circuit_type, num_qubits);
1521
1522                let start = std::time::Instant::now();
1523                let compiled = interface.compile_circuit(&circuit, SimulationBackend::Auto)?;
1524                let compilation_time = start.elapsed().as_secs_f64() * 1000.0;
1525
1526                let start = std::time::Instant::now();
1527                let _result = interface.execute_circuit(&compiled, None)?;
1528                let execution_time = start.elapsed().as_secs_f64() * 1000.0;
1529
1530                results
1531                    .compilation_times
1532                    .push((format!("{}_{}", circuit_type, num_qubits), compilation_time));
1533                results
1534                    .execution_times
1535                    .push((format!("{}_{}", circuit_type, num_qubits), execution_time));
1536            }
1537        }
1538
1539        results.interface_stats = interface.get_stats().clone();
1540        Ok(results)
1541    }
1542}
1543
1544/// Interface benchmark results
1545#[derive(Debug, Clone, Default)]
1546pub struct InterfaceBenchmarkResults {
1547    /// Compilation times (circuit_name, time_ms)
1548    pub compilation_times: Vec<(String, f64)>,
1549    /// Execution times (circuit_name, time_ms)
1550    pub execution_times: Vec<(String, f64)>,
1551    /// Interface statistics
1552    pub interface_stats: CircuitInterfaceStats,
1553}
1554
1555#[cfg(test)]
1556mod tests {
1557    use super::*;
1558    use approx::assert_abs_diff_eq;
1559
1560    #[test]
1561    fn test_interface_gate_creation() {
1562        let gate = InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]);
1563        assert_eq!(gate.qubits, vec![0]);
1564        assert!(gate.is_unitary());
1565        assert!(!gate.is_measurement());
1566    }
1567
1568    #[test]
1569    fn test_measurement_gate() {
1570        let gate = InterfaceGate::measurement(0, 0);
1571        assert!(gate.is_measurement());
1572        assert!(!gate.is_unitary());
1573        assert_eq!(gate.classical_targets, vec![0]);
1574    }
1575
1576    #[test]
1577    fn test_circuit_creation() {
1578        let mut circuit = InterfaceCircuit::new(3, 3);
1579        circuit.add_gate(InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]));
1580        circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![0, 1]));
1581
1582        assert_eq!(circuit.gates.len(), 2);
1583        assert_eq!(circuit.calculate_depth(), 2);
1584    }
1585
1586    #[test]
1587    fn test_circuit_optimization() {
1588        let mut circuit = InterfaceCircuit::new(2, 0);
1589        circuit.add_gate(InterfaceGate::new(InterfaceGateType::PauliX, vec![0]));
1590        circuit.add_gate(InterfaceGate::new(InterfaceGateType::PauliX, vec![0])); // Should cancel
1591        circuit.add_gate(InterfaceGate::new(InterfaceGateType::Identity, vec![1])); // Should be removed
1592
1593        let result = circuit.optimize();
1594        assert_eq!(result.gates_eliminated, 3); // All gates should be eliminated
1595    }
1596
1597    #[test]
1598    fn test_gate_unitary_matrices() {
1599        let hadamard = InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]);
1600        let matrix = hadamard.unitary_matrix().unwrap();
1601
1602        let inv_sqrt2 = 1.0 / (2.0_f64).sqrt();
1603        assert_abs_diff_eq!(matrix[[0, 0]].re, inv_sqrt2, epsilon = 1e-10);
1604        assert_abs_diff_eq!(matrix[[1, 1]].re, -inv_sqrt2, epsilon = 1e-10);
1605    }
1606
1607    #[test]
1608    fn test_rotation_gate_merging() {
1609        let mut circuit = InterfaceCircuit::new(1, 0);
1610        circuit.add_gate(InterfaceGate::new(InterfaceGateType::RX(0.5), vec![0]));
1611        circuit.add_gate(InterfaceGate::new(InterfaceGateType::RX(0.3), vec![0]));
1612
1613        let _ = circuit.optimize();
1614        assert_eq!(circuit.gates.len(), 1);
1615
1616        if let InterfaceGateType::RX(angle) = &circuit.gates[0].gate_type {
1617            assert_abs_diff_eq!(*angle, 0.8, epsilon = 1e-10);
1618        } else {
1619            panic!("Expected merged RX gate");
1620        }
1621    }
1622
1623    #[test]
1624    fn test_circuit_interface_config() {
1625        let config = CircuitInterfaceConfig::default();
1626        assert!(config.auto_backend_selection);
1627        assert!(config.enable_optimization);
1628        assert_eq!(config.max_statevector_qubits, 25);
1629    }
1630
1631    #[test]
1632    fn test_test_circuit_creation() {
1633        let ghz_circuit = CircuitInterfaceUtils::create_test_circuit("ghz", 3);
1634        assert_eq!(ghz_circuit.num_qubits, 3);
1635        assert_eq!(ghz_circuit.gates.len(), 3); // H + 2 CNOTs
1636
1637        let qft_circuit = CircuitInterfaceUtils::create_test_circuit("qft", 3);
1638        assert!(qft_circuit.gates.len() > 3); // Should have multiple gates
1639    }
1640
1641    #[test]
1642    fn test_circuit_metadata() {
1643        let circuit = CircuitInterfaceUtils::create_test_circuit("ghz", 4);
1644        assert_eq!(circuit.metadata.depth, 4); // H on qubit 0, then 3 CNOTs sequentially
1645        assert_eq!(circuit.metadata.two_qubit_gates, 3);
1646    }
1647
1648    #[test]
1649    fn test_clifford_detection() {
1650        let mut circuit = InterfaceCircuit::new(2, 0);
1651        circuit.add_gate(InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]));
1652        circuit.add_gate(InterfaceGate::new(InterfaceGateType::CNOT, vec![0, 1]));
1653        circuit.add_gate(InterfaceGate::new(InterfaceGateType::S, vec![1]));
1654
1655        let config = CircuitInterfaceConfig::default();
1656        let interface = CircuitInterface::new(config).unwrap();
1657        assert!(interface.is_clifford_circuit(&circuit));
1658
1659        // Add non-Clifford gate
1660        circuit.add_gate(InterfaceGate::new(InterfaceGateType::T, vec![0]));
1661        assert!(!interface.is_clifford_circuit(&circuit));
1662    }
1663}