rustiq_core/structures/
isometry.rs1use super::pauli_like::PauliLike;
2use super::pauli_set::PauliSet;
3use crate::routines::f2_linalg::{row_echelon, Matrix};
4use rand::Rng;
5use std::fmt;
6
7#[derive(Clone, Debug, PartialEq)]
8pub struct IsometryTableau {
9 pub n: usize,
10 pub k: usize,
11 pub logicals: PauliSet,
12 pub stabilizers: PauliSet,
13}
14
15impl IsometryTableau {
16 pub fn new(n: usize, k: usize) -> Self {
17 let mut logicals = PauliSet::new(n + k);
18 for i in 0..n {
19 let mut vecbool = vec![false; 2 * n + 2 * k];
20 vecbool[i] = true;
21 logicals.insert_vec_bool(&vecbool, false);
22 }
23 for i in 0..n {
24 let mut vecbool = vec![false; 2 * n + 2 * k];
25 vecbool[i + n + k] = true;
26 logicals.insert_vec_bool(&vecbool, false);
27 }
28 let mut stabilizers = PauliSet::new(n + k);
29 for i in 0..k {
30 let mut vecbool = vec![false; 2 * n + 2 * k];
31 vecbool[n + k + n + i] = true;
32 stabilizers.insert_vec_bool(&vecbool, false);
33 }
34 IsometryTableau {
35 n,
36 k,
37 logicals,
38 stabilizers,
39 }
40 }
41 pub fn random(n: usize, k: usize) -> Self {
42 let mut rng = rand::thread_rng();
43 let mut iso = Self::new(n, k);
44 for _ in 0..(n + k) * (n + k) {
45 let i = rng.gen::<usize>() % (n + k);
46 loop {
47 let j = rng.gen::<usize>() % (n + k);
48 if i == j {
49 continue;
50 }
51 iso.cnot(i, j);
52 break;
53 }
54 for _ in 0..(n + k) {
55 let gate_i = rng.gen::<u8>() % 3;
56 if gate_i == 1 {
57 let q = rng.gen::<usize>() % (n + k);
58 iso.h(q);
59 }
60 if gate_i == 2 {
61 let q = rng.gen::<usize>() % (n + k);
62 iso.s(q);
63 }
64 }
65 }
66 iso
67 }
68 pub fn normalize_inplace(&mut self) {
71 let mut table: Matrix = Vec::new();
72 for i in 0..self.k {
74 let (_, vec) = self.stabilizers.get_as_vec_bool(i);
75 table.push(vec);
76 }
77 for i in 0..2 * self.n {
79 let (_, vec) = self.logicals.get_as_vec_bool(i);
80 table.push(vec);
81 }
82 row_echelon(&mut table, self.k);
83 let mut stabs = PauliSet::new(self.n + self.k);
84 for row in table.iter().take(self.k) {
85 stabs.insert_vec_bool(row, false);
86 }
87 let mut logicals = PauliSet::new(self.n + self.k);
88 for i in 0..2 * self.n {
89 logicals.insert_vec_bool(&table[self.k + i], false);
90 }
91 self.logicals = logicals;
92 self.stabilizers = stabs;
93 }
94}
95
96impl PauliLike for IsometryTableau {
97 fn h(&mut self, i: usize) {
98 self.logicals.h(i);
99 self.stabilizers.h(i);
100 }
101
102 fn s(&mut self, i: usize) {
103 self.logicals.s(i);
104 self.stabilizers.s(i);
105 }
106
107 fn sd(&mut self, i: usize) {
108 self.logicals.sd(i);
109 self.stabilizers.sd(i);
110 }
111
112 fn sqrt_x(&mut self, i: usize) {
113 self.logicals.sqrt_x(i);
114 self.stabilizers.sqrt_x(i);
115 }
116
117 fn sqrt_xd(&mut self, i: usize) {
118 self.logicals.sqrt_xd(i);
119 self.stabilizers.sqrt_xd(i);
120 }
121
122 fn cnot(&mut self, i: usize, j: usize) {
123 self.logicals.cnot(i, j);
124 self.stabilizers.cnot(i, j);
125 }
126}
127
128impl fmt::Display for IsometryTableau {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 write!(
131 f,
132 "Logicals:\n{}Stabilizers:\n{}",
133 self.logicals, self.stabilizers
134 )?;
135 fmt::Result::Ok(())
136 }
137}