1use super::ErrorCorrection;
7use crate::error::{Result, SimulatorError};
8use quantrs2_circuit::builder::Circuit;
9use quantrs2_core::qubit::QubitId;
10
11#[derive(Debug, Clone, Copy)]
16pub struct BitFlipCode;
17
18impl ErrorCorrection for BitFlipCode {
19 fn physical_qubits(&self) -> usize {
20 3
21 }
22
23 fn logical_qubits(&self) -> usize {
24 1
25 }
26
27 fn distance(&self) -> usize {
28 3
29 }
30
31 fn encode_circuit(
32 &self,
33 logical_qubits: &[QubitId],
34 ancilla_qubits: &[QubitId],
35 ) -> Result<Circuit<16>> {
36 let mut circuit = Circuit::<16>::new();
38
39 if logical_qubits.is_empty() {
41 return Err(SimulatorError::InvalidInput(
42 "BitFlipCode requires at least 1 logical qubit".to_string(),
43 ));
44 }
45 if ancilla_qubits.len() < 2 {
46 return Err(SimulatorError::InvalidInput(
47 "BitFlipCode requires at least 2 ancilla qubits".to_string(),
48 ));
49 }
50
51 let q0 = logical_qubits[0];
53 let q1 = ancilla_qubits[0];
54 let q2 = ancilla_qubits[1];
55
56 circuit.cnot(q0, q1).expect(
59 "Failed to apply CNOT from logical qubit to first ancilla in BitFlipCode encoding",
60 );
61 circuit.cnot(q0, q2).expect(
62 "Failed to apply CNOT from logical qubit to second ancilla in BitFlipCode encoding",
63 );
64
65 Ok(circuit)
66 }
67
68 fn decode_circuit(
69 &self,
70 encoded_qubits: &[QubitId],
71 syndrome_qubits: &[QubitId],
72 ) -> Result<Circuit<16>> {
73 let mut circuit = Circuit::<16>::new();
74
75 if encoded_qubits.len() < 3 {
77 return Err(SimulatorError::InvalidInput(
78 "BitFlipCode requires at least 3 encoded qubits".to_string(),
79 ));
80 }
81 if syndrome_qubits.len() < 2 {
82 return Err(SimulatorError::InvalidInput(
83 "BitFlipCode requires at least 2 syndrome qubits".to_string(),
84 ));
85 }
86
87 let q0 = encoded_qubits[0];
89 let q1 = encoded_qubits[1];
90 let q2 = encoded_qubits[2];
91 let s0 = syndrome_qubits[0];
92 let s1 = syndrome_qubits[1];
93
94 circuit
96 .cnot(q0, s0)
97 .expect("Failed to apply CNOT from q0 to s0 in BitFlipCode syndrome extraction");
98 circuit
99 .cnot(q1, s0)
100 .expect("Failed to apply CNOT from q1 to s0 in BitFlipCode syndrome extraction");
101 circuit
102 .cnot(q1, s1)
103 .expect("Failed to apply CNOT from q1 to s1 in BitFlipCode syndrome extraction");
104 circuit
105 .cnot(q2, s1)
106 .expect("Failed to apply CNOT from q2 to s1 in BitFlipCode syndrome extraction");
107
108 circuit
111 .x(s1)
112 .expect("Failed to apply X to s1 before syndrome 01 correction in BitFlipCode");
113 circuit
114 .cx(s0, q0)
115 .expect("Failed to apply controlled-X for syndrome 01 correction in BitFlipCode");
116 circuit
117 .x(s1)
118 .expect("Failed to apply X to s1 after syndrome 01 correction in BitFlipCode");
119
120 circuit
122 .x(s0)
123 .expect("Failed to apply X to s0 before syndrome 10 correction in BitFlipCode");
124 circuit
125 .cx(s1, q1)
126 .expect("Failed to apply controlled-X for syndrome 10 correction in BitFlipCode");
127 circuit
128 .x(s0)
129 .expect("Failed to apply X to s0 after syndrome 10 correction in BitFlipCode");
130
131 circuit
133 .cx(s0, q2)
134 .expect("Failed to apply first controlled-X for syndrome 11 correction in BitFlipCode");
135 circuit.cx(s1, q2).expect(
136 "Failed to apply second controlled-X for syndrome 11 correction in BitFlipCode",
137 );
138
139 Ok(circuit)
140 }
141}
142
143#[derive(Debug, Clone, Copy)]
148pub struct PhaseFlipCode;
149
150impl ErrorCorrection for PhaseFlipCode {
151 fn physical_qubits(&self) -> usize {
152 3
153 }
154
155 fn logical_qubits(&self) -> usize {
156 1
157 }
158
159 fn distance(&self) -> usize {
160 3
161 }
162
163 fn encode_circuit(
164 &self,
165 logical_qubits: &[QubitId],
166 ancilla_qubits: &[QubitId],
167 ) -> Result<Circuit<16>> {
168 let mut circuit = Circuit::<16>::new();
170
171 if logical_qubits.is_empty() {
173 return Err(SimulatorError::InvalidInput(
174 "PhaseFlipCode requires at least 1 logical qubit".to_string(),
175 ));
176 }
177 if ancilla_qubits.len() < 2 {
178 return Err(SimulatorError::InvalidInput(
179 "PhaseFlipCode requires at least 2 ancilla qubits".to_string(),
180 ));
181 }
182
183 let q0 = logical_qubits[0];
185 let q1 = ancilla_qubits[0];
186 let q2 = ancilla_qubits[1];
187
188 circuit
190 .h(q0)
191 .expect("Failed to apply first Hadamard to q0 in PhaseFlipCode encoding");
192 circuit
193 .h(q1)
194 .expect("Failed to apply first Hadamard to q1 in PhaseFlipCode encoding");
195 circuit
196 .h(q2)
197 .expect("Failed to apply first Hadamard to q2 in PhaseFlipCode encoding");
198
199 circuit
201 .cnot(q0, q1)
202 .expect("Failed to apply CNOT from q0 to q1 in PhaseFlipCode encoding");
203 circuit
204 .cnot(q0, q2)
205 .expect("Failed to apply CNOT from q0 to q2 in PhaseFlipCode encoding");
206
207 circuit
209 .h(q0)
210 .expect("Failed to apply second Hadamard to q0 in PhaseFlipCode encoding");
211 circuit
212 .h(q1)
213 .expect("Failed to apply second Hadamard to q1 in PhaseFlipCode encoding");
214 circuit
215 .h(q2)
216 .expect("Failed to apply second Hadamard to q2 in PhaseFlipCode encoding");
217
218 Ok(circuit)
219 }
220
221 fn decode_circuit(
222 &self,
223 encoded_qubits: &[QubitId],
224 syndrome_qubits: &[QubitId],
225 ) -> Result<Circuit<16>> {
226 let mut circuit = Circuit::<16>::new();
227
228 if encoded_qubits.len() < 3 {
230 return Err(SimulatorError::InvalidInput(
231 "PhaseFlipCode requires at least 3 encoded qubits".to_string(),
232 ));
233 }
234 if syndrome_qubits.len() < 2 {
235 return Err(SimulatorError::InvalidInput(
236 "PhaseFlipCode requires at least 2 syndrome qubits".to_string(),
237 ));
238 }
239
240 let q0 = encoded_qubits[0];
242 let q1 = encoded_qubits[1];
243 let q2 = encoded_qubits[2];
244 let s0 = syndrome_qubits[0];
245 let s1 = syndrome_qubits[1];
246
247 circuit
249 .h(q0)
250 .expect("Failed to apply first Hadamard to q0 in PhaseFlipCode decoding");
251 circuit
252 .h(q1)
253 .expect("Failed to apply first Hadamard to q1 in PhaseFlipCode decoding");
254 circuit
255 .h(q2)
256 .expect("Failed to apply first Hadamard to q2 in PhaseFlipCode decoding");
257
258 circuit
260 .cnot(q0, s0)
261 .expect("Failed to apply CNOT from q0 to s0 in PhaseFlipCode syndrome extraction");
262 circuit
263 .cnot(q1, s0)
264 .expect("Failed to apply CNOT from q1 to s0 in PhaseFlipCode syndrome extraction");
265 circuit
266 .cnot(q1, s1)
267 .expect("Failed to apply CNOT from q1 to s1 in PhaseFlipCode syndrome extraction");
268 circuit
269 .cnot(q2, s1)
270 .expect("Failed to apply CNOT from q2 to s1 in PhaseFlipCode syndrome extraction");
271
272 circuit
275 .x(s1)
276 .expect("Failed to apply X to s1 before syndrome 01 correction in PhaseFlipCode");
277 circuit
278 .cx(s0, q0)
279 .expect("Failed to apply controlled-X for syndrome 01 correction in PhaseFlipCode");
280 circuit
281 .x(s1)
282 .expect("Failed to apply X to s1 after syndrome 01 correction in PhaseFlipCode");
283
284 circuit
286 .x(s0)
287 .expect("Failed to apply X to s0 before syndrome 10 correction in PhaseFlipCode");
288 circuit
289 .cx(s1, q1)
290 .expect("Failed to apply controlled-X for syndrome 10 correction in PhaseFlipCode");
291 circuit
292 .x(s0)
293 .expect("Failed to apply X to s0 after syndrome 10 correction in PhaseFlipCode");
294
295 circuit.cx(s0, q2).expect(
297 "Failed to apply first controlled-X for syndrome 11 correction in PhaseFlipCode",
298 );
299 circuit.cx(s1, q2).expect(
300 "Failed to apply second controlled-X for syndrome 11 correction in PhaseFlipCode",
301 );
302
303 circuit
305 .h(q0)
306 .expect("Failed to apply second Hadamard to q0 in PhaseFlipCode decoding");
307 circuit
308 .h(q1)
309 .expect("Failed to apply second Hadamard to q1 in PhaseFlipCode decoding");
310 circuit
311 .h(q2)
312 .expect("Failed to apply second Hadamard to q2 in PhaseFlipCode decoding");
313
314 Ok(circuit)
315 }
316}
317
318#[derive(Debug, Clone, Copy)]
324pub struct ShorCode;
325
326impl ErrorCorrection for ShorCode {
327 fn physical_qubits(&self) -> usize {
328 9
329 }
330
331 fn logical_qubits(&self) -> usize {
332 1
333 }
334
335 fn distance(&self) -> usize {
336 3
337 }
338
339 fn encode_circuit(
340 &self,
341 logical_qubits: &[QubitId],
342 ancilla_qubits: &[QubitId],
343 ) -> Result<Circuit<16>> {
344 let mut circuit = Circuit::<16>::new();
345
346 if logical_qubits.is_empty() {
348 return Err(SimulatorError::InvalidInput(
349 "ShorCode requires at least 1 logical qubit".to_string(),
350 ));
351 }
352 if ancilla_qubits.len() < 8 {
353 return Err(SimulatorError::InvalidInput(
354 "ShorCode requires at least 8 ancilla qubits".to_string(),
355 ));
356 }
357
358 let q = logical_qubits[0]; let a = &ancilla_qubits[0..8]; circuit
365 .h(q)
366 .expect("Failed to apply Hadamard to logical qubit in ShorCode encoding");
367
368 circuit
370 .cnot(q, a[0])
371 .expect("Failed to apply CNOT to create Block 1 in ShorCode encoding"); circuit
373 .cnot(q, a[3])
374 .expect("Failed to apply CNOT to create Block 2 in ShorCode encoding"); circuit
381 .cnot(q, a[1])
382 .expect("Failed to apply first CNOT for Block 1 bit-flip encoding in ShorCode");
383 circuit
384 .cnot(q, a[2])
385 .expect("Failed to apply second CNOT for Block 1 bit-flip encoding in ShorCode");
386
387 circuit
389 .cnot(a[3], a[4])
390 .expect("Failed to apply first CNOT for Block 2 bit-flip encoding in ShorCode");
391 circuit
392 .cnot(a[3], a[5])
393 .expect("Failed to apply second CNOT for Block 2 bit-flip encoding in ShorCode");
394
395 circuit
398 .cnot(q, a[6])
399 .expect("Failed to apply CNOT to create Block 3 in ShorCode encoding");
400 circuit
401 .cnot(a[6], a[7])
402 .expect("Failed to apply CNOT for Block 3 bit-flip encoding in ShorCode");
403
404 Ok(circuit)
413 }
414
415 fn decode_circuit(
416 &self,
417 encoded_qubits: &[QubitId],
418 syndrome_qubits: &[QubitId],
419 ) -> Result<Circuit<16>> {
420 let mut circuit = Circuit::<16>::new();
421
422 if encoded_qubits.len() < 9 {
424 return Err(SimulatorError::InvalidInput(
425 "ShorCode requires at least 9 encoded qubits".to_string(),
426 ));
427 }
428 if syndrome_qubits.len() < 8 {
429 return Err(SimulatorError::InvalidInput(
430 "ShorCode requires at least 8 syndrome qubits".to_string(),
431 ));
432 }
433
434 let data = encoded_qubits;
436 let synd = syndrome_qubits;
437
438 circuit.cnot(data[0], synd[0]).expect(
442 "Failed to apply CNOT from data[0] to synd[0] in ShorCode Group 1 syndrome detection",
443 );
444 circuit.cnot(data[1], synd[0]).expect(
445 "Failed to apply CNOT from data[1] to synd[0] in ShorCode Group 1 syndrome detection",
446 );
447 circuit.cnot(data[1], synd[1]).expect(
448 "Failed to apply CNOT from data[1] to synd[1] in ShorCode Group 1 syndrome detection",
449 );
450 circuit.cnot(data[2], synd[1]).expect(
451 "Failed to apply CNOT from data[2] to synd[1] in ShorCode Group 1 syndrome detection",
452 );
453
454 circuit.cnot(data[3], synd[2]).expect(
456 "Failed to apply CNOT from data[3] to synd[2] in ShorCode Group 2 syndrome detection",
457 );
458 circuit.cnot(data[4], synd[2]).expect(
459 "Failed to apply CNOT from data[4] to synd[2] in ShorCode Group 2 syndrome detection",
460 );
461 circuit.cnot(data[4], synd[3]).expect(
462 "Failed to apply CNOT from data[4] to synd[3] in ShorCode Group 2 syndrome detection",
463 );
464 circuit.cnot(data[5], synd[3]).expect(
465 "Failed to apply CNOT from data[5] to synd[3] in ShorCode Group 2 syndrome detection",
466 );
467
468 circuit.cnot(data[6], synd[4]).expect(
470 "Failed to apply CNOT from data[6] to synd[4] in ShorCode Group 3 syndrome detection",
471 );
472 circuit.cnot(data[7], synd[4]).expect(
473 "Failed to apply CNOT from data[7] to synd[4] in ShorCode Group 3 syndrome detection",
474 );
475 circuit.cnot(data[7], synd[5]).expect(
476 "Failed to apply CNOT from data[7] to synd[5] in ShorCode Group 3 syndrome detection",
477 );
478 circuit.cnot(data[8], synd[5]).expect(
479 "Failed to apply CNOT from data[8] to synd[5] in ShorCode Group 3 syndrome detection",
480 );
481
482 circuit.x(synd[1]).expect(
487 "Failed to apply X to synd[1] before Group 1 syndrome 01 correction in ShorCode",
488 );
489 circuit
490 .cx(synd[0], data[0])
491 .expect("Failed to apply controlled-X for Group 1 syndrome 01 correction in ShorCode");
492 circuit.x(synd[1]).expect(
493 "Failed to apply X to synd[1] after Group 1 syndrome 01 correction in ShorCode",
494 );
495
496 circuit.x(synd[0]).expect(
498 "Failed to apply X to synd[0] before Group 1 syndrome 10 correction in ShorCode",
499 );
500 circuit
501 .cx(synd[1], data[1])
502 .expect("Failed to apply controlled-X for Group 1 syndrome 10 correction in ShorCode");
503 circuit.x(synd[0]).expect(
504 "Failed to apply X to synd[0] after Group 1 syndrome 10 correction in ShorCode",
505 );
506
507 circuit.cx(synd[0], data[2]).expect(
509 "Failed to apply first controlled-X for Group 1 syndrome 11 correction in ShorCode",
510 );
511 circuit.cx(synd[1], data[2]).expect(
512 "Failed to apply second controlled-X for Group 1 syndrome 11 correction in ShorCode",
513 );
514
515 circuit.x(synd[3]).expect(
518 "Failed to apply X to synd[3] before Group 2 syndrome 01 correction in ShorCode",
519 );
520 circuit
521 .cx(synd[2], data[3])
522 .expect("Failed to apply controlled-X for Group 2 syndrome 01 correction in ShorCode");
523 circuit.x(synd[3]).expect(
524 "Failed to apply X to synd[3] after Group 2 syndrome 01 correction in ShorCode",
525 );
526
527 circuit.x(synd[2]).expect(
529 "Failed to apply X to synd[2] before Group 2 syndrome 10 correction in ShorCode",
530 );
531 circuit
532 .cx(synd[3], data[4])
533 .expect("Failed to apply controlled-X for Group 2 syndrome 10 correction in ShorCode");
534 circuit.x(synd[2]).expect(
535 "Failed to apply X to synd[2] after Group 2 syndrome 10 correction in ShorCode",
536 );
537
538 circuit.cx(synd[2], data[5]).expect(
540 "Failed to apply first controlled-X for Group 2 syndrome 11 correction in ShorCode",
541 );
542 circuit.cx(synd[3], data[5]).expect(
543 "Failed to apply second controlled-X for Group 2 syndrome 11 correction in ShorCode",
544 );
545
546 circuit.x(synd[5]).expect(
549 "Failed to apply X to synd[5] before Group 3 syndrome 01 correction in ShorCode",
550 );
551 circuit
552 .cx(synd[4], data[6])
553 .expect("Failed to apply controlled-X for Group 3 syndrome 01 correction in ShorCode");
554 circuit.x(synd[5]).expect(
555 "Failed to apply X to synd[5] after Group 3 syndrome 01 correction in ShorCode",
556 );
557
558 circuit.x(synd[4]).expect(
560 "Failed to apply X to synd[4] before Group 3 syndrome 10 correction in ShorCode",
561 );
562 circuit
563 .cx(synd[5], data[7])
564 .expect("Failed to apply controlled-X for Group 3 syndrome 10 correction in ShorCode");
565 circuit.x(synd[4]).expect(
566 "Failed to apply X to synd[4] after Group 3 syndrome 10 correction in ShorCode",
567 );
568
569 circuit.cx(synd[4], data[8]).expect(
571 "Failed to apply first controlled-X for Group 3 syndrome 11 correction in ShorCode",
572 );
573 circuit.cx(synd[5], data[8]).expect(
574 "Failed to apply second controlled-X for Group 3 syndrome 11 correction in ShorCode",
575 );
576
577 for &q in &[data[0], data[3], data[6]] {
581 circuit
582 .h(q)
583 .expect("Failed to apply Hadamard for phase error detection in ShorCode");
584 }
585
586 circuit.cnot(data[0], synd[6]).expect(
588 "Failed to apply CNOT from data[0] to synd[6] in ShorCode phase error detection",
589 );
590 circuit.cnot(data[3], synd[6]).expect(
591 "Failed to apply CNOT from data[3] to synd[6] in ShorCode phase error detection",
592 );
593 circuit.cnot(data[3], synd[7]).expect(
594 "Failed to apply CNOT from data[3] to synd[7] in ShorCode phase error detection",
595 );
596 circuit.cnot(data[6], synd[7]).expect(
597 "Failed to apply CNOT from data[6] to synd[7] in ShorCode phase error detection",
598 );
599
600 circuit
604 .x(synd[7])
605 .expect("Failed to apply X to synd[7] before phase syndrome 01 correction in ShorCode");
606 for &q in &[data[0], data[1], data[2]] {
607 circuit.cz(synd[6], q).expect(
608 "Failed to apply controlled-Z for Group 1 phase syndrome 01 correction in ShorCode",
609 );
610 }
611 circuit
612 .x(synd[7])
613 .expect("Failed to apply X to synd[7] after phase syndrome 01 correction in ShorCode");
614
615 circuit
617 .x(synd[6])
618 .expect("Failed to apply X to synd[6] before phase syndrome 10 correction in ShorCode");
619 for &q in &[data[3], data[4], data[5]] {
620 circuit.cz(synd[7], q).expect(
621 "Failed to apply controlled-Z for Group 2 phase syndrome 10 correction in ShorCode",
622 );
623 }
624 circuit
625 .x(synd[6])
626 .expect("Failed to apply X to synd[6] after phase syndrome 10 correction in ShorCode");
627
628 for &q in &[data[6], data[7], data[8]] {
630 circuit
631 .cz(synd[6], q)
632 .expect("Failed to apply first controlled-Z for Group 3 phase syndrome 11 correction in ShorCode");
633 circuit
634 .cz(synd[7], q)
635 .expect("Failed to apply second controlled-Z for Group 3 phase syndrome 11 correction in ShorCode");
636 }
637
638 for &q in &[data[0], data[3], data[6]] {
640 circuit.h(q).expect(
641 "Failed to apply Hadamard to transform back from phase error basis in ShorCode",
642 );
643 }
644
645 Ok(circuit)
646 }
647}
648
649#[derive(Debug, Clone, Copy)]
654pub struct FiveQubitCode;
655
656impl ErrorCorrection for FiveQubitCode {
657 fn physical_qubits(&self) -> usize {
658 5
659 }
660
661 fn logical_qubits(&self) -> usize {
662 1
663 }
664
665 fn distance(&self) -> usize {
666 3
667 }
668
669 fn encode_circuit(
670 &self,
671 logical_qubits: &[QubitId],
672 ancilla_qubits: &[QubitId],
673 ) -> Result<Circuit<16>> {
674 let mut circuit = Circuit::<16>::new();
675
676 if logical_qubits.is_empty() {
678 return Err(SimulatorError::InvalidInput(
679 "FiveQubitCode requires at least 1 logical qubit".to_string(),
680 ));
681 }
682 if ancilla_qubits.len() < 4 {
683 return Err(SimulatorError::InvalidInput(
684 "FiveQubitCode requires at least 4 ancilla qubits".to_string(),
685 ));
686 }
687
688 let q0 = logical_qubits[0];
690 let ancs = ancilla_qubits;
691
692 circuit
699 .h(ancs[0])
700 .expect("Failed to apply Hadamard to ancs[0] in FiveQubitCode encoding initialization");
701 circuit
702 .h(ancs[1])
703 .expect("Failed to apply Hadamard to ancs[1] in FiveQubitCode encoding initialization");
704 circuit
705 .h(ancs[2])
706 .expect("Failed to apply Hadamard to ancs[2] in FiveQubitCode encoding initialization");
707 circuit
708 .h(ancs[3])
709 .expect("Failed to apply Hadamard to ancs[3] in FiveQubitCode encoding initialization");
710
711 circuit
714 .cnot(q0, ancs[0])
715 .expect("Failed to apply CNOT from q0 to ancs[0] in FiveQubitCode encoding");
716 circuit
717 .cnot(q0, ancs[1])
718 .expect("Failed to apply CNOT from q0 to ancs[1] in FiveQubitCode encoding");
719 circuit
720 .cnot(q0, ancs[2])
721 .expect("Failed to apply CNOT from q0 to ancs[2] in FiveQubitCode encoding");
722 circuit
723 .cnot(q0, ancs[3])
724 .expect("Failed to apply CNOT from q0 to ancs[3] in FiveQubitCode encoding");
725
726 circuit
731 .h(q0)
732 .expect("Failed to apply Hadamard to q0 for X stabilizer in FiveQubitCode encoding");
733 circuit.h(ancs[1]).expect(
734 "Failed to apply Hadamard to ancs[1] for X stabilizer in FiveQubitCode encoding",
735 );
736 circuit.h(ancs[3]).expect(
737 "Failed to apply Hadamard to ancs[3] for X stabilizer in FiveQubitCode encoding",
738 );
739
740 circuit
741 .cnot(q0, ancs[0])
742 .expect("Failed to apply CNOT for X stabilizer step 1 in FiveQubitCode encoding");
743 circuit
744 .cnot(ancs[1], ancs[0])
745 .expect("Failed to apply CNOT for X stabilizer step 2 in FiveQubitCode encoding");
746 circuit
747 .cnot(ancs[0], ancs[2])
748 .expect("Failed to apply CNOT for X stabilizer step 3 in FiveQubitCode encoding");
749 circuit
750 .cnot(ancs[2], ancs[3])
751 .expect("Failed to apply CNOT for X stabilizer step 4 in FiveQubitCode encoding");
752
753 circuit.cz(q0, ancs[1]).expect(
755 "Failed to apply controlled-Z for Z stabilizer step 1 in FiveQubitCode encoding",
756 );
757 circuit.cz(ancs[0], ancs[2]).expect(
758 "Failed to apply controlled-Z for Z stabilizer step 2 in FiveQubitCode encoding",
759 );
760 circuit.cz(ancs[1], ancs[3]).expect(
761 "Failed to apply controlled-Z for Z stabilizer step 3 in FiveQubitCode encoding",
762 );
763
764 circuit
765 .h(ancs[0])
766 .expect("Failed to apply final Hadamard to ancs[0] in FiveQubitCode encoding");
767 circuit
768 .h(ancs[2])
769 .expect("Failed to apply final Hadamard to ancs[2] in FiveQubitCode encoding");
770
771 Ok(circuit)
775 }
776
777 fn decode_circuit(
778 &self,
779 encoded_qubits: &[QubitId],
780 syndrome_qubits: &[QubitId],
781 ) -> Result<Circuit<16>> {
782 let mut circuit = Circuit::<16>::new();
783
784 if encoded_qubits.len() < 5 {
786 return Err(SimulatorError::InvalidInput(
787 "FiveQubitCode requires at least 5 encoded qubits".to_string(),
788 ));
789 }
790 if syndrome_qubits.len() < 4 {
791 return Err(SimulatorError::InvalidInput(
792 "FiveQubitCode requires at least 4 syndrome qubits".to_string(),
793 ));
794 }
795
796 let data = encoded_qubits;
798 let synd = syndrome_qubits;
799
800 circuit
805 .h(synd[0])
806 .expect("Failed to apply Hadamard to synd[0] before Generator 1 in FiveQubitCode syndrome extraction");
807 circuit
808 .cnot(synd[0], data[0])
809 .expect("Failed to apply CNOT for Generator 1 XZZXI at position 0 in FiveQubitCode");
810 circuit.cz(synd[0], data[1]).expect(
811 "Failed to apply controlled-Z for Generator 1 XZZXI at position 1 in FiveQubitCode",
812 );
813 circuit.cz(synd[0], data[2]).expect(
814 "Failed to apply controlled-Z for Generator 1 XZZXI at position 2 in FiveQubitCode",
815 );
816 circuit
817 .cnot(synd[0], data[3])
818 .expect("Failed to apply CNOT for Generator 1 XZZXI at position 3 in FiveQubitCode");
819 circuit
820 .h(synd[0])
821 .expect("Failed to apply Hadamard to synd[0] after Generator 1 in FiveQubitCode syndrome extraction");
822
823 circuit
825 .h(synd[1])
826 .expect("Failed to apply Hadamard to synd[1] before Generator 2 in FiveQubitCode syndrome extraction");
827 circuit
828 .cnot(synd[1], data[1])
829 .expect("Failed to apply CNOT for Generator 2 IXZZX at position 1 in FiveQubitCode");
830 circuit.cz(synd[1], data[2]).expect(
831 "Failed to apply controlled-Z for Generator 2 IXZZX at position 2 in FiveQubitCode",
832 );
833 circuit.cz(synd[1], data[3]).expect(
834 "Failed to apply controlled-Z for Generator 2 IXZZX at position 3 in FiveQubitCode",
835 );
836 circuit
837 .cnot(synd[1], data[4])
838 .expect("Failed to apply CNOT for Generator 2 IXZZX at position 4 in FiveQubitCode");
839 circuit
840 .h(synd[1])
841 .expect("Failed to apply Hadamard to synd[1] after Generator 2 in FiveQubitCode syndrome extraction");
842
843 circuit
845 .h(synd[2])
846 .expect("Failed to apply Hadamard to synd[2] before Generator 3 in FiveQubitCode syndrome extraction");
847 circuit
848 .cnot(synd[2], data[0])
849 .expect("Failed to apply CNOT for Generator 3 XIXZZ at position 0 in FiveQubitCode");
850 circuit
851 .cnot(synd[2], data[2])
852 .expect("Failed to apply CNOT for Generator 3 XIXZZ at position 2 in FiveQubitCode");
853 circuit.cz(synd[2], data[3]).expect(
854 "Failed to apply controlled-Z for Generator 3 XIXZZ at position 3 in FiveQubitCode",
855 );
856 circuit.cz(synd[2], data[4]).expect(
857 "Failed to apply controlled-Z for Generator 3 XIXZZ at position 4 in FiveQubitCode",
858 );
859 circuit
860 .h(synd[2])
861 .expect("Failed to apply Hadamard to synd[2] after Generator 3 in FiveQubitCode syndrome extraction");
862
863 circuit
865 .h(synd[3])
866 .expect("Failed to apply Hadamard to synd[3] before Generator 4 in FiveQubitCode syndrome extraction");
867 circuit.cz(synd[3], data[0]).expect(
868 "Failed to apply controlled-Z for Generator 4 ZXIXZ at position 0 in FiveQubitCode",
869 );
870 circuit
871 .cnot(synd[3], data[1])
872 .expect("Failed to apply CNOT for Generator 4 ZXIXZ at position 1 in FiveQubitCode");
873 circuit
874 .cnot(synd[3], data[3])
875 .expect("Failed to apply CNOT for Generator 4 ZXIXZ at position 3 in FiveQubitCode");
876 circuit.cz(synd[3], data[4]).expect(
877 "Failed to apply controlled-Z for Generator 4 ZXIXZ at position 4 in FiveQubitCode",
878 );
879 circuit
880 .h(synd[3])
881 .expect("Failed to apply Hadamard to synd[3] after Generator 4 in FiveQubitCode syndrome extraction");
882
883 let syndrome_0001 = [false, false, false, true];
890 self.add_conditional_correction(&mut circuit, synd, syndrome_0001, data[0], 'X')?;
891
892 let syndrome_0010 = [false, false, true, false];
894 self.add_conditional_correction(&mut circuit, synd, syndrome_0010, data[1], 'X')?;
895
896 let syndrome_0100 = [false, true, false, false];
898 self.add_conditional_correction(&mut circuit, synd, syndrome_0100, data[2], 'X')?;
899
900 let syndrome_1000 = [true, false, false, false];
902 self.add_conditional_correction(&mut circuit, synd, syndrome_1000, data[3], 'X')?;
903
904 let syndrome_0011 = [false, false, true, true];
907 self.add_conditional_correction(&mut circuit, synd, syndrome_0011, data[0], 'Z')?;
908
909 let syndrome_0101 = [false, true, false, true];
911 self.add_conditional_correction(&mut circuit, synd, syndrome_0101, data[1], 'Z')?;
912
913 let syndrome_1001 = [true, false, false, true];
915 self.add_conditional_correction(&mut circuit, synd, syndrome_1001, data[2], 'Z')?;
916
917 let syndrome_1100 = [true, true, false, false];
919 self.add_conditional_correction(&mut circuit, synd, syndrome_1100, data[3], 'Z')?;
920
921 let syndrome_0111 = [false, true, true, true];
924 self.add_conditional_correction(&mut circuit, synd, syndrome_0111, data[0], 'Y')?;
925
926 let syndrome_1011 = [true, false, true, true];
928 self.add_conditional_correction(&mut circuit, synd, syndrome_1011, data[1], 'Y')?;
929
930 let syndrome_1101 = [true, true, false, true];
932 self.add_conditional_correction(&mut circuit, synd, syndrome_1101, data[2], 'Y')?;
933
934 let syndrome_1110 = [true, true, true, false];
936 self.add_conditional_correction(&mut circuit, synd, syndrome_1110, data[3], 'Y')?;
937
938 Ok(circuit)
939 }
940}
941
942impl FiveQubitCode {
943 fn add_conditional_correction(
945 &self,
946 circuit: &mut Circuit<16>,
947 syndrome_qubits: &[QubitId],
948 syndrome: [bool; 4],
949 target: QubitId,
950 error_type: char,
951 ) -> Result<()> {
952 for (i, &should_be_one) in syndrome.iter().enumerate() {
957 if !should_be_one {
958 circuit
959 .x(syndrome_qubits[i])
960 .expect("Failed to apply X gate to negate syndrome bit in FiveQubitCode conditional correction");
961 }
962 }
963
964 for i in 1..syndrome_qubits.len() {
972 circuit
973 .cx(syndrome_qubits[i], syndrome_qubits[0])
974 .expect("Failed to apply controlled-X to combine syndrome bits in FiveQubitCode conditional correction");
975 }
976
977 match error_type {
979 'X' => {
980 circuit.cx(syndrome_qubits[0], target).expect(
982 "Failed to apply controlled-X correction for bit flip in FiveQubitCode",
983 );
984 }
985 'Z' => {
986 circuit.cz(syndrome_qubits[0], target).expect(
988 "Failed to apply controlled-Z correction for phase flip in FiveQubitCode",
989 );
990 }
991 'Y' => {
992 circuit
995 .cz(syndrome_qubits[0], target)
996 .expect("Failed to apply controlled-Z for Y correction in FiveQubitCode");
997 circuit
998 .cx(syndrome_qubits[0], target)
999 .expect("Failed to apply controlled-X for Y correction in FiveQubitCode");
1000 }
1001 _ => {
1002 return Err(SimulatorError::UnsupportedOperation(format!(
1003 "Unsupported error type: {error_type}"
1004 )))
1005 }
1006 }
1007
1008 for i in 1..syndrome_qubits.len() {
1010 circuit
1011 .cx(syndrome_qubits[i], syndrome_qubits[0])
1012 .expect("Failed to apply controlled-X to undo syndrome bit combination in FiveQubitCode conditional correction");
1013 }
1014
1015 for (i, &should_be_one) in syndrome.iter().enumerate() {
1017 if !should_be_one {
1018 circuit
1019 .x(syndrome_qubits[i])
1020 .expect("Failed to apply X gate to reset syndrome bit in FiveQubitCode conditional correction");
1021 }
1022 }
1023
1024 Ok(())
1025 }
1026}