Skip to content

Commit

Permalink
Add stim.Circuit.detecting_regions (#711)
Browse files Browse the repository at this point in the history
Fixes #349
  • Loading branch information
Strilanc authored Mar 12, 2024
1 parent b29741d commit dc59667
Show file tree
Hide file tree
Showing 11 changed files with 769 additions and 2 deletions.
136 changes: 136 additions & 0 deletions doc/python_api_reference_vDev.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ API references for stable versions are kept on the [stim github wiki](https://gi
- [`stim.Circuit.compile_sampler`](#stim.Circuit.compile_sampler)
- [`stim.Circuit.copy`](#stim.Circuit.copy)
- [`stim.Circuit.count_determined_measurements`](#stim.Circuit.count_determined_measurements)
- [`stim.Circuit.detecting_regions`](#stim.Circuit.detecting_regions)
- [`stim.Circuit.detector_error_model`](#stim.Circuit.detector_error_model)
- [`stim.Circuit.diagram`](#stim.Circuit.diagram)
- [`stim.Circuit.explain_detector_error_model_errors`](#stim.Circuit.explain_detector_error_model_errors)
Expand Down Expand Up @@ -1272,6 +1273,141 @@ def count_determined_measurements(
"""
```

<a name="stim.Circuit.detecting_regions"></a>
```python
# stim.Circuit.detecting_regions

# (in class stim.Circuit)
def detecting_regions(
self,
*,
targets: Optional[Iterable[stim.DemTarget | str | Iterable[float]]] = None,
ticks: Optional[Iterable[int]] = None,
) -> Dict[stim.DemTarget, Dict[int, stim.PauliString]]:
"""Records where detectors and observables are sensitive to errors over time.
The result of this method is a nested dictionary, mapping detectors/observables
and ticks to Pauli sensitivities for that detector/observable at that time.
For example, if observable 2 has Z-type sensitivity on qubits 5 and 6 during
tick 3, then `result[stim.target_logical_observable_id(2)][3]` will be equal to
`stim.PauliString("Z5*Z6")`.
If you want sensitivities from more places in the circuit, besides just at the
TICK instructions, you can work around this by making a version of the circuit
with more TICKs.
Args:
targets: Defaults to everything (None).
When specified, this should be an iterable of filters where items
matching any one filter are included.
A variety of filters are supported:
stim.DemTarget: Includes the targeted detector or observable.
Iterable[float]: Coordinate prefix match. Includes detectors whose
coordinate data begins with the same floats.
"D": Includes all detectors.
"L": Includes all observables.
"D#" (e.g. "D5"): Includes the detector with the specified index.
"L#" (e.g. "L5"): Includes the observable with the specified index.
ticks: Defaults to everything (None).
When specified, this should be a list of integers corresponding to
the tick indices to report sensitivities for.
ignore_anticommutation_errors: Defaults to False.
When set to False, invalid detecting regions that anticommute with a
reset will cause the method to raise an exception. When set to True,
the offending component will simply be silently dropped. This can
result in broken detectors having apparently enormous detecting
regions.
Returns:
Nested dictionaries keyed first by a `stim.DemTarget` identifying the
detector or observable, then by the index of the tick, leading to a
PauliString with that target's error sensitivity at that tick.
Note you can use `stim.PauliString.pauli_indices` to quickly get to the
non-identity terms in the sensitivity.
Examples:
>>> import stim
>>> detecting_regions = stim.Circuit('''
... R 0
... TICK
... H 0
... TICK
... CX 0 1
... TICK
... MX 0 1
... DETECTOR rec[-1] rec[-2]
... ''').detecting_regions()
>>> for target, tick_regions in detecting_regions.items():
... print("target", target)
... for tick, sensitivity in tick_regions.items():
... print(" tick", tick, "=", sensitivity)
target D0
tick 0 = +Z_
tick 1 = +X_
tick 2 = +XX
>>> circuit = stim.Circuit.generated(
... "surface_code:rotated_memory_x",
... rounds=5,
... distance=4,
... )
>>> detecting_regions = circuit.detecting_regions(
... targets=["L0", (2, 4), stim.DemTarget.relative_detector_id(5)],
... ticks=range(5, 15),
... )
>>> for target, tick_regions in detecting_regions.items():
... print("target", target)
... for tick, sensitivity in tick_regions.items():
... print(" tick", tick, "=", sensitivity)
target D1
tick 5 = +____________________X______________________
tick 6 = +____________________Z______________________
target D5
tick 5 = +______X____________________________________
tick 6 = +______Z____________________________________
target D14
tick 5 = +__________X_X______XXX_____________________
tick 6 = +__________X_X______XZX_____________________
tick 7 = +__________X_X______XZX_____________________
tick 8 = +__________X_X______XXX_____________________
tick 9 = +__________XXX_____XXX______________________
tick 10 = +__________XXX_______X______________________
tick 11 = +__________X_________X______________________
tick 12 = +____________________X______________________
tick 13 = +____________________Z______________________
target D29
tick 7 = +____________________Z______________________
tick 8 = +____________________X______________________
tick 9 = +____________________XX_____________________
tick 10 = +___________________XXX_______X_____________
tick 11 = +____________X______XXXX______X_____________
tick 12 = +__________X_X______XXX_____________________
tick 13 = +__________X_X______XZX_____________________
tick 14 = +__________X_X______XZX_____________________
target D44
tick 14 = +____________________Z______________________
target L0
tick 5 = +_X________X________X________X______________
tick 6 = +_X________X________X________X______________
tick 7 = +_X________X________X________X______________
tick 8 = +_X________X________X________X______________
tick 9 = +_X________X_______XX________X______________
tick 10 = +_X________X________X________X______________
tick 11 = +_X________XX_______X________XX_____________
tick 12 = +_X________X________X________X______________
tick 13 = +_X________X________X________X______________
tick 14 = +_X________X________X________X______________
"""
```

<a name="stim.Circuit.detector_error_model"></a>
```python
# stim.Circuit.detector_error_model
Expand Down
128 changes: 128 additions & 0 deletions doc/stim.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,134 @@ class Circuit:
>>> circuit.num_detectors + circuit.num_observables
217
"""
def detecting_regions(
self,
*,
targets: Optional[Iterable[stim.DemTarget | str | Iterable[float]]] = None,
ticks: Optional[Iterable[int]] = None,
) -> Dict[stim.DemTarget, Dict[int, stim.PauliString]]:
"""Records where detectors and observables are sensitive to errors over time.
The result of this method is a nested dictionary, mapping detectors/observables
and ticks to Pauli sensitivities for that detector/observable at that time.
For example, if observable 2 has Z-type sensitivity on qubits 5 and 6 during
tick 3, then `result[stim.target_logical_observable_id(2)][3]` will be equal to
`stim.PauliString("Z5*Z6")`.
If you want sensitivities from more places in the circuit, besides just at the
TICK instructions, you can work around this by making a version of the circuit
with more TICKs.
Args:
targets: Defaults to everything (None).
When specified, this should be an iterable of filters where items
matching any one filter are included.
A variety of filters are supported:
stim.DemTarget: Includes the targeted detector or observable.
Iterable[float]: Coordinate prefix match. Includes detectors whose
coordinate data begins with the same floats.
"D": Includes all detectors.
"L": Includes all observables.
"D#" (e.g. "D5"): Includes the detector with the specified index.
"L#" (e.g. "L5"): Includes the observable with the specified index.
ticks: Defaults to everything (None).
When specified, this should be a list of integers corresponding to
the tick indices to report sensitivities for.
ignore_anticommutation_errors: Defaults to False.
When set to False, invalid detecting regions that anticommute with a
reset will cause the method to raise an exception. When set to True,
the offending component will simply be silently dropped. This can
result in broken detectors having apparently enormous detecting
regions.
Returns:
Nested dictionaries keyed first by a `stim.DemTarget` identifying the
detector or observable, then by the index of the tick, leading to a
PauliString with that target's error sensitivity at that tick.
Note you can use `stim.PauliString.pauli_indices` to quickly get to the
non-identity terms in the sensitivity.
Examples:
>>> import stim
>>> detecting_regions = stim.Circuit('''
... R 0
... TICK
... H 0
... TICK
... CX 0 1
... TICK
... MX 0 1
... DETECTOR rec[-1] rec[-2]
... ''').detecting_regions()
>>> for target, tick_regions in detecting_regions.items():
... print("target", target)
... for tick, sensitivity in tick_regions.items():
... print(" tick", tick, "=", sensitivity)
target D0
tick 0 = +Z_
tick 1 = +X_
tick 2 = +XX
>>> circuit = stim.Circuit.generated(
... "surface_code:rotated_memory_x",
... rounds=5,
... distance=4,
... )
>>> detecting_regions = circuit.detecting_regions(
... targets=["L0", (2, 4), stim.DemTarget.relative_detector_id(5)],
... ticks=range(5, 15),
... )
>>> for target, tick_regions in detecting_regions.items():
... print("target", target)
... for tick, sensitivity in tick_regions.items():
... print(" tick", tick, "=", sensitivity)
target D1
tick 5 = +____________________X______________________
tick 6 = +____________________Z______________________
target D5
tick 5 = +______X____________________________________
tick 6 = +______Z____________________________________
target D14
tick 5 = +__________X_X______XXX_____________________
tick 6 = +__________X_X______XZX_____________________
tick 7 = +__________X_X______XZX_____________________
tick 8 = +__________X_X______XXX_____________________
tick 9 = +__________XXX_____XXX______________________
tick 10 = +__________XXX_______X______________________
tick 11 = +__________X_________X______________________
tick 12 = +____________________X______________________
tick 13 = +____________________Z______________________
target D29
tick 7 = +____________________Z______________________
tick 8 = +____________________X______________________
tick 9 = +____________________XX_____________________
tick 10 = +___________________XXX_______X_____________
tick 11 = +____________X______XXXX______X_____________
tick 12 = +__________X_X______XXX_____________________
tick 13 = +__________X_X______XZX_____________________
tick 14 = +__________X_X______XZX_____________________
target D44
tick 14 = +____________________Z______________________
target L0
tick 5 = +_X________X________X________X______________
tick 6 = +_X________X________X________X______________
tick 7 = +_X________X________X________X______________
tick 8 = +_X________X________X________X______________
tick 9 = +_X________X_______XX________X______________
tick 10 = +_X________X________X________X______________
tick 11 = +_X________XX_______X________XX_____________
tick 12 = +_X________X________X________X______________
tick 13 = +_X________X________X________X______________
tick 14 = +_X________X________X________X______________
"""
def detector_error_model(
self,
*,
Expand Down
1 change: 1 addition & 0 deletions file_lists/test_files
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ src/stim/cmd/command_gen.test.cc
src/stim/cmd/command_m2d.test.cc
src/stim/cmd/command_sample.test.cc
src/stim/cmd/command_sample_dem.test.cc
src/stim/dem/dem_instruction.test.cc
src/stim/dem/detector_error_model.test.cc
src/stim/diagram/ascii_diagram.test.cc
src/stim/diagram/base64.test.cc
Expand Down
Loading

0 comments on commit dc59667

Please sign in to comment.