Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stim.Circuit.detecting_regions #711

Merged
merged 8 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading