surface-sim 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- surface_sim-0.1.0/LICENSE +21 -0
- surface_sim-0.1.0/PKG-INFO +62 -0
- surface_sim-0.1.0/README.md +17 -0
- surface_sim-0.1.0/pyproject.toml +36 -0
- surface_sim-0.1.0/setup.cfg +4 -0
- surface_sim-0.1.0/surface_sim/__init__.py +16 -0
- surface_sim-0.1.0/surface_sim/circuit_blocks/__init__.py +13 -0
- surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_css.py +185 -0
- surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_css_pipelined.py +117 -0
- surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_xzzx.py +122 -0
- surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_xzzx_google.py +297 -0
- surface_sim-0.1.0/surface_sim/circuit_blocks/util.py +320 -0
- surface_sim-0.1.0/surface_sim/experiments/__init__.py +13 -0
- surface_sim-0.1.0/surface_sim/experiments/surface_code_css.py +58 -0
- surface_sim-0.1.0/surface_sim/experiments/surface_code_css_pipelined.py +58 -0
- surface_sim-0.1.0/surface_sim/experiments/surface_code_xzzx.py +58 -0
- surface_sim-0.1.0/surface_sim/experiments/surface_code_xzzx_google.py +59 -0
- surface_sim-0.1.0/surface_sim/models/__init__.py +17 -0
- surface_sim-0.1.0/surface_sim/models/library.py +478 -0
- surface_sim-0.1.0/surface_sim/models/model.py +40 -0
- surface_sim-0.1.0/surface_sim/models/util.py +112 -0
- surface_sim-0.1.0/surface_sim/setup/__init__.py +3 -0
- surface_sim-0.1.0/surface_sim/setup/setup.py +146 -0
- surface_sim-0.1.0/surface_sim/util/__init__.py +4 -0
- surface_sim-0.1.0/surface_sim/util/data_gen.py +63 -0
- surface_sim-0.1.0/surface_sim/util/distance.py +51 -0
- surface_sim-0.1.0/surface_sim.egg-info/PKG-INFO +62 -0
- surface_sim-0.1.0/surface_sim.egg-info/SOURCES.txt +29 -0
- surface_sim-0.1.0/surface_sim.egg-info/dependency_links.txt +1 -0
- surface_sim-0.1.0/surface_sim.egg-info/requires.txt +13 -0
- surface_sim-0.1.0/surface_sim.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 MarcSerraPeralta
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: surface-sim
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Suface code simulations package
|
|
5
|
+
Author-email: Marc Serra Peralta <marcserraperalta@gmail.com>, Boris Varbanov <b.m.varbanov@gmail.com>
|
|
6
|
+
Maintainer-email: Marc Serra Peralta <marcserraperalta@gmail.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2023 MarcSerraPeralta
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Keywords: quantum,error correction,surface code,stabilizer simulation
|
|
30
|
+
Requires-Python: >=3.10
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
License-File: LICENSE
|
|
33
|
+
Requires-Dist: numpy
|
|
34
|
+
Requires-Dist: xarray
|
|
35
|
+
Requires-Dist: PyYAML
|
|
36
|
+
Requires-Dist: netCDF4
|
|
37
|
+
Requires-Dist: stim>=1.13.0
|
|
38
|
+
Requires-Dist: qec-util
|
|
39
|
+
Requires-Dist: python-sat
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pip-tools; extra == "dev"
|
|
42
|
+
Requires-Dist: pytest; extra == "dev"
|
|
43
|
+
Requires-Dist: black; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest-black; extra == "dev"
|
|
45
|
+
|
|
46
|
+
# Surface-sim
|
|
47
|
+
|
|
48
|
+

