1use scirs2_core::parallel_ops::{
9 IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator,
10};
11use scirs2_core::Complex64;
12use std::sync::Mutex;
13
14use quantrs2_circuit::builder::{Circuit, Simulator};
15use quantrs2_core::{
16 error::{QuantRS2Error, QuantRS2Result},
17 gate::{multi, single, GateOp},
18 qubit::QubitId,
19 register::Register,
20};
21
22use crate::diagnostics::SimulationDiagnostics;
23use crate::optimized_simd;
24use crate::scirs2_integration::{SciRS2Backend, SciRS2Matrix, SciRS2Vector, BLAS};
25use crate::utils::{flip_bit, gate_vec_to_array2};
26
27#[derive(Debug)]
46pub struct StateVectorSimulator {
47 pub parallel: bool,
49
50 pub noise_model: Option<crate::noise::NoiseModel>,
52
53 pub advanced_noise_model: Option<crate::noise_advanced::AdvancedNoiseModel>,
55
56 buffer_pool: Mutex<BufferPool>,
58
59 pub use_simd: bool,
61
62 pub use_gate_fusion: bool,
64
65 pub diagnostics: Option<SimulationDiagnostics>,
67
68 scirs2_backend: SciRS2Backend,
70}
71
72impl Clone for StateVectorSimulator {
73 fn clone(&self) -> Self {
74 Self {
75 parallel: self.parallel,
76 noise_model: self.noise_model.clone(),
77 advanced_noise_model: self.advanced_noise_model.clone(),
78 buffer_pool: Mutex::new(BufferPool::new(4, 1024)), use_simd: self.use_simd,
80 use_gate_fusion: self.use_gate_fusion,
81 diagnostics: self
82 .diagnostics
83 .as_ref()
84 .map(|_| SimulationDiagnostics::new()),
85 scirs2_backend: SciRS2Backend::new(),
86 }
87 }
88}
89
90#[derive(Debug, Clone)]
92pub struct BufferPool {
93 working_buffers: std::collections::VecDeque<Vec<Complex64>>,
95 max_buffers: usize,
97 target_size: usize,
99}
100
101impl BufferPool {
102 #[must_use]
104 pub fn new(max_buffers: usize, target_size: usize) -> Self {
105 Self {
106 working_buffers: std::collections::VecDeque::with_capacity(max_buffers),
107 max_buffers,
108 target_size,
109 }
110 }
111
112 pub fn get_buffer(&mut self, size: usize) -> Vec<Complex64> {
114 if let Some(mut buffer) = self.working_buffers.pop_front() {
116 if buffer.capacity() >= size {
117 buffer.clear();
118 buffer.resize(size, Complex64::new(0.0, 0.0));
119 return buffer;
120 }
121 }
122
123 let capacity = size.max(self.target_size);
125 let mut buffer = Vec::with_capacity(capacity);
126 buffer.resize(size, Complex64::new(0.0, 0.0));
127 buffer
128 }
129
130 pub fn return_buffer(&mut self, buffer: Vec<Complex64>) {
132 if self.working_buffers.len() < self.max_buffers
133 && buffer.capacity() >= self.target_size / 2
134 {
135 self.working_buffers.push_back(buffer);
136 }
137 }
139
140 pub fn clear(&mut self) {
142 self.working_buffers.clear();
143 }
144}
145
146impl StateVectorSimulator {
147 #[must_use]
149 pub fn new() -> Self {
150 Self {
151 parallel: true,
152 noise_model: None,
153 advanced_noise_model: None,
154 buffer_pool: Mutex::new(BufferPool::new(4, 1024)), use_simd: true,
156 use_gate_fusion: true,
157 diagnostics: None,
158 scirs2_backend: SciRS2Backend::new(),
159 }
160 }
161
162 #[must_use]
164 pub fn sequential() -> Self {
165 Self {
166 parallel: false,
167 noise_model: None,
168 advanced_noise_model: None,
169 buffer_pool: Mutex::new(BufferPool::new(2, 512)), use_simd: true,
171 use_gate_fusion: true,
172 diagnostics: None,
173 scirs2_backend: SciRS2Backend::new(),
174 }
175 }
176
177 #[must_use]
179 pub fn with_noise(noise_model: crate::noise::NoiseModel) -> Self {
180 Self {
181 parallel: true,
182 noise_model: Some(noise_model),
183 advanced_noise_model: None,
184 buffer_pool: Mutex::new(BufferPool::new(4, 1024)),
185 use_simd: true,
186 use_gate_fusion: true,
187 diagnostics: None,
188 scirs2_backend: SciRS2Backend::new(),
189 }
190 }
191
192 #[must_use]
194 pub fn with_advanced_noise(
195 advanced_noise_model: crate::noise_advanced::AdvancedNoiseModel,
196 ) -> Self {
197 Self {
198 parallel: true,
199 noise_model: None,
200 advanced_noise_model: Some(advanced_noise_model),
201 buffer_pool: Mutex::new(BufferPool::new(4, 1024)),
202 use_simd: true,
203 use_gate_fusion: true,
204 diagnostics: None,
205 scirs2_backend: SciRS2Backend::new(),
206 }
207 }
208
209 #[must_use]
211 pub fn with_buffer_pool(parallel: bool, max_buffers: usize, target_size: usize) -> Self {
212 Self {
213 parallel,
214 noise_model: None,
215 advanced_noise_model: None,
216 buffer_pool: Mutex::new(BufferPool::new(max_buffers, target_size)),
217 use_simd: true,
218 use_gate_fusion: true,
219 diagnostics: None,
220 scirs2_backend: SciRS2Backend::new(),
221 }
222 }
223
224 pub fn set_noise_model(&mut self, noise_model: crate::noise::NoiseModel) -> &mut Self {
226 self.noise_model = Some(noise_model);
227 self.advanced_noise_model = None; self
229 }
230
231 pub fn set_advanced_noise_model(
233 &mut self,
234 advanced_noise_model: crate::noise_advanced::AdvancedNoiseModel,
235 ) -> &mut Self {
236 self.advanced_noise_model = Some(advanced_noise_model);
237 self.noise_model = None; self
239 }
240
241 pub fn remove_noise_model(&mut self) -> &mut Self {
243 self.noise_model = None;
244 self.advanced_noise_model = None;
245 self
246 }
247
248 pub const fn set_simd_enabled(&mut self, enabled: bool) -> &mut Self {
250 self.use_simd = enabled;
251 self
252 }
253
254 pub const fn set_gate_fusion_enabled(&mut self, enabled: bool) -> &mut Self {
256 self.use_gate_fusion = enabled;
257 self
258 }
259
260 pub const fn get_buffer_pool(&self) -> &Mutex<BufferPool> {
262 &self.buffer_pool
263 }
264
265 pub fn enable_diagnostics(&mut self) -> &mut Self {
267 self.diagnostics = Some(SimulationDiagnostics::new());
268 self
269 }
270
271 pub fn disable_diagnostics(&mut self) -> &mut Self {
273 self.diagnostics = None;
274 self
275 }
276
277 pub fn get_diagnostics_report(&self) -> Option<crate::diagnostics::DiagnosticReport> {
279 self.diagnostics
280 .as_ref()
281 .map(super::diagnostics::SimulationDiagnostics::generate_report)
282 }
283
284 #[must_use]
286 pub fn high_performance() -> Self {
287 Self {
288 parallel: true,
289 noise_model: None,
290 advanced_noise_model: None,
291 buffer_pool: Mutex::new(BufferPool::new(8, 2048)), use_simd: true,
293 use_gate_fusion: true,
294 diagnostics: Some(SimulationDiagnostics::new()),
295 scirs2_backend: SciRS2Backend::new(),
296 }
297 }
298
299 #[cfg(feature = "advanced_math")]
301 fn apply_dense_matrix_vector(
302 &mut self,
303 matrix: &[Complex64],
304 vector: &[Complex64],
305 result: &mut [Complex64],
306 ) -> QuantRS2Result<()> {
307 if self.scirs2_backend.is_available() && matrix.len() >= 64 && vector.len() >= 8 {
308 use scirs2_core::ndarray::{Array1, Array2};
310
311 let rows = result.len();
312 let cols = vector.len();
313
314 if matrix.len() != rows * cols {
315 return Err(QuantRS2Error::InvalidInput(
316 "Dimension mismatch in matrix application".to_string(),
317 ));
318 }
319
320 let matrix_2d =
322 Array2::from_shape_vec((rows, cols), matrix.to_vec()).map_err(|_| {
323 QuantRS2Error::InvalidInput("Matrix shape conversion failed".to_string())
324 })?;
325 let vector_1d = Array1::from_vec(vector.to_vec());
326
327 let scirs2_matrix = SciRS2Matrix::from_array2(matrix_2d);
329 let scirs2_vector = SciRS2Vector::from_array1(vector_1d);
330
331 let scirs2_result = self
333 .scirs2_backend
334 .matrix_vector_multiply(&scirs2_matrix, &scirs2_vector)
335 .map_err(|_| {
336 QuantRS2Error::ComputationError(
337 "Matrix-vector multiplication failed".to_string(),
338 )
339 })?;
340
341 let result_array = scirs2_result.to_array1().map_err(|_| {
343 QuantRS2Error::ComputationError("Result conversion to array failed".to_string())
344 })?;
345 if let Some(slice) = result_array.as_slice() {
346 result.copy_from_slice(slice);
347 } else {
348 return Err(QuantRS2Error::ComputationError(
349 "Result array is not contiguous".to_string(),
350 ));
351 }
352
353 Ok(())
354 } else {
355 for i in 0..result.len() {
357 result[i] = Complex64::new(0.0, 0.0);
358 for j in 0..vector.len() {
359 result[i] += matrix[i * vector.len() + j] * vector[j];
360 }
361 }
362 Ok(())
363 }
364 }
365
366 #[cfg(not(feature = "advanced_math"))]
368 fn apply_dense_matrix_vector(
369 &self,
370 matrix: &[Complex64],
371 vector: &[Complex64],
372 result: &mut [Complex64],
373 ) -> QuantRS2Result<()> {
374 for i in 0..result.len() {
376 result[i] = Complex64::new(0.0, 0.0);
377 for j in 0..vector.len() {
378 result[i] += matrix[i * vector.len() + j] * vector[j];
379 }
380 }
381 Ok(())
382 }
383
384 fn apply_single_qubit_gate<const N: usize>(
386 &self,
387 state: &mut [Complex64],
388 gate_matrix: &[Complex64],
389 target: QubitId,
390 ) -> QuantRS2Result<()> {
391 let target_idx = target.id() as usize;
392 if target_idx >= N {
393 return Err(QuantRS2Error::InvalidQubitId(target.id()));
394 }
395
396 if self.use_simd && state.len() >= 8 {
398 return self.apply_single_qubit_gate_simd::<N>(state, gate_matrix, target_idx);
399 }
400
401 let m00 = gate_matrix[0];
404 let m01 = gate_matrix[1];
405 let m10 = gate_matrix[2];
406 let m11 = gate_matrix[3];
407
408 if self.parallel {
410 let mut state_copy = self
412 .buffer_pool
413 .lock()
414 .expect("buffer pool lock poisoned")
415 .get_buffer(state.len());
416 state_copy.copy_from_slice(state);
417
418 state.par_iter_mut().enumerate().for_each(|(idx, amp)| {
419 let bit_val = (idx >> target_idx) & 1;
420 let paired_idx = if bit_val == 0 {
421 idx | (1 << target_idx)
422 } else {
423 idx & !(1 << target_idx)
424 };
425
426 let idx0 = if bit_val == 0 { idx } else { paired_idx };
427 let idx1 = if bit_val == 0 { paired_idx } else { idx };
428
429 let val0 = state_copy[idx0];
430 let val1 = state_copy[idx1];
431
432 *amp = if idx == idx0 {
434 m00 * val0 + m01 * val1
435 } else {
436 m10 * val0 + m11 * val1
437 };
438 });
439
440 self.buffer_pool
442 .lock()
443 .expect("buffer pool lock poisoned")
444 .return_buffer(state_copy);
445 } else {
446 let dim = state.len();
448 let mut new_state = self
449 .buffer_pool
450 .lock()
451 .expect("buffer pool lock poisoned")
452 .get_buffer(dim);
453
454 for i in 0..dim {
455 let bit_val = (i >> target_idx) & 1;
456 let paired_idx = flip_bit(i, target_idx);
457
458 if bit_val == 0 {
459 new_state[i] = m00 * state[i] + m01 * state[paired_idx];
460 new_state[paired_idx] = m10 * state[i] + m11 * state[paired_idx];
461 }
462 }
463
464 state.copy_from_slice(&new_state);
465 self.buffer_pool
467 .lock()
468 .expect("buffer pool lock poisoned")
469 .return_buffer(new_state);
470 }
471
472 Ok(())
473 }
474
475 fn apply_single_qubit_gate_simd<const N: usize>(
477 &self,
478 state: &mut [Complex64],
479 gate_matrix: &[Complex64],
480 target_idx: usize,
481 ) -> QuantRS2Result<()> {
482 let dim = state.len();
483 let pairs_per_block = 1 << target_idx;
484 let total_pairs = dim / 2;
485
486 let mut pool = self.buffer_pool.lock().expect("buffer pool lock poisoned");
488 let mut in_amps0 = pool.get_buffer(total_pairs);
489 let mut in_amps1 = pool.get_buffer(total_pairs);
490 let mut out_amps0 = pool.get_buffer(total_pairs);
491 let mut out_amps1 = pool.get_buffer(total_pairs);
492
493 let mut pair_idx = 0;
495 for block in 0..(dim / (pairs_per_block * 2)) {
496 let block_start = block * pairs_per_block * 2;
497
498 for offset in 0..pairs_per_block {
499 let idx0 = block_start + offset;
500 let idx1 = block_start + pairs_per_block + offset;
501
502 in_amps0[pair_idx] = state[idx0];
503 in_amps1[pair_idx] = state[idx1];
504 pair_idx += 1;
505 }
506 }
507
508 let gate_matrix_array: [Complex64; 4] = [
510 gate_matrix[0],
511 gate_matrix[1],
512 gate_matrix[2],
513 gate_matrix[3],
514 ];
515
516 optimized_simd::apply_single_qubit_gate_optimized(
518 &gate_matrix_array,
519 &in_amps0,
520 &in_amps1,
521 &mut out_amps0,
522 &mut out_amps1,
523 );
524
525 pair_idx = 0;
527 for block in 0..(dim / (pairs_per_block * 2)) {
528 let block_start = block * pairs_per_block * 2;
529
530 for offset in 0..pairs_per_block {
531 let idx0 = block_start + offset;
532 let idx1 = block_start + pairs_per_block + offset;
533
534 state[idx0] = out_amps0[pair_idx];
535 state[idx1] = out_amps1[pair_idx];
536 pair_idx += 1;
537 }
538 }
539
540 pool.return_buffer(in_amps0);
542 pool.return_buffer(in_amps1);
543 pool.return_buffer(out_amps0);
544 pool.return_buffer(out_amps1);
545
546 Ok(())
547 }
548
549 fn apply_two_qubit_gate<const N: usize>(
551 &self,
552 state: &mut [Complex64],
553 gate_matrix: &[Complex64],
554 control: QubitId,
555 target: QubitId,
556 ) -> QuantRS2Result<()> {
557 let control_idx = control.id() as usize;
558 let target_idx = target.id() as usize;
559
560 if control_idx >= N || target_idx >= N {
561 return Err(QuantRS2Error::InvalidQubitId(if control_idx >= N {
562 control.id()
563 } else {
564 target.id()
565 }));
566 }
567
568 if control_idx == target_idx {
569 return Err(QuantRS2Error::CircuitValidationFailed(
570 "Control and target qubits must be different".into(),
571 ));
572 }
573
574 let m = gate_matrix; if self.parallel {
579 let mut state_copy = self
581 .buffer_pool
582 .lock()
583 .expect("buffer pool lock poisoned")
584 .get_buffer(state.len());
585 state_copy.copy_from_slice(state);
586
587 state.par_iter_mut().enumerate().for_each(|(idx, amp)| {
588 let idx00 = idx & !(1 << control_idx) & !(1 << target_idx);
589 let idx01 = idx00 | (1 << target_idx);
590 let idx10 = idx00 | (1 << control_idx);
591 let idx11 = idx00 | (1 << control_idx) | (1 << target_idx);
592
593 let val00 = state_copy[idx00];
594 let val01 = state_copy[idx01];
595 let val10 = state_copy[idx10];
596 let val11 = state_copy[idx11];
597
598 *amp = match idx {
600 i if i == idx00 => m[0] * val00 + m[1] * val01 + m[2] * val10 + m[3] * val11,
601 i if i == idx01 => m[4] * val00 + m[5] * val01 + m[6] * val10 + m[7] * val11,
602 i if i == idx10 => m[8] * val00 + m[9] * val01 + m[10] * val10 + m[11] * val11,
603 i if i == idx11 => {
604 m[12] * val00 + m[13] * val01 + m[14] * val10 + m[15] * val11
605 }
606 _ => unreachable!(),
607 };
608 });
609
610 self.buffer_pool
612 .lock()
613 .expect("buffer pool lock poisoned")
614 .return_buffer(state_copy);
615 } else {
616 let dim = state.len();
618 let mut new_state = self
619 .buffer_pool
620 .lock()
621 .expect("buffer pool lock poisoned")
622 .get_buffer(dim);
623
624 #[allow(clippy::needless_range_loop)]
625 for i in 0..dim {
626 let control_bit = (i >> control_idx) & 1;
627 let target_bit = (i >> target_idx) & 1;
628
629 let i00 = i & !(1 << control_idx) & !(1 << target_idx);
631 let i01 = i00 | (1 << target_idx);
632 let i10 = i00 | (1 << control_idx);
633 let i11 = i10 | (1 << target_idx);
634
635 let basis_idx = (control_bit << 1) | target_bit;
636
637 let row_offset = basis_idx * 4;
639 new_state[i] = m[row_offset] * state[i00]
640 + m[row_offset + 1] * state[i01]
641 + m[row_offset + 2] * state[i10]
642 + m[row_offset + 3] * state[i11];
643 }
644
645 state.copy_from_slice(&new_state);
646 self.buffer_pool
648 .lock()
649 .expect("buffer pool lock poisoned")
650 .return_buffer(new_state);
651 }
652
653 Ok(())
654 }
655
656 fn apply_cnot<const N: usize>(
658 &self,
659 state: &mut [Complex64],
660 control: QubitId,
661 target: QubitId,
662 ) -> QuantRS2Result<()> {
663 let control_idx = control.id() as usize;
664 let target_idx = target.id() as usize;
665
666 if control_idx >= N || target_idx >= N {
667 return Err(QuantRS2Error::InvalidQubitId(if control_idx >= N {
668 control.id()
669 } else {
670 target.id()
671 }));
672 }
673
674 if control_idx == target_idx {
675 return Err(QuantRS2Error::CircuitValidationFailed(
676 "Control and target qubits must be different".into(),
677 ));
678 }
679
680 if self.parallel {
682 let mut state_copy = self
683 .buffer_pool
684 .lock()
685 .expect("buffer pool lock poisoned")
686 .get_buffer(state.len());
687 state_copy.copy_from_slice(state);
688
689 state.par_iter_mut().enumerate().for_each(|(i, amp)| {
690 if (i >> control_idx) & 1 == 1 {
691 let flipped = flip_bit(i, target_idx);
692 *amp = state_copy[flipped];
693 }
694 });
695
696 self.buffer_pool
697 .lock()
698 .expect("buffer pool lock poisoned")
699 .return_buffer(state_copy);
700 } else {
701 let dim = state.len();
702 let mut new_state = self
703 .buffer_pool
704 .lock()
705 .expect("buffer pool lock poisoned")
706 .get_buffer(dim);
707
708 for i in 0..dim {
709 if (i >> control_idx) & 1 == 1 {
710 let flipped = flip_bit(i, target_idx);
711 new_state[flipped] = state[i];
712 new_state[i] = state[flipped];
713 } else {
714 new_state[i] = state[i];
715 }
716 }
717
718 state.copy_from_slice(&new_state);
719 self.buffer_pool
720 .lock()
721 .expect("buffer pool lock poisoned")
722 .return_buffer(new_state);
723 }
724
725 Ok(())
726 }
727
728 fn apply_swap<const N: usize>(
730 &self,
731 state: &mut [Complex64],
732 qubit1: QubitId,
733 qubit2: QubitId,
734 ) -> QuantRS2Result<()> {
735 let q1_idx = qubit1.id() as usize;
736 let q2_idx = qubit2.id() as usize;
737
738 if q1_idx >= N || q2_idx >= N {
739 return Err(QuantRS2Error::InvalidQubitId(if q1_idx >= N {
740 qubit1.id()
741 } else {
742 qubit2.id()
743 }));
744 }
745
746 if q1_idx == q2_idx {
747 return Err(QuantRS2Error::CircuitValidationFailed(
748 "Qubits must be different for SWAP gate".into(),
749 ));
750 }
751
752 if self.parallel {
754 let mut state_copy = self
755 .buffer_pool
756 .lock()
757 .expect("buffer pool lock poisoned")
758 .get_buffer(state.len());
759 state_copy.copy_from_slice(state);
760
761 state.par_iter_mut().enumerate().for_each(|(i, amp)| {
762 let bit1 = (i >> q1_idx) & 1;
763 let bit2 = (i >> q2_idx) & 1;
764
765 if bit1 != bit2 {
766 let swapped = flip_bit(flip_bit(i, q1_idx), q2_idx);
767 *amp = state_copy[swapped];
768 }
769 });
770
771 self.buffer_pool
772 .lock()
773 .expect("buffer pool lock poisoned")
774 .return_buffer(state_copy);
775 } else {
776 let dim = state.len();
777 let mut new_state = self
778 .buffer_pool
779 .lock()
780 .expect("buffer pool lock poisoned")
781 .get_buffer(dim);
782
783 for i in 0..dim {
784 let bit1 = (i >> q1_idx) & 1;
785 let bit2 = (i >> q2_idx) & 1;
786
787 if bit1 == bit2 {
788 new_state[i] = state[i];
789 } else {
790 let swapped = flip_bit(flip_bit(i, q1_idx), q2_idx);
791 new_state[swapped] = state[i];
792 new_state[i] = state[swapped];
793 }
794 }
795
796 state.copy_from_slice(&new_state);
797 self.buffer_pool
798 .lock()
799 .expect("buffer pool lock poisoned")
800 .return_buffer(new_state);
801 }
802
803 Ok(())
804 }
805}
806
807impl Default for StateVectorSimulator {
808 fn default() -> Self {
809 Self::new()
810 }
811}
812
813impl<const N: usize> Simulator<N> for StateVectorSimulator {
814 fn run(&self, circuit: &Circuit<N>) -> QuantRS2Result<Register<N>> {
815 let dim = 1 << N;
817 let mut state = vec![Complex64::new(0.0, 0.0); dim];
818 state[0] = Complex64::new(1.0, 0.0);
819
820 for gate in circuit.gates() {
822 match gate.name() {
823 "H" => {
825 if let Some(g) = gate.as_any().downcast_ref::<single::Hadamard>() {
826 let matrix = g.matrix()?;
827 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
828 }
829 }
830 "X" => {
831 if let Some(g) = gate.as_any().downcast_ref::<single::PauliX>() {
832 let matrix = g.matrix()?;
833 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
834 }
835 }
836 "Y" => {
837 if let Some(g) = gate.as_any().downcast_ref::<single::PauliY>() {
838 let matrix = g.matrix()?;
839 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
840 }
841 }
842 "Z" => {
843 if let Some(g) = gate.as_any().downcast_ref::<single::PauliZ>() {
844 let matrix = g.matrix()?;
845 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
846 }
847 }
848 "RX" => {
849 if let Some(g) = gate.as_any().downcast_ref::<single::RotationX>() {
850 let matrix = g.matrix()?;
851 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
852 }
853 }
854 "RY" => {
855 if let Some(g) = gate.as_any().downcast_ref::<single::RotationY>() {
856 let matrix = g.matrix()?;
857 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
858 }
859 }
860 "RZ" => {
861 if let Some(g) = gate.as_any().downcast_ref::<single::RotationZ>() {
862 let matrix = g.matrix()?;
863 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
864 }
865 }
866 "S" => {
867 if let Some(g) = gate.as_any().downcast_ref::<single::Phase>() {
868 let matrix = g.matrix()?;
869 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
870 }
871 }
872 "T" => {
873 if let Some(g) = gate.as_any().downcast_ref::<single::T>() {
874 let matrix = g.matrix()?;
875 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
876 }
877 }
878 "S†" => {
879 if let Some(g) = gate.as_any().downcast_ref::<single::PhaseDagger>() {
880 let matrix = g.matrix()?;
881 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
882 }
883 }
884 "T†" => {
885 if let Some(g) = gate.as_any().downcast_ref::<single::TDagger>() {
886 let matrix = g.matrix()?;
887 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
888 }
889 }
890 "√X" => {
891 if let Some(g) = gate.as_any().downcast_ref::<single::SqrtX>() {
892 let matrix = g.matrix()?;
893 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
894 }
895 }
896 "√X†" => {
897 if let Some(g) = gate.as_any().downcast_ref::<single::SqrtXDagger>() {
898 let matrix = g.matrix()?;
899 self.apply_single_qubit_gate::<N>(&mut state, &matrix, g.target)?;
900 }
901 }
902
903 "CNOT" => {
905 if let Some(g) = gate.as_any().downcast_ref::<multi::CNOT>() {
906 self.apply_cnot::<N>(&mut state, g.control, g.target)?;
908 }
909 }
910 "CZ" => {
911 if let Some(g) = gate.as_any().downcast_ref::<multi::CZ>() {
912 let matrix = g.matrix()?;
913 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
914 }
915 }
916 "SWAP" => {
917 if let Some(g) = gate.as_any().downcast_ref::<multi::SWAP>() {
918 self.apply_swap::<N>(&mut state, g.qubit1, g.qubit2)?;
920 }
921 }
922 "CY" => {
923 if let Some(g) = gate.as_any().downcast_ref::<multi::CY>() {
924 let matrix = g.matrix()?;
925 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
926 }
927 }
928 "CH" => {
929 if let Some(g) = gate.as_any().downcast_ref::<multi::CH>() {
930 let matrix = g.matrix()?;
931 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
932 }
933 }
934 "CS" => {
935 if let Some(g) = gate.as_any().downcast_ref::<multi::CS>() {
936 let matrix = g.matrix()?;
937 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
938 }
939 }
940 "CRX" => {
941 if let Some(g) = gate.as_any().downcast_ref::<multi::CRX>() {
942 let matrix = g.matrix()?;
943 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
944 }
945 }
946 "CRY" => {
947 if let Some(g) = gate.as_any().downcast_ref::<multi::CRY>() {
948 let matrix = g.matrix()?;
949 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
950 }
951 }
952 "CRZ" => {
953 if let Some(g) = gate.as_any().downcast_ref::<multi::CRZ>() {
954 let matrix = g.matrix()?;
955 self.apply_two_qubit_gate::<N>(&mut state, &matrix, g.control, g.target)?;
956 }
957 }
958
959 "Toffoli" => {
961 if let Some(toffoli_gate) = gate.as_any().downcast_ref::<multi::Toffoli>() {
962 let control1 = toffoli_gate.control1;
963 let control2 = toffoli_gate.control2;
964 let target = toffoli_gate.target;
965 self.apply_toffoli_to_state::<N>(&mut state, control1, control2, target)?;
966 }
967 }
968 "Fredkin" => {
969 if let Some(fredkin_gate) = gate.as_any().downcast_ref::<multi::Fredkin>() {
970 let control = fredkin_gate.control;
971 let target1 = fredkin_gate.target1;
972 let target2 = fredkin_gate.target2;
973 self.apply_fredkin_to_state::<N>(&mut state, control, target1, target2)?;
974 }
975 }
976
977 _ => {
978 return Err(QuantRS2Error::UnsupportedOperation(format!(
979 "Gate {} not supported",
980 gate.name()
981 )));
982 }
983 }
984
985 if let Some(ref noise_model) = self.noise_model {
987 if noise_model.per_gate {
988 noise_model.apply_to_statevector(&mut state)?;
989 }
990 }
991
992 if let Some(ref advanced_noise_model) = self.advanced_noise_model {
994 if advanced_noise_model.per_gate {
995 advanced_noise_model.apply_to_statevector(&mut state)?;
996 }
997 }
998 }
999
1000 if let Some(ref noise_model) = self.noise_model {
1002 if !noise_model.per_gate {
1003 noise_model.apply_to_statevector(&mut state)?;
1004 }
1005 }
1006
1007 if let Some(ref advanced_noise_model) = self.advanced_noise_model {
1009 if !advanced_noise_model.per_gate {
1010 advanced_noise_model.apply_to_statevector(&mut state)?;
1011 }
1012 }
1013
1014 Register::<N>::with_amplitudes(state)
1016 }
1017}
1018
1019impl StateVectorSimulator {
1020 pub const fn initialize_state(&mut self, num_qubits: usize) -> QuantRS2Result<()> {
1022 Ok(())
1024 }
1025
1026 pub fn get_state(&self) -> Vec<Complex64> {
1028 vec![Complex64::new(1.0, 0.0)]
1030 }
1031
1032 pub fn get_state_mut(&mut self) -> Vec<Complex64> {
1034 vec![Complex64::new(1.0, 0.0)]
1036 }
1037
1038 pub fn set_state(&mut self, _state: Vec<Complex64>) -> QuantRS2Result<()> {
1040 Ok(())
1042 }
1043
1044 pub const fn apply_interface_circuit(
1046 &mut self,
1047 _circuit: &crate::circuit_interfaces::InterfaceCircuit,
1048 ) -> QuantRS2Result<()> {
1049 Ok(())
1051 }
1052
1053 pub const fn apply_h(&mut self, _qubit: usize) -> QuantRS2Result<()> {
1055 Ok(())
1057 }
1058
1059 pub const fn apply_x(&mut self, _qubit: usize) -> QuantRS2Result<()> {
1061 Ok(())
1063 }
1064
1065 pub const fn apply_z_public(&mut self, _qubit: usize) -> QuantRS2Result<()> {
1067 Ok(())
1069 }
1070
1071 pub const fn apply_cnot_public(
1073 &mut self,
1074 _control: usize,
1075 _target: usize,
1076 ) -> QuantRS2Result<()> {
1077 Ok(())
1079 }
1080
1081 fn apply_toffoli_to_state<const N: usize>(
1083 &self,
1084 state: &mut [Complex64],
1085 control1: QubitId,
1086 control2: QubitId,
1087 target: QubitId,
1088 ) -> QuantRS2Result<()> {
1089 let control1_idx = control1.id() as usize;
1090 let control2_idx = control2.id() as usize;
1091 let target_idx = target.id() as usize;
1092
1093 if control1_idx >= N || control2_idx >= N || target_idx >= N {
1094 return Err(QuantRS2Error::InvalidQubitId(if control1_idx >= N {
1095 control1.id()
1096 } else if control2_idx >= N {
1097 control2.id()
1098 } else {
1099 target.id()
1100 }));
1101 }
1102
1103 if self.parallel {
1105 let mut state_copy = self
1106 .buffer_pool
1107 .lock()
1108 .expect("buffer pool lock poisoned")
1109 .get_buffer(state.len());
1110 state_copy.copy_from_slice(state);
1111
1112 state.par_iter_mut().enumerate().for_each(|(i, amp)| {
1113 let control1_bit = (i >> control1_idx) & 1;
1114 let control2_bit = (i >> control2_idx) & 1;
1115
1116 if control1_bit == 1 && control2_bit == 1 {
1117 let flipped = flip_bit(i, target_idx);
1118 *amp = state_copy[flipped];
1119 }
1120 });
1121
1122 self.buffer_pool
1123 .lock()
1124 .expect("buffer pool lock poisoned")
1125 .return_buffer(state_copy);
1126 } else {
1127 let mut new_state = self
1128 .buffer_pool
1129 .lock()
1130 .expect("buffer pool lock poisoned")
1131 .get_buffer(state.len());
1132 new_state.copy_from_slice(state);
1133
1134 for i in 0..state.len() {
1135 let control1_bit = (i >> control1_idx) & 1;
1136 let control2_bit = (i >> control2_idx) & 1;
1137
1138 if control1_bit == 1 && control2_bit == 1 {
1139 let flipped = flip_bit(i, target_idx);
1140 new_state[flipped] = state[i];
1141 new_state[i] = state[flipped];
1142 }
1143 }
1144
1145 state.copy_from_slice(&new_state);
1146 self.buffer_pool
1147 .lock()
1148 .expect("buffer pool lock poisoned")
1149 .return_buffer(new_state);
1150 }
1151
1152 Ok(())
1153 }
1154
1155 fn apply_fredkin_to_state<const N: usize>(
1157 &self,
1158 state: &mut [Complex64],
1159 control: QubitId,
1160 target1: QubitId,
1161 target2: QubitId,
1162 ) -> QuantRS2Result<()> {
1163 let control_idx = control.id() as usize;
1164 let target1_idx = target1.id() as usize;
1165 let target2_idx = target2.id() as usize;
1166
1167 if control_idx >= N || target1_idx >= N || target2_idx >= N {
1168 return Err(QuantRS2Error::InvalidQubitId(if control_idx >= N {
1169 control.id()
1170 } else if target1_idx >= N {
1171 target1.id()
1172 } else {
1173 target2.id()
1174 }));
1175 }
1176
1177 if self.parallel {
1179 let mut state_copy = self
1180 .buffer_pool
1181 .lock()
1182 .expect("buffer pool lock poisoned")
1183 .get_buffer(state.len());
1184 state_copy.copy_from_slice(state);
1185
1186 state.par_iter_mut().enumerate().for_each(|(i, amp)| {
1187 let control_bit = (i >> control_idx) & 1;
1188 let target1_bit = (i >> target1_idx) & 1;
1189 let target2_bit = (i >> target2_idx) & 1;
1190
1191 if control_bit == 1 && target1_bit != target2_bit {
1192 let swapped = flip_bit(flip_bit(i, target1_idx), target2_idx);
1193 *amp = state_copy[swapped];
1194 }
1195 });
1196
1197 self.buffer_pool
1198 .lock()
1199 .expect("buffer pool lock poisoned")
1200 .return_buffer(state_copy);
1201 } else {
1202 let mut new_state = self
1203 .buffer_pool
1204 .lock()
1205 .expect("buffer pool lock poisoned")
1206 .get_buffer(state.len());
1207 new_state.copy_from_slice(state);
1208
1209 for i in 0..state.len() {
1210 let control_bit = (i >> control_idx) & 1;
1211 let target1_bit = (i >> target1_idx) & 1;
1212 let target2_bit = (i >> target2_idx) & 1;
1213
1214 if control_bit == 1 && target1_bit != target2_bit {
1215 let swapped = flip_bit(flip_bit(i, target1_idx), target2_idx);
1216 new_state[swapped] = state[i];
1217 new_state[i] = state[swapped];
1218 }
1219 }
1220
1221 state.copy_from_slice(&new_state);
1222 self.buffer_pool
1223 .lock()
1224 .expect("buffer pool lock poisoned")
1225 .return_buffer(new_state);
1226 }
1227
1228 Ok(())
1229 }
1230
1231 pub const fn apply_toffoli(
1233 &mut self,
1234 control1: QubitId,
1235 control2: QubitId,
1236 target: QubitId,
1237 ) -> QuantRS2Result<()> {
1238 Ok(())
1240 }
1241
1242 pub const fn apply_fredkin(
1244 &mut self,
1245 control: QubitId,
1246 target1: QubitId,
1247 target2: QubitId,
1248 ) -> QuantRS2Result<()> {
1249 Ok(())
1251 }
1252}