quantrs2_sim/
statevector.rs

1use scirs2_core::Complex64;
2use scirs2_core::parallel_ops::*;
3use std::sync::Mutex;
4
5use quantrs2_circuit::builder::{Circuit, Simulator};
6use quantrs2_core::{
7    error::{QuantRS2Error, QuantRS2Result},
8    gate::{multi, single, GateOp},
9    qubit::QubitId,
10    register::Register,
11};
12
13use crate::diagnostics::SimulationDiagnostics;
14use crate::optimized_simd;
15use crate::scirs2_integration::{SciRS2Backend, SciRS2Matrix, SciRS2Vector, BLAS};
16use crate::utils::{flip_bit, gate_vec_to_array2};
17
18/// A state vector simulator for quantum circuits
19///
20/// This simulator implements the state vector approach, where the full quantum
21/// state is represented as a complex vector of dimension 2^N for N qubits.
22#[derive(Debug)]
23pub struct StateVectorSimulator {
24    /// Use parallel execution
25    pub parallel: bool,
26
27    /// Basic noise model (if any)
28    pub noise_model: Option<crate::noise::NoiseModel>,
29
30    /// Advanced noise model (if any)
31    pub advanced_noise_model: Option<crate::noise_advanced::AdvancedNoiseModel>,
32
33    /// Optimized buffer pool for memory reuse (thread-safe)
34    buffer_pool: Mutex<BufferPool>,
35
36    /// Enable SIMD optimizations for gate operations
37    pub use_simd: bool,
38
39    /// Enable gate fusion optimization
40    pub use_gate_fusion: bool,
41
42    /// Diagnostics system for monitoring and error handling
43    pub diagnostics: Option<SimulationDiagnostics>,
44
45    /// SciRS2 backend for optimized linear algebra operations
46    scirs2_backend: SciRS2Backend,
47}
48
49impl Clone for StateVectorSimulator {
50    fn clone(&self) -> Self {
51        Self {
52            parallel: self.parallel,
53            noise_model: self.noise_model.clone(),
54            advanced_noise_model: self.advanced_noise_model.clone(),
55            buffer_pool: Mutex::new(BufferPool::new(4, 1024)), // Create new buffer pool
56            use_simd: self.use_simd,
57            use_gate_fusion: self.use_gate_fusion,
58            diagnostics: self
59                .diagnostics
60                .as_ref()
61                .map(|_| SimulationDiagnostics::new()),
62            scirs2_backend: SciRS2Backend::new(),
63        }
64    }
65}
66
67/// Memory pool for efficient state vector operations
68#[derive(Debug, Clone)]
69pub struct BufferPool {
70    /// Pre-allocated working buffers
71    working_buffers: std::collections::VecDeque<Vec<Complex64>>,
72    /// Maximum number of cached buffers
73    max_buffers: usize,
74    /// Target buffer size for efficient reuse
75    target_size: usize,
76}
77
78impl BufferPool {
79    /// Create new buffer pool
80    pub fn new(max_buffers: usize, target_size: usize) -> Self {
81        Self {
82            working_buffers: std::collections::VecDeque::with_capacity(max_buffers),
83            max_buffers,
84            target_size,
85        }
86    }
87
88    /// Get a buffer from pool or allocate new one
89    pub fn get_buffer(&mut self, size: usize) -> Vec<Complex64> {
90        // Try to reuse existing buffer
91        if let Some(mut buffer) = self.working_buffers.pop_front() {
92            if buffer.capacity() >= size {
93                buffer.clear();
94                buffer.resize(size, Complex64::new(0.0, 0.0));
95                return buffer;
96            }
97        }
98
99        // Allocate new buffer with extra capacity for growth
100        let capacity = size.max(self.target_size);
101        let mut buffer = Vec::with_capacity(capacity);
102        buffer.resize(size, Complex64::new(0.0, 0.0));
103        buffer
104    }
105
106    /// Return buffer to pool
107    pub fn return_buffer(&mut self, buffer: Vec<Complex64>) {
108        if self.working_buffers.len() < self.max_buffers
109            && buffer.capacity() >= self.target_size / 2
110        {
111            self.working_buffers.push_back(buffer);
112        }
113        // Otherwise let buffer be dropped and deallocated
114    }
115
116    /// Clear all cached buffers
117    pub fn clear(&mut self) {
118        self.working_buffers.clear();
119    }
120}
121
122impl StateVectorSimulator {
123    /// Create a new state vector simulator with default settings
124    pub fn new() -> Self {
125        Self {
126            parallel: true,
127            noise_model: None,
128            advanced_noise_model: None,
129            buffer_pool: Mutex::new(BufferPool::new(4, 1024)), // Default: 4 buffers, 1K size target
130            use_simd: true,
131            use_gate_fusion: true,
132            diagnostics: None,
133            scirs2_backend: SciRS2Backend::new(),
134        }
135    }
136
137    /// Create a new state vector simulator with parallel execution disabled
138    pub fn sequential() -> Self {
139        Self {
140            parallel: false,
141            noise_model: None,
142            advanced_noise_model: None,
143            buffer_pool: Mutex::new(BufferPool::new(2, 512)), // Smaller pool for sequential
144            use_simd: true,
145            use_gate_fusion: true,
146            diagnostics: None,
147            scirs2_backend: SciRS2Backend::new(),
148        }
149    }
150
151    /// Create a new state vector simulator with a basic noise model
152    pub fn with_noise(noise_model: crate::noise::NoiseModel) -> Self {
153        Self {
154            parallel: true,
155            noise_model: Some(noise_model),
156            advanced_noise_model: None,
157            buffer_pool: Mutex::new(BufferPool::new(4, 1024)),
158            use_simd: true,
159            use_gate_fusion: true,
160            diagnostics: None,
161            scirs2_backend: SciRS2Backend::new(),
162        }
163    }
164
165    /// Create a new state vector simulator with an advanced noise model
166    pub fn with_advanced_noise(
167        advanced_noise_model: crate::noise_advanced::AdvancedNoiseModel,
168    ) -> Self {
169        Self {
170            parallel: true,
171            noise_model: None,
172            advanced_noise_model: Some(advanced_noise_model),
173            buffer_pool: Mutex::new(BufferPool::new(4, 1024)),
174            use_simd: true,
175            use_gate_fusion: true,
176            diagnostics: None,
177            scirs2_backend: SciRS2Backend::new(),
178        }
179    }
180
181    /// Create simulator with custom buffer pool configuration
182    pub fn with_buffer_pool(parallel: bool, max_buffers: usize, target_size: usize) -> Self {
183        Self {
184            parallel,
185            noise_model: None,
186            advanced_noise_model: None,
187            buffer_pool: Mutex::new(BufferPool::new(max_buffers, target_size)),
188            use_simd: true,
189            use_gate_fusion: true,
190            diagnostics: None,
191            scirs2_backend: SciRS2Backend::new(),
192        }
193    }
194
195    /// Set the basic noise model
196    pub fn set_noise_model(&mut self, noise_model: crate::noise::NoiseModel) -> &mut Self {
197        self.noise_model = Some(noise_model);
198        self.advanced_noise_model = None; // Remove advanced model if it exists
199        self
200    }
201
202    /// Set the advanced noise model
203    pub fn set_advanced_noise_model(
204        &mut self,
205        advanced_noise_model: crate::noise_advanced::AdvancedNoiseModel,
206    ) -> &mut Self {
207        self.advanced_noise_model = Some(advanced_noise_model);
208        self.noise_model = None; // Remove basic model if it exists
209        self
210    }
211
212    /// Remove all noise models
213    pub fn remove_noise_model(&mut self) -> &mut Self {
214        self.noise_model = None;
215        self.advanced_noise_model = None;
216        self
217    }
218
219    /// Enable or disable SIMD optimizations
220    pub fn set_simd_enabled(&mut self, enabled: bool) -> &mut Self {
221        self.use_simd = enabled;
222        self
223    }
224
225    /// Enable or disable gate fusion optimization
226    pub fn set_gate_fusion_enabled(&mut self, enabled: bool) -> &mut Self {
227        self.use_gate_fusion = enabled;
228        self
229    }
230
231    /// Get access to buffer pool for testing purposes
232    pub fn get_buffer_pool(&self) -> &Mutex<BufferPool> {
233        &self.buffer_pool
234    }
235
236    /// Enable diagnostics and monitoring
237    pub fn enable_diagnostics(&mut self) -> &mut Self {
238        self.diagnostics = Some(SimulationDiagnostics::new());
239        self
240    }
241
242    /// Disable diagnostics and monitoring
243    pub fn disable_diagnostics(&mut self) -> &mut Self {
244        self.diagnostics = None;
245        self
246    }
247
248    /// Get diagnostics report if diagnostics are enabled
249    pub fn get_diagnostics_report(&self) -> Option<crate::diagnostics::DiagnosticReport> {
250        self.diagnostics.as_ref().map(|d| d.generate_report())
251    }
252
253    /// Create a high-performance configuration
254    pub fn high_performance() -> Self {
255        Self {
256            parallel: true,
257            noise_model: None,
258            advanced_noise_model: None,
259            buffer_pool: Mutex::new(BufferPool::new(8, 2048)), // Larger pool for high performance
260            use_simd: true,
261            use_gate_fusion: true,
262            diagnostics: Some(SimulationDiagnostics::new()),
263            scirs2_backend: SciRS2Backend::new(),
264        }
265    }
266
267    /// Apply a dense matrix-vector multiplication using SciRS2 when available
268    #[cfg(feature = "advanced_math")]
269    fn apply_dense_matrix_vector(
270        &mut self,
271        matrix: &[Complex64],
272        vector: &[Complex64],
273        result: &mut [Complex64],
274    ) -> QuantRS2Result<()> {
275        if self.scirs2_backend.is_available() && matrix.len() >= 64 && vector.len() >= 8 {
276            // Use SciRS2 for larger operations where the overhead is worthwhile
277            use scirs2_core::ndarray::{Array1, Array2};
278
279            let rows = result.len();
280            let cols = vector.len();
281
282            if matrix.len() != rows * cols {
283                return Err(QuantRS2Error::InvalidInput(
284                    "Dimension mismatch in matrix application".to_string(),
285                ));
286            }
287
288            // Convert to ndarray format
289            let matrix_2d =
290                Array2::from_shape_vec((rows, cols), matrix.to_vec()).map_err(|_| {
291                    QuantRS2Error::InvalidInput("Matrix shape conversion failed".to_string())
292                })?;
293            let vector_1d = Array1::from_vec(vector.to_vec());
294
295            // Convert to SciRS2 format
296            let scirs2_matrix = SciRS2Matrix::from_array2(matrix_2d);
297            let scirs2_vector = SciRS2Vector::from_array1(vector_1d);
298
299            // Perform optimized matrix-vector multiplication
300            let scirs2_result = self
301                .scirs2_backend
302                .matrix_vector_multiply(&scirs2_matrix, &scirs2_vector)
303                .map_err(|_| {
304                    QuantRS2Error::ComputationError(
305                        "Matrix-vector multiplication failed".to_string(),
306                    )
307                })?;
308
309            // Convert back to slice
310            let result_array = scirs2_result.to_array1().map_err(|_| {
311                QuantRS2Error::ComputationError("Result conversion to array failed".to_string())
312            })?;
313            result.copy_from_slice(result_array.as_slice().unwrap());
314
315            Ok(())
316        } else {
317            // Fallback to manual implementation for smaller operations
318            for i in 0..result.len() {
319                result[i] = Complex64::new(0.0, 0.0);
320                for j in 0..vector.len() {
321                    result[i] += matrix[i * vector.len() + j] * vector[j];
322                }
323            }
324            Ok(())
325        }
326    }
327
328    /// Fallback dense matrix-vector multiplication for when SciRS2 is not available
329    #[cfg(not(feature = "advanced_math"))]
330    fn apply_dense_matrix_vector(
331        &mut self,
332        matrix: &[Complex64],
333        vector: &[Complex64],
334        result: &mut [Complex64],
335    ) -> QuantRS2Result<()> {
336        // Manual implementation
337        for i in 0..result.len() {
338            result[i] = Complex64::new(0.0, 0.0);
339            for j in 0..vector.len() {
340                result[i] += matrix[i * vector.len() + j] * vector[j];
341            }
342        }
343        Ok(())
344    }
345
346    /// Apply a single-qubit gate to a state vector
347    fn apply_single_qubit_gate<const N: usize>(
348        &self,
349        state: &mut [Complex64],
350        gate_matrix: &[Complex64],
351        target: QubitId,
352    ) -> QuantRS2Result<()> {
353        let target_idx = target.id() as usize;
354        if target_idx >= N {
355            return Err(QuantRS2Error::InvalidQubitId(target.id()));
356        }
357
358        // Use SIMD optimization if enabled and beneficial
359        if self.use_simd && state.len() >= 8 {
360            return self.apply_single_qubit_gate_simd::<N>(state, gate_matrix, target_idx);
361        }
362
363        // Convert the gate matrix to flat representation for faster access
364        // Gate matrix: [m00, m01, m10, m11]
365        let m00 = gate_matrix[0];
366        let m01 = gate_matrix[1];
367        let m10 = gate_matrix[2];
368        let m11 = gate_matrix[3];
369
370        // Apply the gate to each amplitude
371        if self.parallel {
372            // Get buffer from pool for temporary storage
373            let mut state_copy = self.buffer_pool.lock().unwrap().get_buffer(state.len());
374            state_copy.copy_from_slice(state);
375
376            state.par_iter_mut().enumerate().for_each(|(idx, amp)| {
377                let bit_val = (idx >> target_idx) & 1;
378                let paired_idx = if bit_val == 0 {
379                    idx | (1 << target_idx)
380                } else {
381                    idx & !(1 << target_idx)
382                };
383
384                let idx0 = if bit_val == 0 { idx } else { paired_idx };
385                let idx1 = if bit_val == 0 { paired_idx } else { idx };
386
387                let val0 = state_copy[idx0];
388                let val1 = state_copy[idx1];
389
390                // Use direct matrix element access for better performance
391                *amp = if idx == idx0 {
392                    m00 * val0 + m01 * val1
393                } else {
394                    m10 * val0 + m11 * val1
395                };
396            });
397
398            // Return buffer to pool
399            self.buffer_pool.lock().unwrap().return_buffer(state_copy);
400        } else {
401            // Sequential implementation using buffer pool
402            let dim = state.len();
403            let mut new_state = self.buffer_pool.lock().unwrap().get_buffer(dim);
404
405            for i in 0..dim {
406                let bit_val = (i >> target_idx) & 1;
407                let paired_idx = flip_bit(i, target_idx);
408
409                if bit_val == 0 {
410                    new_state[i] = m00 * state[i] + m01 * state[paired_idx];
411                    new_state[paired_idx] = m10 * state[i] + m11 * state[paired_idx];
412                }
413            }
414
415            state.copy_from_slice(&new_state);
416            // Return buffer to pool
417            self.buffer_pool.lock().unwrap().return_buffer(new_state);
418        }
419
420        Ok(())
421    }
422
423    /// Apply a single-qubit gate using SIMD optimization
424    fn apply_single_qubit_gate_simd<const N: usize>(
425        &self,
426        state: &mut [Complex64],
427        gate_matrix: &[Complex64],
428        target_idx: usize,
429    ) -> QuantRS2Result<()> {
430        let dim = state.len();
431        let pairs_per_block = 1 << target_idx;
432        let total_pairs = dim / 2;
433
434        // Get buffers for SIMD processing
435        let mut pool = self.buffer_pool.lock().unwrap();
436        let mut in_amps0 = pool.get_buffer(total_pairs);
437        let mut in_amps1 = pool.get_buffer(total_pairs);
438        let mut out_amps0 = pool.get_buffer(total_pairs);
439        let mut out_amps1 = pool.get_buffer(total_pairs);
440
441        // Collect amplitudes for target bit = 0 and target bit = 1
442        let mut pair_idx = 0;
443        for block in 0..(dim / (pairs_per_block * 2)) {
444            let block_start = block * pairs_per_block * 2;
445
446            for offset in 0..pairs_per_block {
447                let idx0 = block_start + offset;
448                let idx1 = block_start + pairs_per_block + offset;
449
450                in_amps0[pair_idx] = state[idx0];
451                in_amps1[pair_idx] = state[idx1];
452                pair_idx += 1;
453            }
454        }
455
456        // Convert gate matrix to required format for SIMD
457        let gate_matrix_array: [Complex64; 4] = [
458            gate_matrix[0],
459            gate_matrix[1],
460            gate_matrix[2],
461            gate_matrix[3],
462        ];
463
464        // Apply SIMD gate operation
465        optimized_simd::apply_single_qubit_gate_optimized(
466            &gate_matrix_array,
467            &in_amps0,
468            &in_amps1,
469            &mut out_amps0,
470            &mut out_amps1,
471        );
472
473        // Write results back to state vector
474        pair_idx = 0;
475        for block in 0..(dim / (pairs_per_block * 2)) {
476            let block_start = block * pairs_per_block * 2;
477
478            for offset in 0..pairs_per_block {
479                let idx0 = block_start + offset;
480                let idx1 = block_start + pairs_per_block + offset;
481
482                state[idx0] = out_amps0[pair_idx];
483                state[idx1] = out_amps1[pair_idx];
484                pair_idx += 1;
485            }
486        }
487
488        // Return buffers to pool
489        pool.return_buffer(in_amps0);
490        pool.return_buffer(in_amps1);
491        pool.return_buffer(out_amps0);
492        pool.return_buffer(out_amps1);
493
494        Ok(())
495    }
496
497    /// Apply a two-qubit gate to a state vector
498    fn apply_two_qubit_gate<const N: usize>(
499        &self,
500        state: &mut [Complex64],
501        gate_matrix: &[Complex64],
502        control: QubitId,
503        target: QubitId,
504    ) -> QuantRS2Result<()> {
505        let control_idx = control.id() as usize;
506        let target_idx = target.id() as usize;
507
508        if control_idx >= N || target_idx >= N {
509            return Err(QuantRS2Error::InvalidQubitId(if control_idx >= N {
510                control.id()
511            } else {
512                target.id()
513            }));
514        }
515
516        if control_idx == target_idx {
517            return Err(QuantRS2Error::CircuitValidationFailed(
518                "Control and target qubits must be different".into(),
519            ));
520        }
521
522        // Pre-extract matrix elements for faster access (16 elements total)
523        let m = gate_matrix; // Direct slice access is faster than ndarray indexing
524
525        // Apply the gate to each amplitude
526        if self.parallel {
527            // Get buffer from pool for temporary storage
528            let mut state_copy = self.buffer_pool.lock().unwrap().get_buffer(state.len());
529            state_copy.copy_from_slice(state);
530
531            state.par_iter_mut().enumerate().for_each(|(idx, amp)| {
532                let idx00 = idx & !(1 << control_idx) & !(1 << target_idx);
533                let idx01 = idx00 | (1 << target_idx);
534                let idx10 = idx00 | (1 << control_idx);
535                let idx11 = idx00 | (1 << control_idx) | (1 << target_idx);
536
537                let val00 = state_copy[idx00];
538                let val01 = state_copy[idx01];
539                let val10 = state_copy[idx10];
540                let val11 = state_copy[idx11];
541
542                // Use direct matrix access for better performance
543                *amp = match idx {
544                    i if i == idx00 => m[0] * val00 + m[1] * val01 + m[2] * val10 + m[3] * val11,
545                    i if i == idx01 => m[4] * val00 + m[5] * val01 + m[6] * val10 + m[7] * val11,
546                    i if i == idx10 => m[8] * val00 + m[9] * val01 + m[10] * val10 + m[11] * val11,
547                    i if i == idx11 => {
548                        m[12] * val00 + m[13] * val01 + m[14] * val10 + m[15] * val11
549                    }
550                    _ => unreachable!(),
551                };
552            });
553
554            // Return buffer to pool
555            self.buffer_pool.lock().unwrap().return_buffer(state_copy);
556        } else {
557            // Sequential implementation using buffer pool
558            let dim = state.len();
559            let mut new_state = self.buffer_pool.lock().unwrap().get_buffer(dim);
560
561            #[allow(clippy::needless_range_loop)]
562            for i in 0..dim {
563                let control_bit = (i >> control_idx) & 1;
564                let target_bit = (i >> target_idx) & 1;
565
566                // Calculate the four basis states in the 2-qubit subspace
567                let i00 = i & !(1 << control_idx) & !(1 << target_idx);
568                let i01 = i00 | (1 << target_idx);
569                let i10 = i00 | (1 << control_idx);
570                let i11 = i10 | (1 << target_idx);
571
572                let basis_idx = (control_bit << 1) | target_bit;
573
574                // Calculate the new amplitude for this state using direct access
575                let row_offset = basis_idx * 4;
576                new_state[i] = m[row_offset] * state[i00]
577                    + m[row_offset + 1] * state[i01]
578                    + m[row_offset + 2] * state[i10]
579                    + m[row_offset + 3] * state[i11];
580            }
581
582            state.copy_from_slice(&new_state);
583            // Return buffer to pool
584            self.buffer_pool.lock().unwrap().return_buffer(new_state);
585        }
586
587        Ok(())
588    }
589
590    /// Apply CNOT gate efficiently (special case)
591    fn apply_cnot<const N: usize>(
592        &self,
593        state: &mut [Complex64],
594        control: QubitId,
595        target: QubitId,
596    ) -> QuantRS2Result<()> {
597        let control_idx = control.id() as usize;
598        let target_idx = target.id() as usize;
599
600        if control_idx >= N || target_idx >= N {
601            return Err(QuantRS2Error::InvalidQubitId(if control_idx >= N {
602                control.id()
603            } else {
604                target.id()
605            }));
606        }
607
608        if control_idx == target_idx {
609            return Err(QuantRS2Error::CircuitValidationFailed(
610                "Control and target qubits must be different".into(),
611            ));
612        }
613
614        // Apply the CNOT gate - only swap amplitudes where control is 1
615        if self.parallel {
616            let mut state_copy = self.buffer_pool.lock().unwrap().get_buffer(state.len());
617            state_copy.copy_from_slice(state);
618
619            state.par_iter_mut().enumerate().for_each(|(i, amp)| {
620                if (i >> control_idx) & 1 == 1 {
621                    let flipped = flip_bit(i, target_idx);
622                    *amp = state_copy[flipped];
623                }
624            });
625
626            self.buffer_pool.lock().unwrap().return_buffer(state_copy);
627        } else {
628            let dim = state.len();
629            let mut new_state = self.buffer_pool.lock().unwrap().get_buffer(dim);
630
631            for i in 0..dim {
632                if (i >> control_idx) & 1 == 1 {
633                    let flipped = flip_bit(i, target_idx);
634                    new_state[flipped] = state[i];
635                    new_state[i] = state[flipped];
636                } else {
637                    new_state[i] = state[i];
638                }
639            }
640
641            state.copy_from_slice(&new_state);
642            self.buffer_pool.lock().unwrap().return_buffer(new_state);
643        }
644
645        Ok(())
646    }
647
648    /// Apply SWAP gate efficiently (special case)
649    fn apply_swap<const N: usize>(
650        &self,
651        state: &mut [Complex64],
652        qubit1: QubitId,
653        qubit2: QubitId,
654    ) -> QuantRS2Result<()> {
655        let q1_idx = qubit1.id() as usize;
656        let q2_idx = qubit2.id() as usize;
657
658        if q1_idx >= N || q2_idx >= N {
659            return Err(QuantRS2Error::InvalidQubitId(if q1_idx >= N {
660                qubit1.id()
661            } else {
662                qubit2.id()
663            }));
664        }
665
666        if q1_idx == q2_idx {
667            return Err(QuantRS2Error::CircuitValidationFailed(
668                "Qubits must be different for SWAP gate".into(),
669            ));
670        }
671
672        // Apply the SWAP gate - swap amplitudes where qubits have different values
673        if self.parallel {
674            let mut state_copy = self.buffer_pool.lock().unwrap().get_buffer(state.len());
675            state_copy.copy_from_slice(state);
676
677            state.par_iter_mut().enumerate().for_each(|(i, amp)| {
678                let bit1 = (i >> q1_idx) & 1;
679                let bit2 = (i >> q2_idx) & 1;
680
681                if bit1 != bit2 {
682                    let swapped = flip_bit(flip_bit(i, q1_idx), q2_idx);
683                    *amp = state_copy[swapped];
684                }
685            });
686
687            self.buffer_pool.lock().unwrap().return_buffer(state_copy);
688        } else {
689            let dim = state.len();
690            let mut new_state = self.buffer_pool.lock().unwrap().get_buffer(dim);
691
692            for i in 0..dim {
693                let bit1 = (i >> q1_idx) & 1;
694                let bit2 = (i >> q2_idx) & 1;
695
696                if bit1 != bit2 {
697                    let swapped = flip_bit(flip_bit(i, q1_idx), q2_idx);
698                    new_state[swapped] = state[i];
699                    new_state[i] = state[swapped];
700                } else {
701                    new_state[i] = state[i];
702                }
703            }
704
705            state.copy_from_slice(&new_state);
706            self.buffer_pool.lock().unwrap().return_buffer(new_state);
707        }
708
709        Ok(())
710    }
711}
712
713impl Default for StateVectorSimulator {
714    fn default() -> Self {
715        Self::new()
716    }
717}
718
719impl<const N: usize> Simulator<N> for StateVectorSimulator {
720    fn run(&self, circuit: &Circuit<N>) -> QuantRS2Result<Register<N>> {
721        // Initialize state vector to |0...0⟩
722        let dim = 1 << N;
723        let mut state = vec![Complex64::new(0.0, 0.0); dim];
724        state[0] = Complex64::new(1.0, 0.0);
725
726        // Apply each gate in the circuit
727        for gate in circuit.gates() {
728            match gate.name() {
729                // Single-qubit gates
730                "H" => {
731                    if let Some(g) = gate.as_any().downcast_ref::<single::Hadamard>() {
732                        let matrix = g.matrix()?;
733                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
734                    }
735                }
736                "X" => {
737                    if let Some(g) = gate.as_any().downcast_ref::<single::PauliX>() {
738                        let matrix = g.matrix()?;
739                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
740                    }
741                }
742                "Y" => {
743                    if let Some(g) = gate.as_any().downcast_ref::<single::PauliY>() {
744                        let matrix = g.matrix()?;
745                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
746                    }
747                }
748                "Z" => {
749                    if let Some(g) = gate.as_any().downcast_ref::<single::PauliZ>() {
750                        let matrix = g.matrix()?;
751                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
752                    }
753                }
754                "RX" => {
755                    if let Some(g) = gate.as_any().downcast_ref::<single::RotationX>() {
756                        let matrix = g.matrix()?;
757                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
758                    }
759                }
760                "RY" => {
761                    if let Some(g) = gate.as_any().downcast_ref::<single::RotationY>() {
762                        let matrix = g.matrix()?;
763                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
764                    }
765                }
766                "RZ" => {
767                    if let Some(g) = gate.as_any().downcast_ref::<single::RotationZ>() {
768                        let matrix = g.matrix()?;
769                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
770                    }
771                }
772                "S" => {
773                    if let Some(g) = gate.as_any().downcast_ref::<single::Phase>() {
774                        let matrix = g.matrix()?;
775                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
776                    }
777                }
778                "T" => {
779                    if let Some(g) = gate.as_any().downcast_ref::<single::T>() {
780                        let matrix = g.matrix()?;
781                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
782                    }
783                }
784                "S†" => {
785                    if let Some(g) = gate.as_any().downcast_ref::<single::PhaseDagger>() {
786                        let matrix = g.matrix()?;
787                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
788                    }
789                }
790                "T†" => {
791                    if let Some(g) = gate.as_any().downcast_ref::<single::TDagger>() {
792                        let matrix = g.matrix()?;
793                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
794                    }
795                }
796                "√X" => {
797                    if let Some(g) = gate.as_any().downcast_ref::<single::SqrtX>() {
798                        let matrix = g.matrix()?;
799                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
800                    }
801                }
802                "√X†" => {
803                    if let Some(g) = gate.as_any().downcast_ref::<single::SqrtXDagger>() {
804                        let matrix = g.matrix()?;
805                        self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
806                    }
807                }
808
809                // Two-qubit gates
810                "CNOT" => {
811                    if let Some(g) = gate.as_any().downcast_ref::<multi::CNOT>() {
812                        // Use optimized implementation for CNOT
813                        self.apply_cnot::<N>(&mut state, g.control, g.target)?;
814                    }
815                }
816                "CZ" => {
817                    if let Some(g) = gate.as_any().downcast_ref::<multi::CZ>() {
818                        let matrix = g.matrix()?;
819                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
820                    }
821                }
822                "SWAP" => {
823                    if let Some(g) = gate.as_any().downcast_ref::<multi::SWAP>() {
824                        // Use optimized implementation for SWAP
825                        self.apply_swap::<N>(&mut state, g.qubit1, g.qubit2)?;
826                    }
827                }
828                "CY" => {
829                    if let Some(g) = gate.as_any().downcast_ref::<multi::CY>() {
830                        let matrix = g.matrix()?;
831                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
832                    }
833                }
834                "CH" => {
835                    if let Some(g) = gate.as_any().downcast_ref::<multi::CH>() {
836                        let matrix = g.matrix()?;
837                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
838                    }
839                }
840                "CS" => {
841                    if let Some(g) = gate.as_any().downcast_ref::<multi::CS>() {
842                        let matrix = g.matrix()?;
843                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
844                    }
845                }
846                "CRX" => {
847                    if let Some(g) = gate.as_any().downcast_ref::<multi::CRX>() {
848                        let matrix = g.matrix()?;
849                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
850                    }
851                }
852                "CRY" => {
853                    if let Some(g) = gate.as_any().downcast_ref::<multi::CRY>() {
854                        let matrix = g.matrix()?;
855                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
856                    }
857                }
858                "CRZ" => {
859                    if let Some(g) = gate.as_any().downcast_ref::<multi::CRZ>() {
860                        let matrix = g.matrix()?;
861                        self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
862                    }
863                }
864
865                // Three-qubit gates
866                "Toffoli" => {
867                    if let Some(toffoli_gate) = gate.as_any().downcast_ref::<multi::Toffoli>() {
868                        let control1 = toffoli_gate.control1;
869                        let control2 = toffoli_gate.control2;
870                        let target = toffoli_gate.target;
871                        self.apply_toffoli_to_state::<N>(&mut state, control1, control2, target)?;
872                    }
873                }
874                "Fredkin" => {
875                    if let Some(fredkin_gate) = gate.as_any().downcast_ref::<multi::Fredkin>() {
876                        let control = fredkin_gate.control;
877                        let target1 = fredkin_gate.target1;
878                        let target2 = fredkin_gate.target2;
879                        self.apply_fredkin_to_state::<N>(&mut state, control, target1, target2)?;
880                    }
881                }
882
883                _ => {
884                    return Err(QuantRS2Error::UnsupportedOperation(format!(
885                        "Gate {} not supported",
886                        gate.name()
887                    )));
888                }
889            }
890
891            // Apply per-gate noise if configured
892            if let Some(ref noise_model) = self.noise_model {
893                if noise_model.per_gate {
894                    noise_model.apply_to_statevector(&mut state)?;
895                }
896            }
897
898            // Apply per-gate advanced noise if configured
899            if let Some(ref advanced_noise_model) = self.advanced_noise_model {
900                if advanced_noise_model.per_gate {
901                    advanced_noise_model.apply_to_statevector(&mut state)?;
902                }
903            }
904        }
905
906        // Apply final noise if not per-gate
907        if let Some(ref noise_model) = self.noise_model {
908            if !noise_model.per_gate {
909                noise_model.apply_to_statevector(&mut state)?;
910            }
911        }
912
913        // Apply final advanced noise if not per-gate
914        if let Some(ref advanced_noise_model) = self.advanced_noise_model {
915            if !advanced_noise_model.per_gate {
916                advanced_noise_model.apply_to_statevector(&mut state)?;
917            }
918        }
919
920        // Create register from final state
921        Register::<N>::with_amplitudes(state)
922    }
923}
924
925impl StateVectorSimulator {
926    /// Initialize state with specified number of qubits in |0...0⟩
927    pub fn initialize_state(&mut self, num_qubits: usize) -> QuantRS2Result<()> {
928        // This is a placeholder - actual initialization would need the circuit framework
929        Ok(())
930    }
931
932    /// Get the current quantum state
933    pub fn get_state(&self) -> Vec<Complex64> {
934        // Placeholder - would return the actual state vector
935        vec![Complex64::new(1.0, 0.0)]
936    }
937
938    /// Get mutable reference to the current quantum state
939    pub fn get_state_mut(&mut self) -> Vec<Complex64> {
940        // Placeholder - would return mutable reference to actual state vector
941        vec![Complex64::new(1.0, 0.0)]
942    }
943
944    /// Set the quantum state
945    pub fn set_state(&mut self, _state: Vec<Complex64>) -> QuantRS2Result<()> {
946        // Placeholder - would set the actual state vector
947        Ok(())
948    }
949
950    /// Apply an interface circuit to the quantum state
951    pub fn apply_interface_circuit(
952        &mut self,
953        _circuit: &crate::circuit_interfaces::InterfaceCircuit,
954    ) -> QuantRS2Result<()> {
955        // Placeholder - would apply the circuit gates using the circuit framework
956        Ok(())
957    }
958
959    /// Apply Hadamard gate to qubit
960    pub fn apply_h(&mut self, _qubit: usize) -> QuantRS2Result<()> {
961        // Placeholder - would apply H gate using circuit framework
962        Ok(())
963    }
964
965    /// Apply Pauli-X gate to qubit
966    pub fn apply_x(&mut self, _qubit: usize) -> QuantRS2Result<()> {
967        // Placeholder - would apply X gate using circuit framework
968        Ok(())
969    }
970
971    /// Apply Pauli-Z gate to qubit
972    pub fn apply_z_public(&mut self, _qubit: usize) -> QuantRS2Result<()> {
973        // Placeholder - would apply Z gate using circuit framework
974        Ok(())
975    }
976
977    /// Apply CNOT gate (public interface with usize indices)
978    pub fn apply_cnot_public(&mut self, _control: usize, _target: usize) -> QuantRS2Result<()> {
979        // Placeholder - would apply CNOT gate using circuit framework
980        Ok(())
981    }
982
983    /// Apply Toffoli (CCNOT) gate to state vector
984    fn apply_toffoli_to_state<const N: usize>(
985        &self,
986        state: &mut [Complex64],
987        control1: QubitId,
988        control2: QubitId,
989        target: QubitId,
990    ) -> QuantRS2Result<()> {
991        let control1_idx = control1.id() as usize;
992        let control2_idx = control2.id() as usize;
993        let target_idx = target.id() as usize;
994
995        if control1_idx >= N || control2_idx >= N || target_idx >= N {
996            return Err(QuantRS2Error::InvalidQubitId(if control1_idx >= N {
997                control1.id()
998            } else if control2_idx >= N {
999                control2.id()
1000            } else {
1001                target.id()
1002            }));
1003        }
1004
1005        // Apply Toffoli gate by swapping amplitudes when both controls are |1⟩
1006        if self.parallel {
1007            let mut state_copy = self.buffer_pool.lock().unwrap().get_buffer(state.len());
1008            state_copy.copy_from_slice(state);
1009
1010            state.par_iter_mut().enumerate().for_each(|(i, amp)| {
1011                let control1_bit = (i >> control1_idx) & 1;
1012                let control2_bit = (i >> control2_idx) & 1;
1013
1014                if control1_bit == 1 && control2_bit == 1 {
1015                    let flipped = flip_bit(i, target_idx);
1016                    *amp = state_copy[flipped];
1017                }
1018            });
1019
1020            self.buffer_pool.lock().unwrap().return_buffer(state_copy);
1021        } else {
1022            let mut new_state = self.buffer_pool.lock().unwrap().get_buffer(state.len());
1023            new_state.copy_from_slice(state);
1024
1025            for i in 0..state.len() {
1026                let control1_bit = (i >> control1_idx) & 1;
1027                let control2_bit = (i >> control2_idx) & 1;
1028
1029                if control1_bit == 1 && control2_bit == 1 {
1030                    let flipped = flip_bit(i, target_idx);
1031                    new_state[flipped] = state[i];
1032                    new_state[i] = state[flipped];
1033                }
1034            }
1035
1036            state.copy_from_slice(&new_state);
1037            self.buffer_pool.lock().unwrap().return_buffer(new_state);
1038        }
1039
1040        Ok(())
1041    }
1042
1043    /// Apply Fredkin (CSWAP) gate to state vector
1044    fn apply_fredkin_to_state<const N: usize>(
1045        &self,
1046        state: &mut [Complex64],
1047        control: QubitId,
1048        target1: QubitId,
1049        target2: QubitId,
1050    ) -> QuantRS2Result<()> {
1051        let control_idx = control.id() as usize;
1052        let target1_idx = target1.id() as usize;
1053        let target2_idx = target2.id() as usize;
1054
1055        if control_idx >= N || target1_idx >= N || target2_idx >= N {
1056            return Err(QuantRS2Error::InvalidQubitId(if control_idx >= N {
1057                control.id()
1058            } else if target1_idx >= N {
1059                target1.id()
1060            } else {
1061                target2.id()
1062            }));
1063        }
1064
1065        // Apply Fredkin gate by swapping target qubits when control is |1⟩
1066        if self.parallel {
1067            let mut state_copy = self.buffer_pool.lock().unwrap().get_buffer(state.len());
1068            state_copy.copy_from_slice(state);
1069
1070            state.par_iter_mut().enumerate().for_each(|(i, amp)| {
1071                let control_bit = (i >> control_idx) & 1;
1072                let target1_bit = (i >> target1_idx) & 1;
1073                let target2_bit = (i >> target2_idx) & 1;
1074
1075                if control_bit == 1 && target1_bit != target2_bit {
1076                    let swapped = flip_bit(flip_bit(i, target1_idx), target2_idx);
1077                    *amp = state_copy[swapped];
1078                }
1079            });
1080
1081            self.buffer_pool.lock().unwrap().return_buffer(state_copy);
1082        } else {
1083            let mut new_state = self.buffer_pool.lock().unwrap().get_buffer(state.len());
1084            new_state.copy_from_slice(state);
1085
1086            for i in 0..state.len() {
1087                let control_bit = (i >> control_idx) & 1;
1088                let target1_bit = (i >> target1_idx) & 1;
1089                let target2_bit = (i >> target2_idx) & 1;
1090
1091                if control_bit == 1 && target1_bit != target2_bit {
1092                    let swapped = flip_bit(flip_bit(i, target1_idx), target2_idx);
1093                    new_state[swapped] = state[i];
1094                    new_state[i] = state[swapped];
1095                }
1096            }
1097
1098            state.copy_from_slice(&new_state);
1099            self.buffer_pool.lock().unwrap().return_buffer(new_state);
1100        }
1101
1102        Ok(())
1103    }
1104
1105    /// Apply Toffoli (CCNOT) gate (public interface)
1106    pub fn apply_toffoli(
1107        &mut self,
1108        control1: QubitId,
1109        control2: QubitId,
1110        target: QubitId,
1111    ) -> QuantRS2Result<()> {
1112        // This is a placeholder for external API - real implementation would need circuit framework
1113        Ok(())
1114    }
1115
1116    /// Apply Fredkin (CSWAP) gate (public interface)
1117    pub fn apply_fredkin(
1118        &mut self,
1119        control: QubitId,
1120        target1: QubitId,
1121        target2: QubitId,
1122    ) -> QuantRS2Result<()> {
1123        // This is a placeholder for external API - real implementation would need circuit framework
1124        Ok(())
1125    }
1126}