quantrs2_core/error_correction/
stabilizer.rs1use super::pauli::{Pauli, PauliString};
4use crate::error::{QuantRS2Error, QuantRS2Result};
5
6#[derive(Debug, Clone)]
8pub struct StabilizerCode {
9 pub n: usize,
11 pub k: usize,
13 pub d: usize,
15 pub stabilizers: Vec<PauliString>,
17 pub logical_x: Vec<PauliString>,
19 pub logical_z: Vec<PauliString>,
21}
22
23impl StabilizerCode {
24 pub fn new(
26 n: usize,
27 k: usize,
28 d: usize,
29 stabilizers: Vec<PauliString>,
30 logical_x: Vec<PauliString>,
31 logical_z: Vec<PauliString>,
32 ) -> QuantRS2Result<Self> {
33 if stabilizers.len() > 2 * (n - k) {
37 return Err(QuantRS2Error::InvalidInput(format!(
38 "Too many stabilizers: got {}, maximum is {}",
39 stabilizers.len(),
40 2 * (n - k)
41 )));
42 }
43
44 if logical_x.len() != k || logical_z.len() != k {
45 return Err(QuantRS2Error::InvalidInput(
46 "Number of logical operators must equal k".to_string(),
47 ));
48 }
49
50 for i in 0..stabilizers.len() {
52 for j in i + 1..stabilizers.len() {
53 if !stabilizers[i].commutes_with(&stabilizers[j])? {
54 return Err(QuantRS2Error::InvalidInput(
55 "Stabilizers must commute".to_string(),
56 ));
57 }
58 }
59 }
60
61 Ok(Self {
62 n,
63 k,
64 d,
65 stabilizers,
66 logical_x,
67 logical_z,
68 })
69 }
70
71 pub fn repetition_code() -> Self {
73 let stabilizers = vec![
74 PauliString::new(vec![Pauli::Z, Pauli::Z, Pauli::I]),
75 PauliString::new(vec![Pauli::I, Pauli::Z, Pauli::Z]),
76 ];
77
78 let logical_x = vec![PauliString::new(vec![Pauli::X, Pauli::X, Pauli::X])];
79 let logical_z = vec![PauliString::new(vec![Pauli::Z, Pauli::I, Pauli::I])];
80
81 Self::new(3, 1, 1, stabilizers, logical_x, logical_z)
82 .expect("3-qubit repetition code: verified standard code parameters are always valid")
83 }
84
85 pub fn five_qubit_code() -> Self {
87 let stabilizers = vec![
88 PauliString::new(vec![Pauli::X, Pauli::Z, Pauli::Z, Pauli::X, Pauli::I]),
89 PauliString::new(vec![Pauli::I, Pauli::X, Pauli::Z, Pauli::Z, Pauli::X]),
90 PauliString::new(vec![Pauli::X, Pauli::I, Pauli::X, Pauli::Z, Pauli::Z]),
91 PauliString::new(vec![Pauli::Z, Pauli::X, Pauli::I, Pauli::X, Pauli::Z]),
92 ];
93
94 let logical_x = vec![PauliString::new(vec![
95 Pauli::X,
96 Pauli::X,
97 Pauli::X,
98 Pauli::X,
99 Pauli::X,
100 ])];
101 let logical_z = vec![PauliString::new(vec![
102 Pauli::Z,
103 Pauli::Z,
104 Pauli::Z,
105 Pauli::Z,
106 Pauli::Z,
107 ])];
108
109 Self::new(5, 1, 3, stabilizers, logical_x, logical_z)
110 .expect("5-qubit perfect code: verified standard code parameters are always valid")
111 }
112
113 pub fn steane_code() -> Self {
115 let stabilizers = vec![
116 PauliString::new(vec![
117 Pauli::I,
118 Pauli::I,
119 Pauli::I,
120 Pauli::X,
121 Pauli::X,
122 Pauli::X,
123 Pauli::X,
124 ]),
125 PauliString::new(vec![
126 Pauli::I,
127 Pauli::X,
128 Pauli::X,
129 Pauli::I,
130 Pauli::I,
131 Pauli::X,
132 Pauli::X,
133 ]),
134 PauliString::new(vec![
135 Pauli::X,
136 Pauli::I,
137 Pauli::X,
138 Pauli::I,
139 Pauli::X,
140 Pauli::I,
141 Pauli::X,
142 ]),
143 PauliString::new(vec![
144 Pauli::I,
145 Pauli::I,
146 Pauli::I,
147 Pauli::Z,
148 Pauli::Z,
149 Pauli::Z,
150 Pauli::Z,
151 ]),
152 PauliString::new(vec![
153 Pauli::I,
154 Pauli::Z,
155 Pauli::Z,
156 Pauli::I,
157 Pauli::I,
158 Pauli::Z,
159 Pauli::Z,
160 ]),
161 PauliString::new(vec![
162 Pauli::Z,
163 Pauli::I,
164 Pauli::Z,
165 Pauli::I,
166 Pauli::Z,
167 Pauli::I,
168 Pauli::Z,
169 ]),
170 ];
171
172 let logical_x = vec![PauliString::new(vec![
173 Pauli::X,
174 Pauli::X,
175 Pauli::X,
176 Pauli::X,
177 Pauli::X,
178 Pauli::X,
179 Pauli::X,
180 ])];
181 let logical_z = vec![PauliString::new(vec![
182 Pauli::Z,
183 Pauli::Z,
184 Pauli::Z,
185 Pauli::Z,
186 Pauli::Z,
187 Pauli::Z,
188 Pauli::Z,
189 ])];
190
191 Self::new(7, 1, 3, stabilizers, logical_x, logical_z)
192 .expect("7-qubit Steane code: verified standard code parameters are always valid")
193 }
194
195 pub fn syndrome(&self, error: &PauliString) -> QuantRS2Result<Vec<bool>> {
197 if error.paulis.len() != self.n {
198 return Err(QuantRS2Error::InvalidInput(
199 "Error must act on all physical qubits".to_string(),
200 ));
201 }
202
203 let mut syndrome = Vec::with_capacity(self.stabilizers.len());
204 for stabilizer in &self.stabilizers {
205 syndrome.push(!stabilizer.commutes_with(error)?);
206 }
207
208 Ok(syndrome)
209 }
210}