quantrs2_sim/jit_compilation/
mod.rs

1//! Just-in-time compilation for frequently used gate sequences.
2//!
3//! This module provides advanced JIT compilation capabilities for quantum circuit
4//! simulation, enabling compilation of frequently used gate sequences into optimized
5//! machine code for dramatic performance improvements.
6
7mod analyzer;
8mod compiler;
9mod profiler;
10mod simulator;
11mod types;
12
13// Re-export all public types
14pub use analyzer::*;
15pub use compiler::*;
16pub use profiler::*;
17pub use simulator::*;
18pub use types::*;
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23    use crate::circuit_interfaces::{InterfaceGate, InterfaceGateType};
24    use scirs2_core::Complex64;
25
26    #[test]
27    fn test_jit_compiler_creation() {
28        let config = JITConfig::default();
29        let compiler = JITCompiler::new(config);
30        let stats = compiler.get_stats();
31        assert_eq!(stats.total_compilations, 0);
32    }
33
34    #[test]
35    fn test_pattern_extraction() {
36        let config = JITConfig::default();
37        let _compiler = JITCompiler::new(config);
38
39        let gates = vec![
40            InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]),
41            InterfaceGate::new(InterfaceGateType::PauliX, vec![1]),
42        ];
43
44        let pattern =
45            JITCompiler::extract_pattern(&gates).expect("Pattern extraction should succeed");
46        assert_eq!(pattern.gate_types.len(), 2);
47        assert_eq!(pattern.frequency, 1);
48    }
49
50    #[test]
51    fn test_gate_matrix_generation() {
52        let config = JITConfig::default();
53        let _compiler = JITCompiler::new(config);
54
55        let pauli_x = JITCompiler::get_gate_matrix(&InterfaceGateType::PauliX)
56            .expect("PauliX matrix generation should succeed");
57        assert_eq!(pauli_x.shape(), [2, 2]);
58        assert_eq!(pauli_x[(0, 1)], Complex64::new(1.0, 0.0));
59        assert_eq!(pauli_x[(1, 0)], Complex64::new(1.0, 0.0));
60    }
61
62    #[test]
63    fn test_pattern_analysis() {
64        let mut analyzer = PatternAnalyzer::new();
65
66        let gates = vec![
67            InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]),
68            InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]),
69        ];
70
71        let result = analyzer.analyze_pattern(&gates);
72        assert_eq!(result.frequency, 1);
73        assert!(result
74            .optimization_suggestions
75            .contains(&OptimizationSuggestion::GateFusion));
76    }
77
78    #[test]
79    fn test_complexity_analysis() {
80        let analyzer = ComplexityAnalyzer::new();
81
82        let gates = vec![
83            InterfaceGate::new(InterfaceGateType::PauliX, vec![0]),
84            InterfaceGate::new(InterfaceGateType::CNOT, vec![0, 1]),
85        ];
86
87        let complexity = analyzer.analyze_complexity(&gates);
88        assert_eq!(complexity.gate_count, 2);
89        assert!(complexity.computational_cost > 0.0);
90    }
91
92    #[test]
93    fn test_jit_simulator_creation() {
94        let config = JITConfig::default();
95        let simulator = JITQuantumSimulator::new(2, config);
96
97        assert_eq!(simulator.num_qubits, 2);
98        assert_eq!(simulator.get_state().len(), 4);
99        assert_eq!(simulator.get_state()[0], Complex64::new(1.0, 0.0));
100    }
101
102    #[test]
103    fn test_gate_application() {
104        let config = JITConfig::default();
105        let mut simulator = JITQuantumSimulator::new(1, config);
106
107        let gate = InterfaceGate::new(InterfaceGateType::PauliX, vec![0]);
108
109        simulator
110            .apply_gate_interpreted(&gate)
111            .expect("PauliX gate application should succeed");
112
113        // After Pauli-X, state should be |1⟩
114        assert_eq!(simulator.get_state()[0], Complex64::new(0.0, 0.0));
115        assert_eq!(simulator.get_state()[1], Complex64::new(1.0, 0.0));
116    }
117
118    #[test]
119    fn test_hadamard_gate() {
120        let config = JITConfig::default();
121        let mut simulator = JITQuantumSimulator::new(1, config);
122
123        let gate = InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]);
124
125        simulator
126            .apply_gate_interpreted(&gate)
127            .expect("Hadamard gate application should succeed");
128
129        // After Hadamard, state should be (|0⟩ + |1⟩)/√2
130        let sqrt2_inv = 1.0 / (2.0_f64).sqrt();
131        assert!((simulator.get_state()[0].re - sqrt2_inv).abs() < 1e-10);
132        assert!((simulator.get_state()[1].re - sqrt2_inv).abs() < 1e-10);
133    }
134
135    #[test]
136    fn test_cnot_gate() {
137        let config = JITConfig::default();
138        let mut simulator = JITQuantumSimulator::new(2, config);
139
140        // Prepare |10⟩ state by applying X gate to qubit 1
141        // In little-endian convention: |10⟩ means qubit 1 is |1⟩, qubit 0 is |0⟩
142        let x_gate = InterfaceGate::new(InterfaceGateType::PauliX, vec![1]);
143        simulator
144            .apply_gate_interpreted(&x_gate)
145            .expect("PauliX gate application should succeed");
146
147        // Verify we have |10⟩ state (index 2 in little-endian)
148        assert!((simulator.get_state()[0].norm() - 0.0).abs() < 1e-10);
149        assert!((simulator.get_state()[1].norm() - 0.0).abs() < 1e-10);
150        assert!((simulator.get_state()[2].norm() - 1.0).abs() < 1e-10);
151        assert!((simulator.get_state()[3].norm() - 0.0).abs() < 1e-10);
152
153        let gate = InterfaceGate::new(InterfaceGateType::CNOT, vec![1, 0]);
154
155        simulator
156            .apply_gate_interpreted(&gate)
157            .expect("CNOT gate application should succeed");
158
159        // After CNOT with control=1, target=0: |10⟩ → |11⟩ (index 3)
160        assert!((simulator.get_state()[0].norm() - 0.0).abs() < 1e-10);
161        assert!((simulator.get_state()[1].norm() - 0.0).abs() < 1e-10);
162        assert!((simulator.get_state()[2].norm() - 0.0).abs() < 1e-10);
163        assert!((simulator.get_state()[3].norm() - 1.0).abs() < 1e-10);
164    }
165
166    #[test]
167    fn test_rotation_gates() {
168        let config = JITConfig::default();
169        let mut simulator = JITQuantumSimulator::new(1, config);
170
171        // Test RX gate
172        let gate_rx = InterfaceGate::new(InterfaceGateType::RX(std::f64::consts::PI), vec![0]);
173
174        simulator
175            .apply_gate_interpreted(&gate_rx)
176            .expect("RX gate application should succeed");
177
178        // RX(π) should be equivalent to Pauli-X up to global phase
179        assert!((simulator.get_state()[0].norm() - 0.0).abs() < 1e-10);
180        assert!((simulator.get_state()[1].norm() - 1.0).abs() < 1e-10);
181    }
182
183    #[test]
184    fn test_gate_sequence_compilation() {
185        let mut config = JITConfig::default();
186        config.compilation_threshold = 1; // Compile after 1 usage
187
188        let mut simulator = JITQuantumSimulator::new(2, config);
189
190        let sequence = vec![
191            InterfaceGate::new(InterfaceGateType::Hadamard, vec![0]),
192            InterfaceGate::new(InterfaceGateType::PauliX, vec![1]),
193        ];
194
195        // First execution should be interpreted
196        let _time1 = simulator
197            .apply_gate_sequence(&sequence)
198            .expect("First gate sequence should succeed");
199        assert_eq!(simulator.get_stats().interpreted_executions, 1);
200
201        // Second execution might be compiled
202        let _time2 = simulator
203            .apply_gate_sequence(&sequence)
204            .expect("Second gate sequence should succeed");
205        assert!(simulator.get_compiler_stats().patterns_analyzed > 0);
206    }
207
208    #[test]
209    fn test_optimization_suggestions() {
210        let mut analyzer = PatternAnalyzer::new();
211
212        let gates = vec![
213            InterfaceGate::new(InterfaceGateType::RX(std::f64::consts::PI / 4.0), vec![0]),
214            InterfaceGate::new(InterfaceGateType::RY(std::f64::consts::PI / 2.0), vec![0]),
215        ];
216
217        let result = analyzer.analyze_pattern(&gates);
218        assert!(result
219            .optimization_suggestions
220            .contains(&OptimizationSuggestion::GateFusion));
221    }
222
223    #[test]
224    fn test_runtime_profiler() {
225        use std::time::Duration;
226
227        let mut profiler = RuntimeProfiler::new();
228
229        profiler.record_execution_time(Duration::from_millis(100));
230        profiler.record_execution_time(Duration::from_millis(200));
231        profiler.record_memory_usage(1024);
232        profiler.record_memory_usage(2048);
233
234        let stats = profiler.get_stats();
235        assert_eq!(stats.sample_count, 2);
236        assert_eq!(stats.average_memory_usage, 1536);
237        assert_eq!(stats.peak_memory_usage, 2048);
238    }
239
240    #[test]
241    fn test_constant_folding_optimization() {
242        let config = JITConfig::default();
243        let _compiler = JITCompiler::new(config);
244
245        let mut instructions = vec![
246            BytecodeInstruction::ApplySingleQubit {
247                gate_type: InterfaceGateType::RX(0.0), // Zero rotation
248                target: 0,
249            },
250            BytecodeInstruction::ApplySingleQubit {
251                gate_type: InterfaceGateType::RY(std::f64::consts::PI),
252                target: 0,
253            },
254        ];
255
256        JITCompiler::apply_constant_folding(&mut instructions)
257            .expect("Constant folding should succeed");
258
259        // Check that zero rotation was folded to identity
260        if let BytecodeInstruction::ApplySingleQubit { gate_type, .. } = &instructions[0] {
261            assert_eq!(*gate_type, InterfaceGateType::Identity);
262        }
263    }
264
265    #[test]
266    fn test_dead_code_elimination() {
267        let config = JITConfig::default();
268        let _compiler = JITCompiler::new(config);
269
270        let mut instructions = vec![
271            BytecodeInstruction::ApplySingleQubit {
272                gate_type: InterfaceGateType::Identity,
273                target: 0,
274            },
275            BytecodeInstruction::ApplySingleQubit {
276                gate_type: InterfaceGateType::RY(std::f64::consts::PI),
277                target: 0,
278            },
279        ];
280
281        let original_len = instructions.len();
282        JITCompiler::apply_dead_code_elimination(&mut instructions)
283            .expect("Dead code elimination should succeed");
284
285        assert!(instructions.len() <= original_len);
286    }
287
288    #[test]
289    fn test_benchmark_jit_compilation() {
290        let results =
291            benchmark_jit_compilation().expect("JIT benchmark should complete successfully");
292
293        assert!(results.total_sequences > 0);
294        assert!(results.compilation_success_rate >= 0.0);
295        assert!(results.compilation_success_rate <= 1.0);
296        assert!(results.speedup_factor >= 0.0);
297    }
298}