1use crate::{CliffordSimulator, Gens, QuantumSimulator};
14use core::fmt::Debug;
15use core::mem;
16use pecos_core::SimRng;
17use pecos_core::{IndexableElement, Set};
18use rand_chacha::ChaCha8Rng;
19#[derive(Clone, Debug)]
22pub struct SparseStab<T, E, R = ChaCha8Rng>
23where
24 T: for<'a> Set<'a, Element = E>,
25 E: IndexableElement,
26 R: SimRng,
27{
28 num_qubits: usize,
29 stabs: Gens<T, E>,
30 destabs: Gens<T, E>,
31 rng: R,
32}
33impl<T, E, R> SparseStab<T, E, R>
34where
35 E: IndexableElement,
36 R: SimRng,
37 T: for<'a> Set<'a, Element = E>,
38{
39 #[inline]
40 #[must_use]
41 fn new(num_qubits: usize) -> Self {
42 let rng = SimRng::from_entropy();
43 Self::with_rng(num_qubits, rng)
44 }
45
46 #[inline]
47 pub fn with_rng(num_qubits: usize, rng: R) -> Self {
48 let mut stab = Self {
49 num_qubits,
50 stabs: Gens::<T, E>::new(num_qubits),
51 destabs: Gens::<T, E>::new(num_qubits),
52 rng,
53 };
54 stab.reset();
55 stab
56 }
57
58 #[expect(clippy::single_call_fn)]
59 #[inline]
60 fn reset(&mut self) -> &mut Self {
61 self.stabs.init_all_z();
62 self.destabs.init_all_x();
63 self
64 }
65
66 #[inline]
67 pub fn verify_matrix(&self) {
68 Self::check_row_eq_col(&self.stabs);
69 Self::check_row_eq_col(&self.destabs);
70
71 todo!()
75 }
76
77 #[inline]
78 fn check_row_eq_col(gens: &Gens<T, E>) {
79 for (i, row) in gens.row_x.iter().enumerate() {
81 for j in row.iter() {
82 assert!(
83 gens.col_x[j.to_usize()].contains(&E::from_usize(i)),
84 "Column-wise sparse matrix doesn't match row-wise spare matrix"
85 );
86 }
87 }
88 }
89
90 fn tableau_string(num_qubits: usize, gens: &Gens<T, E>) -> String {
92 let mut result =
94 String::with_capacity(num_qubits * gens.row_x.len() + gens.row_x.len() + 2);
95 for i in 0..gens.row_x.len() {
96 if gens.signs_minus.contains(&(E::from_usize(i))) {
97 result.push('-');
98 } else {
99 result.push('+');
100 }
101 if gens.signs_i.contains(&(E::from_usize(i))) {
102 result.push('i');
103 }
104
105 for qubit in 0..num_qubits {
106 let qubit_u = E::from_usize(qubit);
107 let in_row_x = gens.row_x[i].contains(&qubit_u);
108 let in_row_z = gens.row_z[i].contains(&qubit_u);
109
110 let char = match (in_row_x, in_row_z) {
111 (false, false) => 'I',
112 (true, false) => 'X',
113 (false, true) => 'Z',
114 (true, true) => 'Y',
115 };
116 result.push(char);
117 }
118 result.push('\n');
119 }
120
121 result
122 }
123
124 #[inline]
126 pub fn stab_tableau(&self) -> String {
127 Self::tableau_string(self.num_qubits, &self.stabs)
128 }
129
130 #[inline]
132 pub fn destab_tableau(&self) -> String {
133 Self::tableau_string(self.num_qubits, &self.destabs)
134 }
135
136 #[inline]
138 pub fn neg(&mut self, s: E) {
139 self.stabs.signs_minus ^= &s;
140 }
141
142 #[inline]
143 pub fn signs_minus(&self) -> &T {
144 &self.stabs.signs_minus
145 }
146
147 #[inline]
150 fn deterministic_meas(&mut self, q: E) -> bool {
151 let qu = q.to_usize();
152
153 let mut num_minuses = self.destabs.col_x[qu]
154 .intersection(&self.stabs.signs_minus)
155 .count();
156
157 let num_is = &self.destabs.col_x[qu]
158 .intersection(&self.stabs.signs_i)
159 .count();
160
161 let mut cumulative_x = T::new();
162 for row in self.destabs.col_x[qu].iter() {
163 let rowu = row.to_usize();
164 num_minuses += &self.stabs.row_z[rowu].intersection(&cumulative_x).count();
165 cumulative_x ^= &self.stabs.row_x[rowu];
166 }
167 if num_is & 3 != 0 {
168 num_minuses += 1;
170 }
171 num_minuses & 1 != 0 }
173
174 #[inline]
177 fn nondeterministic_meas(&mut self, q: E) -> E {
178 let qu = q.to_usize();
179
180 let mut anticom_stabs_col = self.stabs.col_x[qu].clone();
181 let mut anticom_destabs_col = self.destabs.col_x[qu].clone();
182
183 let mut smallest_wt = 2 * self.num_qubits + 2;
184 let mut removed_id: Option<E> = None;
185
186 for stab_id in anticom_stabs_col.iter() {
187 let stab_usize = stab_id.to_usize();
188 let weight = self.stabs.row_x[stab_usize].len() + self.stabs.row_z[stab_usize].len();
189
190 if weight < smallest_wt {
191 smallest_wt = weight;
192 removed_id = Some(*stab_id);
193 }
197 }
198
199 let id = removed_id.expect("Critical error: removed_id was None");
200
201 anticom_stabs_col.remove(&id);
202 let id_usize = id.to_usize(); let removed_row_x = self.stabs.row_x[id_usize].clone();
204 let removed_row_z = self.stabs.row_z[id_usize].clone();
205
206 if self.stabs.signs_minus.contains(&id) {
207 self.stabs.signs_minus ^= &anticom_stabs_col;
208 }
209
210 if self.stabs.signs_i.contains(&id) {
211 self.stabs.signs_i.remove(&id);
212
213 let gens_common = self
214 .stabs
215 .signs_i
216 .intersection(&anticom_stabs_col)
217 .copied()
218 .collect::<Vec<_>>();
219 let gens_only_stabs = anticom_stabs_col
220 .difference(&self.stabs.signs_i)
221 .copied()
222 .collect::<Vec<_>>();
223
224 for i in gens_common {
225 self.stabs.signs_minus ^= &i;
226 self.stabs.signs_i.remove(&i);
227 }
228
229 for i in gens_only_stabs {
230 self.stabs.signs_i.insert(i);
231 }
232 }
233
234 for gen in anticom_stabs_col.iter() {
235 let gen_usize = gen.to_usize(); let num_minuses = removed_row_z
237 .intersection(&self.stabs.row_x[gen_usize])
238 .count();
239
240 if num_minuses & 1 != 0 {
241 self.stabs.signs_minus ^= gen;
243 }
244
245 self.stabs.row_x[gen_usize] ^= &removed_row_x;
246 self.stabs.row_z[gen_usize] ^= &removed_row_z;
247 }
249
250 for i in removed_row_x.iter() {
251 let iu = i.to_usize();
252 self.stabs.col_x[iu] ^= &anticom_stabs_col;
253 }
254
255 for i in removed_row_z.iter() {
256 let iu = i.to_usize();
257 self.stabs.col_z[iu] ^= &anticom_stabs_col;
258 }
259
260 for i in self.stabs.row_x[id_usize].iter() {
261 let iu = i.to_usize();
262 self.stabs.col_x[iu].remove(&id);
263 }
264
265 for i in self.stabs.row_z[id_usize].iter() {
266 let iu = i.to_usize();
267 self.stabs.col_z[iu].remove(&id);
268 }
269
270 self.stabs.col_z[qu].insert(id);
272
273 self.stabs.row_x[id_usize].clear();
275 self.stabs.row_z[id_usize].clear();
276 self.stabs.row_z[id_usize].insert(q);
277
278 for i in self.destabs.row_x[id_usize].iter() {
279 let iu = i.to_usize();
280 self.destabs.col_x[iu].remove(&id);
281 }
282
283 for i in self.destabs.row_z[id_usize].iter() {
284 let iu = i.to_usize();
285 self.destabs.col_z[iu].remove(&id);
286 }
287
288 anticom_destabs_col.remove(&id);
289
290 for i in removed_row_x.iter() {
291 let iu = i.to_usize();
292 self.destabs.col_x[iu].insert(id);
293 self.destabs.col_x[iu] ^= &anticom_destabs_col;
294 }
295
296 for i in removed_row_z.iter() {
297 let iu = i.to_usize();
298 self.destabs.col_z[iu].insert(id);
299 self.destabs.col_z[iu] ^= &anticom_destabs_col;
300 }
301
302 for row in anticom_destabs_col.iter() {
303 let ru = row.to_usize();
304 self.destabs.row_x[ru] ^= &removed_row_x;
305 self.destabs.row_z[ru] ^= &removed_row_z;
306 }
307
308 self.destabs.row_x[id_usize] = removed_row_x;
309 self.destabs.row_z[id_usize] = removed_row_z;
310
311 id
312 }
313
314 #[inline]
318 pub fn mz_forced(&mut self, q: E, forced_outcome: bool) -> (bool, bool) {
319 let qu = q.to_usize();
320
321 let deterministic = self.stabs.col_x[qu].is_empty();
322
323 let meas_out = if deterministic {
325 self.deterministic_meas(q)
326 } else {
327 let id = self.nondeterministic_meas(q);
328
329 self.apply_outcome(id, forced_outcome)
330 };
331 (meas_out, deterministic)
332 }
333
334 #[inline]
338 pub fn pz_forced(&mut self, q: E, forced_outcome: bool) -> (bool, bool) {
339 let (meas, deter) = self.mz_forced(q, forced_outcome);
340 if meas {
341 self.x(q);
342 }
343 (meas, deter)
344 }
345
346 #[inline]
348 fn apply_outcome(&mut self, id: E, meas_outcome: bool) -> bool {
349 if meas_outcome {
350 self.stabs.signs_minus.insert(id);
351 } else {
352 self.stabs.signs_minus.remove(&id);
353 }
354 meas_outcome
355 }
356}
357
358impl<T, E, R> QuantumSimulator for SparseStab<T, E, R>
359where
360 E: IndexableElement,
361 R: SimRng,
362 T: for<'a> Set<'a, Element = E>,
363{
364 #[inline]
365 #[must_use]
366 fn new(num_qubits: usize) -> Self {
367 Self::new(num_qubits)
368 }
369
370 #[inline]
371 fn num_qubits(&self) -> usize {
372 self.num_qubits
373 }
374
375 #[inline]
376 fn reset(&mut self) -> &mut Self {
377 Self::reset(self)
378 }
379}
380
381impl<T, E, R> CliffordSimulator<E> for SparseStab<T, E, R>
382where
383 T: for<'a> Set<'a, Element = E>,
384 E: IndexableElement,
385 R: SimRng,
386{
387 #[inline]
394 fn mz(&mut self, q: E) -> (bool, bool) {
395 let qu = q.to_usize();
396
397 let deterministic = self.stabs.col_x[qu].is_empty();
398
399 let meas_out = if deterministic {
401 self.deterministic_meas(q)
402 } else {
403 let id = self.nondeterministic_meas(q);
404
405 let meas_outcome = self.rng.gen_bool(0.5);
406
407 self.apply_outcome(id, meas_outcome)
408 };
409 (meas_out, deterministic)
410 }
411
412 #[inline]
416 fn x(&mut self, q: E) {
417 let qu = q.to_usize();
418 self.stabs.signs_minus ^= &self.stabs.col_z[qu];
419 }
420
421 #[inline]
425 fn y(&mut self, q: E) {
426 let qu = q.to_usize();
428 for i in self.stabs.col_x[qu].symmetric_difference(&self.stabs.col_z[qu]) {
430 self.stabs.signs_minus ^= i;
431 }
432 }
433
434 #[inline]
438 fn z(&mut self, q: E) {
439 self.stabs.signs_minus ^= &self.stabs.col_x[q.to_usize()];
441 }
442
443 #[inline]
451 fn sz(&mut self, q: E) {
452 let qu = q.to_usize();
453
454 for i in self.stabs.signs_i.intersection(&self.stabs.col_x[qu]) {
461 self.stabs.signs_minus ^= i;
462 }
463 self.stabs.signs_i ^= &self.stabs.col_x[qu];
464
465 for g in [&mut self.stabs, &mut self.destabs] {
466 g.col_z[qu] ^= &g.col_x[qu];
467
468 for &i in g.col_x[qu].iter() {
469 let iu = i.to_usize();
470 g.row_z[iu] ^= &q;
471 }
472 }
473 }
474
475 #[inline]
479 fn h(&mut self, q: E) {
480 let qu = q.to_usize();
481
482 for i in self.stabs.col_x[qu].intersection(&self.stabs.col_z[qu]) {
485 self.stabs.signs_minus ^= i;
486 }
487
488 for g in [&mut self.stabs, &mut self.destabs] {
489 for i in g.col_x[qu].difference(&g.col_z[qu]) {
490 let iu = i.to_usize();
491 g.row_x[iu].remove(&q);
492 g.row_z[iu].insert(q);
493 }
494
495 for i in g.col_z[qu].difference(&g.col_x[qu]) {
496 let iu = i.to_usize();
497 g.row_z[iu].remove(&q);
498 g.row_x[iu].insert(q);
499 }
500
501 mem::swap(&mut g.col_x[qu], &mut g.col_z[qu]);
502 }
503 }
504
505 #[inline]
509 fn cx(&mut self, q1: E, q2: E) {
510 let qu1 = q1.to_usize();
511 let qu2 = q2.to_usize();
512
513 for g in &mut [&mut self.stabs, &mut self.destabs] {
514 let (qu_min, qu_max) = if qu1 < qu2 { (qu1, qu2) } else { (qu2, qu1) };
515
516 {
518 let (_left, right) = g.col_x.split_at_mut(qu_min);
519 let (mid, right) = right.split_at_mut(qu_max - qu_min);
520 let col_x_min = &mut mid[0];
521 let col_x_max = &mut right[0];
522
523 let (col_x_qu1, col_x_qu2) = if qu1 < qu2 {
524 (col_x_min, col_x_max)
525 } else {
526 (col_x_max, col_x_min)
527 };
528
529 let mut q2_set = T::new();
530 q2_set.insert(q2);
531
532 for i in col_x_qu1.iter() {
533 let iu = i.to_usize();
534 g.row_x[iu].symmetric_difference_update(&q2_set);
535 }
536 col_x_qu2.symmetric_difference_update(col_x_qu1);
537 }
538
539 {
541 let (_left, right) = g.col_z.split_at_mut(qu_min);
542 let (mid, right) = right.split_at_mut(qu_max - qu_min);
543 let col_z_min = &mut mid[0];
544 let col_z_max = &mut right[0];
545
546 let (col_z_qu1, col_z_qu2) = if qu1 < qu2 {
547 (col_z_min, col_z_max)
548 } else {
549 (col_z_max, col_z_min)
550 };
551
552 let mut q1_set = T::new();
553 q1_set.insert(q1);
554
555 for i in col_z_qu2.iter() {
556 let iu = i.to_usize();
557 g.row_z[iu].symmetric_difference_update(&q1_set);
558 }
559 col_z_qu1.symmetric_difference_update(col_z_qu2);
560 }
561 }
562 }
563}
564
565#[cfg(test)]
566mod tests {
567 use super::*;
568 use pecos_core::VecSet;
569
570 #[allow(clippy::cast_possible_truncation)]
571 fn check_matrix(m: &[&str], gens: &Gens<VecSet<u32>, u32>) {
572 for (r, v) in m.iter().enumerate() {
573 let ru32 = &(r as u32);
574
575 let (_, phase, v) = split_pauli(v);
576
577 match phase {
581 "+" => {
582 assert!(!gens.signs_minus.contains(ru32));
583 assert!(!gens.signs_i.contains(ru32));
584 }
585 "-" => {
586 assert!(gens.signs_minus.contains(ru32));
587 assert!(!gens.signs_i.contains(ru32));
588 }
589 "+i" => {
590 assert!(!gens.signs_minus.contains(ru32));
591 assert!(gens.signs_i.contains(ru32));
592 }
593 "-i" => {
594 assert!(gens.signs_minus.contains(ru32));
595 assert!(gens.signs_i.contains(ru32));
596 }
597 _ => unreachable!(),
598 }
599
600 for (c, val) in v.chars().enumerate() {
601 let cu32 = &(c as u32);
602 match val {
603 'I' => {
604 assert!(!gens.col_x[c].contains(ru32));
605 assert!(!gens.col_z[c].contains(ru32));
606 assert!(!gens.row_x[r].contains(cu32));
607 assert!(!gens.row_z[r].contains(cu32));
608 }
609 'X' => {
610 assert!(gens.col_x[c].contains(ru32));
611 assert!(!gens.col_z[c].contains(ru32));
612 assert!(gens.row_x[r].contains(cu32));
613 assert!(!gens.row_z[r].contains(cu32));
614 }
615 'Z' => {
616 assert!(!gens.col_x[c].contains(ru32));
617 assert!(gens.col_z[c].contains(ru32));
618 assert!(!gens.row_x[r].contains(cu32));
619 assert!(gens.row_z[r].contains(cu32));
620 }
621 'W' => {
622 assert!(gens.col_x[c].contains(ru32));
623 assert!(gens.col_z[c].contains(ru32));
624 assert!(gens.row_x[r].contains(cu32));
625 assert!(gens.row_z[r].contains(cu32));
626 }
627 _ => unreachable!(),
628 }
629 }
630 }
631 }
632
633 fn check_state(state: &SparseStab<VecSet<u32>, u32>, stabs: &[&str], destabs: &[&str]) {
634 check_matrix(stabs, &state.stabs);
635 check_matrix(destabs, &state.destabs);
636 }
639
640 fn split_pauli(pauli_str: &str) -> (usize, &str, &str) {
641 let (phase, pauli_str) = if pauli_str.contains("+i") || pauli_str.contains("-i") {
642 pauli_str.split_at(2)
643 } else if pauli_str.contains('+') || pauli_str.contains('-') || pauli_str.contains('i') {
644 pauli_str.split_at(1)
645 } else {
646 ("+", pauli_str)
647 };
648 let n = pauli_str.chars().count();
649
650 let phase = if phase == "i" { "+i" } else { phase };
651
652 (n, phase, pauli_str)
653 }
654
655 #[allow(clippy::cast_possible_truncation)]
656 fn prep_pauli_gens(pauli_vec: &[&str], gens: &mut Gens<VecSet<u32>, u32>) {
657 gens.signs_i.clear();
660 gens.signs_minus.clear();
661
662 let (n, _, _) = split_pauli(pauli_vec[0]);
663
664 for u in 0..n {
665 gens.col_x[u].clear();
666 gens.col_z[u].clear();
667 gens.row_x[u].clear();
668 gens.row_z[u].clear();
669 }
670
671 for (ru, pauli_str) in pauli_vec.iter().enumerate() {
672 let (n_, phase, pauli_str) = split_pauli(pauli_str);
673
674 assert_eq!(
675 n, n_,
676 "The number of qubits differs between the first generator and another!"
677 );
678
679 match phase {
680 "+" => {}
681 "-" => {
682 gens.signs_minus.insert(ru as u32);
683 }
684 "+i" => {
685 gens.signs_i.insert(ru as u32);
686 }
687 "-i" => {
688 gens.signs_minus.insert(ru as u32);
689 gens.signs_i.insert(ru as u32);
690 }
691 _ => unreachable!(),
692 }
693
694 for (cu, p) in pauli_str.chars().enumerate() {
695 match p {
696 'I' => {}
697 'X' => {
698 gens.col_x[cu].insert(ru as u32);
699 gens.row_x[ru].insert(cu as u32);
700 }
701 'W' => {
702 gens.col_x[cu].insert(ru as u32);
703 gens.col_z[cu].insert(ru as u32);
704 gens.row_x[ru].insert(cu as u32);
705 gens.row_z[ru].insert(cu as u32);
706 }
707 'Z' => {
708 gens.col_z[cu].insert(ru as u32);
709 gens.row_z[ru].insert(cu as u32);
710 }
711 _ => unreachable!(),
712 }
713 }
714 }
715 }
716
717 fn prep_state(stabs: &[&str], destabs: &[&str]) -> SparseStab<VecSet<u32>, u32> {
718 let mut state = SparseStab::<VecSet<u32>, u32>::new(3);
719 prep_pauli_gens(stabs, &mut state.stabs);
720 prep_pauli_gens(destabs, &mut state.destabs);
721
722 state
723 }
724
725 #[test]
726 fn test_setting_up_stab_state() {
727 let tab_stab = vec!["XII", "iIWI", "IIZ"];
728 let tab_destab = vec!["ZII", "IXI", "IIX"];
729
730 let state = prep_state(&tab_stab, &tab_destab);
731 check_state(&state, &tab_stab, &tab_destab);
732 }
733
734 #[test]
735 fn test_setting_up_neg_stab_state() {
736 let tab_stab = vec!["-XII", "-iIWI", "-IIZ"];
737 let tab_destab = vec!["ZII", "IXI", "IIX"];
738
739 let state = prep_state(&tab_stab, &tab_destab);
740 check_state(&state, &tab_stab, &tab_destab);
741 }
742
743 #[test]
744 fn test_nondeterministic_px() {
745 for _ in 1_u32..=100 {
746 let mut state = prep_state(&["Z"], &["X"]);
747 let (_m0, d0) = state.px(0);
748 let (m1, d1) = state.mx(0);
749 let m1_int = u8::from(m1);
750
751 assert_eq!(m1_int, 0); assert!(!d0); assert!(d1); }
755 }
756
757 #[test]
758 fn test_deterministic_px() {
759 let mut state = prep_state(&["X"], &["Z"]);
760 let (m0, d0) = state.px(0);
761 let m0_int = u8::from(m0);
762
763 assert!(d0); assert_eq!(m0_int, 0); }
766
767 #[test]
768 fn test_nondeterministic_pnx() {
769 for _ in 1_u32..=100 {
770 let mut state = prep_state(&["Z"], &["X"]);
771 let (_m0, d0) = state.pnx(0);
772 let (m1, d1) = state.mx(0);
773 let m1_int = u8::from(m1);
774
775 assert_eq!(m1_int, 1); assert!(!d0); assert!(d1); }
779 }
780
781 #[test]
782 fn test_deterministic_pnx() {
783 let mut state = prep_state(&["-X"], &["Z"]);
784 let (m0, d0) = state.pnx(0);
785 let m0_int = u8::from(m0);
786
787 assert!(d0); assert_eq!(m0_int, 0); }
790
791 #[test]
792 fn test_nondeterministic_py() {
793 for _ in 1_u32..=100 {
794 let mut state = prep_state(&["Z"], &["X"]);
795 let (_m0, d0) = state.py(0);
796 let (m1, d1) = state.my(0);
797 let m1_int = u8::from(m1);
798
799 assert_eq!(m1_int, 0); assert!(!d0); assert!(d1); }
803 }
804
805 #[test]
806 fn test_deterministic_py() {
807 let mut state = prep_state(&["iW"], &["Z"]);
808 let (m0, d0) = state.py(0);
809 let m0_int = u8::from(m0);
810
811 assert!(d0); assert_eq!(m0_int, 0); }
814
815 #[test]
816 fn test_nondeterministic_pny() {
817 for _ in 1_u32..=100 {
818 let mut state = prep_state(&["Z"], &["X"]);
819 let (_m0, d0) = state.pny(0);
820 let (m1, d1) = state.my(0);
821 let m1_int = u8::from(m1);
822
823 assert_eq!(m1_int, 1); assert!(!d0); assert!(d1); }
827 }
828
829 #[test]
830 fn test_deterministic_pny() {
831 let mut state = prep_state(&["-iW"], &["Z"]);
832 let (m0, d0) = state.pny(0);
833 let m0_int = u8::from(m0);
834
835 assert!(d0); assert_eq!(m0_int, 0); }
838
839 #[test]
840 fn test_nondeterministic_pz() {
841 for _ in 1_u32..=100 {
842 let mut state = prep_state(&["X"], &["Z"]);
843 let (_m0, d0) = state.pz(0);
844 let (m1, d1) = state.mz(0);
845 let m1_int = u8::from(m1);
846
847 assert_eq!(m1_int, 0); assert!(!d0); assert!(d1); }
851 }
852
853 #[test]
854 fn test_deterministic_pz() {
855 let mut state = prep_state(&["Z"], &["X"]);
856 let (m0, d0) = state.pz(0);
857 let m0_int = u8::from(m0);
858
859 assert!(d0); assert_eq!(m0_int, 0); }
862
863 #[test]
864 fn test_nondeterministic_pnz() {
865 for _ in 1_u32..=100 {
866 let mut state = prep_state(&["X"], &["Z"]);
867 let (_m0, d0) = state.pnz(0);
868 let (m1, d1) = state.mz(0);
869 let m1_int = u8::from(m1);
870
871 assert_eq!(m1_int, 1); assert!(!d0); assert!(d1); }
875 }
876
877 #[test]
878 fn test_deterministic_pnz() {
879 let mut state = prep_state(&["-Z"], &["X"]);
880 let (m0, d0) = state.pnz(0);
881 let m0_int = u8::from(m0);
882
883 assert!(d0); assert_eq!(m0_int, 0); }
886
887 #[test]
888 fn test_nondeterministic_mx() {
889 let mut state = prep_state(&["Z"], &["X"]);
890 let (_meas, determined) = state.mx(0);
891 assert!(!determined);
892 }
893
894 #[test]
895 fn test_deterministic_mx() {
896 let mut state0 = prep_state(&["X"], &["Z"]);
897 let (meas0, determined0) = state0.mx(0);
898 assert!(determined0);
899 assert!(!meas0);
900
901 let mut state1 = prep_state(&["-X"], &["Z"]);
902 let (meas1, determined1) = state1.mx(0);
903 assert!(determined1);
904 assert!(meas1);
905 }
906
907 #[test]
908 fn test_nondeterministic_mnx() {
909 let mut state = prep_state(&["Z"], &["X"]);
910 let (_meas, determined) = state.mnx(0);
911 assert!(!determined);
912 }
913
914 #[test]
915 fn test_deterministic_mnx() {
916 let mut state0 = prep_state(&["-X"], &["Z"]);
917 let (meas0, determined0) = state0.mnx(0);
918 assert!(determined0);
919 assert!(!meas0);
920
921 let mut state1 = prep_state(&["X"], &["Z"]);
922 let (meas1, determined1) = state1.mnx(0);
923 assert!(determined1);
924 assert!(meas1);
925 }
926
927 #[test]
928 fn test_nondeterministic_my() {
929 let mut state = prep_state(&["Z"], &["X"]);
930 let (_meas, determined) = state.my(0);
931 assert!(!determined);
932 }
933
934 #[test]
935 fn test_deterministic_my() {
936 let mut state0 = prep_state(&["iW"], &["Z"]);
937 let (meas0, determined0) = state0.my(0);
938 assert!(determined0);
939 assert!(!meas0);
940
941 let mut state1 = prep_state(&["-iW"], &["Z"]);
942 let (meas1, determined1) = state1.my(0);
943 assert!(determined1);
944 assert!(meas1);
945 }
946
947 #[test]
948 fn test_nondeterministic_mny() {
949 let mut state = prep_state(&["Z"], &["X"]);
950 let (_meas, determined) = state.mny(0);
951 assert!(!determined);
952 }
953
954 #[test]
955 fn test_deterministic_mny() {
956 let mut state0 = prep_state(&["-iW"], &["Z"]);
957 let (meas0, determined0) = state0.mny(0);
958 assert!(determined0);
959 assert!(!meas0);
960
961 let mut state1 = prep_state(&["iW"], &["Z"]);
962 let (meas1, determined1) = state1.mny(0);
963 assert!(determined1);
964 assert!(meas1);
965 }
966
967 #[test]
968 fn test_nondeterministic_mz() {
969 let mut state = prep_state(&["X"], &["Z"]);
970 let (_meas, determined) = state.mz(0);
971 assert!(!determined);
972 }
973
974 #[test]
975 fn test_deterministic_mz() {
976 let mut state0 = prep_state(&["Z"], &["X"]);
977 let (meas0, determined0) = state0.mz(0);
978 assert!(determined0);
979 assert!(!meas0);
980
981 let mut state1 = prep_state(&["-Z"], &["X"]);
982 let (meas1, determined1) = state1.mz(0);
983 assert!(determined1);
984 assert!(meas1);
985 }
986
987 #[test]
988 fn test_nondeterministic_mnz() {
989 let mut state = prep_state(&["X"], &["Z"]);
990 let (_meas, determined) = state.mnz(0);
991 assert!(!determined);
992 }
993
994 #[test]
995 fn test_deterministic_mnz() {
996 let mut state0 = prep_state(&["Z"], &["X"]);
997 let (meas0, determined0) = state0.mnz(0);
998 assert!(determined0);
999 assert!(meas0);
1000
1001 let mut state1 = prep_state(&["-Z"], &["X"]);
1002 let (meas1, determined1) = state1.mnz(0);
1003 assert!(determined1);
1004 assert!(!meas1);
1005 }
1006
1007 #[test]
1008 fn test_identity() {
1009 let mut state = prep_state(&["X"], &["Z"]);
1013 state.identity(0);
1014 check_state(&state, &["X"], &["Z"]);
1015
1016 let mut state = prep_state(&["iW"], &["X"]);
1018 state.identity(0);
1019 check_state(&state, &["iW"], &["X"]);
1020
1021 let mut state = prep_state(&["Z"], &["X"]);
1023 state.identity(0);
1024 check_state(&state, &["Z"], &["X"]);
1025
1026 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1028 state.identity(1);
1029 check_state(&state, &["-iIWI"], &["IXI"]);
1030 }
1031
1032 #[test]
1033 #[expect(clippy::shadow_unrelated)]
1034 fn test_x() {
1035 let mut state = prep_state(&["X"], &["Z"]);
1039 state.x(0);
1040 check_state(&state, &["X"], &["Z"]);
1041
1042 let mut state = prep_state(&["iW"], &["X"]);
1044 state.x(0);
1045 check_state(&state, &["-iW"], &["X"]);
1046
1047 let mut state = prep_state(&["Z"], &["X"]);
1049 state.x(0);
1050 check_state(&state, &["-Z"], &["X"]);
1051
1052 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1054 state.x(1);
1055 check_state(&state, &["iIWI"], &["IXI"]);
1056 }
1057
1058 #[test]
1059 #[expect(clippy::shadow_unrelated)]
1060 fn test_y() {
1061 let mut state = prep_state(&["X"], &["Z"]);
1065 state.y(0);
1066 check_state(&state, &["-X"], &["Z"]);
1067
1068 let mut state = prep_state(&["iW"], &["X"]);
1070 state.y(0);
1071 check_state(&state, &["iW"], &["X"]);
1072
1073 let mut state = prep_state(&["Z"], &["X"]);
1075 state.y(0);
1076 check_state(&state, &["-Z"], &["X"]);
1077
1078 let mut state = prep_state(&["-IXI"], &["IZI"]);
1080 state.y(1);
1081 check_state(&state, &["IXI"], &["IZI"]);
1082 }
1083
1084 #[test]
1085 #[expect(clippy::shadow_unrelated)]
1086 fn test_z() {
1087 let mut state = prep_state(&["X"], &["Z"]);
1091 state.z(0);
1092 check_state(&state, &["-X"], &["Z"]);
1093
1094 let mut state = prep_state(&["iW"], &["X"]);
1096 state.z(0);
1097 check_state(&state, &["-iW"], &["X"]);
1098
1099 let mut state = prep_state(&["Z"], &["X"]);
1101 state.z(0);
1102 check_state(&state, &["Z"], &["X"]);
1103
1104 let mut state = prep_state(&["-IXI"], &["IZI"]);
1106 state.z(1);
1107 check_state(&state, &["IXI"], &["IZI"]);
1108 }
1109
1110 #[test]
1111 #[expect(clippy::shadow_unrelated)]
1112 fn test_sx() {
1113 let mut state = prep_state(&["X"], &["Z"]);
1117 state.sx(0);
1118 check_state(&state, &["X"], &["W"]);
1119
1120 let mut state = prep_state(&["iW"], &["X"]);
1122 state.sx(0);
1123 check_state(&state, &["Z"], &["X"]);
1124
1125 let mut state = prep_state(&["Z"], &["X"]);
1127 state.sx(0);
1128 check_state(&state, &["-iW"], &["X"]);
1129
1130 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1132 state.sx(1);
1133 check_state(&state, &["-IZI"], &["IXI"]);
1134 }
1135
1136 #[test]
1137 #[expect(clippy::shadow_unrelated)]
1138 fn test_sxdg() {
1139 let mut state = prep_state(&["X"], &["Z"]);
1143 state.sxdg(0);
1144 check_state(&state, &["X"], &["W"]);
1145
1146 let mut state = prep_state(&["iW"], &["X"]);
1148 state.sxdg(0);
1149 check_state(&state, &["-Z"], &["X"]);
1150
1151 let mut state = prep_state(&["Z"], &["X"]);
1153 state.sxdg(0);
1154 check_state(&state, &["iW"], &["X"]);
1155
1156 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1158 state.sxdg(1);
1159 check_state(&state, &["IZI"], &["IXI"]);
1160 }
1161
1162 #[test]
1163 #[expect(clippy::shadow_unrelated)]
1164 fn test_sy() {
1165 let mut state = prep_state(&["X"], &["Z"]);
1169 state.sy(0);
1170 check_state(&state, &["-Z"], &["X"]);
1171
1172 let mut state = prep_state(&["iW"], &["X"]);
1174 state.sy(0);
1175 check_state(&state, &["iW"], &["Z"]);
1176
1177 let mut state = prep_state(&["Z"], &["X"]);
1179 state.sy(0);
1180 check_state(&state, &["X"], &["Z"]);
1181
1182 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1184 state.sy(1);
1185 check_state(&state, &["-iIWI"], &["IZI"]);
1186 }
1187
1188 #[test]
1189 #[expect(clippy::shadow_unrelated)]
1190 fn test_sydg() {
1191 let mut state = prep_state(&["X"], &["Z"]);
1195 state.sydg(0);
1196 check_state(&state, &["Z"], &["X"]);
1197
1198 let mut state = prep_state(&["iW"], &["X"]);
1200 state.sydg(0);
1201 check_state(&state, &["iW"], &["Z"]);
1202
1203 let mut state = prep_state(&["Z"], &["X"]);
1205 state.sydg(0);
1206 check_state(&state, &["-X"], &["Z"]);
1207
1208 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1210 state.sydg(1);
1211 check_state(&state, &["-iIWI"], &["IZI"]);
1212 }
1213
1214 #[test]
1215 #[expect(clippy::shadow_unrelated)]
1216 fn test_sz() {
1217 let mut state = prep_state(&["X"], &["Z"]);
1221 state.sz(0);
1222 check_state(&state, &["iW"], &["Z"]);
1223
1224 let mut state = prep_state(&["iW"], &["X"]);
1226 state.sz(0);
1227 check_state(&state, &["-X"], &["W"]);
1228
1229 let mut state = prep_state(&["Z"], &["X"]);
1231 state.sz(0);
1232 check_state(&state, &["Z"], &["W"]);
1233
1234 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1236 state.sz(1);
1237 check_state(&state, &["IXI"], &["IWI"]);
1238 }
1239
1240 #[test]
1241 fn test_szdg() {
1242 let mut state = prep_state(&["X"], &["Z"]);
1246 state.szdg(0);
1247 check_state(&state, &["-iW"], &["Z"]);
1248
1249 let mut state = prep_state(&["iW"], &["X"]);
1251 state.szdg(0);
1252 check_state(&state, &["X"], &["W"]);
1253
1254 let mut state = prep_state(&["Z"], &["X"]);
1256 state.szdg(0);
1257 check_state(&state, &["Z"], &["W"]);
1258
1259 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1261 state.szdg(1);
1262 check_state(&state, &["-IXI"], &["IWI"]);
1263 }
1264
1265 #[test]
1266 #[expect(clippy::shadow_unrelated)]
1267 fn test_h() {
1268 let mut state = prep_state(&["X"], &["Z"]);
1272 state.h(0);
1273 check_state(&state, &["Z"], &["X"]);
1274
1275 let mut state = prep_state(&["iW"], &["X"]);
1277 state.h(0);
1278 check_state(&state, &["-iW"], &["Z"]);
1279
1280 let mut state = prep_state(&["Z"], &["X"]);
1282 state.h(0);
1283 check_state(&state, &["X"], &["Z"]);
1284
1285 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1287 state.h(1);
1288 check_state(&state, &["iIWI"], &["IZI"]);
1289 }
1290
1291 #[test]
1292 #[expect(clippy::shadow_unrelated)]
1293 fn test_h2() {
1294 let mut state = prep_state(&["X"], &["Z"]);
1298 state.h2(0);
1299 check_state(&state, &["-Z"], &["X"]);
1300
1301 let mut state = prep_state(&["iW"], &["X"]);
1303 state.h2(0);
1304 check_state(&state, &["-iW"], &["Z"]);
1305
1306 let mut state = prep_state(&["Z"], &["X"]);
1308 state.h2(0);
1309 check_state(&state, &["-X"], &["Z"]);
1310
1311 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1313 state.h2(1);
1314 check_state(&state, &["iIWI"], &["IZI"]);
1315 }
1316
1317 #[test]
1318 #[expect(clippy::shadow_unrelated)]
1319 fn test_h3() {
1320 let mut state = prep_state(&["X"], &["Z"]);
1324 state.h3(0);
1325 check_state(&state, &["iW"], &["Z"]);
1326
1327 let mut state = prep_state(&["iW"], &["X"]);
1329 state.h3(0);
1330 check_state(&state, &["X"], &["W"]);
1331
1332 let mut state = prep_state(&["Z"], &["X"]);
1334 state.h3(0);
1335 check_state(&state, &["-Z"], &["W"]);
1336
1337 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1339 state.h3(1);
1340 check_state(&state, &["-IXI"], &["IWI"]);
1341 }
1342
1343 #[test]
1344 #[expect(clippy::shadow_unrelated)]
1345 fn test_h4() {
1346 let mut state = prep_state(&["X"], &["Z"]);
1350 state.h4(0);
1351 check_state(&state, &["-iW"], &["Z"]);
1352
1353 let mut state = prep_state(&["iW"], &["X"]);
1355 state.h4(0);
1356 check_state(&state, &["-X"], &["W"]);
1357
1358 let mut state = prep_state(&["Z"], &["X"]);
1360 state.h4(0);
1361 check_state(&state, &["-Z"], &["W"]);
1362
1363 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1365 state.h4(1);
1366 check_state(&state, &["IXI"], &["IWI"]);
1367 }
1368
1369 #[test]
1370 #[expect(clippy::shadow_unrelated)]
1371 fn test_h5() {
1372 let mut state = prep_state(&["X"], &["Z"]);
1376 state.h5(0);
1377 check_state(&state, &["-X"], &["W"]);
1378
1379 let mut state = prep_state(&["iW"], &["X"]);
1381 state.h5(0);
1382 check_state(&state, &["Z"], &["X"]);
1383
1384 let mut state = prep_state(&["Z"], &["X"]);
1386 state.h5(0);
1387 check_state(&state, &["iW"], &["X"]);
1388
1389 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1391 state.h5(1);
1392 check_state(&state, &["-IZI"], &["IXI"]);
1393 }
1394
1395 #[test]
1396 #[expect(clippy::shadow_unrelated)]
1397 fn test_h6() {
1398 let mut state = prep_state(&["X"], &["Z"]);
1402 state.h6(0);
1403 check_state(&state, &["-X"], &["W"]);
1404
1405 let mut state = prep_state(&["iW"], &["X"]);
1407 state.h6(0);
1408 check_state(&state, &["-Z"], &["X"]);
1409
1410 let mut state = prep_state(&["Z"], &["X"]);
1412 state.h6(0);
1413 check_state(&state, &["-iW"], &["X"]);
1414
1415 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1417 state.h6(1);
1418 check_state(&state, &["IZI"], &["IXI"]);
1419 }
1420
1421 #[test]
1422 #[expect(clippy::shadow_unrelated)]
1423 fn test_f() {
1424 let mut state = prep_state(&["X"], &["Z"]);
1428 state.f(0);
1429 check_state(&state, &["iW"], &["X"]);
1430
1431 let mut state = prep_state(&["iW"], &["X"]);
1433 state.f(0);
1434 check_state(&state, &["Z"], &["W"]);
1435
1436 let mut state = prep_state(&["Z"], &["X"]);
1438 state.f(0);
1439 check_state(&state, &["X"], &["W"]);
1440
1441 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1443 state.f(1);
1444 check_state(&state, &["-IZI"], &["IWI"]);
1445 }
1446
1447 #[test]
1448 #[expect(clippy::shadow_unrelated)]
1449 fn test_fdg() {
1450 let mut state = prep_state(&["X"], &["Z"]);
1454 state.fdg(0);
1455 check_state(&state, &["Z"], &["W"]);
1456
1457 let mut state = prep_state(&["iW"], &["X"]);
1459 state.fdg(0);
1460 check_state(&state, &["X"], &["Z"]);
1461
1462 let mut state = prep_state(&["Z"], &["X"]);
1464 state.fdg(0);
1465 check_state(&state, &["iW"], &["Z"]);
1466
1467 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1469 state.fdg(1);
1470 check_state(&state, &["-IXI"], &["IZI"]);
1471 }
1472
1473 #[test]
1474 #[expect(clippy::shadow_unrelated)]
1475 fn test_f2() {
1476 let mut state = prep_state(&["X"], &["Z"]);
1480 state.f2(0);
1481 check_state(&state, &["-Z"], &["W"]);
1482
1483 let mut state = prep_state(&["iW"], &["X"]);
1485 state.f2(0);
1486 check_state(&state, &["-X"], &["Z"]);
1487
1488 let mut state = prep_state(&["Z"], &["X"]);
1490 state.f2(0);
1491 check_state(&state, &["iW"], &["Z"]);
1492
1493 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1495 state.f2(1);
1496 check_state(&state, &["IXI"], &["IZI"]);
1497 }
1498
1499 #[test]
1500 #[expect(clippy::shadow_unrelated)]
1501 fn test_f2dg() {
1502 let mut state = prep_state(&["X"], &["Z"]);
1506 state.f2dg(0);
1507 check_state(&state, &["-iW"], &["X"]);
1508
1509 let mut state = prep_state(&["iW"], &["X"]);
1511 state.f2dg(0);
1512 check_state(&state, &["Z"], &["W"]);
1513
1514 let mut state = prep_state(&["Z"], &["X"]);
1516 state.f2dg(0);
1517 check_state(&state, &["-X"], &["W"]);
1518
1519 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1521 state.f2dg(1);
1522 check_state(&state, &["-IZI"], &["IWI"]);
1523 }
1524
1525 #[test]
1526 #[expect(clippy::shadow_unrelated)]
1527 fn test_f3() {
1528 let mut state = prep_state(&["X"], &["Z"]);
1532 state.f3(0);
1533 check_state(&state, &["iW"], &["X"]);
1534
1535 let mut state = prep_state(&["iW"], &["X"]);
1537 state.f3(0);
1538 check_state(&state, &["-Z"], &["W"]);
1539
1540 let mut state = prep_state(&["Z"], &["X"]);
1542 state.f3(0);
1543 check_state(&state, &["-X"], &["W"]);
1544
1545 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1547 state.f3(1);
1548 check_state(&state, &["IZI"], &["IWI"]);
1549 }
1550
1551 #[test]
1552 #[expect(clippy::shadow_unrelated)]
1553 fn test_f3dg() {
1554 let mut state = prep_state(&["X"], &["Z"]);
1558 state.f3dg(0);
1559 check_state(&state, &["-Z"], &["W"]);
1560
1561 let mut state = prep_state(&["iW"], &["X"]);
1563 state.f3dg(0);
1564 check_state(&state, &["X"], &["Z"]);
1565
1566 let mut state = prep_state(&["Z"], &["X"]);
1568 state.f3dg(0);
1569 check_state(&state, &["-iW"], &["Z"]);
1570
1571 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1573 state.f3dg(1);
1574 check_state(&state, &["-IXI"], &["IZI"]);
1575 }
1576
1577 #[test]
1578 #[expect(clippy::shadow_unrelated)]
1579 fn test_f4() {
1580 let mut state = prep_state(&["X"], &["Z"]);
1584 state.f4(0);
1585 check_state(&state, &["Z"], &["W"]);
1586
1587 let mut state = prep_state(&["iW"], &["X"]);
1589 state.f4(0);
1590 check_state(&state, &["-X"], &["Z"]);
1591
1592 let mut state = prep_state(&["Z"], &["X"]);
1594 state.f4(0);
1595 check_state(&state, &["-iW"], &["Z"]);
1596
1597 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1599 state.f4(1);
1600 check_state(&state, &["IXI"], &["IZI"]);
1601 }
1602
1603 #[test]
1604 #[expect(clippy::shadow_unrelated)]
1605 fn test_f4dg() {
1606 let mut state = prep_state(&["X"], &["Z"]);
1610 state.f4dg(0);
1611 check_state(&state, &["-iW"], &["X"]);
1612
1613 let mut state = prep_state(&["iW"], &["X"]);
1615 state.f4dg(0);
1616 check_state(&state, &["-Z"], &["W"]);
1617
1618 let mut state = prep_state(&["Z"], &["X"]);
1620 state.f4dg(0);
1621 check_state(&state, &["X"], &["W"]);
1622
1623 let mut state = prep_state(&["-iIWI"], &["IXI"]);
1625 state.f4dg(1);
1626 check_state(&state, &["IZI"], &["IWI"]);
1627 }
1628
1629 #[test]
1630 #[expect(clippy::shadow_unrelated)]
1631 fn test_cx() {
1632 let mut state = prep_state(&["IX"], &["IZ"]);
1638 state.cx(0, 1);
1639 check_state(&state, &["IX"], &["ZZ"]);
1640
1641 let mut state = prep_state(&["IZ"], &["IX"]);
1643 state.cx(0, 1);
1644 check_state(&state, &["ZZ"], &["IX"]);
1645
1646 let mut state = prep_state(&["XI"], &["ZI"]);
1648 state.cx(0, 1);
1649 check_state(&state, &["XX"], &["ZI"]);
1650
1651 let mut state = prep_state(&["ZI"], &["XI"]);
1653 state.cx(0, 1);
1654 check_state(&state, &["ZI"], &["XX"]);
1655 }
1656
1657 #[test]
1658 fn test_cy() {
1659 let mut state = prep_state(&["IX"], &["IZ"]);
1665 state.cy(0, 1);
1666 check_state(&state, &["ZX"], &["ZZ"]);
1667
1668 let mut state = prep_state(&["IZ"], &["IX"]);
1670 state.cy(0, 1);
1671 check_state(&state, &["ZZ"], &["ZX"]);
1672
1673 let mut state = prep_state(&["XI"], &["ZI"]);
1675 state.cy(0, 1);
1676 check_state(&state, &["-iXW"], &["ZI"]);
1677
1678 let mut state = prep_state(&["ZI"], &["XI"]);
1680 state.cy(0, 1);
1681 check_state(&state, &["ZI"], &["XW"]);
1682 }
1683
1684 #[test]
1685 #[expect(clippy::shadow_unrelated)]
1686 fn test_cz() {
1687 let mut state = prep_state(&["IX"], &["IZ"]);
1693 state.cz(0, 1);
1694 check_state(&state, &["ZX"], &["IZ"]);
1695
1696 let mut state = prep_state(&["IZ"], &["IX"]);
1698 state.cz(0, 1);
1699 check_state(&state, &["IZ"], &["ZX"]);
1700
1701 let mut state = prep_state(&["XI"], &["ZI"]);
1703 state.cz(0, 1);
1704 check_state(&state, &["XZ"], &["ZI"]);
1705
1706 let mut state = prep_state(&["ZI"], &["XI"]);
1708 state.cz(0, 1);
1709 check_state(&state, &["ZI"], &["XZ"]);
1710 }
1711
1712 #[test]
1713 #[expect(clippy::shadow_unrelated)]
1714 fn test_sxx() {
1715 let mut state = prep_state(&["IX"], &["IZ"]);
1724 state.sxx(0, 1);
1725 check_state(&state, &["IX"], &["XW"]);
1726
1727 let mut state = prep_state(&["IZ"], &["IX"]);
1729 state.sxx(0, 1);
1730 check_state(&state, &["-iXW"], &["IX"]);
1731
1732 let mut state = prep_state(&["XI"], &["ZI"]);
1734 state.sxx(0, 1);
1735 check_state(&state, &["XI"], &["WX"]);
1736
1737 let mut state = prep_state(&["ZI"], &["XI"]);
1739 state.sxx(0, 1);
1740 check_state(&state, &["-iWX"], &["XI"]);
1741 }
1742
1743 #[test]
1744 #[expect(clippy::shadow_unrelated)]
1745 fn test_sxxdg() {
1746 let mut state = prep_state(&["IX"], &["IZ"]);
1755 state.sxxdg(0, 1);
1756 check_state(&state, &["IX"], &["XW"]);
1757
1758 let mut state = prep_state(&["IZ"], &["IX"]);
1760 state.sxxdg(0, 1);
1761 check_state(&state, &["iXW"], &["IX"]);
1762
1763 let mut state = prep_state(&["XI"], &["ZI"]);
1765 state.sxxdg(0, 1);
1766 check_state(&state, &["XI"], &["WX"]);
1767
1768 let mut state = prep_state(&["ZI"], &["XI"]);
1770 state.sxxdg(0, 1);
1771 check_state(&state, &["iWX"], &["XI"]);
1772 }
1773
1774 #[test]
1775 #[expect(clippy::shadow_unrelated)]
1776 fn test_syy() {
1777 let mut state = prep_state(&["IX"], &["IZ"]);
1786 state.syy(0, 1);
1787 check_state(&state, &["-iWZ"], &["WX"]);
1788
1789 let mut state = prep_state(&["IZ"], &["IX"]);
1791 state.syy(0, 1);
1792 check_state(&state, &["iWX"], &["WZ"]);
1793
1794 let mut state = prep_state(&["XI"], &["ZI"]);
1796 state.syy(0, 1);
1797 check_state(&state, &["-iZW"], &["XW"]);
1798
1799 let mut state = prep_state(&["ZI"], &["XI"]);
1801 state.syy(0, 1);
1802 check_state(&state, &["iXW"], &["ZW"]);
1803 }
1804
1805 #[test]
1806 #[expect(clippy::shadow_unrelated)]
1807 fn test_syydg() {
1808 let mut state = prep_state(&["IX"], &["IZ"]);
1817 state.syydg(0, 1);
1818 check_state(&state, &["iWZ"], &["WX"]);
1819
1820 let mut state = prep_state(&["IZ"], &["IX"]);
1822 state.syydg(0, 1);
1823 check_state(&state, &["-iWX"], &["WZ"]);
1824
1825 let mut state = prep_state(&["XI"], &["ZI"]);
1827 state.syydg(0, 1);
1828 check_state(&state, &["iZW"], &["XW"]);
1829
1830 let mut state = prep_state(&["ZI"], &["XI"]);
1832 state.syydg(0, 1);
1833 check_state(&state, &["-iXW"], &["ZW"]);
1834 }
1835
1836 #[test]
1837 #[expect(clippy::shadow_unrelated)]
1838 fn test_szz() {
1839 let mut state = prep_state(&["IX"], &["IZ"]);
1848 state.szz(0, 1);
1849 check_state(&state, &["iZW"], &["IZ"]);
1850
1851 let mut state = prep_state(&["IZ"], &["IX"]);
1853 state.szz(0, 1);
1854 check_state(&state, &["IZ"], &["ZW"]);
1855
1856 let mut state = prep_state(&["XI"], &["ZI"]);
1858 state.szz(0, 1);
1859 check_state(&state, &["iWZ"], &["ZI"]);
1860
1861 let mut state = prep_state(&["ZI"], &["XI"]);
1863 state.szz(0, 1);
1864 check_state(&state, &["ZI"], &["WZ"]);
1865 }
1866
1867 #[test]
1868 #[expect(clippy::shadow_unrelated)]
1869 fn test_szzdg() {
1870 let mut state = prep_state(&["IX"], &["IZ"]);
1879 state.szzdg(0, 1);
1880 check_state(&state, &["-iZW"], &["IZ"]);
1881
1882 let mut state = prep_state(&["IZ"], &["IX"]);
1884 state.szzdg(0, 1);
1885 check_state(&state, &["IZ"], &["ZW"]);
1886
1887 let mut state = prep_state(&["XI"], &["ZI"]);
1889 state.szzdg(0, 1);
1890 check_state(&state, &["-iWZ"], &["ZI"]);
1891
1892 let mut state = prep_state(&["ZI"], &["XI"]);
1894 state.szzdg(0, 1);
1895 check_state(&state, &["ZI"], &["WZ"]);
1896 }
1897
1898 #[test]
1899 #[expect(clippy::shadow_unrelated)]
1900 fn test_swap() {
1901 let mut state = prep_state(&["IX"], &["IZ"]);
1910 state.swap(0, 1);
1911 check_state(&state, &["XI"], &["ZI"]);
1912
1913 let mut state = prep_state(&["IZ"], &["IX"]);
1915 state.swap(0, 1);
1916 check_state(&state, &["ZI"], &["XI"]);
1917
1918 let mut state = prep_state(&["XI"], &["ZI"]);
1920 state.swap(0, 1);
1921 check_state(&state, &["IX"], &["IZ"]);
1922
1923 let mut state = prep_state(&["ZI"], &["XI"]);
1925 state.swap(0, 1);
1926 check_state(&state, &["IZ"], &["IX"]);
1927 }
1928
1929 #[test]
1930 #[expect(clippy::shadow_unrelated)]
1931 fn test_g2() {
1932 let mut state = prep_state(&["IX"], &["IZ"]);
1941 state.g2(0, 1);
1942 check_state(&state, &["XI"], &["ZX"]);
1943
1944 let mut state = prep_state(&["IZ"], &["IX"]);
1946 state.g2(0, 1);
1947 check_state(&state, &["ZX"], &["XI"]);
1948
1949 let mut state = prep_state(&["XI"], &["ZI"]);
1951 state.g2(0, 1);
1952 check_state(&state, &["IX"], &["XZ"]);
1953
1954 let mut state = prep_state(&["ZI"], &["XI"]);
1956 state.g2(0, 1);
1957 check_state(&state, &["XZ"], &["IX"]);
1958 }
1959
1960 fn one_bit_z_teleport(
1961 mut state: SparseStab<VecSet<u32>, u32>,
1962 ) -> (SparseStab<VecSet<u32>, u32>, bool) {
1963 state.cx(1, 0);
1964 state.h(1);
1965 let (m1, d1) = state.mz(1);
1966 if m1 {
1967 state.z(0);
1968 }
1969 (state, d1)
1970 }
1971
1972 #[test]
1974 fn test_nondeterministic_mz_one_bit_z_teleportation_of_x() {
1975 for _ in 1_u32..=100 {
1978 let d1;
1979 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(2);
1980 state.h(1); (state, d1) = one_bit_z_teleport(state);
1982 state.h(0);
1984 let (m0, d0) = state.mz(0);
1985 let m0_int = u8::from(m0);
1986 assert_eq!(m0_int, 0); assert!(!d1); assert!(d0); }
1990 }
1991
1992 #[test]
1994 fn test_nondeterministic_mz_one_bit_z_teleportation_of_nx() {
1995 for _ in 1_u32..=100 {
1998 let d1;
1999 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(2);
2000 state.x(1);
2001 state.h(1); (state, d1) = one_bit_z_teleport(state);
2003 state.h(0);
2005 let (m0, d0) = state.mz(0);
2006 let m0_int = u8::from(m0);
2007 assert_eq!(m0_int, 1); assert!(!d1); assert!(d0); }
2011 }
2012
2013 #[test]
2015 fn test_nondeterministic_mz_one_bit_z_teleportation_of_y() {
2016 for _ in 1_u32..=100 {
2019 let d1;
2020 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(2);
2021 state.sxdg(1); (state, d1) = one_bit_z_teleport(state);
2023 state.sx(0); let (m0, d0) = state.mz(0);
2026 let m0_int = u8::from(m0);
2027 assert_eq!(m0_int, 0); assert!(!d1); assert!(d0); }
2031 }
2032
2033 #[test]
2035 fn test_nondeterministic_mz_one_bit_z_teleportation_of_ny() {
2036 for _ in 1_u32..=100 {
2039 let d1;
2040 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(2);
2041 state.x(1);
2042 state.sxdg(1); (state, d1) = one_bit_z_teleport(state);
2044 state.sx(0); let (m0, d0) = state.mz(0);
2047 let m0_int = u8::from(m0);
2048 assert_eq!(m0_int, 1); assert!(!d1); assert!(d0); }
2052 }
2053
2054 #[test]
2056 fn test_nondeterministic_mz_one_bit_z_teleportation_of_z() {
2057 for _ in 1_u32..=100 {
2060 let d1;
2061 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(2);
2062 (state, d1) = one_bit_z_teleport(state);
2064 let (m0, d0) = state.mz(0);
2065 let m0_int = u8::from(m0);
2066 assert_eq!(m0_int, 0); assert!(!d1); assert!(d0); }
2070 }
2071
2072 #[test]
2074 fn test_nondeterministic_mz_one_bit_z_teleportation_of_nz() {
2075 for _ in 1_u32..=100 {
2078 let d1;
2079 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(2);
2080 state.x(1); (state, d1) = one_bit_z_teleport(state);
2082 let (m0, d0) = state.mz(0);
2083 let m0_int = u8::from(m0);
2084 assert_eq!(m0_int, 1); assert!(!d1); assert!(d0); }
2088 }
2089
2090 fn teleport(
2091 mut state: SparseStab<VecSet<u32>, u32>,
2092 ) -> (SparseStab<VecSet<u32>, u32>, bool, bool) {
2093 state.h(1);
2100 state.cx(1, 2);
2101 state.cx(0, 1);
2102 state.h(0);
2103 let (m0, d0) = state.mz(0);
2104 let (m1, d1) = state.mz(1);
2105 if m1 {
2106 state.x(2);
2107 }
2108 if m0 {
2109 state.z(2);
2110 }
2111 (state, d0, d1)
2112 }
2113
2114 #[test]
2115 fn test_nondeterministic_mz_via_teleportation_x() {
2116 for _ in 1_u32..=100 {
2117 let d0;
2118 let d1;
2119 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(3);
2120 state.h(0);
2121 (state, d0, d1) = teleport(state);
2122 state.h(2);
2123 let (m2, d2) = state.mz(2);
2124 let m2_int = u8::from(m2);
2125 assert_eq!(m2_int, 0);
2126 assert!(!d0);
2127 assert!(!d1);
2128 assert!(d2);
2129 }
2130 }
2131
2132 #[test]
2133 fn test_nondeterministic_mz_via_teleportation_nx() {
2134 for _ in 1_u32..=100 {
2135 let d0;
2136 let d1;
2137 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(3);
2138 state.x(0);
2139 state.h(0);
2140 (state, d0, d1) = teleport(state);
2141 state.h(2);
2142 let (m2, d2) = state.mz(2);
2143 let m2_int = u8::from(m2);
2144
2145 assert_eq!(m2_int, 1);
2146 assert!(!d0);
2147 assert!(!d1);
2148 assert!(d2);
2149 }
2150 }
2151
2152 #[test]
2153 fn test_nondeterministic_mz_via_teleportation_y() {
2154 for _ in 1_u32..=100 {
2155 let d0;
2156 let d1;
2157 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(3);
2158 state.sxdg(0);
2159 (state, d0, d1) = teleport(state);
2160 state.sx(2);
2161 let (m2, d2) = state.mz(2);
2162 let m2_int = u8::from(m2);
2163 assert_eq!(m2_int, 0);
2164 assert!(!d0);
2165 assert!(!d1);
2166 assert!(d2);
2167 }
2168 }
2169
2170 #[test]
2171 fn test_nondeterministic_mz_via_teleportation_ny() {
2172 for _ in 1_u32..=100 {
2173 let d0;
2174 let d1;
2175 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(3);
2176 state.x(0);
2177 state.sxdg(0);
2178 (state, d0, d1) = teleport(state);
2179 state.sx(2);
2180 let (m2, d2) = state.mz(2);
2181 let m2_int = u8::from(m2);
2182 assert_eq!(m2_int, 1);
2183 assert!(!d0);
2184 assert!(!d1);
2185 assert!(d2);
2186 }
2187 }
2188
2189 #[test]
2190 fn test_nondeterministic_mz_via_teleportation_z() {
2191 for _ in 1_u32..=100 {
2192 let d0;
2193 let d1;
2194 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(3);
2195 (state, d0, d1) = teleport(state);
2196 let (m2, d2) = state.mz(2);
2197 let m2_int = u8::from(m2);
2198
2199 assert_eq!(m2_int, 0);
2200 assert!(!d0);
2201 assert!(!d1);
2202 assert!(d2);
2203 }
2204 }
2205
2206 #[test]
2207 fn test_nondeterministic_mz_via_teleportation_nz() {
2208 for _ in 1_u32..=100 {
2209 let d0;
2210 let d1;
2211 let mut state: SparseStab<VecSet<u32>, u32> = SparseStab::new(3);
2212 state.x(0); (state, d0, d1) = teleport(state);
2214 let (m2, d2) = state.mz(2);
2215 let m2_int = u8::from(m2);
2216
2217 assert_eq!(m2_int, 1);
2218 assert!(!d0);
2219 assert!(!d1);
2220 assert!(d2);
2221 }
2222 }
2223
2224 }