Skip to content

Commit 16a3593

Browse files
authored
Add support for ignored nodes and returning a weight (#6)
- 4th detector coordinate set to -1 now means 'ignore this detector' - Improve some of the decomposition logic - Add `chromobius.CompiledDecoder.predict_weighted_obs_flips_from_dets_bit_packed` - Update some of the `gen` utilities for making test circuits - Fix bit rotted CI configuration
1 parent 3b4220b commit 16a3593

File tree

171 files changed

+5790
-9075
lines changed

Some content is hidden

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

171 files changed

+5790
-9075
lines changed

.github/workflows/ci.yml

+49-18
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,41 @@ jobs:
5353
MACOSX_DEPLOYMENT_TARGET: "10.15"
5454
CIBW_BUILD: "${{ matrix.os_dist.dist }}"
5555
CIBW_ARCHS_MACOS: "${{ matrix.os_dist.macosarch }}"
56-
CIBW_TEST_REQUIRES: pytest stim sinter pygltflib
56+
CIBW_TEST_REQUIRES: pytest stim~=1.14 sinter pygltflib
5757
CIBW_TEST_COMMAND: pytest {project}/src
5858
steps:
5959
- uses: actions/checkout@v3
6060
- uses: actions/setup-python@v3
6161
- run: python tools/overwrite_dev_versions_with_date.py
62-
- run: mkdir -p output/stim
63-
- run: mkdir -p output/stimcirq
64-
- run: mkdir -p output/sinter
6562
- run: python -m pip install pybind11~=2.11.1 cibuildwheel~=2.16.2 setuptools
6663
- run: python -m cibuildwheel --print-build-identifiers
6764
- run: python -m cibuildwheel --output-dir output/chromobius
65+
- uses: actions/[email protected]
66+
with:
67+
name: "dist-chromobius-${{ matrix.os_dist.os }}-${{ matrix.os_dist.dist }}-${{ matrix.os_dist.macosarch }}"
68+
path: dist/*
69+
build_sdist:
70+
runs-on: ubuntu-latest
71+
steps:
72+
- uses: actions/checkout@v3
73+
- uses: actions/setup-python@v3
74+
- run: python -m pip install setuptools pybind11~=2.11.1
75+
- run: python tools/overwrite_dev_versions_with_date.py
76+
- run: mkdir output
6877
- run: python setup.py sdist
69-
- run: mv dist/* output/chromobius
70-
- uses: actions/upload-artifact@v3
78+
- uses: actions/[email protected]
7179
with:
72-
name: dist
73-
path: |
74-
./output/chromobius/*
80+
name: "dist-chromobius-sdist"
81+
path: dist/*.tar.gz
82+
merge_upload_artifacts:
83+
needs: ["build_dist", "build_sdist"]
84+
runs-on: ubuntu-latest
85+
steps:
86+
- name: Merge Artifacts
87+
uses: actions/upload-artifact/merge@v4
88+
with:
89+
name: dist-chromobius
90+
pattern: dist-chromobius-*
7591
check_sdist_installs:
7692
runs-on: ubuntu-latest
7793
steps:
@@ -90,14 +106,19 @@ jobs:
90106
build_bazel:
91107
runs-on: ubuntu-latest
92108
steps:
93-
- uses: actions/checkout@v1
94-
- uses: bazelbuild/setup-bazelisk@v1
109+
- uses: actions/checkout@v3
110+
- uses: bazel-contrib/[email protected]
111+
with:
112+
bazelisk-cache: true
113+
disk-cache: ${{ github.workflow }}
114+
repository-cache: true
115+
bazelisk-version: 1.x
95116
- run: bazel build :all
96117
- run: bazel test :chromobius_test
97118
build_clang:
98119
runs-on: ubuntu-20.04
99120
steps:
100-
- uses: actions/checkout@v1
121+
- uses: actions/checkout@v3
101122
- run: |
102123
cd ..
103124
git clone https://github.com/google/googletest.git -b release-1.12.1
@@ -115,14 +136,14 @@ jobs:
115136
perf:
116137
runs-on: ubuntu-latest
117138
steps:
118-
- uses: actions/checkout@v1
139+
- uses: actions/checkout@v3
119140
- run: cmake .
120141
- run: make chromobius_perf -j 2
121142
- run: out/chromobius_perf
122143
test:
123144
runs-on: ubuntu-latest
124145
steps:
125-
- uses: actions/checkout@v1
146+
- uses: actions/checkout@v3
126147
- run: |
127148
cd ..
128149
git clone https://github.com/google/googletest.git -b release-1.12.1
@@ -136,7 +157,7 @@ jobs:
136157
test_o3:
137158
runs-on: ubuntu-latest
138159
steps:
139-
- uses: actions/checkout@v1
160+
- uses: actions/checkout@v3
140161
- run: |
141162
cd ..
142163
git clone https://github.com/google/googletest.git -b release-1.12.1
@@ -152,7 +173,12 @@ jobs:
152173
steps:
153174
- uses: actions/checkout@v3
154175
- uses: actions/setup-python@v3
155-
- uses: bazelbuild/setup-bazelisk@v1
176+
- uses: bazel-contrib/[email protected]
177+
with:
178+
bazelisk-cache: true
179+
disk-cache: ${{ github.workflow }}
180+
repository-cache: true
181+
bazelisk-version: 1.x
156182
- run: bazel build :chromobius_dev_wheel
157183
- run: pip install bazel-bin/chromobius-0.0.dev0-py3-none-any.whl
158184
- run: diff <(python tools/gen_chromobius_api_reference.py -dev) doc/chromobius_api_reference.md
@@ -172,10 +198,15 @@ jobs:
172198
steps:
173199
- uses: actions/checkout@v3
174200
- uses: actions/setup-python@v3
175-
- uses: bazelbuild/setup-bazelisk@v1
201+
- uses: bazel-contrib/[email protected]
202+
with:
203+
bazelisk-cache: true
204+
disk-cache: ${{ github.workflow }}
205+
repository-cache: true
206+
bazelisk-version: 1.x
176207
- run: bazel build :chromobius_dev_wheel
177208
- run: pip install bazel-bin/chromobius-0.0.dev0-py3-none-any.whl
178-
- run: pip install pytest stim sinter pygltflib
209+
- run: pip install pytest stim~=1.14 sinter pygltflib
179210
- run: pytest src
180211
- run: tools/doctest_proper.py --module chromobius
181212
upload_dev_release_to_pypi:

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ set(SIMD_WIDTH 128)
4343
include(FetchContent)
4444
FetchContent_Declare(stim
4545
GIT_REPOSITORY https://github.com/quantumlib/stim.git
46-
GIT_TAG 3e38d12d0a0fb3022646b694137b733a4700d300)
46+
GIT_TAG da4594c5ede00a063ec2b84bd830f846b5d097dd)
4747
FetchContent_GetProperties(stim)
4848
if(NOT stim_POPULATED)
4949
FetchContent_Populate(stim)

WORKSPACE

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
33

44
git_repository(
55
name = "stim",
6-
commit = "3e38d12d0a0fb3022646b694137b733a4700d300",
6+
commit = "da4594c5ede00a063ec2b84bd830f846b5d097dd",
77
remote = "https://github.com/quantumlib/stim.git",
88
)
99

doc/chromobius.pyi

+83
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class CompiledDecoder:
4848
3 = Red Z
4949
4 = Green Z
5050
5 = Blue Z
51+
-1 = Ignore this Detector
5152
2. Rainbow triplets. Bulk errors with three symptoms in one basis should
5253
have one symptom of each color. Errors with three symptoms that
5354
repeat a color will cause an exception unless they can be decomposed
@@ -161,6 +162,87 @@ class CompiledDecoder:
161162
>>> mistakes = np.count_nonzero(differences)
162163
>>> assert mistakes < shots / 5
163164
"""
165+
@staticmethod
166+
def predict_weighted_obs_flips_from_dets_bit_packed(
167+
dets: np.ndarray,
168+
) -> tuple[np.ndarray, np.ndarray]:
169+
"""Predicts observable flips and weights from detection events.
170+
171+
The returned weight comes directly from the underlying call to pymatching, not
172+
accounting for the lifting process.
173+
174+
Args:
175+
dets: A bit packed numpy array of detection event data. The array can either
176+
be 1-dimensional (a single shot to decode) or 2-dimensional (multiple
177+
shots to decode, with the first axis being the shot axis and the second
178+
axis being the detection event byte axis).
179+
180+
The array's dtype must be np.uint8. If you have an array of dtype
181+
np.bool_, you have data that's not bit packed. You can pack it by
182+
using `np.packbits(array, bitorder='little')`. But ideally you
183+
should attempt to never have unpacked data in the first place,
184+
since it's 8x larger which can be a large performance loss. For
185+
example, stim's sampler methods all have a `bit_packed=True` argument
186+
that cause them to return bit packed data.
187+
188+
Returns:
189+
A tuple (obs, weights).
190+
Obs is a bit packed numpy array of observable flip data.
191+
Weights is a numpy array (or scalar) of floats.
192+
193+
If dets is a 1D array, then the result has:
194+
obs.shape = (math.ceil(num_obs / 8),)
195+
obs.dtype = np.uint8
196+
weights.shape = ()
197+
weights.dtype = np.float32
198+
If dets is a 2D array, then the result has:
199+
shape = (dets.shape[0], math.ceil(num_obs / 8),)
200+
dtype = np.uint8
201+
weights.shape = (dets.shape[0],)
202+
weights.dtype = np.float32
203+
204+
To determine if the observable with index k was flipped in shot s, compute:
205+
`bool((obs[s, k // 8] >> (k % 8)) & 1)`
206+
207+
Example:
208+
>>> import stim
209+
>>> import chromobius
210+
>>> import numpy as np
211+
212+
>>> repetition_color_code = stim.Circuit('''
213+
... # Apply noise.
214+
... X_ERROR(0.1) 0 1 2 3 4 5 6 7
215+
... # Measure three-body stabilizers to catch errors.
216+
... MPP Z0*Z1*Z2 Z1*Z2*Z3 Z2*Z3*Z4 Z3*Z4*Z5 Z4*Z5*Z6 Z5*Z6*Z7
217+
...
218+
... # Annotate detectors, with a coloring in the 4th coordinate.
219+
... DETECTOR(0, 0, 0, 2) rec[-6]
220+
... DETECTOR(1, 0, 0, 0) rec[-5]
221+
... DETECTOR(2, 0, 0, 1) rec[-4]
222+
... DETECTOR(3, 0, 0, 2) rec[-3]
223+
... DETECTOR(4, 0, 0, 0) rec[-2]
224+
... DETECTOR(5, 0, 0, 1) rec[-1]
225+
...
226+
... # Check on the message.
227+
... M 0
228+
... OBSERVABLE_INCLUDE(0) rec[-1]
229+
... ''')
230+
231+
>>> # Sample the circuit.
232+
>>> shots = 4096
233+
>>> sampler = repetition_color_code.compile_detector_sampler()
234+
>>> dets, actual_obs_flips = sampler.sample(
235+
... shots=shots,
236+
... separate_observables=True,
237+
... bit_packed=True,
238+
... )
239+
240+
>>> # Decode with Chromobius.
241+
>>> dem = repetition_color_code.detector_error_model()
242+
>>> decoder = chromobius.compile_decoder_for_dem(dem)
243+
>>> result = decoder.predict_weighted_obs_flips_from_dets_bit_packed(dets)
244+
>>> pred, weights = result
245+
"""
164246
def compile_decoder_for_dem(
165247
dem: stim.DetectorErrorModel,
166248
) -> chromobius.CompiledDecoder:
@@ -178,6 +260,7 @@ def compile_decoder_for_dem(
178260
3 = Red Z
179261
4 = Green Z
180262
5 = Blue Z
263+
-1 = Ignore this Detector
181264
2. Rainbow triplets. Bulk errors with three symptoms in one basis should
182265
have one symptom of each color. Errors with three symptoms that
183266
repeat a color will cause an exception unless they can be decomposed

doc/chromobius_api_reference.md

+91
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [`chromobius.CompiledDecoder`](#chromobius.CompiledDecoder)
88
- [`chromobius.CompiledDecoder.from_dem`](#chromobius.CompiledDecoder.from_dem)
99
- [`chromobius.CompiledDecoder.predict_obs_flips_from_dets_bit_packed`](#chromobius.CompiledDecoder.predict_obs_flips_from_dets_bit_packed)
10+
- [`chromobius.CompiledDecoder.predict_weighted_obs_flips_from_dets_bit_packed`](#chromobius.CompiledDecoder.predict_weighted_obs_flips_from_dets_bit_packed)
1011
```python
1112
# Types used by the method definitions.
1213
from typing import overload, TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Union
@@ -37,6 +38,7 @@ def compile_decoder_for_dem(
3738
3 = Red Z
3839
4 = Green Z
3940
5 = Blue Z
41+
-1 = Ignore this Detector
4042
2. Rainbow triplets. Bulk errors with three symptoms in one basis should
4143
have one symptom of each color. Errors with three symptoms that
4244
repeat a color will cause an exception unless they can be decomposed
@@ -143,6 +145,7 @@ def from_dem(
143145
3 = Red Z
144146
4 = Green Z
145147
5 = Blue Z
148+
-1 = Ignore this Detector
146149
2. Rainbow triplets. Bulk errors with three symptoms in one basis should
147150
have one symptom of each color. Errors with three symptoms that
148151
repeat a color will cause an exception unless they can be decomposed
@@ -264,3 +267,91 @@ def predict_obs_flips_from_dets_bit_packed(
264267
>>> assert mistakes < shots / 5
265268
"""
266269
```
270+
271+
<a name="chromobius.CompiledDecoder.predict_weighted_obs_flips_from_dets_bit_packed"></a>
272+
```python
273+
# chromobius.CompiledDecoder.predict_weighted_obs_flips_from_dets_bit_packed
274+
275+
# (in class chromobius.CompiledDecoder)
276+
@staticmethod
277+
def predict_weighted_obs_flips_from_dets_bit_packed(
278+
dets: np.ndarray,
279+
) -> tuple[np.ndarray, np.ndarray]:
280+
"""Predicts observable flips and weights from detection events.
281+
282+
The returned weight comes directly from the underlying call to pymatching, not
283+
accounting for the lifting process.
284+
285+
Args:
286+
dets: A bit packed numpy array of detection event data. The array can either
287+
be 1-dimensional (a single shot to decode) or 2-dimensional (multiple
288+
shots to decode, with the first axis being the shot axis and the second
289+
axis being the detection event byte axis).
290+
291+
The array's dtype must be np.uint8. If you have an array of dtype
292+
np.bool_, you have data that's not bit packed. You can pack it by
293+
using `np.packbits(array, bitorder='little')`. But ideally you
294+
should attempt to never have unpacked data in the first place,
295+
since it's 8x larger which can be a large performance loss. For
296+
example, stim's sampler methods all have a `bit_packed=True` argument
297+
that cause them to return bit packed data.
298+
299+
Returns:
300+
A tuple (obs, weights).
301+
Obs is a bit packed numpy array of observable flip data.
302+
Weights is a numpy array (or scalar) of floats.
303+
304+
If dets is a 1D array, then the result has:
305+
obs.shape = (math.ceil(num_obs / 8),)
306+
obs.dtype = np.uint8
307+
weights.shape = ()
308+
weights.dtype = np.float32
309+
If dets is a 2D array, then the result has:
310+
shape = (dets.shape[0], math.ceil(num_obs / 8),)
311+
dtype = np.uint8
312+
weights.shape = (dets.shape[0],)
313+
weights.dtype = np.float32
314+
315+
To determine if the observable with index k was flipped in shot s, compute:
316+
`bool((obs[s, k // 8] >> (k % 8)) & 1)`
317+
318+
Example:
319+
>>> import stim
320+
>>> import chromobius
321+
>>> import numpy as np
322+
323+
>>> repetition_color_code = stim.Circuit('''
324+
... # Apply noise.
325+
... X_ERROR(0.1) 0 1 2 3 4 5 6 7
326+
... # Measure three-body stabilizers to catch errors.
327+
... MPP Z0*Z1*Z2 Z1*Z2*Z3 Z2*Z3*Z4 Z3*Z4*Z5 Z4*Z5*Z6 Z5*Z6*Z7
328+
...
329+
... # Annotate detectors, with a coloring in the 4th coordinate.
330+
... DETECTOR(0, 0, 0, 2) rec[-6]
331+
... DETECTOR(1, 0, 0, 0) rec[-5]
332+
... DETECTOR(2, 0, 0, 1) rec[-4]
333+
... DETECTOR(3, 0, 0, 2) rec[-3]
334+
... DETECTOR(4, 0, 0, 0) rec[-2]
335+
... DETECTOR(5, 0, 0, 1) rec[-1]
336+
...
337+
... # Check on the message.
338+
... M 0
339+
... OBSERVABLE_INCLUDE(0) rec[-1]
340+
... ''')
341+
342+
>>> # Sample the circuit.
343+
>>> shots = 4096
344+
>>> sampler = repetition_color_code.compile_detector_sampler()
345+
>>> dets, actual_obs_flips = sampler.sample(
346+
... shots=shots,
347+
... separate_observables=True,
348+
... bit_packed=True,
349+
... )
350+
351+
>>> # Decode with Chromobius.
352+
>>> dem = repetition_color_code.detector_error_model()
353+
>>> decoder = chromobius.compile_decoder_for_dem(dem)
354+
>>> result = decoder.predict_weighted_obs_flips_from_dets_bit_packed(dets)
355+
>>> pred, weights = result
356+
"""
357+
```

doc/getting_started.ipynb

+1
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@
346346
"- 3: red Z\n",
347347
"- 4: green Z\n",
348348
"- 5: blue Z.\n",
349+
"- (-1): ignore this detector (e.g. it's from something beyond the color code).\n",
349350
"\n",
350351
"As you can maybe tell, making a circuit can be a very involved process!\n",
351352
"This notebook isn't really about making circuits, and you probably don't want to get too bogged down in this detail, so let's not get stuck on this.\n",

file_lists/source_files_no_main

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ src/chromobius/datatypes/color_basis.h
1414
src/chromobius/datatypes/conf.h
1515
src/chromobius/datatypes/rgb_edge.cc
1616
src/chromobius/datatypes/rgb_edge.h
17+
src/chromobius/datatypes/stim_integration.cc
18+
src/chromobius/datatypes/stim_integration.h
19+
src/chromobius/datatypes/xor_vec.h
1720
src/chromobius/decode/decoder.cc
1821
src/chromobius/decode/decoder.h
1922
src/chromobius/decode/matcher_interface.h

file_lists/test_files

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ src/chromobius/commands/main_predict.test.cc
66
src/chromobius/datatypes/atomic_error.test.cc
77
src/chromobius/datatypes/color_basis.test.cc
88
src/chromobius/datatypes/rgb_edge.test.cc
9+
src/chromobius/datatypes/stim_integration.test.cc
10+
src/chromobius/datatypes/xor_vec.test.cc
911
src/chromobius/decode/decoder.test.cc
1012
src/chromobius/decode/decoder_integration.test.cc
1113
src/chromobius/graph/charge_graph.test.cc

0 commit comments

Comments
 (0)