Skip to content

Commit 6d43398

Browse files
authored
Merge branch 'main' into sinter-correlated-pymatching
2 parents 6f1d93b + 365a1d8 commit 6d43398

26 files changed

+1708
-35
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,7 @@ jobs:
126126
{os: windows-2025, dist: cp310-win_amd64},
127127
{os: windows-2025, dist: cp311-win_amd64},
128128
{os: windows-2025, dist: cp312-win_amd64},
129-
130-
# (April 2024) disabled because numpy fails to build. Unsure why it's not using a prebuilt wheel.
131-
# {os: windows-2025, dist: cp313-win_amd64},
129+
{os: windows-2025, dist: cp313-win_amd64},
132130

133131
{os: windows-2025, dist: cp36-win32},
134132
{os: windows-2025, dist: cp37-win32},

doc/circuit_data_references.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
- [arXiv:2408.00758](https://arxiv.org/abs/2408.00758)[Stim circuits for ``To reset, or not to reset -- that is the question" manuscript](https://zenodo.org/records/13152440)
3434
- [arXiv:2408.11894](https://arxiv.org/abs/2408.11894)[Stim circuits for 'Automated Synthesis of Fault-Tolerant State Preparation Circuits for Quantum Error Correction Codes'](https://github.com/cda-tum/mqt-qecc/tree/main/src/mqt/qecc/ft_stateprep/eval/circuits)
3535
- [arXiv:2408.13687](https://arxiv.org/abs/2408.13687)[Data for "Quantum error correction below the surface code threshold"](https://zenodo.org/records/13273331)
36+
- [arXiv:2409.04628](https://arxiv.org/abs/2409.04628)[Stim implementation of the [[16,4,4]] Tesseract Code](https://github.com/DeDuckProject/tesseract-code-stim) (circuits are in the stim_circuits/ directory)
3637
- [arXiv:2409.17595](https://arxiv.org/abs/2409.17595)[Data for "Magic state cultivation: growing T states as cheap as CNOT gates"](https://zenodo.org/records/13777072)
3738
- [arXiv:2412.01391](https://arxiv.org/abs/2412.01391)[GitHub repo for "Transversal Logical Clifford gates on rotated surface codes with reconfigurable neutral atom arrays"](https://github.com/Zihan-Chen-PhMA/Dynamical-S-gate-decoding/) (circuits are in the circuit_garage/ directory)
3839
- [arXiv:2412.14256](https://arxiv.org/abs/2412.14256)[Data for "Scaling and logic in the color code on a superconducting quantum processor"](https://zenodo.org/records/14238944)

doc/file_format_stim_circuit.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ and annotations for tasks such as detection event sampling and drawing the circu
2525
## Encoding
2626

2727
Stim circuit files are always encoded using UTF-8.
28-
Furthermore, the only place in the file where non-ASCII characters are permitted is inside of comments.
28+
29+
(Also, the only place in the file where non-ASCII characters can validly appear is inside of comments and tags.)
2930

3031
## Syntax
3132

doc/gates.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,7 @@ Example:
17841784
# Apply Y to qubit 5 controlled by qubit 2.
17851785
CY 2 5
17861786

1787-
# Perform CY 2 5 then CX 4 2.
1787+
# Perform CY 2 5 then CY 4 2.
17881788
CY 2 5 4 2
17891789

17901790
# Apply Y to qubit 6 if the most recent measurement result was TRUE.

doc/python_api_reference_vDev.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ API references for stable versions are kept on the [stim github wiki](https://gi
4343
- [`stim.Circuit.insert`](#stim.Circuit.insert)
4444
- [`stim.Circuit.inverse`](#stim.Circuit.inverse)
4545
- [`stim.Circuit.likeliest_error_sat_problem`](#stim.Circuit.likeliest_error_sat_problem)
46+
- [`stim.Circuit.missing_detectors`](#stim.Circuit.missing_detectors)
4647
- [`stim.Circuit.num_detectors`](#stim.Circuit.num_detectors)
4748
- [`stim.Circuit.num_measurements`](#stim.Circuit.num_measurements)
4849
- [`stim.Circuit.num_observables`](#stim.Circuit.num_observables)
@@ -197,6 +198,7 @@ API references for stable versions are kept on the [stim github wiki](https://gi
197198
- [`stim.ExplainedError.dem_error_terms`](#stim.ExplainedError.dem_error_terms)
198199
- [`stim.FlipSimulator`](#stim.FlipSimulator)
199200
- [`stim.FlipSimulator.__init__`](#stim.FlipSimulator.__init__)
201+
- [`stim.FlipSimulator.append_measurement_flips`](#stim.FlipSimulator.append_measurement_flips)
200202
- [`stim.FlipSimulator.batch_size`](#stim.FlipSimulator.batch_size)
201203
- [`stim.FlipSimulator.broadcast_pauli_errors`](#stim.FlipSimulator.broadcast_pauli_errors)
202204
- [`stim.FlipSimulator.clear`](#stim.FlipSimulator.clear)
@@ -1249,6 +1251,8 @@ def copy(
12491251
# (in class stim.Circuit)
12501252
def count_determined_measurements(
12511253
self,
1254+
*,
1255+
unknown_input: bool = False,
12521256
) -> int:
12531257
"""Counts the number of predictable measurements in the circuit.
12541258

@@ -1280,6 +1284,13 @@ def count_determined_measurements(
12801284
the Z basis. Typically this relationship is not declared as a detector, because
12811285
it's not local, or as an observable, because it doesn't store a qubit.
12821286

1287+
Args:
1288+
unknown_input: Defaults to False (inputs assumed to be in the |0> state).
1289+
When set to True, the inputs are instead treated as being in unknown
1290+
random states. For example, this means that Z-basis measurements at
1291+
the very beginning of the circuit will be considered random rather
1292+
than determined.
1293+
12831294
Returns:
12841295
The number of measurements that were predictable.
12851296

@@ -1299,6 +1310,24 @@ def count_determined_measurements(
12991310
... ''').count_determined_measurements()
13001311
0
13011312

1313+
>>> stim.Circuit('''
1314+
... M 0
1315+
... ''').count_determined_measurements()
1316+
1
1317+
1318+
>>> stim.Circuit('''
1319+
... M 0
1320+
... ''').count_determined_measurements(unknown_input=True)
1321+
0
1322+
1323+
>>> stim.Circuit('''
1324+
... M 0
1325+
... M 0 1
1326+
... M 0 1 2
1327+
... M 0 1 2 3
1328+
... ''').count_determined_measurements(unknown_input=True)
1329+
6
1330+
13021331
>>> stim.Circuit('''
13031332
... R 0 1
13041333
... MZZ 0 1
@@ -2542,6 +2571,72 @@ def likeliest_error_sat_problem(
25422571
"""
25432572
```
25442573

2574+
<a name="stim.Circuit.missing_detectors"></a>
2575+
```python
2576+
# stim.Circuit.missing_detectors
2577+
2578+
# (in class stim.Circuit)
2579+
def missing_detectors(
2580+
self,
2581+
*,
2582+
unknown_input: bool = False,
2583+
) -> int:
2584+
"""Finds deterministic measurements independent of declared detectors/observables.
2585+
2586+
This method is useful for debugging missing detectors in a circuit, because it
2587+
identifies generators for uncovered degrees of freedom.
2588+
2589+
It's not recommended to use this method to solve for the detectors of a circuit.
2590+
The returned detectors are not guaranteed to be stable across versions, and
2591+
aren't optimized to be "good" (e.g. form a low weight basis or be matchable
2592+
if possible). It will also identify things that are technically determined
2593+
but that the user may not want to use as a detector, such as the fact that
2594+
in the first round after transversal Z basis initialization of a toric code
2595+
the product of all X stabilizer measurements is deterministic even though the
2596+
individual measurements are all random.
2597+
2598+
Args:
2599+
unknown_input: Defaults to False (inputs assumed to be in the |0> state).
2600+
When set to True, the inputs are instead treated as being in unknown
2601+
random states. For example, this means that Z-basis measurements at
2602+
the very beginning of the circuit will be considered random rather
2603+
than determined.
2604+
2605+
Returns:
2606+
A circuit containing DETECTOR instructions that specify the uncovered
2607+
degrees of freedom in the deterministic measurement sets of the input
2608+
circuit. The returned circuit can be appended to the input circuit to
2609+
get a circuit with no missing detectors.
2610+
2611+
Examples:
2612+
>>> import stim
2613+
2614+
>>> stim.Circuit('''
2615+
... R 0
2616+
... M 0
2617+
... ''').missing_detectors()
2618+
stim.Circuit('''
2619+
DETECTOR rec[-1]
2620+
''')
2621+
2622+
>>> stim.Circuit('''
2623+
... MZZ 0 1
2624+
... MYY 0 1
2625+
... MXX 0 1
2626+
... DEPOLARIZE1(0.1) 0 1
2627+
... MZZ 0 1
2628+
... MYY 0 1
2629+
... MXX 0 1
2630+
... DETECTOR rec[-1] rec[-4]
2631+
... DETECTOR rec[-2] rec[-5]
2632+
... DETECTOR rec[-3] rec[-6]
2633+
... ''').missing_detectors(unknown_input=True)
2634+
stim.Circuit('''
2635+
DETECTOR rec[-3] rec[-2] rec[-1]
2636+
''')
2637+
"""
2638+
```
2639+
25452640
<a name="stim.Circuit.num_detectors"></a>
25462641
```python
25472642
# stim.Circuit.num_detectors
@@ -8050,6 +8145,86 @@ def __init__(
80508145
"""
80518146
```
80528147

8148+
<a name="stim.FlipSimulator.append_measurement_flips"></a>
8149+
```python
8150+
# stim.FlipSimulator.append_measurement_flips
8151+
8152+
# (in class stim.FlipSimulator)
8153+
def append_measurement_flips(
8154+
self,
8155+
measurement_flip_data: np.ndarray,
8156+
) -> None:
8157+
"""Appends measurement flip data to the simulator's measurement record.
8158+
8159+
Args:
8160+
measurement_flip_data: The flip data to append. The following shape/dtype
8161+
combinations are supported.
8162+
8163+
Single measurement without bit packing:
8164+
shape=(self.batch_size,)
8165+
dtype=np.bool_
8166+
8167+
Single measurement with bit packing:
8168+
shape=(math.ceil(self.batch_size / 8),)
8169+
dtype=np.uint8
8170+
8171+
Multiple measurements without bit packing:
8172+
shape=(num_measurements, self.batch_size)
8173+
dtype=np.bool_
8174+
8175+
Multiple measurements with bit packing:
8176+
shape=(num_measurements, math.ceil(self.batch_size / 8))
8177+
dtype=np.uint8
8178+
8179+
Examples:
8180+
>>> import stim
8181+
>>> import numpy as np
8182+
>>> sim = stim.FlipSimulator(batch_size=9)
8183+
>>> sim.append_measurement_flips(np.array(
8184+
... [0, 1, 0, 0, 1, 0, 0, 1, 1],
8185+
... dtype=np.bool_,
8186+
... ))
8187+
8188+
>>> sim.get_measurement_flips()
8189+
array([[False, True, False, False, True, False, False, True, True]])
8190+
8191+
>>> sim.append_measurement_flips(np.array(
8192+
... [0b11001001, 0],
8193+
... dtype=np.uint8,
8194+
... ))
8195+
8196+
>>> sim.get_measurement_flips()
8197+
array([[False, True, False, False, True, False, False, True, True],
8198+
[ True, False, False, True, False, False, True, True, False]])
8199+
8200+
>>> sim.append_measurement_flips(np.array(
8201+
... [[0b11111111, 0b1], [0b00000000, 0b0], [0b11111111, 0b1]],
8202+
... dtype=np.uint8,
8203+
... ))
8204+
8205+
>>> sim.get_measurement_flips()
8206+
array([[False, True, False, False, True, False, False, True, True],
8207+
[ True, False, False, True, False, False, True, True, False],
8208+
[ True, True, True, True, True, True, True, True, True],
8209+
[False, False, False, False, False, False, False, False, False],
8210+
[ True, True, True, True, True, True, True, True, True]])
8211+
8212+
>>> sim.append_measurement_flips(np.array(
8213+
... [[1, 0, 1, 0, 1, 0, 1, 0, 1], [0, 1, 0, 1, 0, 1, 0, 1, 0]],
8214+
... dtype=np.bool_,
8215+
... ))
8216+
8217+
>>> sim.get_measurement_flips()
8218+
array([[False, True, False, False, True, False, False, True, True],
8219+
[ True, False, False, True, False, False, True, True, False],
8220+
[ True, True, True, True, True, True, True, True, True],
8221+
[False, False, False, False, False, False, False, False, False],
8222+
[ True, True, True, True, True, True, True, True, True],
8223+
[ True, False, True, False, True, False, True, False, True],
8224+
[False, True, False, True, False, True, False, True, False]])
8225+
"""
8226+
```
8227+
80538228
<a name="stim.FlipSimulator.batch_size"></a>
80548229
```python
80558230
# stim.FlipSimulator.batch_size
@@ -10911,6 +11086,14 @@ def __init__(
1091111086
Iterable: initializes by interpreting each item as a Pauli.
1091211087
Each item can be a single-qubit Pauli string (like "X"),
1091311088
or an integer. Integers use the convention 0=I, 1=X, 2=Y, 3=Z.
11089+
Dict[int, Union[int, str]]: initializes by interpreting keys as
11090+
the qubit index and values as the Pauli for that index.
11091+
Each value can be a single-qubit Pauli string (like "X"),
11092+
or an integer. Integers use the convention 0=I, 1=X, 2=Y, 3=Z.
11093+
Dict[Union[int, str], Iterable[int]]: initializes by interpreting keys
11094+
as Pauli operators and values as the qubit indices for that Pauli.
11095+
Each key can be a single-qubit Pauli string (like "X"),
11096+
or an integer. Integers use the convention 0=I, 1=X, 2=Y, 3=Z.
1091411097

1091511098
Examples:
1091611099
>>> import stim
@@ -10938,6 +11121,15 @@ def __init__(
1093811121

1093911122
>>> stim.PauliString("X6*Y6")
1094011123
stim.PauliString("+i______Z")
11124+
11125+
>>> stim.PauliString({0: "X", 2: "Y", 3: "X"})
11126+
stim.PauliString("+X_YX")
11127+
11128+
>>> stim.PauliString({0: "X", 2: 2, 3: 1})
11129+
stim.PauliString("+X_YX")
11130+
11131+
>>> stim.PauliString({"X": [1], 2: [4], "Z": [0, 3]})
11132+
stim.PauliString("+ZX_ZY")
1094111133
"""
1094211134
```
1094311135

0 commit comments

Comments
 (0)