quantrs2_device/
cross_compiler_scirs2_ir.rs

1//! Cross-Compilation with SciRS2 IR Tools
2//!
3//! This module provides quantum circuit cross-compilation using SciRS2's intermediate
4//! representation (IR) tools for multi-backend optimization and code generation.
5
6use crate::{DeviceError, DeviceResult};
7use scirs2_core::ndarray::{Array1, Array2};
8use scirs2_core::Complex64;
9use std::collections::HashMap;
10
11/// Target backend for cross-compilation
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum TargetBackend {
14    /// IBM Quantum (OpenQASM 2.0)
15    IBMQuantum,
16    /// AWS Braket
17    AWSBraket,
18    /// Azure Quantum
19    AzureQuantum,
20    /// Generic QASM
21    GenericQASM,
22    /// Custom backend
23    Custom,
24}
25
26/// Optimization level for IR compilation
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum OptimizationLevel {
29    /// No optimization
30    O0,
31    /// Basic optimization
32    O1,
33    /// Moderate optimization
34    O2,
35    /// Aggressive optimization
36    O3,
37}
38
39/// Cross-compiler configuration
40#[derive(Debug, Clone)]
41pub struct CrossCompilerConfig {
42    /// Target backend
43    pub target: TargetBackend,
44    /// Optimization level
45    pub optimization_level: OptimizationLevel,
46    /// Enable gate fusion
47    pub enable_gate_fusion: bool,
48    /// Enable commutation-based optimization
49    pub enable_commutation_opt: bool,
50    /// Enable backend-specific optimizations
51    pub enable_backend_opt: bool,
52    /// Maximum circuit depth (None for unlimited)
53    pub max_circuit_depth: Option<usize>,
54}
55
56impl Default for CrossCompilerConfig {
57    fn default() -> Self {
58        Self {
59            target: TargetBackend::GenericQASM,
60            optimization_level: OptimizationLevel::O2,
61            enable_gate_fusion: true,
62            enable_commutation_opt: true,
63            enable_backend_opt: true,
64            max_circuit_depth: None,
65        }
66    }
67}
68
69/// Quantum circuit intermediate representation
70#[derive(Debug, Clone)]
71pub struct QuantumIR {
72    /// Number of qubits
73    pub num_qubits: usize,
74    /// IR instructions
75    pub instructions: Vec<IRInstruction>,
76    /// Metadata
77    pub metadata: IRMetadata,
78}
79
80/// IR instruction representing quantum operations
81#[derive(Debug, Clone)]
82pub enum IRInstruction {
83    /// Single-qubit gate
84    SingleQubitGate {
85        gate_type: SingleQubitGateType,
86        target: usize,
87        parameters: Vec<f64>,
88    },
89    /// Two-qubit gate
90    TwoQubitGate {
91        gate_type: TwoQubitGateType,
92        control: usize,
93        target: usize,
94        parameters: Vec<f64>,
95    },
96    /// Measurement
97    Measure { qubit: usize, classical_bit: usize },
98    /// Barrier (prevents optimization across it)
99    Barrier { qubits: Vec<usize> },
100    /// Custom gate
101    Custom {
102        name: String,
103        qubits: Vec<usize>,
104        parameters: Vec<f64>,
105    },
106}
107
108/// Single-qubit gate types
109#[derive(Debug, Clone, Copy, PartialEq, Eq)]
110pub enum SingleQubitGateType {
111    Hadamard,
112    PauliX,
113    PauliY,
114    PauliZ,
115    Phase,
116    T,
117    TDagger,
118    S,
119    SDagger,
120    Rx,
121    Ry,
122    Rz,
123    U3,
124}
125
126/// Two-qubit gate types
127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128pub enum TwoQubitGateType {
129    CNOT,
130    CZ,
131    SWAP,
132    Controlled,
133}
134
135/// IR metadata
136#[derive(Debug, Clone)]
137pub struct IRMetadata {
138    /// Circuit name
139    pub name: String,
140    /// Creation timestamp
141    pub created: std::time::SystemTime,
142    /// Source backend (if converted)
143    pub source_backend: Option<TargetBackend>,
144    /// Optimization passes applied
145    pub optimization_passes: Vec<String>,
146}
147
148impl Default for IRMetadata {
149    fn default() -> Self {
150        Self {
151            name: "quantum_circuit".to_string(),
152            created: std::time::SystemTime::now(),
153            source_backend: None,
154            optimization_passes: Vec::new(),
155        }
156    }
157}
158
159/// Compilation result
160#[derive(Debug, Clone)]
161pub struct CompilationResult {
162    /// Compiled code for target backend
163    pub code: String,
164    /// Optimized IR
165    pub optimized_ir: QuantumIR,
166    /// Compilation statistics
167    pub statistics: CompilationStatistics,
168}
169
170/// Compilation statistics
171#[derive(Debug, Clone)]
172pub struct CompilationStatistics {
173    /// Original instruction count
174    pub original_instruction_count: usize,
175    /// Optimized instruction count
176    pub optimized_instruction_count: usize,
177    /// Circuit depth before optimization
178    pub original_depth: usize,
179    /// Circuit depth after optimization
180    pub optimized_depth: usize,
181    /// Number of optimization passes applied
182    pub num_optimization_passes: usize,
183    /// Compilation time (milliseconds)
184    pub compilation_time_ms: u128,
185}
186
187/// Cross-compiler using SciRS2 IR tools
188pub struct CrossCompiler {
189    config: CrossCompilerConfig,
190}
191
192impl CrossCompiler {
193    /// Create a new cross-compiler
194    pub fn new(config: CrossCompilerConfig) -> Self {
195        Self { config }
196    }
197
198    /// Create compiler with default configuration
199    pub fn default() -> Self {
200        Self::new(CrossCompilerConfig::default())
201    }
202
203    /// Compile quantum IR to target backend
204    ///
205    /// # Arguments
206    /// * `ir` - Quantum circuit in IR format
207    ///
208    /// # Returns
209    /// Compilation result with backend-specific code
210    pub fn compile(&self, ir: QuantumIR) -> DeviceResult<CompilationResult> {
211        let start_time = std::time::Instant::now();
212
213        let original_count = ir.instructions.len();
214        let original_depth = self.compute_circuit_depth(&ir);
215
216        // Apply optimization passes based on configuration
217        let mut optimized_ir = ir.clone();
218        let mut num_passes = 0;
219
220        if self.config.optimization_level != OptimizationLevel::O0 {
221            // Gate fusion pass
222            if self.config.enable_gate_fusion {
223                optimized_ir = self.apply_gate_fusion(optimized_ir)?;
224                num_passes += 1;
225            }
226
227            // Commutation-based optimization
228            if self.config.enable_commutation_opt {
229                optimized_ir = self.apply_commutation_optimization(optimized_ir)?;
230                num_passes += 1;
231            }
232
233            // Backend-specific optimizations
234            if self.config.enable_backend_opt {
235                optimized_ir = self.apply_backend_optimization(optimized_ir)?;
236                num_passes += 1;
237            }
238
239            // Remove identity gates
240            optimized_ir = self.remove_identity_gates(optimized_ir)?;
241            num_passes += 1;
242        }
243
244        let optimized_count = optimized_ir.instructions.len();
245        let optimized_depth = self.compute_circuit_depth(&optimized_ir);
246
247        // Generate code for target backend
248        let code = self.generate_backend_code(&optimized_ir)?;
249
250        let compilation_time = start_time.elapsed().as_millis();
251
252        Ok(CompilationResult {
253            code,
254            optimized_ir,
255            statistics: CompilationStatistics {
256                original_instruction_count: original_count,
257                optimized_instruction_count: optimized_count,
258                original_depth,
259                optimized_depth,
260                num_optimization_passes: num_passes,
261                compilation_time_ms: compilation_time,
262            },
263        })
264    }
265
266    /// Compute circuit depth
267    fn compute_circuit_depth(&self, ir: &QuantumIR) -> usize {
268        let mut qubit_depths = vec![0; ir.num_qubits];
269
270        for instr in &ir.instructions {
271            match instr {
272                IRInstruction::SingleQubitGate { target, .. } => {
273                    qubit_depths[*target] += 1;
274                }
275                IRInstruction::TwoQubitGate {
276                    control, target, ..
277                } => {
278                    let max_depth = qubit_depths[*control].max(qubit_depths[*target]);
279                    qubit_depths[*control] = max_depth + 1;
280                    qubit_depths[*target] = max_depth + 1;
281                }
282                IRInstruction::Measure { qubit, .. } => {
283                    qubit_depths[*qubit] += 1;
284                }
285                IRInstruction::Barrier { qubits } => {
286                    if !qubits.is_empty() {
287                        let max_depth = qubits.iter().map(|&q| qubit_depths[q]).max().unwrap_or(0);
288                        for &q in qubits {
289                            qubit_depths[q] = max_depth + 1;
290                        }
291                    }
292                }
293                IRInstruction::Custom { qubits, .. } => {
294                    if !qubits.is_empty() {
295                        let max_depth = qubits.iter().map(|&q| qubit_depths[q]).max().unwrap_or(0);
296                        for &q in qubits {
297                            qubit_depths[q] = max_depth + 1;
298                        }
299                    }
300                }
301            }
302        }
303
304        qubit_depths.into_iter().max().unwrap_or(0)
305    }
306
307    /// Apply gate fusion optimization
308    fn apply_gate_fusion(&self, mut ir: QuantumIR) -> DeviceResult<QuantumIR> {
309        let mut optimized_instructions = Vec::new();
310        let mut i = 0;
311
312        while i < ir.instructions.len() {
313            // Look for consecutive rotation gates on the same qubit
314            if i + 1 < ir.instructions.len() {
315                match (&ir.instructions[i], &ir.instructions[i + 1]) {
316                    (
317                        IRInstruction::SingleQubitGate {
318                            gate_type: SingleQubitGateType::Rz,
319                            target: t1,
320                            parameters: p1,
321                        },
322                        IRInstruction::SingleQubitGate {
323                            gate_type: SingleQubitGateType::Rz,
324                            target: t2,
325                            parameters: p2,
326                        },
327                    ) if t1 == t2 && p1.len() == 1 && p2.len() == 1 => {
328                        // Fuse consecutive Rz gates
329                        optimized_instructions.push(IRInstruction::SingleQubitGate {
330                            gate_type: SingleQubitGateType::Rz,
331                            target: *t1,
332                            parameters: vec![p1[0] + p2[0]],
333                        });
334                        i += 2;
335                        continue;
336                    }
337                    _ => {}
338                }
339            }
340
341            optimized_instructions.push(ir.instructions[i].clone());
342            i += 1;
343        }
344
345        ir.instructions = optimized_instructions;
346        ir.metadata
347            .optimization_passes
348            .push("gate_fusion".to_string());
349        Ok(ir)
350    }
351
352    /// Apply commutation-based optimization
353    fn apply_commutation_optimization(&self, mut ir: QuantumIR) -> DeviceResult<QuantumIR> {
354        // Simplified commutation optimization: move measurements to the end
355        let mut measurements = Vec::new();
356        let mut other_instructions = Vec::new();
357
358        for instr in ir.instructions {
359            match instr {
360                IRInstruction::Measure { .. } => measurements.push(instr),
361                _ => other_instructions.push(instr),
362            }
363        }
364
365        other_instructions.extend(measurements);
366        ir.instructions = other_instructions;
367        ir.metadata
368            .optimization_passes
369            .push("commutation_opt".to_string());
370        Ok(ir)
371    }
372
373    /// Apply backend-specific optimizations
374    fn apply_backend_optimization(&self, mut ir: QuantumIR) -> DeviceResult<QuantumIR> {
375        match self.config.target {
376            TargetBackend::IBMQuantum => {
377                // IBM prefers U3 gates and CX
378                ir = self.decompose_to_ibm_basis(ir)?;
379            }
380            TargetBackend::AWSBraket => {
381                // AWS Braket supports various gate sets
382                // Keep standard gates
383            }
384            TargetBackend::AzureQuantum => {
385                // Azure supports standard gates
386                // Keep standard gates
387            }
388            _ => {}
389        }
390
391        ir.metadata
392            .optimization_passes
393            .push("backend_specific".to_string());
394        Ok(ir)
395    }
396
397    /// Decompose gates to IBM basis (U3, CX)
398    fn decompose_to_ibm_basis(&self, mut ir: QuantumIR) -> DeviceResult<QuantumIR> {
399        let mut decomposed = Vec::new();
400
401        for instr in ir.instructions {
402            match instr {
403                IRInstruction::SingleQubitGate {
404                    gate_type: SingleQubitGateType::Hadamard,
405                    target,
406                    ..
407                } => {
408                    // H = U3(π/2, 0, π)
409                    decomposed.push(IRInstruction::SingleQubitGate {
410                        gate_type: SingleQubitGateType::U3,
411                        target,
412                        parameters: vec![std::f64::consts::PI / 2.0, 0.0, std::f64::consts::PI],
413                    });
414                }
415                IRInstruction::TwoQubitGate {
416                    gate_type: TwoQubitGateType::CNOT,
417                    control,
418                    target,
419                    ..
420                } => {
421                    // CNOT is native, keep as is
422                    decomposed.push(IRInstruction::TwoQubitGate {
423                        gate_type: TwoQubitGateType::CNOT,
424                        control,
425                        target,
426                        parameters: vec![],
427                    });
428                }
429                other => decomposed.push(other),
430            }
431        }
432
433        ir.instructions = decomposed;
434        Ok(ir)
435    }
436
437    /// Remove identity gates and no-ops
438    fn remove_identity_gates(&self, mut ir: QuantumIR) -> DeviceResult<QuantumIR> {
439        ir.instructions.retain(|instr| {
440            !matches!(
441                instr,
442                IRInstruction::SingleQubitGate {
443                    gate_type: SingleQubitGateType::Rz,
444                    parameters,
445                    ..
446                } if parameters.len() == 1 && parameters[0].abs() < 1e-10
447            )
448        });
449
450        ir.metadata
451            .optimization_passes
452            .push("identity_removal".to_string());
453        Ok(ir)
454    }
455
456    /// Generate backend-specific code
457    fn generate_backend_code(&self, ir: &QuantumIR) -> DeviceResult<String> {
458        match self.config.target {
459            TargetBackend::IBMQuantum | TargetBackend::GenericQASM => self.generate_qasm_code(ir),
460            TargetBackend::AWSBraket => self.generate_braket_code(ir),
461            TargetBackend::AzureQuantum => self.generate_azure_code(ir),
462            TargetBackend::Custom => {
463                Ok("// Custom backend code generation not implemented\n".to_string())
464            }
465        }
466    }
467
468    /// Generate OpenQASM 2.0 code
469    fn generate_qasm_code(&self, ir: &QuantumIR) -> DeviceResult<String> {
470        let mut code = String::new();
471        code.push_str("OPENQASM 2.0;\n");
472        code.push_str("include \"qelib1.inc\";\n");
473        code.push_str(&format!("qreg q[{}];\n", ir.num_qubits));
474        code.push_str(&format!("creg c[{}];\n", ir.num_qubits));
475
476        for instr in &ir.instructions {
477            match instr {
478                IRInstruction::SingleQubitGate {
479                    gate_type,
480                    target,
481                    parameters,
482                } => {
483                    let gate_str = match gate_type {
484                        SingleQubitGateType::Hadamard => format!("h q[{}];", target),
485                        SingleQubitGateType::PauliX => format!("x q[{}];", target),
486                        SingleQubitGateType::PauliY => format!("y q[{}];", target),
487                        SingleQubitGateType::PauliZ => format!("z q[{}];", target),
488                        SingleQubitGateType::T => format!("t q[{}];", target),
489                        SingleQubitGateType::TDagger => format!("tdg q[{}];", target),
490                        SingleQubitGateType::S => format!("s q[{}];", target),
491                        SingleQubitGateType::SDagger => format!("sdg q[{}];", target),
492                        SingleQubitGateType::Rx if parameters.len() == 1 => {
493                            format!("rx({}) q[{}];", parameters[0], target)
494                        }
495                        SingleQubitGateType::Ry if parameters.len() == 1 => {
496                            format!("ry({}) q[{}];", parameters[0], target)
497                        }
498                        SingleQubitGateType::Rz if parameters.len() == 1 => {
499                            format!("rz({}) q[{}];", parameters[0], target)
500                        }
501                        SingleQubitGateType::U3 if parameters.len() == 3 => {
502                            format!(
503                                "u3({},{},{}) q[{}];",
504                                parameters[0], parameters[1], parameters[2], target
505                            )
506                        }
507                        _ => format!("// Unknown gate on q[{}]", target),
508                    };
509                    code.push_str(&gate_str);
510                    code.push('\n');
511                }
512                IRInstruction::TwoQubitGate {
513                    gate_type,
514                    control,
515                    target,
516                    ..
517                } => {
518                    let gate_str = match gate_type {
519                        TwoQubitGateType::CNOT => format!("cx q[{}],q[{}];", control, target),
520                        TwoQubitGateType::CZ => format!("cz q[{}],q[{}];", control, target),
521                        TwoQubitGateType::SWAP => format!("swap q[{}],q[{}];", control, target),
522                        _ => "// Unknown two-qubit gate".to_string(),
523                    };
524                    code.push_str(&gate_str);
525                    code.push('\n');
526                }
527                IRInstruction::Measure {
528                    qubit,
529                    classical_bit,
530                } => {
531                    code.push_str(&format!("measure q[{}] -> c[{}];\n", qubit, classical_bit));
532                }
533                IRInstruction::Barrier { qubits } => {
534                    if qubits.is_empty() {
535                        code.push_str("barrier q;\n");
536                    } else {
537                        let qubit_list = qubits
538                            .iter()
539                            .map(|q| format!("q[{}]", q))
540                            .collect::<Vec<_>>()
541                            .join(",");
542                        code.push_str(&format!("barrier {};\n", qubit_list));
543                    }
544                }
545                IRInstruction::Custom {
546                    name,
547                    qubits,
548                    parameters,
549                } => {
550                    let qubit_list = qubits
551                        .iter()
552                        .map(|q| format!("q[{}]", q))
553                        .collect::<Vec<_>>()
554                        .join(",");
555                    if parameters.is_empty() {
556                        code.push_str(&format!("{} {};\n", name, qubit_list));
557                    } else {
558                        let param_list = parameters
559                            .iter()
560                            .map(|p| p.to_string())
561                            .collect::<Vec<_>>()
562                            .join(",");
563                        code.push_str(&format!("{}({}) {};\n", name, param_list, qubit_list));
564                    }
565                }
566            }
567        }
568
569        Ok(code)
570    }
571
572    /// Generate AWS Braket code (OpenQASM-like)
573    fn generate_braket_code(&self, ir: &QuantumIR) -> DeviceResult<String> {
574        // AWS Braket uses OpenQASM with some extensions
575        self.generate_qasm_code(ir)
576    }
577
578    /// Generate Azure Quantum code
579    fn generate_azure_code(&self, ir: &QuantumIR) -> DeviceResult<String> {
580        // Azure Quantum supports OpenQASM
581        self.generate_qasm_code(ir)
582    }
583
584    /// Create IR from gate sequence
585    pub fn create_ir_from_gates(&self, num_qubits: usize, gates: Vec<IRInstruction>) -> QuantumIR {
586        QuantumIR {
587            num_qubits,
588            instructions: gates,
589            metadata: IRMetadata::default(),
590        }
591    }
592}
593
594#[cfg(test)]
595mod tests {
596    use super::*;
597
598    #[test]
599    fn test_compiler_creation() {
600        let config = CrossCompilerConfig::default();
601        let compiler = CrossCompiler::new(config);
602        assert_eq!(compiler.config.target, TargetBackend::GenericQASM);
603    }
604
605    #[test]
606    fn test_ir_creation() {
607        let compiler = CrossCompiler::default();
608        let gates = vec![
609            IRInstruction::SingleQubitGate {
610                gate_type: SingleQubitGateType::Hadamard,
611                target: 0,
612                parameters: vec![],
613            },
614            IRInstruction::TwoQubitGate {
615                gate_type: TwoQubitGateType::CNOT,
616                control: 0,
617                target: 1,
618                parameters: vec![],
619            },
620        ];
621
622        let ir = compiler.create_ir_from_gates(2, gates);
623        assert_eq!(ir.num_qubits, 2);
624        assert_eq!(ir.instructions.len(), 2);
625    }
626
627    #[test]
628    fn test_circuit_depth_calculation() {
629        let compiler = CrossCompiler::default();
630        let gates = vec![
631            IRInstruction::SingleQubitGate {
632                gate_type: SingleQubitGateType::Hadamard,
633                target: 0,
634                parameters: vec![],
635            },
636            IRInstruction::SingleQubitGate {
637                gate_type: SingleQubitGateType::Hadamard,
638                target: 1,
639                parameters: vec![],
640            },
641            IRInstruction::TwoQubitGate {
642                gate_type: TwoQubitGateType::CNOT,
643                control: 0,
644                target: 1,
645                parameters: vec![],
646            },
647        ];
648
649        let ir = compiler.create_ir_from_gates(2, gates);
650        let depth = compiler.compute_circuit_depth(&ir);
651        assert_eq!(depth, 2); // H on q0, H on q1 (parallel), then CNOT
652    }
653
654    #[test]
655    fn test_qasm_code_generation() {
656        let config = CrossCompilerConfig {
657            target: TargetBackend::GenericQASM,
658            optimization_level: OptimizationLevel::O0,
659            ..Default::default()
660        };
661        let compiler = CrossCompiler::new(config);
662
663        let gates = vec![
664            IRInstruction::SingleQubitGate {
665                gate_type: SingleQubitGateType::Hadamard,
666                target: 0,
667                parameters: vec![],
668            },
669            IRInstruction::TwoQubitGate {
670                gate_type: TwoQubitGateType::CNOT,
671                control: 0,
672                target: 1,
673                parameters: vec![],
674            },
675            IRInstruction::Measure {
676                qubit: 0,
677                classical_bit: 0,
678            },
679        ];
680
681        let ir = compiler.create_ir_from_gates(2, gates);
682        let result = compiler.compile(ir);
683
684        assert!(result.is_ok());
685        let result = result.expect("Compilation failed");
686        assert!(result.code.contains("OPENQASM 2.0"));
687        assert!(result.code.contains("h q[0]"));
688        assert!(result.code.contains("cx q[0],q[1]"));
689        assert!(result.code.contains("measure q[0] -> c[0]"));
690    }
691
692    #[test]
693    fn test_gate_fusion_optimization() {
694        let config = CrossCompilerConfig {
695            optimization_level: OptimizationLevel::O2,
696            enable_gate_fusion: true,
697            ..Default::default()
698        };
699        let compiler = CrossCompiler::new(config);
700
701        let gates = vec![
702            IRInstruction::SingleQubitGate {
703                gate_type: SingleQubitGateType::Rz,
704                target: 0,
705                parameters: vec![0.5],
706            },
707            IRInstruction::SingleQubitGate {
708                gate_type: SingleQubitGateType::Rz,
709                target: 0,
710                parameters: vec![0.3],
711            },
712        ];
713
714        let ir = compiler.create_ir_from_gates(1, gates);
715        let result = compiler.compile(ir);
716
717        assert!(result.is_ok());
718        let result = result.expect("Compilation failed");
719
720        // Should have fused the two Rz gates into one
721        assert_eq!(result.statistics.optimized_instruction_count, 1);
722    }
723
724    #[test]
725    fn test_identity_gate_removal() {
726        let config = CrossCompilerConfig {
727            optimization_level: OptimizationLevel::O2,
728            ..Default::default()
729        };
730        let compiler = CrossCompiler::new(config);
731
732        let gates = vec![
733            IRInstruction::SingleQubitGate {
734                gate_type: SingleQubitGateType::Hadamard,
735                target: 0,
736                parameters: vec![],
737            },
738            IRInstruction::SingleQubitGate {
739                gate_type: SingleQubitGateType::Rz,
740                target: 0,
741                parameters: vec![0.0], // Identity (no rotation)
742            },
743            IRInstruction::Measure {
744                qubit: 0,
745                classical_bit: 0,
746            },
747        ];
748
749        let ir = compiler.create_ir_from_gates(1, gates);
750        let result = compiler.compile(ir);
751
752        assert!(result.is_ok());
753        let result = result.expect("Compilation failed");
754
755        // Should have removed the identity Rz gate
756        assert_eq!(result.statistics.optimized_instruction_count, 2);
757    }
758
759    #[test]
760    fn test_compilation_statistics() {
761        let config = CrossCompilerConfig {
762            optimization_level: OptimizationLevel::O2,
763            ..Default::default()
764        };
765        let compiler = CrossCompiler::new(config);
766
767        let gates = vec![
768            IRInstruction::SingleQubitGate {
769                gate_type: SingleQubitGateType::Hadamard,
770                target: 0,
771                parameters: vec![],
772            },
773            IRInstruction::SingleQubitGate {
774                gate_type: SingleQubitGateType::Rz,
775                target: 0,
776                parameters: vec![0.0],
777            },
778        ];
779
780        let ir = compiler.create_ir_from_gates(1, gates);
781        let result = compiler.compile(ir);
782
783        assert!(result.is_ok());
784        let result = result.expect("Compilation failed");
785
786        assert_eq!(result.statistics.original_instruction_count, 2);
787        assert!(result.statistics.num_optimization_passes > 0);
788        // Compilation time is u64, always non-negative
789    }
790
791    #[test]
792    fn test_different_backends() {
793        let backends = vec![
794            TargetBackend::IBMQuantum,
795            TargetBackend::AWSBraket,
796            TargetBackend::AzureQuantum,
797        ];
798
799        for backend in backends {
800            let config = CrossCompilerConfig {
801                target: backend,
802                optimization_level: OptimizationLevel::O0,
803                ..Default::default()
804            };
805            let compiler = CrossCompiler::new(config);
806
807            let gates = vec![IRInstruction::SingleQubitGate {
808                gate_type: SingleQubitGateType::Hadamard,
809                target: 0,
810                parameters: vec![],
811            }];
812
813            let ir = compiler.create_ir_from_gates(1, gates);
814            let result = compiler.compile(ir);
815
816            assert!(result.is_ok());
817        }
818    }
819
820    #[test]
821    fn test_barrier_instruction() {
822        let compiler = CrossCompiler::default();
823
824        let gates = vec![
825            IRInstruction::SingleQubitGate {
826                gate_type: SingleQubitGateType::Hadamard,
827                target: 0,
828                parameters: vec![],
829            },
830            IRInstruction::Barrier { qubits: vec![0, 1] },
831            IRInstruction::TwoQubitGate {
832                gate_type: TwoQubitGateType::CNOT,
833                control: 0,
834                target: 1,
835                parameters: vec![],
836            },
837        ];
838
839        let ir = compiler.create_ir_from_gates(2, gates);
840        let result = compiler.compile(ir);
841
842        assert!(result.is_ok());
843        let result = result.expect("Compilation failed");
844        assert!(result.code.contains("barrier"));
845    }
846
847    #[test]
848    fn test_optimization_levels() {
849        let levels = vec![
850            OptimizationLevel::O0,
851            OptimizationLevel::O1,
852            OptimizationLevel::O2,
853            OptimizationLevel::O3,
854        ];
855
856        for level in levels {
857            let config = CrossCompilerConfig {
858                optimization_level: level,
859                ..Default::default()
860            };
861            let compiler = CrossCompiler::new(config);
862
863            let gates = vec![IRInstruction::SingleQubitGate {
864                gate_type: SingleQubitGateType::Hadamard,
865                target: 0,
866                parameters: vec![],
867            }];
868
869            let ir = compiler.create_ir_from_gates(1, gates);
870            let result = compiler.compile(ir);
871
872            assert!(result.is_ok());
873        }
874    }
875}