Skip to content

Commit 56807ac

Browse files
authored
Cat states (#543)
## Description This PR introduces functionality for constructing high-distance fault-tolerant cat (GHZ) state preparation circuits using two cat states and a transversal CNOT. ### TODO - [x] Add combinatorial search methods - [x] Update Docs - [x] Add Circuits - [x] Add Scripts ## Checklist: <!--- This checklist serves as a reminder of a couple of things that ensure your pull request will be merged swiftly. --> - [x] The pull request only contains commits that are focused and relevant to this change. - [x] I have added appropriate tests that cover the new/changed functionality. - [x] I have updated the documentation to reflect these changes. - [x] I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals. - [x] I have added migration instructions to the upgrade guide (if needed). - [x] The changes follow the project's style guidelines and introduce no new warnings. - [x] The changes are fully tested and pass the CI checks. - [x] I have reviewed my own code changes.
1 parent b001f55 commit 56807ac

File tree

219 files changed

+4092
-298
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

219 files changed

+4092
-298
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel
1919
- Added `NoiseModel` class for applying noise to a given stim circuit. ([#453]) ([**@pehamtom**])
2020
- New `PureFaultSet` class for representing collections of X or Z faults. ([#443]) ([**@pehamtom**])
2121
- New `CNOTCircuit` class to serve as an intermediate representation during circuit synthesis for simplifying work with CSS encoding isometries. ([#443]) ([**@pehamtom**])
22+
- Combinatorial search methods for constructing fault-tolerant cat state preparation circuits. ([#543]) ([**@pehamtom**])
2223

2324
### Changed
2425

@@ -27,6 +28,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel
2728
- Refactored state preparation circuit synthesis code to utilize the new `PureFaultSet` and `CNOTCircuit` classes. ([#443]) ([**@pehamtom**])
2829
- Refactored encoding circuit synthesis code to utilize the new `PureFaultSet` and `CNOTCircuit` classes. ([#443]) ([**@pehamtom**])
2930
- Renamed `StatePrepCircuit` class to `FaultyStatePrepCircuit`, reflecting its new role in combining circuit and fault information. ([#443]) ([**@pehamtom**])
31+
- Changed the construction in `CatStatePreparationExperiment` to allow for ancillas with less qubits than the data cat state.
3032

3133
### Removed
3234

@@ -43,6 +45,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool
4345

4446
<!-- PR links -->
4547

48+
[#543]: https://github.com/munich-quantum-toolkit/qecc/pull/543
4649
[#503]: https://github.com/munich-quantum-toolkit/qecc/pull/503
4750
[#499]: https://github.com/munich-quantum-toolkit/qecc/pull/499
4851
[#486]: https://github.com/munich-quantum-toolkit/qecc/pull/486

docs/CatStates.md

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ noisy_cnot(circ, 6, 7, p)
4545
QuantumCircuit.from_qasm_str(circ.without_noise().to_qasm(open_qasm_version=2)).draw('mpl')
4646
```
4747

48-
This circuit is not fault-tolerant. A single $X$-error in the circuit might spread to high-weight $X$-errors. We can show this by simulating the circuit. The cat state is a particularly easy state to analyse because it is resilient to $Z$-errors (every $Z$-error is equivalent to a weight-zero or weight-one error) and all $X$ errors simply flip a bit in the state. The distribution of bit flips can be obtained via simulations.
48+
This circuit is not fault-tolerant. A single $X$-error in the circuit might spread to high-weight $X$-errors. We can show this by simulating the circuit. The cat state is a particularly easy state to analyse because it is resilient to $Z$-errors (every $Z$-error is equivalent to a weight-zero or weight-one error) and all $X$ errors simply flip a bit in the state.
4949

5050
```{code-cell} ipython3
5151
:tags: [hide-input]
@@ -94,7 +94,7 @@ plt.title(f"Error distribution for w = {w}, p = {p:.2f}")
9494
plt.show()
9595
```
9696

97-
We see that 1,2 and 4 errors occur on the order of the physical error rate, which we set to $p = 0.05$. Interestingly, 3 errors occur only with a probability of about $p^2$. This is due to the structure of the circuit. If an $X$ error occurs, it either propagates to one or two CNOTs, or it doesn't propagate at all. Three errors are caused by a propagated error and another single-qubit error.
97+
We see that 1,2 and 4 errors occur on the order of the physical error rate, which we set to $p = 0.05$. In fact, there are about twice as many weight-four errors as there are weight-two errors, since there are four CNOTs that propagate an $X$ fault to a weight-two error and two CNOTs that propagate an $X$ fault to a weight-four error. Weight-three errors occur only with a probability of about $p^2$. This is due to the structure of the circuit. If an $X$ error occurs, it either propagates to one or two CNOTs, or it doesn't propagate at all. Three errors are caused by a propagated error and another single-qubit error.
9898

9999
## First Attempt at Fault-tolerant Preparation
100100

@@ -135,9 +135,9 @@ The problem in the previous construction is that both circuits propagate errors
135135
- Prepare the ancilla with a different circuit.
136136
- Permute the transversal CNOTs.
137137

138-
The second case is actually a special case of the first one. Permuting how qubits are connected via the transversal CNOT is equivalent to permuting the CNOTs in the ancilla preparation circuit. We want to find a permutation such that no errors cancel each other out anymore.
138+
Permuting how qubits are connected via the transversal CNOT is equivalent to permuting the CNOTs in the ancilla preparation circuit. We want to find a permutation such that no errors cancel each other out anymore.
139139

140-
We have seen that weight-four errors can cancel out in these circuits. There actually only two weight-four errors that can occur as a consequence of a weight-one error in the circuits, namely $X_0X_1X_2X_3$ and $X_4X_5X_6X_7$ (these are actually stabilizer equivalent). Therefore, performing the transversal such that it connects qubit $q_0$ of the data with qubit $q_7$ of the ancilla and vice versa should avoid that the weight-four errors cancel out.
140+
We have seen that weight-four errors can cancel out in these circuits. There actually only two weight-four errors that can occur as a consequence of a weight-one error in the circuits, namely $X_0X_1X_2X_3$ and $X_4X_5X_6X_7$ (these are actually stabilizer equivalent). Therefore, performing the transversal cnot such that it connects qubit $q_0$ of the data with qubit $q_7$ of the ancilla and vice versa should avoid that the weight-four errors cancel out.
141141

142142
In QECC we can pass a permutation on integers $0, \cdot, w-1$ to the `CatStatePreparationExperiment` object during construction.
143143

@@ -162,67 +162,73 @@ experiment.plot_one_p(p, n_samples=100000)
162162

163163
It worked! And it doesn't even come at the cost of a lower acceptance rate.
164164

165-
## Preparing larger cat states
166-
167-
The question now is whether we can make this work for higher-weight cat states. With the framework in place, we can just plug in higher-weight cat states and try different permutations. Let's consider the case of $w=16$ and try the following:
165+
## Reducing Qubit Overhead
168166

169-
- $\pi_1 = \mathrm{id}$
170-
- $\pi_2 = (0 \quad 15)$
171-
- $\pi_2 =
172-
\begin{pmatrix}
173-
0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 & 13 & 14 & 15\\
174-
0 & 1 & 6 & 10 & 12 & 3 & 5 & 15 & 2 & 8 & 11 & 14 & 4 & 9 & 12 & 7
175-
\end{pmatrix}$
167+
When copying errors from the data to the ancilla cat state, it is not necessary, that the ancilla state has the same size as the data state. In fact, as long as the ancilla state consists of at least two qubits, any transversal CNOT connecting a subset of the data qubits to all ancilla qubits acts trivially on the data state. For the eight qubit case, it turns out that a six qubit ancilla is sufficient. Care still needs to be taken with how the (partial) transversal CNOT is connected.
176168

177169
```{code-cell} ipython3
178-
from mqt.qecc.circuit_synthesis import CatStatePreparationExperiment, cat_state_balanced_tree
170+
from mqt.qecc.circuit_synthesis.cat_states import cat_state_pruned_balanced_circuit
179171
180-
w = 16
181-
data = cat_state_balanced_tree(w)
182-
ancilla = cat_state_balanced_tree(w)
172+
w1 = 8
173+
w2 = 6
174+
data = cat_state_pruned_balanced_circuit(w1)
175+
ancilla = cat_state_pruned_balanced_circuit(w2)
183176
184-
pi_1 = list(range(w))
177+
ctrls = [1,2,3,5,6,7]
178+
perm = [2,5,0,4,3,1]
179+
experiment = CatStatePreparationExperiment(data, ancilla, perm, ctrls)
180+
experiment.plot_one_p(p, n_samples=100000)
181+
```
185182

186-
pi_2 = list(range(w))
187-
pi_2[0] = 15
188-
pi_2[15] = 0
183+
## Preparing larger cat states
189184

190-
pi_3 = [0, 1, 6, 10, 13, 3, 5, 15, 2, 8, 11, 14, 4, 9, 12, 7]
185+
Constructing fault tolerant partial transversal CNOTs and finding the required ancilla sizes for given cat state preparation circuits becomes more difficult at higher qubit counts and fault distances. QECC has functions for finding such CNOTs automatically.
191186

192-
e_1 = CatStatePreparationExperiment(data, ancilla, pi_1)
193-
e_2 = CatStatePreparationExperiment(data, ancilla, pi_2)
194-
e_3 = CatStatePreparationExperiment(data, ancilla, pi_3)
187+
The most general search approach is `search_ft_cnot_cegar` which uses counterexample-guided abstraction refinement (CEGAR) to construct both a selection of control qubits and the fault-tolerant permutation at the same time.
195188

196-
```
189+
```{code-cell} ipython3
190+
from mqt.qecc.circuit_synthesis.cat_states import search_ft_cnot_cegar
197191
198-
Let's see the distribution for the identity permutation $\pi_1$ first.
192+
t = 4
193+
ctrls, perm, _ = search_ft_cnot_cegar(data, ancilla, t)
199194
200-
```{code-cell} ipython3
201-
:tags: [hide-input]
202-
e_1.plot_one_p(p, n_samples=10000000)
195+
experiment = CatStatePreparationExperiment(data, ancilla, perm, ctrls)
196+
experiment.plot_one_p(p, n_samples=100000)
203197
```
204198

205-
At $p=0.05$ we only accept about $12\%$ of all states. We also see that while errors of weight three or higher are less likely as lower-weight errors, the distribution shows that higher-weight errors all occur more or less similarly often.
206-
207-
When we permute the transversal CNOT slightly according to $\pi_2$, we also suppress the errors to some extent.
199+
The `search_ft_cnot_local_search` method uses a heuristic local repair strategy to find fault-tolerant CNOTs. This is faster than the CEGAR approach but is not guaranteed to converge:
208200

209201
```{code-cell} ipython3
210-
:tags: [hide-input]
211-
e_2.plot_one_p(p, n_samples=10000000)
212-
print(e_2.circ.to_crumble_url())
213-
```
202+
from mqt.qecc.circuit_synthesis.cat_states import search_ft_cnot_local_search
214203
215-
We see that simply exchanging two qubits is not sufficient to protect the $w=16$ cat state against higher-weight errors cancelling out. There are, in fact many undetected weight-four errors that lead to a residual error of higher weight on the data qubits. One example is shown in [this crumble circuit](<https://algassert.com/crumble#circuit=Q(0,0)0;Q(0,1)1;Q(0,2)2;Q(0,3)3;Q(0,4)4;Q(0,5)5;Q(0,6)6;Q(0,7)7;Q(0,8)8;Q(0,9)9;Q(0,10)10;Q(0,11)11;Q(0,12)12;Q(0,13)13;Q(0,14)14;Q(0,15)15;Q(0,16)16;Q(0,17)17;Q(0,18)18;Q(0,19)19;Q(0,20)20;Q(0,21)21;Q(0,22)22;Q(0,23)23;Q(0,24)24;Q(0,25)25;Q(0,26)26;Q(0,27)27;Q(0,28)28;Q(0,29)29;Q(0,30)30;Q(0,31)31;H_0_16;TICK;CX_0_8_16_24;MARKX(0)0_16;TICK;CX_0_4_16_20;TICK;CX_0_2_16_18;TICK;CX_0_1_2_3_4_6_16_17_18_19_20_22;TICK;CX_4_5_6_7_8_12_20_21_22_23_24_28;TICK;CX_8_10_24_26;TICK;CX_8_9_10_11_12_14_24_25_26_27_28_30;TICK;CX_12_13_14_15_28_29_30_31;TICK;TICK;CX_0_31;TICK;CX_1_17;TICK;CX_2_18;TICK;CX_3_19;TICK;CX_4_20;TICK;CX_5_21;TICK;CX_6_22;TICK;CX_7_23;TICK;CX_8_24;TICK;CX_9_25;TICK;CX_10_26;MARKX(0)16_31;TICK;CX_11_27;TICK;CX_12_28;TICK;CX_13_29;TICK;CX_14_30;TICK;CX_15_16;TICK;MR_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31>).
204+
w1 = 16
205+
w2 = 15
206+
t= 8
207+
data = cat_state_pruned_balanced_circuit(w1)
208+
ancilla = cat_state_pruned_balanced_circuit(w2)
209+
ctrls = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
210+
ctrls, perm, _ = search_ft_cnot_local_search(data, ancilla, t, ctrls=ctrls)
216211
217-
Since there are fewer combinations of errors that cancel out in such a fashion, the error rate still declines, but for a fault-tolerant preparation we would wish for an error of weight $t$ on the data to occur with probability $O(p^t)$
212+
experiment = CatStatePreparationExperiment(data, ancilla, perm, ctrls)
213+
experiment.plot_one_p(p, n_samples=100000)
214+
```
218215

219-
Applying $\pi_3$ actually yields the desired result:
216+
If we already know a good selection of control qubits, performance-wise somewhere in the middle is the `search_ft_cnot_smt` method, which directly encodes all problematic fault propagations instead of iteratively refining the SMT encoding. Especially for UNSAT instances this usually terminates quickly.
220217

221218
```{code-cell} ipython3
222-
:tags: [hide-input]
223-
e_3.plot_one_p(p, n_samples=10000000)
219+
from mqt.qecc.circuit_synthesis.cat_states import search_ft_cnot_smt
220+
221+
w1 = 12
222+
w2 = 11
223+
t= 6
224+
data = cat_state_pruned_balanced_circuit(w1)
225+
ancilla = cat_state_pruned_balanced_circuit(w2)
226+
ctrls, perm, _ = search_ft_cnot_smt(data, ancilla, t)
227+
228+
experiment = CatStatePreparationExperiment(data, ancilla, perm, ctrls)
229+
experiment.plot_one_p(p, n_samples=100000)
224230
```
225231

226-
At some point, high-weight errors are so unlikely that they do not occur during the simulation. Getting a better error estimate therefore requires a larger sample-size. Furthermore, to get an estimate of the scaling of the probability of a residual error of a certain size on the data requires sampling at different physical error rates. The `cat_prep_experiment` method of the `CatStatePreparationExperiment` class returns the histogram over multiple physical error rates.
232+
## Loading already Constructed FT Cat States
227233

228-
Permuting the connectivity of the transversal CNOT is not the only way to improve the robustness of non-deterministic cat state preparation. Another way would be to use different circuits or combine the two methods. The `CatStatePreparationExperiment` class is intended for evaluating such different preparation schemes.
234+
To avoid redoing redundant computations, stim circuits for cat states of sizes up $49$ qubits and fault distances up to $9$ can be found [here](https://github.com/munich-quantum-toolkit/qecc/tree/main/scripts/cat_states/circuits). There is also a [json file](https://github.com/munich-quantum-toolkit/qecc/tree/main/scripts/cat_states/constructions.json) which explicitly lists control qubits and target permutation for a given combination of data cat state size ($w_1$), ancilla cat state size ($w_2$) and fault distance ($t$).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
H 0 10
2+
CX 0 8 10 14 0 4 8 9 10 12 0 2 4 6 10 11 12 13 9 14 0 1 2 3 4 5 6 7
3+
MR 14
4+
CX 1 11 3 13 5 10 7 12
5+
MR 10 11 12 13
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
H 0 10
2+
CX 0 8 10 14 0 4 8 9 10 12 14 16 0 2 4 6 10 11 12 13 14 15 0 1 2 3 4 5 6 7 9 13 1 16 2 14 3 10 4 11 5 12 6 15
3+
MR 13 10 11 12 14 15 16
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
H 0 10
2+
CX 0 8 10 14 0 4 8 9 10 12 14 16 0 2 4 6 10 11 12 13 14 15 9 16 0 1 2 3 4 5 6 7
3+
MR 16
4+
CX 1 11 2 12 3 14 4 15 5 10 6 13
5+
MR 10 11 12 13 14 15
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
H 0 10
2+
CX 0 8 10 14 0 4 8 9 10 12 14 16 0 2 4 6 10 11 12 13 14 15 9 16 0 1 2 3 4 5 6 7
3+
MR 16
4+
CX 1 11 2 12 3 14 4 15 5 10 6 13
5+
MR 10 11 12 13 14 15
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
H 0 11
2+
CX 0 8 11 15 0 4 8 10 11 13 15 16 0 2 4 6 8 9 11 12 13 14 0 1 2 3 4 5 6 7 8 12 10 13 0 11 3 15 5 16 6 14
3+
MR 12 13 11 14 15 16
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
H 0 11
2+
CX 0 8 11 15 0 4 8 10 11 13 15 17 0 2 4 6 8 9 11 12 13 14 15 16 17 18 0 1 2 3 4 5 6 7 8 15 10 11 0 18 2 14 3 16 4 17 5 13 6 12
3+
MR 11 15 12 13 14 16 17 18
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
H 0 11
2+
CX 0 8 11 15 0 4 8 10 11 13 15 17 0 2 4 6 8 9 11 12 13 14 15 16 17 18 0 1 2 3 4 5 6 7 8 16 10 13 0 11 2 14 3 18 4 12 5 15 6 17
3+
MR 13 16 11 12 14 15 17 18
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
H 0 11
2+
CX 0 8 11 15 0 4 8 10 11 13 15 17 0 2 4 6 8 9 11 12 13 14 15 16 17 18 0 1 2 3 4 5 6 7 8 16 10 13 0 11 2 14 3 18 4 12 5 15 6 17
3+
MR 13 16 11 12 14 15 17 18

0 commit comments

Comments
 (0)