1use lay::{Layer, Measured, OpsVec, operations::{opid, OpArgs, Operation, PauliOperation, HOperation, SOperation, CXOperation}, gates::{PauliGate, HGate, SGate, CXGate}};
2use lay_simulator_gk::{ GottesmanKnillSimulator, DefaultRng };
3
4use num_traits::cast::{cast, NumCast};
5
6macro_rules! cast { ($n:expr) => { cast($n).unwrap() } }
7
8const PHYSQUBIT_PER_LOGQUBIT: u32 = 7;
9const MEASURE_ANCILLA_QUBITS: u32 = 6;
10
11#[derive(Debug)]
12pub struct SteaneLayer<L: Layer> {
13 pub instance: L,
14 n_logical_qubits: u32,
15 instance_buf: L::Buffer,
16 measured: Vec<bool>,
17}
18
19const ERR_TABLE_X: [u32;8] = [999 , 0, 1, 6, 2, 4, 3, 5];
20const ERR_TABLE_Z: [u32;8] = [999 , 3, 4, 6, 5, 0, 1, 2];
21
22pub fn required_physical_qubits(n_logical_qubits: u32) -> u32 {
23 PHYSQUBIT_PER_LOGQUBIT * n_logical_qubits + MEASURE_ANCILLA_QUBITS
24}
25
26impl<L: Layer> SteaneLayer<L> {
27 pub fn from_instance(instance: L, n_logical_qubits: u32) -> Self {
28 let instance_buf = instance.make_buffer();
29 Self { instance,
30 n_logical_qubits,
31 instance_buf,
32 measured: vec![false; n_logical_qubits as usize]
33 }
34 }
35}
36
37impl SteaneLayer<GottesmanKnillSimulator<DefaultRng>> {
38 pub fn from_seed_with_gk(n_logical_qubits: u32, seed: u64) -> Self {
39 SteaneLayer::from_instance(
40 GottesmanKnillSimulator::from_seed(required_physical_qubits(n_logical_qubits) as _, seed),
41 n_logical_qubits)
42 }
43}
44
45#[derive(Debug, PartialEq, Eq)]
46pub struct SteaneBuffer(Vec<bool>);
47
48impl Measured for SteaneBuffer
49{
50 type Slot = u32;
51 fn get(&self, s: u32) -> bool {
52 (self.0)[s as usize]
53 }
54}
55
56impl<L: Layer + PauliGate + HGate + SGate + CXGate> Layer for SteaneLayer<L>
57where
58 L : Layer + PauliGate + HGate + SGate + CXGate,
59 L::Operation: Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
60 L::Qubit: NumCast,
61 L::Slot : NumCast,
62{
63 type Operation = OpArgs<Self>;
64 type Qubit = u32;
65 type Slot = u32;
66 type Buffer = SteaneBuffer;
67 type Requested = L::Requested;
68 type Response = L::Response;
69
70 fn send(&mut self, ops: &[Self::Operation]) -> L::Requested {
71 let mut lowlevel_ops = OpsVec::new();
72 for op in ops {
73 match op {
74 OpArgs::Empty(id) if *id == opid::INIT => {
75 self.initialize(&mut lowlevel_ops);
76 },
77 OpArgs::Empty(id) if *id == opid::USERDEF => {
78 self.syndrome_measure_and_recover(&mut lowlevel_ops);
79 },
80 OpArgs::Q(id, q) => {
81 match *id {
82 opid::X => {
83 self.x(*q, &mut lowlevel_ops);
84 },
85 opid::Y => {
86 self.y(*q, &mut lowlevel_ops);
87 },
88 opid::Z => {
89 self.z(*q, &mut lowlevel_ops);
90 },
91 opid::H => {
92 self.h(*q, &mut lowlevel_ops);
93 },
94 opid::S => {
95 self.s(*q, &mut lowlevel_ops);
96 },
97 opid::SDG => {
98 self.sdg(*q, &mut lowlevel_ops);
99 },
100 _ => {
101 unimplemented!("Unknown 1 qubit op");
102 }
103 }
104 },
105 OpArgs::QS(id, q, s) if *id == opid::MEAS => {
106 self.measure(*q, *s, &mut lowlevel_ops);
107 },
108 OpArgs::QQ(id, c, t) if *id == opid::CX => {
109 self.cx(*c, *t, &mut lowlevel_ops);
110 },
111 _ => unimplemented!("Unknown op")
112 }
113 }
114 self.instance.send(lowlevel_ops.as_ref())
115 }
116
117 fn receive(&mut self, buf: &mut Self::Buffer) -> L::Response {
118 let res = self.instance.receive(&mut self.instance_buf);
119 std::mem::swap(&mut self.measured, &mut buf.0);
120 res
121 }
122
123 fn send_receive(&mut self, ops: &[Self::Operation], buf: &mut Self::Buffer) -> L::Response {
124 self.send(&ops);
125 self.receive(buf)
126 }
127
128 fn make_buffer(&self) -> Self::Buffer {
129 SteaneBuffer(vec![false; self.n_logical_qubits as usize])
130 }
131}
132
133impl<L: Layer + PauliGate + HGate + SGate + CXGate> PauliGate for SteaneLayer<L>
134where
135 L : Layer + PauliGate + HGate + SGate + CXGate,
136 L::Operation: Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
137 L::Qubit : NumCast,
138 L::Slot : NumCast {}
139
140impl<L: Layer + PauliGate + HGate + SGate + CXGate> HGate for SteaneLayer<L>
141where
142 L : Layer + PauliGate + HGate + SGate + CXGate,
143 L::Operation: Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
144 L::Qubit : NumCast,
145 L::Slot : NumCast {}
146
147impl<L: Layer + PauliGate + HGate + SGate + CXGate> SGate for SteaneLayer<L>
148where
149 L : Layer + PauliGate + HGate + SGate + CXGate,
150 L::Operation: Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
151 L::Qubit : NumCast,
152 L::Slot : NumCast {}
153
154impl<L: Layer + PauliGate + HGate + SGate + CXGate> CXGate for SteaneLayer<L>
155where
156 L : Layer + PauliGate + HGate + SGate + CXGate,
157 L::Operation: Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
158 L::Qubit : NumCast,
159 L::Slot : NumCast {}
160
161impl<L: Layer + PauliGate + HGate + SGate + CXGate> SteaneLayer<L>
162where
163 L : Layer + PauliGate + HGate + SGate + CXGate,
164 L::Operation: Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
165 L::Qubit : NumCast,
166 L::Slot : NumCast,
167{
168 fn measure_ancilla(&self) -> u32 {
169 self.n_logical_qubits * PHYSQUBIT_PER_LOGQUBIT
171 }
172
173 fn initialize(&mut self, ops: &mut OpsVec<L>) {
174 ops.initialize();
175 self.syndrome_measure_and_recover(ops);
176 }
177
178 fn syndrome_measure_and_recover(&mut self, ops: &mut OpsVec<L>) {
179 let m0 = self.measure_ancilla();
181 for i in 0..self.n_logical_qubits {
182 let offset = i * PHYSQUBIT_PER_LOGQUBIT;
183 for j in 0..PHYSQUBIT_PER_LOGQUBIT {
184 ops.h(cast!(offset + j));
185 }
186 ops.cx(cast!(offset), cast!(m0));
187 ops.cx(cast!(offset + 1), cast!(m0 + 1));
188 ops.cx(cast!(offset + 2), cast!(m0 + 2));
189 ops.cx(cast!(offset + 3), cast!(m0 + 1));
190 ops.cx(cast!(offset + 3), cast!(m0 + 2));
191 ops.cx(cast!(offset + 4), cast!(m0));
192 ops.cx(cast!(offset + 4), cast!(m0 + 2));
193 ops.cx(cast!(offset + 5), cast!(m0));
194 ops.cx(cast!(offset + 5), cast!(m0 + 1));
195 ops.cx(cast!(offset + 5), cast!(m0 + 2));
196 ops.cx(cast!(offset + 6), cast!(m0));
197 ops.cx(cast!(offset + 6), cast!(m0 + 1));
198
199 for j in 0..PHYSQUBIT_PER_LOGQUBIT {
200 ops.h(cast!(offset + j));
201 }
202 ops.cx(cast!(offset), cast!(m0 + 3));
203 ops.cx(cast!(offset), cast!(m0 + 5));
204 ops.cx(cast!(offset + 1), cast!(m0 + 4));
205 ops.cx(cast!(offset + 1), cast!(m0 + 5));
206 ops.cx(cast!(offset + 2), cast!(m0 + 3));
207 ops.cx(cast!(offset + 2), cast!(m0 + 4));
208 ops.cx(cast!(offset + 2), cast!(m0 + 5));
209 ops.cx(cast!(offset + 3), cast!(m0 + 3));
210 ops.cx(cast!(offset + 4), cast!(m0 + 4));
211 ops.cx(cast!(offset + 5), cast!(m0 + 5));
212 ops.cx(cast!(offset + 6), cast!(m0 + 3));
213 ops.cx(cast!(offset + 6), cast!(m0 + 4));
214 for j in 0..MEASURE_ANCILLA_QUBITS {
215 ops.measure(cast!(m0 + j), cast!(j));
216 }
217 let mut buf = self.instance.make_buffer();
218 self.instance.send_receive(ops.as_ref(), &mut buf);
219 let measured = buf.get_range_u8(0, MEASURE_ANCILLA_QUBITS as usize);
220 ops.clear();
222 for j in 0..MEASURE_ANCILLA_QUBITS {
223 if measured & (1 << j) != 0 {
225 ops.x(cast!(m0 + j));
226 }
227 }
228 if measured & 7 > 0 {
229 let err_x = ERR_TABLE_X[(measured & 7) as usize] + i * PHYSQUBIT_PER_LOGQUBIT;
230 ops.z(cast!(err_x));
232 }
233 if (measured >> 3) > 0 {
234 let err_z = ERR_TABLE_Z[(measured >> 3) as usize] + i * PHYSQUBIT_PER_LOGQUBIT;
235 ops.x(cast!(err_z));
237 }
238 }
239 }
241
242 fn x(&mut self, q: u32, ops: &mut OpsVec<L>) {
243 for i in (q * PHYSQUBIT_PER_LOGQUBIT)..(q * PHYSQUBIT_PER_LOGQUBIT + PHYSQUBIT_PER_LOGQUBIT) {
244 ops.x(cast!(i));
245 }
246 }
247
248 fn y(&mut self, q: u32, ops: &mut OpsVec<L>) {
249 for i in (q * PHYSQUBIT_PER_LOGQUBIT)..(q * PHYSQUBIT_PER_LOGQUBIT + PHYSQUBIT_PER_LOGQUBIT) {
250 ops.y(cast!(i));
251 }
252 }
253
254 fn z(&mut self, q: u32, ops: &mut OpsVec<L>) {
255 for i in (q * PHYSQUBIT_PER_LOGQUBIT)..(q * PHYSQUBIT_PER_LOGQUBIT + PHYSQUBIT_PER_LOGQUBIT) {
256 ops.z(cast!(i));
257 }
258 }
259
260 fn h(&mut self, q: u32, ops: &mut OpsVec<L>) {
261 for i in (q * PHYSQUBIT_PER_LOGQUBIT)..(q * PHYSQUBIT_PER_LOGQUBIT + PHYSQUBIT_PER_LOGQUBIT) {
262 ops.h(cast!(i));
263 }
264 }
265
266 fn s(&mut self, q: u32, ops: &mut OpsVec<L>) {
267 for i in (q * PHYSQUBIT_PER_LOGQUBIT)..(q * PHYSQUBIT_PER_LOGQUBIT + PHYSQUBIT_PER_LOGQUBIT) {
268 ops.s(cast!(i));
269 }
270 }
271
272 fn sdg(&mut self, q: u32, ops: &mut OpsVec<L>) {
273 for i in (q * PHYSQUBIT_PER_LOGQUBIT)..(q * PHYSQUBIT_PER_LOGQUBIT + PHYSQUBIT_PER_LOGQUBIT) {
274 ops.sdg(cast!(i));
275 }
276 }
277
278 fn cx(&mut self, c: u32, t: u32, ops: &mut OpsVec<L>) {
279 for i in 0..PHYSQUBIT_PER_LOGQUBIT {
280 ops.cx(cast!(c * PHYSQUBIT_PER_LOGQUBIT + i), cast!(t * PHYSQUBIT_PER_LOGQUBIT + i));
281 }
282 }
283
284 fn measure(&mut self, q: u32, s: u32, ops: &mut OpsVec<L>) {
285 let m0 = self.measure_ancilla();
286 for i in 0..PHYSQUBIT_PER_LOGQUBIT {
287 ops.cx(cast!(q * PHYSQUBIT_PER_LOGQUBIT + i), cast!(m0));
288 }
289 ops.measure(cast!(m0), cast!(0));
290 self.instance.send_receive(ops.as_ref(), &mut self.instance_buf);
291 ops.clear();
292 let result = self.instance_buf.get(cast!(0));
293 self.measured[s as usize] = result;
294 if result {
296 ops.x(cast!(m0));
297 }
298 }
299}
300
301pub trait Syndrome<L>
302where
303 L : Layer + PauliGate + HGate + SGate + CXGate,
304 L::Operation : Operation<L>,
305 L::Qubit : NumCast,
306 L::Slot : NumCast
307{
308 fn syndrome(&mut self);
309}
310
311impl<L> Syndrome<L> for OpsVec<SteaneLayer<L>>
312where
313 L : Layer + PauliGate + HGate + SGate + CXGate,
314 L::Operation : Operation<L> + PauliOperation<L> + HOperation<L> + SOperation<L> + CXOperation<L>,
315 L::Qubit : NumCast,
316 L::Slot : NumCast
317{
318 fn syndrome(&mut self) {
319 self.as_mut_vec().push(OpArgs::Empty(opid::USERDEF));
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 #[allow(unused_imports)]
326 use lay::{Layer, OpsVec, Measured};
327 #[allow(unused_imports)]
328 use lay_simulator_gk::{ GottesmanKnillSimulator, DefaultRng };
329 #[allow(unused_imports)]
330 use crate::{SteaneLayer, Syndrome};
331
332 #[test]
333 fn initialize() {
334 let mut steane = SteaneLayer::from_seed_with_gk(16, 1);
335 let mut ops = OpsVec::<SteaneLayer<_>>::new();
336 ops.initialize();
337 steane.send(ops.as_ref());
338 }
339
340 #[test]
341 fn initialize_and_measure() {
342 let mut steane = SteaneLayer::from_seed_with_gk(16, 1);
343 let mut ops = steane.opsvec();
344 let mut buf = steane.make_buffer();
345 ops.initialize();
346 ops.x(1);
347 ops.measure(0, 0);
348 ops.measure(1, 1);
349 steane.send_receive(ops.as_ref(), &mut buf);
350 assert_eq!(buf.get(0), false);
351 assert_eq!(buf.get(1), true);
352 }
353
354 #[test]
355 fn cx() {
356 let mut steane = SteaneLayer::from_seed_with_gk(4, 4);
357 let mut ops = steane.opsvec();
358 let mut buf = steane.make_buffer();
359 ops.initialize();
360 ops.x(1);
361 ops.cx(1, 0);
362 ops.measure(0, 0);
363 for i in 0..10 {
364 steane.send_receive(ops.as_ref(), &mut buf);
365 assert!(buf.get(0));
366 }
367 }
368
369 #[test]
370 fn cx2() {
371 let mut steane = SteaneLayer::from_seed_with_gk(4, 4);
372 let mut ops = steane.opsvec();
373 let mut buf = steane.make_buffer();
374 ops.initialize();
375 ops.x(1);
376 ops.cx(1, 0);
377 ops.measure(0, 0);
378 ops.measure(1, 1);
379 for i in 0..10 {
380 steane.send_receive(ops.as_ref(), &mut buf);
381 assert!(buf.get(0));
382 assert!(buf.get(1));
383 }
384 }
385
386 #[test]
387 fn cx3() {
388 let mut steane = SteaneLayer::from_seed_with_gk(4, 4);
389 let mut ops = steane.opsvec();
390 let mut buf = steane.make_buffer();
391 ops.initialize();
392 ops.cx(0, 2);
393 ops.measure(0, 0);
394 ops.measure(2, 2);
395 for i in 0..10 {
396 steane.send_receive(ops.as_ref(), &mut buf);
397 assert!(!buf.get(0));
398 assert!(!buf.get(2));
399 }
400 }
401
402 #[test]
403 fn bell() {
404 let mut steane = SteaneLayer::from_seed_with_gk(4, 4);
405 let mut ops = steane.opsvec();
406 let mut buf = steane.make_buffer();
407 ops.initialize();
408 ops.h(1);
409 ops.cx(1, 0);
410 ops.measure(0, 0);
411 ops.measure(1, 1);
412 for i in 0..10 {
413 steane.send_receive(ops.as_ref(), &mut buf);
414 eprintln!("try: {}, |{}{}>", i, buf.get(0) as u8, buf.get(1) as u8);
415 assert_eq!(buf.get(0), buf.get(1));
416 }
417 }
418
419 #[test]
420 fn ghz() {
421 let mut steane = SteaneLayer::from_seed_with_gk(4, 4);
422 let mut ops = steane.opsvec();
423 let mut buf = steane.make_buffer();
424 ops.initialize();
425 ops.h(1);
426 ops.cx(1, 0);
427 ops.cx(1, 2);
428 ops.measure(0, 0);
429 ops.measure(1, 1);
430 ops.measure(2, 2);
431 for i in 0..10 {
432 steane.send_receive(ops.as_ref(), &mut buf);
433 let m0 = buf.get(0);
434 let m1 = buf.get(1);
435 let m2 = buf.get(2);
436 eprintln!("try: {}, |{}{}{}>", i, m0 as u8, m1 as u8, m2 as u8);
437 assert_eq!(m0, m1);
438 assert_eq!(m0, m2);
439 }
440 }
441
442 #[cfg(feature = "test-blueqat")]
443 #[test]
444 fn bell_bq() {
445 use lay_simulator_blueqat::BlueqatSimulator;
446 let mut steane = SteaneLayer::from_instance(
447 BlueqatSimulator::new().unwrap(),
448 2,
449 );
450 let mut ops = steane.opsvec();
451 let mut buf = steane.make_buffer();
452 ops.initialize();
453 ops.h(1);
454 ops.cx(1, 0);
455 ops.measure(0, 0);
456 let mut ops2 = steane.opsvec();
457 ops2.measure(1, 1);
458 for i in 0..10 {
459 steane.send_receive(ops.as_ref(), &mut buf).unwrap();
460 let s0 = buf.get(0);
461 steane.send_receive(ops2.as_ref(), &mut buf).unwrap();
462 let s1 = buf.get(1);
463 eprintln!("try: {}, |{}{}>", i, buf.get(0) as u8, buf.get(1) as u8);
464 assert_eq!(s0, s1);
465 }
466 }
467}