|
|
49
|
+
[](https://github.com/psf/black)
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
This package is a wrapper around Stim that aims to help the construction of QEC-code circuits easier. The package implements model classes that help with inserting ciruit-level noise models. It uses a code layout that helps with qubit labeling, indexing and connectivity. Finally, there are a number of circuits for the rotated surface code that are implemented in the package.
|
|
54
|
+
|
|
55
|
+
For more information see the documentation in `docs/`.
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
git clone git@github.com:MarcSerraPeralta/surface-sim.git
|
|
61
|
+
pip install surface-sim/
|
|
62
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Surface-sim
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://github.com/psf/black)
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
This package is a wrapper around Stim that aims to help the construction of QEC-code circuits easier. The package implements model classes that help with inserting ciruit-level noise models. It uses a code layout that helps with qubit labeling, indexing and connectivity. Finally, there are a number of circuits for the rotated surface code that are implemented in the package.
|
|
9
|
+
|
|
10
|
+
For more information see the documentation in `docs/`.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
git clone git@github.com:MarcSerraPeralta/surface-sim.git
|
|
16
|
+
pip install surface-sim/
|
|
17
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
name = "surface-sim"
|
|
8
|
+
description = "Suface code simulations package"
|
|
9
|
+
version = "0.1.0"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Marc Serra Peralta", email = "marcserraperalta@gmail.com" },
|
|
12
|
+
{ name = "Boris Varbanov", email = "b.m.varbanov@gmail.com"}
|
|
13
|
+
]
|
|
14
|
+
maintainers = [
|
|
15
|
+
{ name = "Marc Serra Peralta", email = "marcserraperalta@gmail.com" },
|
|
16
|
+
]
|
|
17
|
+
license = {file = "LICENSE"}
|
|
18
|
+
readme = "README.md"
|
|
19
|
+
dependencies = [
|
|
20
|
+
"numpy",
|
|
21
|
+
"xarray",
|
|
22
|
+
"PyYAML",
|
|
23
|
+
"netCDF4",
|
|
24
|
+
"stim >= 1.13.0",
|
|
25
|
+
"qec-util",
|
|
26
|
+
"python-sat",
|
|
27
|
+
]
|
|
28
|
+
keywords = ["quantum", "error correction", "surface code", "stabilizer simulation"]
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.packages.find]
|
|
31
|
+
include = ["surface_sim", "surface_sim.*"] # package names should match these glob patterns (["*"] by default)
|
|
32
|
+
namespaces = false # to disable scanning PEP 420 namespaces (true by default)
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = ["pip-tools", "pytest", "black", "pytest-black"]
|
|
36
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Main surface-sim module."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
from . import experiments, models, util, circuit_blocks
|
|
6
|
+
from .setup import Setup
|
|
7
|
+
from .models import Model
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"models",
|
|
11
|
+
"experiments",
|
|
12
|
+
"util",
|
|
13
|
+
"circuit_blocks",
|
|
14
|
+
"Setup",
|
|
15
|
+
"Model",
|
|
16
|
+
]
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
from itertools import chain
|
|
2
|
+
|
|
3
|
+
from stim import Circuit, target_rec
|
|
4
|
+
from qec_util import Layout
|
|
5
|
+
|
|
6
|
+
from ..models import Model
|
|
7
|
+
|
|
8
|
+
# methods to have in this script
|
|
9
|
+
from .util import qubit_coords, log_meas, log_x, log_z, init_qubits
|
|
10
|
+
|
|
11
|
+
__all__ = ["qubit_coords", "log_meas", "log_x", "log_z", "qec_round", "init_qubits"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def qec_round(
|
|
15
|
+
model: Model,
|
|
16
|
+
layout: Layout,
|
|
17
|
+
meas_reset: bool = False,
|
|
18
|
+
meas_comparison: bool = True,
|
|
19
|
+
) -> Circuit:
|
|
20
|
+
"""
|
|
21
|
+
Returns stim circuit corresponding to a QEC cycle
|
|
22
|
+
of the given model.
|
|
23
|
+
|
|
24
|
+
This implementation follows:
|
|
25
|
+
|
|
26
|
+
https://doi.org/10.1103/PhysRevApplied.8.034021
|
|
27
|
+
|
|
28
|
+
Params
|
|
29
|
+
-------
|
|
30
|
+
meas_comparison
|
|
31
|
+
If True, the detector is set to the measurement of the ancilla
|
|
32
|
+
instead of to the comparison of consecutive syndromes.
|
|
33
|
+
"""
|
|
34
|
+
data_qubits = layout.get_qubits(role="data")
|
|
35
|
+
anc_qubits = layout.get_qubits(role="anc")
|
|
36
|
+
qubits = set(data_qubits + anc_qubits)
|
|
37
|
+
|
|
38
|
+
int_order = layout.interaction_order
|
|
39
|
+
stab_types = list(int_order.keys())
|
|
40
|
+
x_stabs = layout.get_qubits(role="anc", stab_type="x_type")
|
|
41
|
+
|
|
42
|
+
# With reset defect[n] = m[n] XOR m[n-1]
|
|
43
|
+
# Wihtout reset defect[n] = m[n] XOR m[n-2]
|
|
44
|
+
comp_round = 1 if meas_reset else 2
|
|
45
|
+
|
|
46
|
+
circuit = Circuit()
|
|
47
|
+
|
|
48
|
+
# a
|
|
49
|
+
directions = [int_order["x_type"][0], int_order["x_type"][3]]
|
|
50
|
+
rot_qubits = set(anc_qubits)
|
|
51
|
+
rot_qubits.update(layout.get_neighbors(x_stabs, direction=directions[0]))
|
|
52
|
+
rot_qubits.update(layout.get_neighbors(x_stabs, direction=directions[1]))
|
|
53
|
+
for instruction in model.hadamard(rot_qubits):
|
|
54
|
+
circuit.append(instruction)
|
|
55
|
+
idle_qubits = qubits - rot_qubits
|
|
56
|
+
for instruction in model.idle(idle_qubits):
|
|
57
|
+
circuit.append(instruction)
|
|
58
|
+
circuit.append("TICK")
|
|
59
|
+
|
|
60
|
+
# b
|
|
61
|
+
interacted_qubits = set()
|
|
62
|
+
for stab_type in stab_types:
|
|
63
|
+
stab_qubits = layout.get_qubits(role="anc", stab_type=stab_type)
|
|
64
|
+
ord_dir = int_order[stab_type][0]
|
|
65
|
+
int_pairs = layout.get_neighbors(stab_qubits, direction=ord_dir, as_pairs=True)
|
|
66
|
+
int_qubits = list(chain.from_iterable(int_pairs))
|
|
67
|
+
interacted_qubits.update(int_qubits)
|
|
68
|
+
|
|
69
|
+
for instruction in model.cphase(int_qubits):
|
|
70
|
+
circuit.append(instruction)
|
|
71
|
+
|
|
72
|
+
idle_qubits = qubits - set(interacted_qubits)
|
|
73
|
+
for instruction in model.idle(idle_qubits):
|
|
74
|
+
circuit.append(instruction)
|
|
75
|
+
circuit.append("TICK")
|
|
76
|
+
|
|
77
|
+
# c
|
|
78
|
+
for instruction in model.hadamard(data_qubits):
|
|
79
|
+
circuit.append(instruction)
|
|
80
|
+
for instruction in model.idle(anc_qubits):
|
|
81
|
+
circuit.append(instruction)
|
|
82
|
+
circuit.append("TICK")
|
|
83
|
+
|
|
84
|
+
# d
|
|
85
|
+
interacted_qubits = set()
|
|
86
|
+
for stab_type in stab_types:
|
|
87
|
+
stab_qubits = layout.get_qubits(role="anc", stab_type=stab_type)
|
|
88
|
+
ord_dir = int_order[stab_type][1]
|
|
89
|
+
int_pairs = layout.get_neighbors(stab_qubits, direction=ord_dir, as_pairs=True)
|
|
90
|
+
int_qubits = list(chain.from_iterable(int_pairs))
|
|
91
|
+
interacted_qubits.update(int_qubits)
|
|
92
|
+
|
|
93
|
+
for instruction in model.cphase(int_qubits):
|
|
94
|
+
circuit.append(instruction)
|
|
95
|
+
|
|
96
|
+
idle_qubits = qubits - set(interacted_qubits)
|
|
97
|
+
for instruction in model.idle(idle_qubits):
|
|
98
|
+
circuit.append(instruction)
|
|
99
|
+
circuit.append("TICK")
|
|
100
|
+
|
|
101
|
+
# e
|
|
102
|
+
interacted_qubits = set()
|
|
103
|
+
for stab_type in stab_types:
|
|
104
|
+
stab_qubits = layout.get_qubits(role="anc", stab_type=stab_type)
|
|
105
|
+
ord_dir = int_order[stab_type][2]
|
|
106
|
+
int_pairs = layout.get_neighbors(stab_qubits, direction=ord_dir, as_pairs=True)
|
|
107
|
+
int_qubits = list(chain.from_iterable(int_pairs))
|
|
108
|
+
interacted_qubits.update(int_qubits)
|
|
109
|
+
|
|
110
|
+
for instruction in model.cphase(int_qubits):
|
|
111
|
+
circuit.append(instruction)
|
|
112
|
+
|
|
113
|
+
idle_qubits = qubits - set(interacted_qubits)
|
|
114
|
+
for instruction in model.idle(idle_qubits):
|
|
115
|
+
circuit.append(instruction)
|
|
116
|
+
circuit.append("TICK")
|
|
117
|
+
|
|
118
|
+
# f
|
|
119
|
+
for instruction in model.hadamard(data_qubits):
|
|
120
|
+
circuit.append(instruction)
|
|
121
|
+
for instruction in model.idle(anc_qubits):
|
|
122
|
+
circuit.append(instruction)
|
|
123
|
+
circuit.append("TICK")
|
|
124
|
+
|
|
125
|
+
# g
|
|
126
|
+
interacted_qubits = set()
|
|
127
|
+
for stab_type in stab_types:
|
|
128
|
+
stab_qubits = layout.get_qubits(role="anc", stab_type=stab_type)
|
|
129
|
+
ord_dir = int_order[stab_type][3]
|
|
130
|
+
int_pairs = layout.get_neighbors(stab_qubits, direction=ord_dir, as_pairs=True)
|
|
131
|
+
int_qubits = list(chain.from_iterable(int_pairs))
|
|
132
|
+
interacted_qubits.update(int_qubits)
|
|
133
|
+
|
|
134
|
+
for instruction in model.cphase(int_qubits):
|
|
135
|
+
circuit.append(instruction)
|
|
136
|
+
|
|
137
|
+
idle_qubits = qubits - set(interacted_qubits)
|
|
138
|
+
for instruction in model.idle(idle_qubits):
|
|
139
|
+
circuit.append(instruction)
|
|
140
|
+
circuit.append("TICK")
|
|
141
|
+
|
|
142
|
+
# h
|
|
143
|
+
directions = [int_order["x_type"][0], int_order["x_type"][3]]
|
|
144
|
+
rot_qubits = set(anc_qubits)
|
|
145
|
+
rot_qubits.update(layout.get_neighbors(x_stabs, direction=directions[0]))
|
|
146
|
+
rot_qubits.update(layout.get_neighbors(x_stabs, direction=directions[1]))
|
|
147
|
+
for instruction in model.hadamard(rot_qubits):
|
|
148
|
+
circuit.append(instruction)
|
|
149
|
+
idle_qubits = qubits - rot_qubits
|
|
150
|
+
for instruction in model.idle(idle_qubits):
|
|
151
|
+
circuit.append(instruction)
|
|
152
|
+
circuit.append("TICK")
|
|
153
|
+
|
|
154
|
+
# i
|
|
155
|
+
for instruction in model.measure(anc_qubits):
|
|
156
|
+
circuit.append(instruction)
|
|
157
|
+
|
|
158
|
+
for instruction in model.idle(data_qubits):
|
|
159
|
+
circuit.append(instruction)
|
|
160
|
+
circuit.append("TICK")
|
|
161
|
+
|
|
162
|
+
if meas_reset:
|
|
163
|
+
for instruction in model.reset(anc_qubits):
|
|
164
|
+
circuit.append(instruction)
|
|
165
|
+
|
|
166
|
+
for instruction in model.idle(data_qubits):
|
|
167
|
+
circuit.append(instruction)
|
|
168
|
+
|
|
169
|
+
circuit.append("TICK")
|
|
170
|
+
|
|
171
|
+
# detectors ordered as in the measurements
|
|
172
|
+
num_anc = len(anc_qubits)
|
|
173
|
+
if meas_comparison:
|
|
174
|
+
det_targets = []
|
|
175
|
+
for ind in range(num_anc):
|
|
176
|
+
target_inds = [ind - (comp_round + 1) * num_anc, ind - num_anc]
|
|
177
|
+
targets = [target_rec(ind) for ind in target_inds]
|
|
178
|
+
det_targets.append(targets)
|
|
179
|
+
else:
|
|
180
|
+
det_targets = [[target_rec(ind - num_anc)] for ind in range(num_anc)]
|
|
181
|
+
|
|
182
|
+
for targets in det_targets:
|
|
183
|
+
circuit.append("DETECTOR", targets)
|
|
184
|
+
|
|
185
|
+
return circuit
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from itertools import chain
|
|
2
|
+
|
|
3
|
+
from stim import Circuit, target_rec
|
|
4
|
+
|
|
5
|
+
from qec_util import Layout
|
|
6
|
+
|
|
7
|
+
from ..models import Model
|
|
8
|
+
|
|
9
|
+
# methods to have in this script
|
|
10
|
+
from .util import qubit_coords, log_meas, log_x, log_z, init_qubits
|
|
11
|
+
|
|
12
|
+
__all__ = ["qubit_coords", "log_meas", "log_x", "log_z", "qec_round", "init_qubits"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def qec_round(
|
|
16
|
+
model: Model,
|
|
17
|
+
layout: Layout,
|
|
18
|
+
meas_reset: bool = False,
|
|
19
|
+
meas_comparison: bool = True,
|
|
20
|
+
) -> Circuit:
|
|
21
|
+
"""
|
|
22
|
+
Returns stim circuit corresponding to a QEC cycle
|
|
23
|
+
of the given model.
|
|
24
|
+
|
|
25
|
+
Params
|
|
26
|
+
-------
|
|
27
|
+
meas_comparison
|
|
28
|
+
If True, the detector is set to the measurement of the ancilla
|
|
29
|
+
instead of to the comparison of consecutive syndromes.
|
|
30
|
+
stab_type_det
|
|
31
|
+
If specified, only adds detectors to the ancillas for the
|
|
32
|
+
specific stabilizator type.
|
|
33
|
+
"""
|
|
34
|
+
data_qubits = layout.get_qubits(role="data")
|
|
35
|
+
anc_qubits = layout.get_qubits(role="anc")
|
|
36
|
+
|
|
37
|
+
qubits = set(data_qubits + anc_qubits)
|
|
38
|
+
# With reset defect[n] = m[n] XOR m[n-1]
|
|
39
|
+
# Wihtout reset defect[n] = m[n] XOR m[n-2]
|
|
40
|
+
comp_round = 1 if meas_reset else 2
|
|
41
|
+
|
|
42
|
+
circuit = Circuit()
|
|
43
|
+
int_order = layout.interaction_order
|
|
44
|
+
stab_types = list(int_order.keys())
|
|
45
|
+
|
|
46
|
+
for ind, stab_type in enumerate(stab_types):
|
|
47
|
+
stab_qubits = layout.get_qubits(role="anc", stab_type=stab_type)
|
|
48
|
+
rot_qubits = set(stab_qubits)
|
|
49
|
+
if stab_type == "x_type":
|
|
50
|
+
rot_qubits.update(data_qubits)
|
|
51
|
+
|
|
52
|
+
if not ind:
|
|
53
|
+
for instruction in model.hadamard(rot_qubits):
|
|
54
|
+
circuit.append(instruction)
|
|
55
|
+
|
|
56
|
+
idle_qubits = qubits - rot_qubits
|
|
57
|
+
for instruction in model.idle(idle_qubits):
|
|
58
|
+
circuit.append(instruction)
|
|
59
|
+
circuit.append("TICK")
|
|
60
|
+
|
|
61
|
+
for ord_dir in int_order[stab_type]:
|
|
62
|
+
int_pairs = layout.get_neighbors(
|
|
63
|
+
stab_qubits, direction=ord_dir, as_pairs=True
|
|
64
|
+
)
|
|
65
|
+
int_qubits = list(chain.from_iterable(int_pairs))
|
|
66
|
+
|
|
67
|
+
for instruction in model.cphase(int_qubits):
|
|
68
|
+
circuit.append(instruction)
|
|
69
|
+
|
|
70
|
+
idle_qubits = qubits - set(int_qubits)
|
|
71
|
+
for instruction in model.idle(idle_qubits):
|
|
72
|
+
circuit.append(instruction)
|
|
73
|
+
circuit.append("TICK")
|
|
74
|
+
|
|
75
|
+
if not ind:
|
|
76
|
+
for instruction in model.hadamard(qubits):
|
|
77
|
+
circuit.append(instruction)
|
|
78
|
+
else:
|
|
79
|
+
for instruction in model.hadamard(rot_qubits):
|
|
80
|
+
circuit.append(instruction)
|
|
81
|
+
|
|
82
|
+
idle_qubits = qubits - rot_qubits
|
|
83
|
+
for instruction in model.idle(idle_qubits):
|
|
84
|
+
circuit.append(instruction)
|
|
85
|
+
|
|
86
|
+
circuit.append("TICK")
|
|
87
|
+
|
|
88
|
+
for instruction in model.measure(anc_qubits):
|
|
89
|
+
circuit.append(instruction)
|
|
90
|
+
|
|
91
|
+
for instruction in model.idle(data_qubits):
|
|
92
|
+
circuit.append(instruction)
|
|
93
|
+
circuit.append("TICK")
|
|
94
|
+
|
|
95
|
+
if meas_reset:
|
|
96
|
+
for instruction in model.reset(anc_qubits):
|
|
97
|
+
circuit.append(instruction)
|
|
98
|
+
for instruction in model.idle(data_qubits):
|
|
99
|
+
circuit.append(instruction)
|
|
100
|
+
|
|
101
|
+
circuit.append("TICK")
|
|
102
|
+
|
|
103
|
+
# detectors ordered as in the measurements
|
|
104
|
+
num_anc = len(anc_qubits)
|
|
105
|
+
if meas_comparison:
|
|
106
|
+
det_targets = []
|
|
107
|
+
for ind in range(num_anc):
|
|
108
|
+
target_inds = [ind - (comp_round + 1) * num_anc, ind - num_anc]
|
|
109
|
+
targets = [target_rec(ind) for ind in target_inds]
|
|
110
|
+
det_targets.append(targets)
|
|
111
|
+
else:
|
|
112
|
+
det_targets = [[target_rec(ind - num_anc)] for ind in range(num_anc)]
|
|
113
|
+
|
|
114
|
+
for targets in det_targets:
|
|
115
|
+
circuit.append("DETECTOR", targets)
|
|
116
|
+
|
|
117
|
+
return circuit
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
from itertools import chain
|
|
2
|
+
|
|
3
|
+
from stim import Circuit, target_rec
|
|
4
|
+
from qec_util import Layout
|
|
5
|
+
|
|
6
|
+
from ..models import Model
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# methods to have in this script
|
|
10
|
+
from .util import qubit_coords, log_x, log_z
|
|
11
|
+
from .util import log_meas_xzzx as log_meas, init_qubits_xzzx as init_qubits
|
|
12
|
+
|
|
13
|
+
__all__ = ["qubit_coords", "log_meas", "log_x", "log_z", "qec_round", "init_qubits"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def qec_round(
|
|
17
|
+
model: Model,
|
|
18
|
+
layout: Layout,
|
|
19
|
+
meas_reset: bool = False,
|
|
20
|
+
meas_comparison: bool = True,
|
|
21
|
+
) -> Circuit:
|
|
22
|
+
"""
|
|
23
|
+
Returns stim circuit corresponding to a QEC cycle
|
|
24
|
+
of the given model.
|
|
25
|
+
|
|
26
|
+
Params
|
|
27
|
+
-------
|
|
28
|
+
meas_comparison
|
|
29
|
+
If True, the detector is set to the measurement of the ancilla
|
|
30
|
+
instead of to the comparison of consecutive syndromes.
|
|
31
|
+
stab_type_det
|
|
32
|
+
If specified, only adds detectors to the ancillas for the
|
|
33
|
+
specific stabilizator type.
|
|
34
|
+
"""
|
|
35
|
+
data_qubits = layout.get_qubits(role="data")
|
|
36
|
+
anc_qubits = layout.get_qubits(role="anc")
|
|
37
|
+
|
|
38
|
+
qubits = set(data_qubits + anc_qubits)
|
|
39
|
+
|
|
40
|
+
# With reset defect[n] = m[n] XOR m[n-1]
|
|
41
|
+
# Wihtout reset defect[n] = m[n] XOR m[n-2]
|
|
42
|
+
comp_round = 1 if meas_reset else 2
|
|
43
|
+
|
|
44
|
+
circuit = Circuit()
|
|
45
|
+
int_order = layout.interaction_order
|
|
46
|
+
stab_types = list(int_order.keys())
|
|
47
|
+
|
|
48
|
+
for ind, stab_type in enumerate(stab_types):
|
|
49
|
+
stab_qubits = layout.get_qubits(role="anc", stab_type=stab_type)
|
|
50
|
+
|
|
51
|
+
rot_qubits = set(stab_qubits)
|
|
52
|
+
for direction in ("north_west", "south_east"):
|
|
53
|
+
neighbors = layout.get_neighbors(stab_qubits, direction=direction)
|
|
54
|
+
rot_qubits.update(neighbors)
|
|
55
|
+
|
|
56
|
+
if not ind:
|
|
57
|
+
for instruction in model.hadamard(rot_qubits):
|
|
58
|
+
circuit.append(instruction)
|
|
59
|
+
|
|
60
|
+
idle_qubits = qubits - rot_qubits
|
|
61
|
+
for instruction in model.idle(idle_qubits):
|
|
62
|
+
circuit.append(instruction)
|
|
63
|
+
circuit.append("TICK")
|
|
64
|
+
|
|
65
|
+
for ord_dir in int_order[stab_type]:
|
|
66
|
+
int_pairs = layout.get_neighbors(
|
|
67
|
+
stab_qubits, direction=ord_dir, as_pairs=True
|
|
68
|
+
)
|
|
69
|
+
int_qubits = list(chain.from_iterable(int_pairs))
|
|
70
|
+
|
|
71
|
+
for instruction in model.cphase(int_qubits):
|
|
72
|
+
circuit.append(instruction)
|
|
73
|
+
|
|
74
|
+
idle_qubits = qubits - set(int_qubits)
|
|
75
|
+
for instruction in model.idle(idle_qubits):
|
|
76
|
+
circuit.append(instruction)
|
|
77
|
+
circuit.append("TICK")
|
|
78
|
+
|
|
79
|
+
if not ind:
|
|
80
|
+
for instruction in model.hadamard(qubits):
|
|
81
|
+
circuit.append(instruction)
|
|
82
|
+
else:
|
|
83
|
+
for instruction in model.hadamard(rot_qubits):
|
|
84
|
+
circuit.append(instruction)
|
|
85
|
+
|
|
86
|
+
idle_qubits = qubits - rot_qubits
|
|
87
|
+
for instruction in model.idle(idle_qubits):
|
|
88
|
+
circuit.append(instruction)
|
|
89
|
+
|
|
90
|
+
circuit.append("TICK")
|
|
91
|
+
|
|
92
|
+
for instruction in model.measure(anc_qubits):
|
|
93
|
+
circuit.append(instruction)
|
|
94
|
+
|
|
95
|
+
for instruction in model.idle(data_qubits):
|
|
96
|
+
circuit.append(instruction)
|
|
97
|
+
circuit.append("TICK")
|
|
98
|
+
|
|
99
|
+
if meas_reset:
|
|
100
|
+
for instruction in model.reset(anc_qubits):
|
|
101
|
+
circuit.append(instruction)
|
|
102
|
+
|
|
103
|
+
for instruction in model.idle(data_qubits):
|
|
104
|
+
circuit.append(instruction)
|
|
105
|
+
|
|
106
|
+
circuit.append("TICK")
|
|
107
|
+
|
|
108
|
+
# detectors ordered as in the measurements
|
|
109
|
+
num_anc = len(anc_qubits)
|
|
110
|
+
if meas_comparison:
|
|
111
|
+
det_targets = []
|
|
112
|
+
for ind in range(num_anc):
|
|
113
|
+
target_inds = [ind - (comp_round + 1) * num_anc, ind - num_anc]
|
|
114
|
+
targets = [target_rec(ind) for ind in target_inds]
|
|
115
|
+
det_targets.append(targets)
|
|
116
|
+
else:
|
|
117
|
+
det_targets = [[target_rec(ind - num_anc)] for ind in range(num_anc)]
|
|
118
|
+
|
|
119
|
+
for targets in det_targets:
|
|
120
|
+
circuit.append("DETECTOR", targets)
|
|
121
|
+
|
|
122
|
+
return circuit
|