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            Self::Identity => 0u8.hash(state),
109            Self::PauliX => 1u8.hash(state),
110            Self::X => 2u8.hash(state),
111            Self::PauliY => 3u8.hash(state),
112            Self::PauliZ => 4u8.hash(state),
113            Self::Hadamard => 5u8.hash(state),
114            Self::H => 6u8.hash(state),
115            Self::S => 7u8.hash(state),
116            Self::T => 8u8.hash(state),
117            Self::Phase(angle) => {
118                9u8.hash(state);
119                angle.to_bits().hash(state);
120            }
121            Self::RX(angle) => {
122                10u8.hash(state);
123                angle.to_bits().hash(state);
124            }
125            Self::RY(angle) => {
126                11u8.hash(state);
127                angle.to_bits().hash(state);
128            }
129            Self::RZ(angle) => {
130                12u8.hash(state);
131                angle.to_bits().hash(state);
132            }
133            Self::U1(angle) => {
134                13u8.hash(state);
135                angle.to_bits().hash(state);
136            }
137            Self::U2(theta, phi) => {
138                14u8.hash(state);
139                theta.to_bits().hash(state);
140                phi.to_bits().hash(state);
141            }
142            Self::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            Self::CNOT => 16u8.hash(state),
149            Self::CZ => 17u8.hash(state),
150            Self::CY => 18u8.hash(state),
151            Self::SWAP => 19u8.hash(state),
152            Self::ISwap => 20u8.hash(state),
153            Self::CRX(angle) => {
154                21u8.hash(state);
155                angle.to_bits().hash(state);
156            }
157            Self::CRY(angle) => {
158                22u8.hash(state);
159                angle.to_bits().hash(state);
160            }
161            Self::CRZ(angle) => {
162                23u8.hash(state);
163                angle.to_bits().hash(state);
164            }
165            Self::CPhase(angle) => {
166                24u8.hash(state);
167                angle.to_bits().hash(state);
168            }
169            Self::Toffoli => 25u8.hash(state),
170            Self::Fredkin => 26u8.hash(state),
171            Self::MultiControlledX(n) => {
172                27u8.hash(state);
173                n.hash(state);
174            }
175            Self::MultiControlledZ(n) => {
176                28u8.hash(state);
177                n.hash(state);
178            }
179            Self::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            Self::Measure => 30u8.hash(state),
186            Self::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 const 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 const 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 const fn is_measurement(&self) -> bool {
505        matches!(self.gate_type, InterfaceGateType::Measure)
506    }
507
508    /// Check if this gate is unitary
509    pub const 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<Self> {
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 = Self::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 = self
969                    .stats
970                    .cache_hit_rate
971                    .mul_add(self.stats.circuits_compiled as f64, 1.0)
972                    / (self.stats.circuits_compiled + 1) as f64;
973                return Ok(compiled.clone());
974            }
975        }
976
977        // Select backend automatically if needed
978        let selected_backend = if backend == SimulationBackend::Auto {
979            self.select_optimal_backend(circuit)?
980        } else {
981            backend
982        };
983
984        // Optimize circuit if enabled
985        let mut optimized_circuit = circuit.clone();
986        let mut optimization_passes = Vec::new();
987
988        if self.config.enable_optimization {
989            let opt_result = optimized_circuit.optimize();
990            optimization_passes.push("basic_optimization".to_string());
991
992            self.stats.optimization_stats.total_gates_eliminated += opt_result.gates_eliminated;
993            self.stats.optimization_stats.total_depth_reduction += opt_result.depth_reduction;
994        }
995
996        // Compile for specific backend
997        let backend_data = self.compile_for_backend(&optimized_circuit, selected_backend)?;
998
999        // Estimate execution time and memory
1000        let estimated_execution_time_ms =
1001            self.estimate_execution_time(&optimized_circuit, selected_backend);
1002        let estimated_memory_bytes =
1003            self.estimate_memory_requirements(&optimized_circuit, selected_backend);
1004
1005        let compilation_time_ms = start_time.elapsed().as_secs_f64() * 1000.0;
1006
1007        let compiled = CompiledCircuit {
1008            original: circuit.clone(),
1009            optimized_gates: optimized_circuit.gates,
1010            backend_data,
1011            metadata: CompilationMetadata {
1012                compilation_time_ms,
1013                backend: selected_backend,
1014                optimization_passes,
1015                estimated_execution_time_ms,
1016                estimated_memory_bytes,
1017            },
1018        };
1019
1020        // Update cache
1021        if self.config.enable_circuit_cache {
1022            let mut cache = self.circuit_cache.lock().unwrap();
1023            if cache.len() >= self.config.max_cache_size {
1024                // Simple LRU: remove oldest entry
1025                if let Some(oldest_key) = cache.keys().next().copied() {
1026                    cache.remove(&oldest_key);
1027                }
1028            }
1029            cache.insert(circuit_hash, compiled.clone());
1030        }
1031
1032        // Update statistics
1033        self.stats.circuits_compiled += 1;
1034        self.stats.total_compilation_time_ms += compilation_time_ms;
1035        *self
1036            .stats
1037            .backend_selections
1038            .entry(format!("{selected_backend:?}"))
1039            .or_insert(0) += 1;
1040
1041        Ok(compiled)
1042    }
1043
1044    /// Execute compiled circuit
1045    pub fn execute_circuit(
1046        &mut self,
1047        compiled: &CompiledCircuit,
1048        initial_state: Option<Array1<Complex64>>,
1049    ) -> Result<CircuitExecutionResult> {
1050        let start_time = std::time::Instant::now();
1051
1052        let result = match compiled.metadata.backend {
1053            SimulationBackend::StateVector => self.execute_statevector(compiled, initial_state)?,
1054            SimulationBackend::MPS => self.execute_mps(compiled, initial_state)?,
1055            SimulationBackend::Stabilizer => self.execute_stabilizer(compiled)?,
1056            SimulationBackend::Sparse => self.execute_sparse(compiled, initial_state)?,
1057            #[cfg(feature = "advanced_math")]
1058            SimulationBackend::TensorNetwork => {
1059                self.execute_tensor_network(compiled, initial_state)?
1060            }
1061            #[cfg(not(feature = "advanced_math"))]
1062            SimulationBackend::TensorNetwork => {
1063                return Err(SimulatorError::UnsupportedOperation(
1064                    "Tensor network simulation requires advanced_math feature".to_string(),
1065                ))
1066            }
1067            SimulationBackend::Auto => {
1068                unreachable!("Auto backend should be resolved during compilation")
1069            }
1070        };
1071
1072        let execution_time_ms = start_time.elapsed().as_secs_f64() * 1000.0;
1073
1074        Ok(CircuitExecutionResult {
1075            final_state: result.final_state,
1076            measurement_results: result.measurement_results,
1077            classical_bits: result.classical_bits,
1078            execution_time_ms,
1079            backend_used: compiled.metadata.backend,
1080            memory_used_bytes: result.memory_used_bytes,
1081        })
1082    }
1083
1084    /// Select optimal backend for circuit
1085    fn select_optimal_backend(&self, circuit: &InterfaceCircuit) -> Result<SimulationBackend> {
1086        let num_qubits = circuit.num_qubits;
1087        let two_qubit_gates = circuit.metadata.two_qubit_gates;
1088        let total_gates = circuit.gates.len();
1089
1090        // Check if circuit is Clifford (can use stabilizer simulation)
1091        if self.is_clifford_circuit(circuit) {
1092            return Ok(SimulationBackend::Stabilizer);
1093        }
1094
1095        // For small circuits, use state vector
1096        if num_qubits <= self.config.max_statevector_qubits {
1097            return Ok(SimulationBackend::StateVector);
1098        }
1099
1100        // For circuits with low entanglement, use MPS
1101        let entanglement_score = two_qubit_gates as f64 / total_gates as f64;
1102        if entanglement_score < 0.3 {
1103            return Ok(SimulationBackend::MPS);
1104        }
1105
1106        // For very sparse circuits, use sparse simulation
1107        let sparsity_score = self.estimate_sparsity(circuit);
1108        if sparsity_score > 0.8 {
1109            return Ok(SimulationBackend::Sparse);
1110        }
1111
1112        // For highly structured circuits, use tensor networks
1113        if self.has_tensor_network_structure(circuit) {
1114            return Ok(SimulationBackend::TensorNetwork);
1115        }
1116
1117        // Default to MPS for large circuits
1118        Ok(SimulationBackend::MPS)
1119    }
1120
1121    /// Check if circuit is Clifford
1122    fn is_clifford_circuit(&self, circuit: &InterfaceCircuit) -> bool {
1123        circuit.gates.iter().all(|gate| {
1124            matches!(
1125                gate.gate_type,
1126                InterfaceGateType::Identity
1127                    | InterfaceGateType::PauliX
1128                    | InterfaceGateType::PauliY
1129                    | InterfaceGateType::PauliZ
1130                    | InterfaceGateType::Hadamard
1131                    | InterfaceGateType::S
1132                    | InterfaceGateType::CNOT
1133                    | InterfaceGateType::CZ
1134                    | InterfaceGateType::SWAP
1135                    | InterfaceGateType::Measure
1136                    | InterfaceGateType::Reset
1137            )
1138        })
1139    }
1140
1141    /// Estimate circuit sparsity
1142    fn estimate_sparsity(&self, circuit: &InterfaceCircuit) -> f64 {
1143        // Heuristic: circuits with many single-qubit gates are typically sparser
1144        let single_qubit_gates = circuit.gates.iter().filter(|g| g.num_qubits() == 1).count();
1145
1146        single_qubit_gates as f64 / circuit.gates.len() as f64
1147    }
1148
1149    /// Check if circuit has tensor network structure
1150    fn has_tensor_network_structure(&self, circuit: &InterfaceCircuit) -> bool {
1151        // Heuristic: circuits with regular structure and moderate entanglement
1152        let depth = circuit.metadata.depth;
1153        let num_qubits = circuit.num_qubits;
1154
1155        // Look for regular patterns
1156        depth > num_qubits && circuit.metadata.complexity_score > 100.0
1157    }
1158
1159    /// Compile circuit for specific backend
1160    fn compile_for_backend(
1161        &self,
1162        circuit: &InterfaceCircuit,
1163        backend: SimulationBackend,
1164    ) -> Result<BackendCompiledData> {
1165        match backend {
1166            SimulationBackend::StateVector => {
1167                let mut unitary_matrices = Vec::new();
1168                let mut gate_indices = Vec::new();
1169
1170                for gate in &circuit.gates {
1171                    if gate.is_unitary() {
1172                        unitary_matrices.push(gate.unitary_matrix()?);
1173                        gate_indices.push(gate.qubits.clone());
1174                    }
1175                }
1176
1177                Ok(BackendCompiledData::StateVector {
1178                    unitary_matrices,
1179                    gate_indices,
1180                })
1181            }
1182            SimulationBackend::MPS => {
1183                // Analyze circuit to determine optimal bond dimensions
1184                let bond_dimensions = self.calculate_optimal_bond_dimensions(circuit);
1185                let truncation_thresholds = vec![1e-12; circuit.gates.len()];
1186
1187                Ok(BackendCompiledData::MPS {
1188                    bond_dimensions,
1189                    truncation_thresholds,
1190                })
1191            }
1192            SimulationBackend::Stabilizer => {
1193                let mut clifford_sequence = Vec::new();
1194
1195                for gate in &circuit.gates {
1196                    match &gate.gate_type {
1197                        InterfaceGateType::Hadamard => {
1198                            clifford_sequence.push(StabilizerOp::H(gate.qubits[0]));
1199                        }
1200                        InterfaceGateType::S => {
1201                            clifford_sequence.push(StabilizerOp::S(gate.qubits[0]));
1202                        }
1203                        InterfaceGateType::PauliX => {
1204                            clifford_sequence.push(StabilizerOp::X(gate.qubits[0]));
1205                        }
1206                        InterfaceGateType::PauliY => {
1207                            clifford_sequence.push(StabilizerOp::Y(gate.qubits[0]));
1208                        }
1209                        InterfaceGateType::PauliZ => {
1210                            clifford_sequence.push(StabilizerOp::Z(gate.qubits[0]));
1211                        }
1212                        InterfaceGateType::CNOT => clifford_sequence
1213                            .push(StabilizerOp::CNOT(gate.qubits[0], gate.qubits[1])),
1214                        _ => {} // Skip non-Clifford gates
1215                    }
1216                }
1217
1218                Ok(BackendCompiledData::Stabilizer { clifford_sequence })
1219            }
1220            SimulationBackend::Sparse => {
1221                let sparse_matrices = Vec::new(); // Would be implemented with actual sparse matrix compilation
1222                Ok(BackendCompiledData::Sparse { sparse_matrices })
1223            }
1224            SimulationBackend::TensorNetwork => {
1225                // For now, use the same data as state vector
1226                let mut unitary_matrices = Vec::new();
1227                let mut gate_indices = Vec::new();
1228
1229                for gate in &circuit.gates {
1230                    if gate.is_unitary() {
1231                        unitary_matrices.push(gate.unitary_matrix()?);
1232                        gate_indices.push(gate.qubits.clone());
1233                    }
1234                }
1235
1236                Ok(BackendCompiledData::StateVector {
1237                    unitary_matrices,
1238                    gate_indices,
1239                })
1240            }
1241            SimulationBackend::Auto => unreachable!(),
1242        }
1243    }
1244
1245    /// Calculate optimal bond dimensions for MPS
1246    fn calculate_optimal_bond_dimensions(&self, circuit: &InterfaceCircuit) -> Vec<usize> {
1247        let base_bond_dim = self.config.max_mps_bond_dim.min(64);
1248        vec![base_bond_dim; circuit.num_qubits - 1]
1249    }
1250
1251    /// Execute state vector simulation
1252    fn execute_statevector(
1253        &self,
1254        compiled: &CompiledCircuit,
1255        initial_state: Option<Array1<Complex64>>,
1256    ) -> Result<BackendExecutionResult> {
1257        let _simulator = StateVectorSimulator::new();
1258
1259        // For now, use a placeholder implementation
1260        let num_qubits = compiled.original.num_qubits;
1261        let state_size = 1 << num_qubits;
1262
1263        let final_state = initial_state.unwrap_or_else(|| {
1264            let mut state = Array1::zeros(state_size);
1265            state[0] = Complex64::new(1.0, 0.0);
1266            state
1267        });
1268        let memory_used = final_state.len() * std::mem::size_of::<Complex64>();
1269
1270        Ok(BackendExecutionResult {
1271            final_state: Some(final_state),
1272            measurement_results: Vec::new(),
1273            classical_bits: vec![false; compiled.original.num_classical],
1274            memory_used_bytes: memory_used,
1275        })
1276    }
1277
1278    /// Execute MPS simulation
1279    fn execute_mps(
1280        &self,
1281        compiled: &CompiledCircuit,
1282        initial_state: Option<Array1<Complex64>>,
1283    ) -> Result<BackendExecutionResult> {
1284        // Placeholder implementation
1285        Ok(BackendExecutionResult {
1286            final_state: None,
1287            measurement_results: Vec::new(),
1288            classical_bits: vec![false; compiled.original.num_classical],
1289            memory_used_bytes: 0,
1290        })
1291    }
1292
1293    /// Execute stabilizer simulation
1294    fn execute_stabilizer(&self, compiled: &CompiledCircuit) -> Result<BackendExecutionResult> {
1295        // Placeholder implementation
1296        Ok(BackendExecutionResult {
1297            final_state: None,
1298            measurement_results: Vec::new(),
1299            classical_bits: vec![false; compiled.original.num_classical],
1300            memory_used_bytes: 0,
1301        })
1302    }
1303
1304    /// Execute sparse simulation
1305    fn execute_sparse(
1306        &self,
1307        compiled: &CompiledCircuit,
1308        initial_state: Option<Array1<Complex64>>,
1309    ) -> Result<BackendExecutionResult> {
1310        // Placeholder implementation
1311        Ok(BackendExecutionResult {
1312            final_state: None,
1313            measurement_results: Vec::new(),
1314            classical_bits: vec![false; compiled.original.num_classical],
1315            memory_used_bytes: 0,
1316        })
1317    }
1318
1319    /// Execute tensor network simulation
1320    #[cfg(feature = "advanced_math")]
1321    fn execute_tensor_network(
1322        &self,
1323        compiled: &CompiledCircuit,
1324        initial_state: Option<Array1<Complex64>>,
1325    ) -> Result<BackendExecutionResult> {
1326        // Placeholder implementation
1327        Ok(BackendExecutionResult {
1328            final_state: None,
1329            measurement_results: Vec::new(),
1330            classical_bits: vec![false; compiled.original.num_classical],
1331            memory_used_bytes: 0,
1332        })
1333    }
1334
1335    #[cfg(not(feature = "advanced_math"))]
1336    fn execute_tensor_network(
1337        &self,
1338        _compiled: &CompiledCircuit,
1339        _initial_state: Option<Array1<Complex64>>,
1340    ) -> Result<BackendExecutionResult> {
1341        Err(SimulatorError::UnsupportedOperation(
1342            "Tensor network simulation requires advanced_math feature".to_string(),
1343        ))
1344    }
1345
1346    /// Calculate circuit hash for caching
1347    fn calculate_circuit_hash(&self, circuit: &InterfaceCircuit) -> u64 {
1348        let mut hasher = DefaultHasher::new();
1349        circuit.num_qubits.hash(&mut hasher);
1350        circuit.num_classical.hash(&mut hasher);
1351
1352        for gate in &circuit.gates {
1353            // Hash gate type discriminant
1354            std::mem::discriminant(&gate.gate_type).hash(&mut hasher);
1355            // Hash gate parameters separately
1356            match &gate.gate_type {
1357                InterfaceGateType::Phase(angle)
1358                | InterfaceGateType::RX(angle)
1359                | InterfaceGateType::RY(angle)
1360                | InterfaceGateType::RZ(angle) => {
1361                    angle.to_bits().hash(&mut hasher);
1362                }
1363                _ => {}
1364            }
1365            gate.qubits.hash(&mut hasher);
1366        }
1367
1368        hasher.finish()
1369    }
1370
1371    /// Estimate execution time
1372    fn estimate_execution_time(
1373        &self,
1374        circuit: &InterfaceCircuit,
1375        backend: SimulationBackend,
1376    ) -> f64 {
1377        let base_time_per_gate = match backend {
1378            SimulationBackend::StateVector => 0.1, // ms per gate
1379            SimulationBackend::MPS => 1.0,
1380            SimulationBackend::Stabilizer => 0.01,
1381            SimulationBackend::Sparse => 0.5,
1382            SimulationBackend::TensorNetwork => 2.0,
1383            SimulationBackend::Auto => 1.0,
1384        };
1385
1386        circuit.gates.len() as f64 * base_time_per_gate * (1.1_f64).powi(circuit.num_qubits as i32)
1387    }
1388
1389    /// Estimate memory requirements
1390    fn estimate_memory_requirements(
1391        &self,
1392        circuit: &InterfaceCircuit,
1393        backend: SimulationBackend,
1394    ) -> usize {
1395        match backend {
1396            SimulationBackend::StateVector => {
1397                (1_usize << circuit.num_qubits) * std::mem::size_of::<Complex64>()
1398            }
1399            SimulationBackend::MPS => {
1400                circuit.num_qubits
1401                    * self.config.max_mps_bond_dim
1402                    * self.config.max_mps_bond_dim
1403                    * std::mem::size_of::<Complex64>()
1404            }
1405            SimulationBackend::Stabilizer => {
1406                circuit.num_qubits * circuit.num_qubits * 2 // Stabilizer tableau
1407            }
1408            SimulationBackend::Sparse => {
1409                circuit.gates.len() * 1000 * std::mem::size_of::<Complex64>() // Rough estimate
1410            }
1411            SimulationBackend::TensorNetwork => {
1412                circuit.num_qubits * 64 * std::mem::size_of::<Complex64>() // Bond dimension 64
1413            }
1414            SimulationBackend::Auto => 0,
1415        }
1416    }
1417
1418    /// Get performance statistics
1419    pub const 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}