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.
Files changed (31) hide show
  1. surface_sim-0.1.0/LICENSE +21 -0
  2. surface_sim-0.1.0/PKG-INFO +62 -0
  3. surface_sim-0.1.0/README.md +17 -0
  4. surface_sim-0.1.0/pyproject.toml +36 -0
  5. surface_sim-0.1.0/setup.cfg +4 -0
  6. surface_sim-0.1.0/surface_sim/__init__.py +16 -0
  7. surface_sim-0.1.0/surface_sim/circuit_blocks/__init__.py +13 -0
  8. surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_css.py +185 -0
  9. surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_css_pipelined.py +117 -0
  10. surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_xzzx.py +122 -0
  11. surface_sim-0.1.0/surface_sim/circuit_blocks/surface_code_xzzx_google.py +297 -0
  12. surface_sim-0.1.0/surface_sim/circuit_blocks/util.py +320 -0
  13. surface_sim-0.1.0/surface_sim/experiments/__init__.py +13 -0
  14. surface_sim-0.1.0/surface_sim/experiments/surface_code_css.py +58 -0
  15. surface_sim-0.1.0/surface_sim/experiments/surface_code_css_pipelined.py +58 -0
  16. surface_sim-0.1.0/surface_sim/experiments/surface_code_xzzx.py +58 -0
  17. surface_sim-0.1.0/surface_sim/experiments/surface_code_xzzx_google.py +59 -0
  18. surface_sim-0.1.0/surface_sim/models/__init__.py +17 -0
  19. surface_sim-0.1.0/surface_sim/models/library.py +478 -0
  20. surface_sim-0.1.0/surface_sim/models/model.py +40 -0
  21. surface_sim-0.1.0/surface_sim/models/util.py +112 -0
  22. surface_sim-0.1.0/surface_sim/setup/__init__.py +3 -0
  23. surface_sim-0.1.0/surface_sim/setup/setup.py +146 -0
  24. surface_sim-0.1.0/surface_sim/util/__init__.py +4 -0
  25. surface_sim-0.1.0/surface_sim/util/data_gen.py +63 -0
  26. surface_sim-0.1.0/surface_sim/util/distance.py +51 -0
  27. surface_sim-0.1.0/surface_sim.egg-info/PKG-INFO +62 -0
  28. surface_sim-0.1.0/surface_sim.egg-info/SOURCES.txt +29 -0
  29. surface_sim-0.1.0/surface_sim.egg-info/dependency_links.txt +1 -0
  30. surface_sim-0.1.0/surface_sim.egg-info/requires.txt +13 -0
  31. 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
+ ![example workflow](https://github.com/MarcSerraPeralta/surface-sim/actions/workflows/actions.yaml/badge.svg)
49
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
50
+ ![PyPI](https://img.shields.io/pypi/v/surface-sim?label=pypi%20package)
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
+ ![example workflow](https://github.com/MarcSerraPeralta/surface-sim/actions/workflows/actions.yaml/badge.svg)
4
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
5
+ ![PyPI](https://img.shields.io/pypi/v/surface-sim?label=pypi%20package)
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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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,13 @@
1
+ from . import (
2
+ surface_code_css,
3
+ surface_code_css_pipelined,
4
+ surface_code_xzzx,
5
+ surface_code_xzzx_google,
6
+ )
7
+
8
+ __all__ = [
9
+ "surface_code_css",
10
+ "surface_code_css_pipelined",
11
+ "surface_code_xzzx",
12
+ "surface_code_xzzx_google",
13
+ ]
@@ -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