1use crate::simulator::{Simulator, SimulatorResult};
9use quantrs2_circuit::prelude::*;
10use quantrs2_core::gate::GateOp;
11use quantrs2_core::prelude::*;
12use scirs2_core::ndarray::{Array2, ArrayView2};
13use scirs2_core::random::prelude::*;
14use scirs2_core::Complex64;
15use std::collections::HashMap;
16use std::sync::Arc;
17
18pub type StabilizerPhase = u8;
21
22pub mod phase {
24 pub const PLUS_ONE: u8 = 0;
26 pub const PLUS_I: u8 = 1;
28 pub const MINUS_ONE: u8 = 2;
30 pub const MINUS_I: u8 = 3;
32}
33
34#[derive(Debug, Clone)]
45pub struct StabilizerTableau {
46 num_qubits: usize,
48 x_matrix: Array2<bool>,
50 z_matrix: Array2<bool>,
52 phase: Vec<StabilizerPhase>,
54 destab_x: Array2<bool>,
56 destab_z: Array2<bool>,
58 destab_phase: Vec<StabilizerPhase>,
60 stim_format: bool,
62}
63
64impl StabilizerTableau {
65 #[must_use]
67 pub fn new(num_qubits: usize) -> Self {
68 Self::with_format(num_qubits, false)
69 }
70
71 #[must_use]
77 pub fn with_format(num_qubits: usize, stim_format: bool) -> Self {
78 let mut x_matrix = Array2::from_elem((num_qubits, num_qubits), false);
79 let mut z_matrix = Array2::from_elem((num_qubits, num_qubits), false);
80 let mut destab_x = Array2::from_elem((num_qubits, num_qubits), false);
81 let mut destab_z = Array2::from_elem((num_qubits, num_qubits), false);
82
83 for i in 0..num_qubits {
85 z_matrix[[i, i]] = true; destab_x[[i, i]] = true; }
88
89 Self {
90 num_qubits,
91 x_matrix,
92 z_matrix,
93 phase: vec![phase::PLUS_ONE; num_qubits],
94 destab_x,
95 destab_z,
96 destab_phase: vec![phase::PLUS_ONE; num_qubits],
97 stim_format,
98 }
99 }
100
101 pub fn set_stim_format(&mut self, stim_format: bool) {
103 self.stim_format = stim_format;
104 }
105
106 #[must_use]
108 pub const fn is_stim_format(&self) -> bool {
109 self.stim_format
110 }
111
112 #[inline]
114 fn negate_phase(p: StabilizerPhase) -> StabilizerPhase {
115 (p + 2) & 3
116 }
117
118 #[inline]
120 fn multiply_by_i(p: StabilizerPhase) -> StabilizerPhase {
121 (p + 1) & 3
122 }
123
124 #[inline]
126 fn multiply_by_minus_i(p: StabilizerPhase) -> StabilizerPhase {
127 (p + 3) & 3
128 }
129
130 #[inline]
132 fn add_phases(p1: StabilizerPhase, p2: StabilizerPhase) -> StabilizerPhase {
133 (p1 + p2) & 3
134 }
135
136 #[inline]
140 fn rowsum_phase(x1: bool, z1: bool, x2: bool, z2: bool) -> StabilizerPhase {
141 match (x1, z1, x2, z2) {
146 (false, false, _, _) | (_, _, false, false) => 0,
148 (true, false, false, true) => 1,
150 (false, true, true, false) => 3,
152 (true, false, true, true) => 1, (true, true, true, false) => 3, (true, true, false, true) => 1, (false, true, true, true) => 3, (true, false, true, false) => 0, (false, true, false, true) => 0, (true, true, true, true) => 0, }
163 }
164
165 fn compute_multiplication_phase(
168 &self,
169 result_x: &[bool],
170 result_z: &[bool],
171 row_idx: usize,
172 ) -> StabilizerPhase {
173 let mut total_phase: StabilizerPhase = 0;
174 for j in 0..self.num_qubits {
175 let phase_contrib = Self::rowsum_phase(
176 result_x[j],
177 result_z[j],
178 self.x_matrix[[row_idx, j]],
179 self.z_matrix[[row_idx, j]],
180 );
181 total_phase = Self::add_phases(total_phase, phase_contrib);
182 }
183 total_phase
184 }
185
186 pub fn apply_h(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
191 if qubit >= self.num_qubits {
192 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
193 }
194
195 for i in 0..self.num_qubits {
197 let x_val = self.x_matrix[[i, qubit]];
199 let z_val = self.z_matrix[[i, qubit]];
200
201 if x_val && z_val {
207 self.phase[i] = Self::negate_phase(self.phase[i]);
208 }
209
210 self.x_matrix[[i, qubit]] = z_val;
212 self.z_matrix[[i, qubit]] = x_val;
213
214 let dx_val = self.destab_x[[i, qubit]];
216 let dz_val = self.destab_z[[i, qubit]];
217
218 if dx_val && dz_val {
219 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
220 }
221
222 self.destab_x[[i, qubit]] = dz_val;
223 self.destab_z[[i, qubit]] = dx_val;
224 }
225
226 Ok(())
227 }
228
229 pub fn apply_s(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
239 if qubit >= self.num_qubits {
240 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
241 }
242
243 for i in 0..self.num_qubits {
245 let x_val = self.x_matrix[[i, qubit]];
246 let z_val = self.z_matrix[[i, qubit]];
247
248 if x_val {
250 if !z_val {
252 self.z_matrix[[i, qubit]] = true;
254 } else {
255 self.z_matrix[[i, qubit]] = false;
257 self.phase[i] = Self::negate_phase(self.phase[i]);
258 }
259 }
260 let dx_val = self.destab_x[[i, qubit]];
264 let dz_val = self.destab_z[[i, qubit]];
265
266 if dx_val {
267 if !dz_val {
268 self.destab_z[[i, qubit]] = true;
270 } else {
271 self.destab_z[[i, qubit]] = false;
273 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
274 }
275 }
276 }
277
278 Ok(())
279 }
280
281 pub fn apply_cnot(&mut self, control: usize, target: usize) -> Result<(), QuantRS2Error> {
283 if control >= self.num_qubits || target >= self.num_qubits {
284 return Err(QuantRS2Error::InvalidQubitId(control.max(target) as u32));
285 }
286
287 if control == target {
288 return Err(QuantRS2Error::InvalidInput(
289 "CNOT control and target must be different".to_string(),
290 ));
291 }
292
293 for i in 0..self.num_qubits {
295 if self.x_matrix[[i, control]] {
297 self.x_matrix[[i, target]] ^= true;
298 }
299 if self.z_matrix[[i, target]] {
300 self.z_matrix[[i, control]] ^= true;
301 }
302
303 if self.destab_x[[i, control]] {
305 self.destab_x[[i, target]] ^= true;
306 }
307 if self.destab_z[[i, target]] {
308 self.destab_z[[i, control]] ^= true;
309 }
310 }
311
312 Ok(())
313 }
314
315 pub fn apply_x(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
320 if qubit >= self.num_qubits {
321 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
322 }
323
324 for i in 0..self.num_qubits {
326 if self.z_matrix[[i, qubit]] {
327 self.phase[i] = Self::negate_phase(self.phase[i]);
328 }
329 if self.destab_z[[i, qubit]] {
330 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
331 }
332 }
333
334 Ok(())
335 }
336
337 pub fn apply_y(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
342 if qubit >= self.num_qubits {
343 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
344 }
345
346 for i in 0..self.num_qubits {
348 let has_x = self.x_matrix[[i, qubit]];
349 let has_z = self.z_matrix[[i, qubit]];
350
351 if has_x != has_z {
353 self.phase[i] = Self::negate_phase(self.phase[i]);
354 }
355
356 let has_dx = self.destab_x[[i, qubit]];
357 let has_dz = self.destab_z[[i, qubit]];
358
359 if has_dx != has_dz {
360 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
361 }
362 }
363
364 Ok(())
365 }
366
367 pub fn apply_z(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
372 if qubit >= self.num_qubits {
373 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
374 }
375
376 for i in 0..self.num_qubits {
378 if self.x_matrix[[i, qubit]] {
379 self.phase[i] = Self::negate_phase(self.phase[i]);
380 }
381 if self.destab_x[[i, qubit]] {
382 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
383 }
384 }
385
386 Ok(())
387 }
388
389 pub fn apply_s_dag(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
396 if qubit >= self.num_qubits {
397 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
398 }
399
400 for i in 0..self.num_qubits {
402 let x_val = self.x_matrix[[i, qubit]];
403 let z_val = self.z_matrix[[i, qubit]];
404
405 if x_val {
406 if !z_val {
407 self.z_matrix[[i, qubit]] = true;
409 self.phase[i] = Self::negate_phase(self.phase[i]);
410 } else {
411 self.z_matrix[[i, qubit]] = false;
413 }
414 }
415 let dx_val = self.destab_x[[i, qubit]];
419 let dz_val = self.destab_z[[i, qubit]];
420
421 if dx_val {
422 if !dz_val {
423 self.destab_z[[i, qubit]] = true;
425 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
426 } else {
427 self.destab_z[[i, qubit]] = false;
429 }
430 }
431 }
432
433 Ok(())
434 }
435
436 pub fn apply_sqrt_x(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
443 if qubit >= self.num_qubits {
444 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
445 }
446
447 for i in 0..self.num_qubits {
449 let x_val = self.x_matrix[[i, qubit]];
450 let z_val = self.z_matrix[[i, qubit]];
451
452 match (x_val, z_val) {
453 (false, false) => {} (true, false) => {} (false, true) => {
456 self.x_matrix[[i, qubit]] = true;
458 }
459 (true, true) => {
460 self.x_matrix[[i, qubit]] = false;
462 self.phase[i] = Self::negate_phase(self.phase[i]);
463 }
464 }
465
466 let dx_val = self.destab_x[[i, qubit]];
468 let dz_val = self.destab_z[[i, qubit]];
469
470 match (dx_val, dz_val) {
471 (false, false) => {}
472 (true, false) => {}
473 (false, true) => {
474 self.destab_x[[i, qubit]] = true;
475 }
476 (true, true) => {
477 self.destab_x[[i, qubit]] = false;
478 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
479 }
480 }
481 }
482
483 Ok(())
484 }
485
486 pub fn apply_sqrt_x_dag(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
493 if qubit >= self.num_qubits {
494 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
495 }
496
497 for i in 0..self.num_qubits {
499 let x_val = self.x_matrix[[i, qubit]];
500 let z_val = self.z_matrix[[i, qubit]];
501
502 match (x_val, z_val) {
503 (false, false) => {}
504 (true, false) => {}
505 (false, true) => {
506 self.x_matrix[[i, qubit]] = true;
508 self.phase[i] = Self::negate_phase(self.phase[i]);
509 }
510 (true, true) => {
511 self.x_matrix[[i, qubit]] = false;
513 }
514 }
515
516 let dx_val = self.destab_x[[i, qubit]];
518 let dz_val = self.destab_z[[i, qubit]];
519
520 match (dx_val, dz_val) {
521 (false, false) => {}
522 (true, false) => {}
523 (false, true) => {
524 self.destab_x[[i, qubit]] = true;
525 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
526 }
527 (true, true) => {
528 self.destab_x[[i, qubit]] = false;
529 }
530 }
531 }
532
533 Ok(())
534 }
535
536 pub fn apply_sqrt_y(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
543 if qubit >= self.num_qubits {
544 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
545 }
546
547 for i in 0..self.num_qubits {
549 let x_val = self.x_matrix[[i, qubit]];
550 let z_val = self.z_matrix[[i, qubit]];
551
552 match (x_val, z_val) {
553 (false, false) => {}
554 (true, false) => {
555 self.x_matrix[[i, qubit]] = false;
557 self.z_matrix[[i, qubit]] = true;
558 }
559 (false, true) => {
560 self.x_matrix[[i, qubit]] = true;
562 self.z_matrix[[i, qubit]] = false;
563 self.phase[i] = Self::negate_phase(self.phase[i]);
564 }
565 (true, true) => {} }
567
568 let dx_val = self.destab_x[[i, qubit]];
570 let dz_val = self.destab_z[[i, qubit]];
571
572 match (dx_val, dz_val) {
573 (false, false) => {}
574 (true, false) => {
575 self.destab_x[[i, qubit]] = false;
576 self.destab_z[[i, qubit]] = true;
577 }
578 (false, true) => {
579 self.destab_x[[i, qubit]] = true;
580 self.destab_z[[i, qubit]] = false;
581 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
582 }
583 (true, true) => {}
584 }
585 }
586
587 Ok(())
588 }
589
590 pub fn apply_sqrt_y_dag(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
597 if qubit >= self.num_qubits {
598 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
599 }
600
601 for i in 0..self.num_qubits {
603 let x_val = self.x_matrix[[i, qubit]];
604 let z_val = self.z_matrix[[i, qubit]];
605
606 match (x_val, z_val) {
607 (false, false) => {}
608 (true, false) => {
609 self.x_matrix[[i, qubit]] = false;
611 self.z_matrix[[i, qubit]] = true;
612 self.phase[i] = Self::negate_phase(self.phase[i]);
613 }
614 (false, true) => {
615 self.x_matrix[[i, qubit]] = true;
617 self.z_matrix[[i, qubit]] = false;
618 }
619 (true, true) => {} }
621
622 let dx_val = self.destab_x[[i, qubit]];
624 let dz_val = self.destab_z[[i, qubit]];
625
626 match (dx_val, dz_val) {
627 (false, false) => {}
628 (true, false) => {
629 self.destab_x[[i, qubit]] = false;
630 self.destab_z[[i, qubit]] = true;
631 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
632 }
633 (false, true) => {
634 self.destab_x[[i, qubit]] = true;
635 self.destab_z[[i, qubit]] = false;
636 }
637 (true, true) => {}
638 }
639 }
640
641 Ok(())
642 }
643
644 pub fn apply_cz(&mut self, control: usize, target: usize) -> Result<(), QuantRS2Error> {
649 if control >= self.num_qubits {
650 return Err(QuantRS2Error::InvalidQubitId(control as u32));
651 }
652 if target >= self.num_qubits {
653 return Err(QuantRS2Error::InvalidQubitId(target as u32));
654 }
655
656 for i in 0..self.num_qubits {
658 if self.x_matrix[[i, control]] && self.x_matrix[[i, target]] {
659 self.phase[i] = Self::negate_phase(self.phase[i]);
660 }
661 if self.x_matrix[[i, control]] {
662 self.z_matrix[[i, target]] = !self.z_matrix[[i, target]];
663 }
664 if self.x_matrix[[i, target]] {
665 self.z_matrix[[i, control]] = !self.z_matrix[[i, control]];
666 }
667
668 if self.destab_x[[i, control]] && self.destab_x[[i, target]] {
670 self.destab_phase[i] = Self::negate_phase(self.destab_phase[i]);
671 }
672 if self.destab_x[[i, control]] {
673 self.destab_z[[i, target]] = !self.destab_z[[i, target]];
674 }
675 if self.destab_x[[i, target]] {
676 self.destab_z[[i, control]] = !self.destab_z[[i, control]];
677 }
678 }
679
680 Ok(())
681 }
682
683 pub fn apply_cy(&mut self, control: usize, target: usize) -> Result<(), QuantRS2Error> {
685 if control >= self.num_qubits {
686 return Err(QuantRS2Error::InvalidQubitId(control as u32));
687 }
688 if target >= self.num_qubits {
689 return Err(QuantRS2Error::InvalidQubitId(target as u32));
690 }
691
692 self.apply_s_dag(target)?;
694 self.apply_cnot(control, target)?;
695 self.apply_s(target)?;
696
697 Ok(())
698 }
699
700 pub fn apply_swap(&mut self, qubit1: usize, qubit2: usize) -> Result<(), QuantRS2Error> {
702 if qubit1 >= self.num_qubits {
703 return Err(QuantRS2Error::InvalidQubitId(qubit1 as u32));
704 }
705 if qubit2 >= self.num_qubits {
706 return Err(QuantRS2Error::InvalidQubitId(qubit2 as u32));
707 }
708
709 self.apply_cnot(qubit1, qubit2)?;
711 self.apply_cnot(qubit2, qubit1)?;
712 self.apply_cnot(qubit1, qubit2)?;
713
714 Ok(())
715 }
716
717 pub fn measure(&mut self, qubit: usize) -> Result<bool, QuantRS2Error> {
724 if qubit >= self.num_qubits {
725 return Err(QuantRS2Error::InvalidQubitId(qubit as u32));
726 }
727
728 let mut anticommuting_row = None;
730
731 for i in 0..self.num_qubits {
732 if self.x_matrix[[i, qubit]] {
733 anticommuting_row = Some(i);
734 break;
735 }
736 }
737
738 if let Some(p) = anticommuting_row {
739 for j in 0..self.num_qubits {
742 self.x_matrix[[p, j]] = false;
743 self.z_matrix[[p, j]] = j == qubit;
744 }
745
746 let mut rng = thread_rng();
748 let outcome = rng.gen_bool(0.5);
749 self.phase[p] = if outcome {
751 phase::MINUS_ONE
752 } else {
753 phase::PLUS_ONE
754 };
755
756 for i in 0..self.num_qubits {
758 if i != p && self.x_matrix[[i, qubit]] {
759 let mut total_phase_contrib: StabilizerPhase = 0;
762 for j in 0..self.num_qubits {
763 let phase_contrib = Self::rowsum_phase(
764 self.x_matrix[[i, j]],
765 self.z_matrix[[i, j]],
766 self.x_matrix[[p, j]],
767 self.z_matrix[[p, j]],
768 );
769 total_phase_contrib = Self::add_phases(total_phase_contrib, phase_contrib);
770 self.x_matrix[[i, j]] ^= self.x_matrix[[p, j]];
771 self.z_matrix[[i, j]] ^= self.z_matrix[[p, j]];
772 }
773 self.phase[i] = Self::add_phases(
775 Self::add_phases(self.phase[i], self.phase[p]),
776 total_phase_contrib,
777 );
778 }
779 }
780
781 Ok(outcome)
782 } else {
783 let mut pivot_row = None;
795 for i in 0..self.num_qubits {
796 if self.z_matrix[[i, qubit]] && !self.x_matrix[[i, qubit]] {
797 pivot_row = Some(i);
798 break;
799 }
800 }
801
802 let Some(pivot) = pivot_row else {
803 return Ok(false);
805 };
806
807 let mut result_x = vec![false; self.num_qubits];
809 let mut result_z = vec![false; self.num_qubits];
810 let mut result_phase = self.phase[pivot];
811
812 for j in 0..self.num_qubits {
813 result_x[j] = self.x_matrix[[pivot, j]];
814 result_z[j] = self.z_matrix[[pivot, j]];
815 }
816
817 for other_qubit in 0..self.num_qubits {
819 if other_qubit == qubit {
820 continue;
821 }
822
823 if result_z[other_qubit] && !result_x[other_qubit] {
825 for i in 0..self.num_qubits {
827 if i == pivot {
828 continue;
829 }
830 if self.z_matrix[[i, other_qubit]] && !self.x_matrix[[i, other_qubit]] {
831 let phase_contrib =
833 self.compute_multiplication_phase(&result_x, &result_z, i);
834 result_phase = Self::add_phases(result_phase, self.phase[i]);
835 result_phase = Self::add_phases(result_phase, phase_contrib);
836
837 for j in 0..self.num_qubits {
838 result_x[j] ^= self.x_matrix[[i, j]];
839 result_z[j] ^= self.z_matrix[[i, j]];
840 }
841 break;
842 }
843 }
844 }
845 }
846
847 let outcome = result_phase >= phase::MINUS_ONE;
851
852 Ok(outcome)
853 }
854 }
855
856 pub fn measure_x(&mut self, qubit: usize) -> Result<bool, QuantRS2Error> {
860 self.apply_h(qubit)?;
862
863 let outcome = self.measure(qubit)?;
865
866 self.apply_h(qubit)?;
868
869 Ok(outcome)
870 }
871
872 pub fn measure_y(&mut self, qubit: usize) -> Result<bool, QuantRS2Error> {
876 self.apply_s_dag(qubit)?;
878 self.apply_h(qubit)?;
879
880 let outcome = self.measure(qubit)?;
882
883 self.apply_h(qubit)?;
885 self.apply_s(qubit)?;
886
887 Ok(outcome)
888 }
889
890 pub fn reset(&mut self, qubit: usize) -> Result<(), QuantRS2Error> {
894 let outcome = self.measure(qubit)?;
896
897 if outcome {
899 self.apply_x(qubit)?;
900 }
901
902 Ok(())
903 }
904
905 #[must_use]
917 pub fn get_stabilizers(&self) -> Vec<String> {
918 let mut stabilizers = Vec::new();
919 let identity_char = if self.stim_format { '_' } else { 'I' };
920
921 for i in 0..self.num_qubits {
922 let mut stab = String::new();
923
924 match self.phase[i] & 3 {
926 phase::PLUS_ONE => stab.push('+'),
927 phase::PLUS_I => stab.push_str("+i"),
928 phase::MINUS_ONE => stab.push('-'),
929 phase::MINUS_I => stab.push_str("-i"),
930 _ => unreachable!(), }
932
933 for j in 0..self.num_qubits {
935 let has_x = self.x_matrix[[i, j]];
936 let has_z = self.z_matrix[[i, j]];
937
938 match (has_x, has_z) {
939 (false, false) => stab.push(identity_char),
940 (true, false) => stab.push('X'),
941 (false, true) => stab.push('Z'),
942 (true, true) => stab.push('Y'),
943 }
944 }
945
946 stabilizers.push(stab);
947 }
948
949 stabilizers
950 }
951
952 #[must_use]
956 pub fn get_destabilizers(&self) -> Vec<String> {
957 let mut destabilizers = Vec::new();
958 let identity_char = if self.stim_format { '_' } else { 'I' };
959
960 for i in 0..self.num_qubits {
961 let mut destab = String::new();
962
963 match self.destab_phase[i] & 3 {
965 phase::PLUS_ONE => destab.push('+'),
966 phase::PLUS_I => destab.push_str("+i"),
967 phase::MINUS_ONE => destab.push('-'),
968 phase::MINUS_I => destab.push_str("-i"),
969 _ => unreachable!(), }
971
972 for j in 0..self.num_qubits {
974 let has_x = self.destab_x[[i, j]];
975 let has_z = self.destab_z[[i, j]];
976
977 match (has_x, has_z) {
978 (false, false) => destab.push(identity_char),
979 (true, false) => destab.push('X'),
980 (false, true) => destab.push('Z'),
981 (true, true) => destab.push('Y'),
982 }
983 }
984
985 destabilizers.push(destab);
986 }
987
988 destabilizers
989 }
990}
991
992#[derive(Debug, Clone)]
994pub struct StabilizerSimulator {
995 pub tableau: StabilizerTableau,
997 measurement_record: Vec<(usize, bool)>,
998}
999
1000impl StabilizerSimulator {
1001 #[must_use]
1003 pub fn new(num_qubits: usize) -> Self {
1004 Self {
1005 tableau: StabilizerTableau::new(num_qubits),
1006 measurement_record: Vec::new(),
1007 }
1008 }
1009
1010 pub fn apply_gate(&mut self, gate: StabilizerGate) -> Result<(), QuantRS2Error> {
1012 match gate {
1013 StabilizerGate::H(q) => self.tableau.apply_h(q),
1014 StabilizerGate::S(q) => self.tableau.apply_s(q),
1015 StabilizerGate::SDag(q) => self.tableau.apply_s_dag(q),
1016 StabilizerGate::SqrtX(q) => self.tableau.apply_sqrt_x(q),
1017 StabilizerGate::SqrtXDag(q) => self.tableau.apply_sqrt_x_dag(q),
1018 StabilizerGate::SqrtY(q) => self.tableau.apply_sqrt_y(q),
1019 StabilizerGate::SqrtYDag(q) => self.tableau.apply_sqrt_y_dag(q),
1020 StabilizerGate::X(q) => self.tableau.apply_x(q),
1021 StabilizerGate::Y(q) => self.tableau.apply_y(q),
1022 StabilizerGate::Z(q) => self.tableau.apply_z(q),
1023 StabilizerGate::CNOT(c, t) => self.tableau.apply_cnot(c, t),
1024 StabilizerGate::CZ(c, t) => self.tableau.apply_cz(c, t),
1025 StabilizerGate::CY(c, t) => self.tableau.apply_cy(c, t),
1026 StabilizerGate::SWAP(q1, q2) => self.tableau.apply_swap(q1, q2),
1027 }
1028 }
1029
1030 pub fn measure(&mut self, qubit: usize) -> Result<bool, QuantRS2Error> {
1032 let outcome = self.tableau.measure(qubit)?;
1033 self.measurement_record.push((qubit, outcome));
1034 Ok(outcome)
1035 }
1036
1037 #[must_use]
1039 pub fn get_stabilizers(&self) -> Vec<String> {
1040 self.tableau.get_stabilizers()
1041 }
1042
1043 #[must_use]
1045 pub fn get_measurements(&self) -> &[(usize, bool)] {
1046 &self.measurement_record
1047 }
1048
1049 pub fn reset(&mut self) {
1051 let num_qubits = self.tableau.num_qubits;
1052 self.tableau = StabilizerTableau::new(num_qubits);
1053 self.measurement_record.clear();
1054 }
1055
1056 #[must_use]
1058 pub const fn num_qubits(&self) -> usize {
1059 self.tableau.num_qubits
1060 }
1061
1062 #[must_use]
1065 pub fn get_statevector(&self) -> Vec<Complex64> {
1066 let n = self.tableau.num_qubits;
1067 let dim = 1 << n;
1068 let mut state = vec![Complex64::new(0.0, 0.0); dim];
1069
1070 state[0] = Complex64::new(1.0, 0.0);
1077 state
1078 }
1079}
1080
1081#[derive(Debug, Clone, Copy)]
1083pub enum StabilizerGate {
1084 H(usize),
1085 S(usize),
1086 SDag(usize),
1087 SqrtX(usize),
1088 SqrtXDag(usize),
1089 SqrtY(usize),
1090 SqrtYDag(usize),
1091 X(usize),
1092 Y(usize),
1093 Z(usize),
1094 CNOT(usize, usize),
1095 CZ(usize, usize),
1096 CY(usize, usize),
1097 SWAP(usize, usize),
1098}
1099
1100#[must_use]
1102pub fn is_clifford_circuit<const N: usize>(circuit: &Circuit<N>) -> bool {
1103 circuit.gates().iter().all(|gate| {
1106 matches!(
1107 gate.name(),
1108 "H" | "S" | "S†" | "CNOT" | "X" | "Y" | "Z" | "CZ" | "Phase" | "PhaseDagger"
1109 )
1110 })
1111}
1112
1113fn gate_to_stabilizer(gate: &Arc<dyn GateOp + Send + Sync>) -> Option<StabilizerGate> {
1115 let gate_name = gate.name();
1116 let qubits = gate.qubits();
1117
1118 match gate_name {
1119 "H" => {
1120 if qubits.len() == 1 {
1121 Some(StabilizerGate::H(qubits[0].0 as usize))
1122 } else {
1123 None
1124 }
1125 }
1126 "S" | "Phase" => {
1127 if qubits.len() == 1 {
1128 Some(StabilizerGate::S(qubits[0].0 as usize))
1129 } else {
1130 None
1131 }
1132 }
1133 "X" => {
1134 if qubits.len() == 1 {
1135 Some(StabilizerGate::X(qubits[0].0 as usize))
1136 } else {
1137 None
1138 }
1139 }
1140 "Y" => {
1141 if qubits.len() == 1 {
1142 Some(StabilizerGate::Y(qubits[0].0 as usize))
1143 } else {
1144 None
1145 }
1146 }
1147 "Z" => {
1148 if qubits.len() == 1 {
1149 Some(StabilizerGate::Z(qubits[0].0 as usize))
1150 } else {
1151 None
1152 }
1153 }
1154 "CNOT" => {
1155 if qubits.len() == 2 {
1156 Some(StabilizerGate::CNOT(
1157 qubits[0].0 as usize,
1158 qubits[1].0 as usize,
1159 ))
1160 } else {
1161 None
1162 }
1163 }
1164 "CZ" => {
1165 if qubits.len() == 2 {
1166 None
1170 } else {
1171 None
1172 }
1173 }
1174 _ => None,
1175 }
1176}
1177
1178impl Simulator for StabilizerSimulator {
1180 fn run<const N: usize>(
1181 &mut self,
1182 circuit: &Circuit<N>,
1183 ) -> crate::error::Result<SimulatorResult<N>> {
1184 let mut sim = Self::new(N);
1186
1187 for gate in circuit.gates() {
1189 if let Some(stab_gate) = gate_to_stabilizer(gate) {
1190 let _ = sim.apply_gate(stab_gate);
1192 }
1193 }
1194
1195 let amplitudes = sim.get_statevector();
1197
1198 Ok(SimulatorResult::new(amplitudes))
1199 }
1200}
1201
1202pub struct CliffordCircuitBuilder {
1204 gates: Vec<StabilizerGate>,
1205 num_qubits: usize,
1206}
1207
1208impl CliffordCircuitBuilder {
1209 #[must_use]
1211 pub const fn new(num_qubits: usize) -> Self {
1212 Self {
1213 gates: Vec::new(),
1214 num_qubits,
1215 }
1216 }
1217
1218 #[must_use]
1220 pub fn h(mut self, qubit: usize) -> Self {
1221 self.gates.push(StabilizerGate::H(qubit));
1222 self
1223 }
1224
1225 #[must_use]
1227 pub fn s(mut self, qubit: usize) -> Self {
1228 self.gates.push(StabilizerGate::S(qubit));
1229 self
1230 }
1231
1232 #[must_use]
1234 pub fn s_dag(mut self, qubit: usize) -> Self {
1235 self.gates.push(StabilizerGate::SDag(qubit));
1236 self
1237 }
1238
1239 #[must_use]
1241 pub fn sqrt_x(mut self, qubit: usize) -> Self {
1242 self.gates.push(StabilizerGate::SqrtX(qubit));
1243 self
1244 }
1245
1246 #[must_use]
1248 pub fn sqrt_x_dag(mut self, qubit: usize) -> Self {
1249 self.gates.push(StabilizerGate::SqrtXDag(qubit));
1250 self
1251 }
1252
1253 #[must_use]
1255 pub fn sqrt_y(mut self, qubit: usize) -> Self {
1256 self.gates.push(StabilizerGate::SqrtY(qubit));
1257 self
1258 }
1259
1260 #[must_use]
1262 pub fn sqrt_y_dag(mut self, qubit: usize) -> Self {
1263 self.gates.push(StabilizerGate::SqrtYDag(qubit));
1264 self
1265 }
1266
1267 #[must_use]
1269 pub fn x(mut self, qubit: usize) -> Self {
1270 self.gates.push(StabilizerGate::X(qubit));
1271 self
1272 }
1273
1274 #[must_use]
1276 pub fn y(mut self, qubit: usize) -> Self {
1277 self.gates.push(StabilizerGate::Y(qubit));
1278 self
1279 }
1280
1281 #[must_use]
1283 pub fn z(mut self, qubit: usize) -> Self {
1284 self.gates.push(StabilizerGate::Z(qubit));
1285 self
1286 }
1287
1288 #[must_use]
1290 pub fn cnot(mut self, control: usize, target: usize) -> Self {
1291 self.gates.push(StabilizerGate::CNOT(control, target));
1292 self
1293 }
1294
1295 #[must_use]
1297 pub fn cz(mut self, control: usize, target: usize) -> Self {
1298 self.gates.push(StabilizerGate::CZ(control, target));
1299 self
1300 }
1301
1302 #[must_use]
1304 pub fn cy(mut self, control: usize, target: usize) -> Self {
1305 self.gates.push(StabilizerGate::CY(control, target));
1306 self
1307 }
1308
1309 #[must_use]
1311 pub fn swap(mut self, qubit1: usize, qubit2: usize) -> Self {
1312 self.gates.push(StabilizerGate::SWAP(qubit1, qubit2));
1313 self
1314 }
1315
1316 pub fn run(self) -> Result<StabilizerSimulator, QuantRS2Error> {
1318 let mut sim = StabilizerSimulator::new(self.num_qubits);
1319
1320 for gate in self.gates {
1321 sim.apply_gate(gate)?;
1322 }
1323
1324 Ok(sim)
1325 }
1326}
1327
1328#[cfg(test)]
1329mod tests {
1330 use super::*;
1331
1332 #[test]
1333 fn test_stabilizer_init() {
1334 let sim = StabilizerSimulator::new(3);
1335 let stabs = sim.get_stabilizers();
1336
1337 assert_eq!(stabs.len(), 3);
1338 assert_eq!(stabs[0], "+ZII");
1339 assert_eq!(stabs[1], "+IZI");
1340 assert_eq!(stabs[2], "+IIZ");
1341 }
1342
1343 #[test]
1344 fn test_hadamard_gate() {
1345 let mut sim = StabilizerSimulator::new(1);
1346 sim.apply_gate(StabilizerGate::H(0))
1347 .expect("Hadamard gate application should succeed");
1348
1349 let stabs = sim.get_stabilizers();
1350 assert_eq!(stabs[0], "+X");
1351 }
1352
1353 #[test]
1354 fn test_bell_state() {
1355 let mut sim = StabilizerSimulator::new(2);
1356 sim.apply_gate(StabilizerGate::H(0))
1357 .expect("Hadamard gate application should succeed");
1358 sim.apply_gate(StabilizerGate::CNOT(0, 1))
1359 .expect("CNOT gate application should succeed");
1360
1361 let stabs = sim.get_stabilizers();
1362 assert!(stabs.contains(&"+XX".to_string()));
1363 assert!(stabs.contains(&"+ZZ".to_string()));
1364 }
1365
1366 #[test]
1367 fn test_ghz_state() {
1368 let mut sim = StabilizerSimulator::new(3);
1369 sim.apply_gate(StabilizerGate::H(0))
1370 .expect("Hadamard gate application should succeed");
1371 sim.apply_gate(StabilizerGate::CNOT(0, 1))
1372 .expect("CNOT gate application should succeed");
1373 sim.apply_gate(StabilizerGate::CNOT(1, 2))
1374 .expect("CNOT gate application should succeed");
1375
1376 let stabs = sim.get_stabilizers();
1377 assert!(stabs.contains(&"+XXX".to_string()));
1378 assert!(stabs.contains(&"+ZZI".to_string()));
1379 assert!(stabs.contains(&"+IZZ".to_string()));
1380 }
1381
1382 #[test]
1383 fn test_s_dag_gate() {
1384 let mut sim = StabilizerSimulator::new(1);
1386 sim.apply_gate(StabilizerGate::S(0))
1387 .expect("S gate application should succeed");
1388 sim.apply_gate(StabilizerGate::SDag(0))
1389 .expect("S† gate application should succeed");
1390
1391 let stabs = sim.get_stabilizers();
1392 assert_eq!(stabs[0], "+Z"); }
1394
1395 #[test]
1396 fn test_sqrt_x_gate() {
1397 let mut sim1 = StabilizerSimulator::new(1);
1399 sim1.apply_gate(StabilizerGate::SqrtX(0))
1400 .expect("√X gate application should succeed");
1401 sim1.apply_gate(StabilizerGate::SqrtX(0))
1402 .expect("√X gate application should succeed");
1403
1404 let stabs1 = sim1.get_stabilizers();
1405
1406 let mut sim2 = StabilizerSimulator::new(1);
1408 sim2.apply_gate(StabilizerGate::X(0))
1409 .expect("X gate application should succeed");
1410
1411 let stabs2 = sim2.get_stabilizers();
1412
1413 assert!(stabs1[0] == "+Z" || stabs1[0] == "-Z");
1415 assert!(stabs2[0] == "+Z" || stabs2[0] == "-Z");
1416 }
1417
1418 #[test]
1419 fn test_sqrt_y_gate() {
1420 let mut sim1 = StabilizerSimulator::new(1);
1422 sim1.apply_gate(StabilizerGate::SqrtY(0))
1423 .expect("√Y gate application should succeed");
1424 sim1.apply_gate(StabilizerGate::SqrtY(0))
1425 .expect("√Y gate application should succeed");
1426
1427 let stabs1 = sim1.get_stabilizers();
1428
1429 let mut sim2 = StabilizerSimulator::new(1);
1431 sim2.apply_gate(StabilizerGate::Y(0))
1432 .expect("Y gate application should succeed");
1433
1434 let stabs2 = sim2.get_stabilizers();
1435 assert_eq!(stabs1[0], stabs2[0]);
1436 }
1437
1438 #[test]
1439 fn test_cz_gate() {
1440 let mut sim = StabilizerSimulator::new(2);
1442 sim.apply_gate(StabilizerGate::H(0))
1443 .expect("Hadamard gate application should succeed");
1444 sim.apply_gate(StabilizerGate::H(1))
1445 .expect("Hadamard gate application should succeed");
1446 sim.apply_gate(StabilizerGate::CZ(0, 1))
1447 .expect("CZ gate application should succeed");
1448
1449 let stabs = sim.get_stabilizers();
1450 assert!(stabs.len() == 2);
1453 }
1454
1455 #[test]
1456 fn test_cy_gate() {
1457 let mut sim = StabilizerSimulator::new(2);
1459 sim.apply_gate(StabilizerGate::H(0))
1460 .expect("Hadamard gate application should succeed");
1461 sim.apply_gate(StabilizerGate::CY(0, 1))
1462 .expect("CY gate application should succeed");
1463
1464 let stabs = sim.get_stabilizers();
1465 assert!(stabs.len() == 2);
1466 }
1467
1468 #[test]
1469 fn test_swap_gate() {
1470 let mut sim = StabilizerSimulator::new(2);
1472 sim.apply_gate(StabilizerGate::X(1))
1474 .expect("X gate application should succeed");
1475
1476 sim.apply_gate(StabilizerGate::SWAP(0, 1))
1478 .expect("SWAP gate application should succeed");
1479
1480 let stabs = sim.get_stabilizers();
1481 assert!(stabs.len() == 2);
1483 }
1484
1485 #[test]
1486 fn test_builder_pattern_new_gates() {
1487 let sim = CliffordCircuitBuilder::new(2)
1489 .h(0)
1490 .s_dag(0)
1491 .sqrt_x(1)
1492 .cz(0, 1)
1493 .run()
1494 .expect("Circuit execution should succeed");
1495
1496 let stabs = sim.get_stabilizers();
1497 assert!(stabs.len() == 2);
1498 }
1499
1500 #[test]
1501 fn test_large_clifford_circuit() {
1502 let mut sim = StabilizerSimulator::new(100);
1504
1505 for i in 0..100 {
1507 sim.apply_gate(StabilizerGate::H(i))
1508 .expect("Hadamard gate application should succeed");
1509 }
1510
1511 for i in 0..99 {
1513 sim.apply_gate(StabilizerGate::CNOT(i, i + 1))
1514 .expect("CNOT gate application should succeed");
1515 }
1516
1517 let stabs = sim.get_stabilizers();
1518 assert_eq!(stabs.len(), 100);
1519 }
1520
1521 #[test]
1522 fn test_measurement_randomness() {
1523 let mut sim = StabilizerSimulator::new(1);
1525 sim.apply_gate(StabilizerGate::H(0))
1526 .expect("Hadamard gate application should succeed");
1527
1528 let mut outcomes = Vec::new();
1530 for _ in 0..10 {
1531 let mut test_sim = StabilizerSimulator::new(1);
1532 test_sim
1533 .apply_gate(StabilizerGate::H(0))
1534 .expect("Hadamard gate application should succeed");
1535 let outcome = test_sim.measure(0).expect("Measurement should succeed");
1536 outcomes.push(outcome);
1537 }
1538
1539 let first = outcomes[0];
1541 let all_same = outcomes.iter().all(|&x| x == first);
1542 assert!(
1543 !all_same || outcomes.len() < 5,
1544 "Measurements should show randomness"
1545 );
1546 }
1547
1548 #[test]
1549 fn test_measure_x_basis() {
1550 let mut sim = StabilizerSimulator::new(1);
1552 sim.apply_gate(StabilizerGate::H(0))
1553 .expect("Hadamard gate application should succeed");
1554
1555 let outcome = sim
1557 .tableau
1558 .measure_x(0)
1559 .expect("X-basis measurement should succeed");
1560
1561 assert!(!outcome);
1563 }
1564
1565 #[test]
1566 fn test_measure_y_basis() {
1567 let mut sim = StabilizerSimulator::new(1);
1570 sim.apply_gate(StabilizerGate::H(0)).unwrap();
1571 sim.apply_gate(StabilizerGate::S(0)).unwrap();
1572
1573 let stabs = sim.get_stabilizers();
1575 assert_eq!(stabs[0], "+Y");
1576
1577 let outcome = sim
1579 .tableau
1580 .measure_y(0)
1581 .expect("Y-basis measurement should succeed");
1582
1583 assert!(!outcome);
1585 }
1586
1587 #[test]
1588 fn test_reset_operation() {
1589 let mut sim = StabilizerSimulator::new(1);
1591 sim.apply_gate(StabilizerGate::X(0))
1592 .expect("X gate application should succeed");
1593
1594 sim.tableau.reset(0).expect("Reset should succeed");
1596
1597 let outcome = sim.measure(0).expect("Measurement should succeed");
1599 assert!(!outcome);
1600
1601 let stabs = sim.get_stabilizers();
1603 assert_eq!(stabs[0], "+Z");
1604 }
1605
1606 #[test]
1607 fn test_reset_from_superposition() {
1608 let mut sim = StabilizerSimulator::new(1);
1610 sim.apply_gate(StabilizerGate::H(0))
1611 .expect("Hadamard gate application should succeed");
1612
1613 sim.tableau.reset(0).expect("Reset should succeed");
1615
1616 let outcome = sim.measure(0).expect("Measurement should succeed");
1618 assert!(!outcome);
1619 }
1620
1621 #[test]
1622 fn test_x_y_measurements_commute() {
1623 let mut sim = StabilizerSimulator::new(2);
1625 sim.apply_gate(StabilizerGate::H(0)).unwrap();
1626 sim.apply_gate(StabilizerGate::H(1)).unwrap();
1627 sim.apply_gate(StabilizerGate::S(1)).unwrap();
1628
1629 let _outcome_x = sim.tableau.measure_x(0).unwrap();
1631 let _outcome_y = sim.tableau.measure_y(1).unwrap();
1632
1633 }
1635
1636 #[test]
1637 fn test_imaginary_phase_tracking() {
1638 let mut tableau = StabilizerTableau::new(1);
1645 tableau.apply_h(0).unwrap();
1646 tableau.apply_s(0).unwrap();
1647
1648 let stabs = tableau.get_stabilizers();
1649 assert_eq!(stabs[0], "+Y");
1653 }
1654
1655 #[test]
1656 fn test_imaginary_phase_with_s_dag() {
1657 let mut tableau = StabilizerTableau::new(1);
1660 tableau.apply_h(0).unwrap();
1661 tableau.apply_s_dag(0).unwrap();
1662
1663 let stabs = tableau.get_stabilizers();
1664 assert_eq!(stabs[0], "-Y");
1666 }
1667
1668 #[test]
1669 fn test_stim_format_identity() {
1670 let mut tableau = StabilizerTableau::with_format(2, true);
1672 let stabs = tableau.get_stabilizers();
1673
1674 assert_eq!(stabs[0], "+Z_");
1676 assert_eq!(stabs[1], "+_Z");
1677
1678 tableau.apply_h(0).unwrap();
1680 let stabs = tableau.get_stabilizers();
1681 assert_eq!(stabs[0], "+X_");
1682 assert_eq!(stabs[1], "+_Z");
1683 }
1684
1685 #[test]
1686 fn test_standard_format_identity() {
1687 let tableau = StabilizerTableau::with_format(2, false);
1689 let stabs = tableau.get_stabilizers();
1690
1691 assert_eq!(stabs[0], "+ZI");
1692 assert_eq!(stabs[1], "+IZ");
1693 }
1694
1695 #[test]
1696 fn test_destabilizers_output() {
1697 let mut tableau = StabilizerTableau::new(2);
1699
1700 let destabs = tableau.get_destabilizers();
1702 assert_eq!(destabs[0], "+XI");
1703 assert_eq!(destabs[1], "+IX");
1704
1705 tableau.apply_h(0).unwrap();
1707 let destabs = tableau.get_destabilizers();
1708 assert_eq!(destabs[0], "+ZI");
1709 assert_eq!(destabs[1], "+IX");
1710 }
1711
1712 #[test]
1713 fn test_phase_constants() {
1714 assert_eq!(phase::PLUS_ONE, 0);
1716 assert_eq!(phase::PLUS_I, 1);
1717 assert_eq!(phase::MINUS_ONE, 2);
1718 assert_eq!(phase::MINUS_I, 3);
1719 }
1720
1721 #[test]
1722 fn test_phase_arithmetic() {
1723 assert_eq!(
1726 StabilizerTableau::negate_phase(phase::PLUS_ONE),
1727 phase::MINUS_ONE
1728 );
1729 assert_eq!(
1730 StabilizerTableau::negate_phase(phase::PLUS_I),
1731 phase::MINUS_I
1732 );
1733 assert_eq!(
1734 StabilizerTableau::negate_phase(phase::MINUS_ONE),
1735 phase::PLUS_ONE
1736 );
1737 assert_eq!(
1738 StabilizerTableau::negate_phase(phase::MINUS_I),
1739 phase::PLUS_I
1740 );
1741
1742 assert_eq!(
1744 StabilizerTableau::multiply_by_i(phase::PLUS_ONE),
1745 phase::PLUS_I
1746 );
1747 assert_eq!(
1748 StabilizerTableau::multiply_by_i(phase::PLUS_I),
1749 phase::MINUS_ONE
1750 );
1751 assert_eq!(
1752 StabilizerTableau::multiply_by_i(phase::MINUS_ONE),
1753 phase::MINUS_I
1754 );
1755 assert_eq!(
1756 StabilizerTableau::multiply_by_i(phase::MINUS_I),
1757 phase::PLUS_ONE
1758 );
1759
1760 assert_eq!(
1762 StabilizerTableau::multiply_by_minus_i(phase::PLUS_ONE),
1763 phase::MINUS_I
1764 );
1765 assert_eq!(
1766 StabilizerTableau::multiply_by_minus_i(phase::PLUS_I),
1767 phase::PLUS_ONE
1768 );
1769 assert_eq!(
1770 StabilizerTableau::multiply_by_minus_i(phase::MINUS_ONE),
1771 phase::PLUS_I
1772 );
1773 assert_eq!(
1774 StabilizerTableau::multiply_by_minus_i(phase::MINUS_I),
1775 phase::MINUS_ONE
1776 );
1777 }
1778
1779 #[test]
1780 fn test_y_gate_phase_tracking() {
1781 let mut tableau = StabilizerTableau::new(1);
1784 tableau.apply_y(0).unwrap();
1785
1786 let stabs = tableau.get_stabilizers();
1787 assert_eq!(stabs[0], "-Z");
1789 }
1790
1791 #[test]
1792 fn test_sqrt_gates_produce_imaginary_phases() {
1793 let mut tableau = StabilizerTableau::new(1);
1796 tableau.apply_sqrt_y(0).unwrap();
1797
1798 let stabs = tableau.get_stabilizers();
1799 assert_eq!(stabs[0], "-X");
1801 }
1802}