Skip to content

Commit e4ae925

Browse files
authored
Add stim.Circuit.explain_detector_error_model_errors (#194)
- Add `stim.Circuit.get_detector_coordinates` - Add `stim.Circuit.get_final_qubit_coordinates` - Add `stim.DetectorErrorModel.get_detecetor_coordinates` - Rename `MatchedError` to `ExplainedError` - Rename `match_errors` command line mode to `explain_errors - Move `vec_pad_add_mul` to `stim::` namespace - Make asking for coordinates of impossible detector ids an error - Add `stim::DetectorErrorModel::final_detector_and_coord_shift` - Re-order measurement errors to be "more complicated" than unitary errors when reducing to single errors Example usage: ``` >>> import stim >>> circuit = stim.Circuit(''' ... # Create Bell pair. ... H 0 ... CNOT 0 1 ... ... # Noise. ... DEPOLARIZE1(0.01) 0 ... ... # Bell basis measurement. ... CNOT 0 1 ... H 0 ... M 0 1 ... ... # Both measurements should be False under noiseless execution. ... DETECTOR rec[-1] ... DETECTOR rec[-2] ... ''') >>> explained_errors = circuit.explain_detector_error_model_errors( ... dem_filter=stim.DetectorErrorModel('error(1) D0 D1'), ... reduce_to_one_representative_error=True, ... ) >>> print(explained_errors[0].circuit_error_locations[0]) CircuitErrorLocation { flipped_pauli_product: Y0 Circuit location stack trace: (after 0 TICKs) at instruction #3 (DEPOLARIZE1) in the circuit at target #1 of the instruction resolving to DEPOLARIZE1(0.01) 0 } ```
1 parent d5fea8e commit e4ae925

25 files changed

+1049
-273
lines changed

doc/python_api_reference_vDev.md

Lines changed: 165 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
- [`stim.Circuit.compile_sampler`](#stim.Circuit.compile_sampler)
2525
- [`stim.Circuit.copy`](#stim.Circuit.copy)
2626
- [`stim.Circuit.detector_error_model`](#stim.Circuit.detector_error_model)
27+
- [`stim.Circuit.explain_detector_error_model_errors`](#stim.Circuit.explain_detector_error_model_errors)
2728
- [`stim.Circuit.flattened_operations`](#stim.Circuit.flattened_operations)
2829
- [`stim.Circuit.generated`](#stim.Circuit.generated)
30+
- [`stim.Circuit.get_detector_coordinates`](#stim.Circuit.get_detector_coordinates)
31+
- [`stim.Circuit.get_final_qubit_coordinates`](#stim.Circuit.get_final_qubit_coordinates)
2932
- [`stim.Circuit.num_detectors`](#stim.Circuit.num_detectors)
3033
- [`stim.Circuit.num_measurements`](#stim.Circuit.num_measurements)
3134
- [`stim.Circuit.num_observables`](#stim.Circuit.num_observables)
@@ -133,10 +136,15 @@
133136
- [`stim.DetectorErrorModel.approx_equals`](#stim.DetectorErrorModel.approx_equals)
134137
- [`stim.DetectorErrorModel.clear`](#stim.DetectorErrorModel.clear)
135138
- [`stim.DetectorErrorModel.copy`](#stim.DetectorErrorModel.copy)
139+
- [`stim.DetectorErrorModel.get_detector_coordinates`](#stim.DetectorErrorModel.get_detector_coordinates)
136140
- [`stim.DetectorErrorModel.num_detectors`](#stim.DetectorErrorModel.num_detectors)
137141
- [`stim.DetectorErrorModel.num_errors`](#stim.DetectorErrorModel.num_errors)
138142
- [`stim.DetectorErrorModel.num_observables`](#stim.DetectorErrorModel.num_observables)
139143
- [`stim.DetectorErrorModel.shortest_graphlike_error`](#stim.DetectorErrorModel.shortest_graphlike_error)
144+
- [`stim.ExplainedError`](#stim.ExplainedError)
145+
- [`stim.ExplainedError.__init__`](#stim.ExplainedError.__init__)
146+
- [`stim.ExplainedError.circuit_error_locations`](#stim.ExplainedError.circuit_error_locations)
147+
- [`stim.ExplainedError.dem_error_terms`](#stim.ExplainedError.dem_error_terms)
140148
- [`stim.FlippedMeasurement`](#stim.FlippedMeasurement)
141149
- [`stim.FlippedMeasurement.__init__`](#stim.FlippedMeasurement.__init__)
142150
- [`stim.FlippedMeasurement.observable`](#stim.FlippedMeasurement.observable)
@@ -159,10 +167,6 @@
159167
- [`stim.GateTargetWithCoords.__init__`](#stim.GateTargetWithCoords.__init__)
160168
- [`stim.GateTargetWithCoords.coords`](#stim.GateTargetWithCoords.coords)
161169
- [`stim.GateTargetWithCoords.gate_target`](#stim.GateTargetWithCoords.gate_target)
162-
- [`stim.MatchedError`](#stim.MatchedError)
163-
- [`stim.MatchedError.__init__`](#stim.MatchedError.__init__)
164-
- [`stim.MatchedError.circuit_error_locations`](#stim.MatchedError.circuit_error_locations)
165-
- [`stim.MatchedError.dem_error_terms`](#stim.MatchedError.dem_error_terms)
166170
- [`stim.PauliString`](#stim.PauliString)
167171
- [`stim.PauliString.__add__`](#stim.PauliString.__add__)
168172
- [`stim.PauliString.__eq__`](#stim.PauliString.__eq__)
@@ -458,6 +462,11 @@
458462
> ''')
459463
> ```
460464
465+
## `stim.ExplainedError`<a name="stim.ExplainedError"></a>
466+
> ```
467+
> Describes the location of an error mechanism from a stim circuit.
468+
> ```
469+
461470
## `stim.FlippedMeasurement`<a name="stim.FlippedMeasurement"></a>
462471
> ```
463472
> Describes a measurement that was flipped.
@@ -495,11 +504,6 @@
495504
> what is happening.
496505
> ```
497506
498-
## `stim.MatchedError`<a name="stim.MatchedError"></a>
499-
> ```
500-
> Describes the location of an error mechanism from a stim circuit.
501-
> ```
502-
503507
## `stim.PauliString`<a name="stim.PauliString"></a>
504508
> ```
505509
> A signed Pauli tensor product (e.g. "+X \u2297 X \u2297 X" or "-Y \u2297 Z".
@@ -1282,6 +1286,56 @@
12821286
> ''')
12831287
> ```
12841288
1289+
### `stim.Circuit.explain_detector_error_model_errors(self, *, dem_filter: object = None, reduce_to_one_representative_error: bool = False) -> List[stim.ExplainedError]`<a name="stim.Circuit.explain_detector_error_model_errors"></a>
1290+
> ```
1291+
> Explains how detector error model errors are produced by circuit errors.
1292+
>
1293+
> Args:
1294+
> dem_filter: Defaults to None (unused). When used, the output will only contain detector error
1295+
> model errors that appear in the given `stim.DetectorErrorModel`. Any error mechanisms from the
1296+
> detector error model that can't be reproduced using one error from the circuit will also be included
1297+
> in the result, but with an empty list of associated circuit error mechanisms.
1298+
> reduce_to_one_representative_error: Defaults to False. When True, the items in the result will contain
1299+
> at most one circuit error mechanism.
1300+
>
1301+
> Returns:
1302+
> A `List[stim.ExplainedError]` (see `stim.ExplainedError` for more information). Each item in the list
1303+
> describes how a detector error model error can be produced by individual circuit errors.
1304+
>
1305+
> Examples:
1306+
> >>> import stim
1307+
> >>> circuit = stim.Circuit('''
1308+
> ... # Create Bell pair.
1309+
> ... H 0
1310+
> ... CNOT 0 1
1311+
> ...
1312+
> ... # Noise.
1313+
> ... DEPOLARIZE1(0.01) 0
1314+
> ...
1315+
> ... # Bell basis measurement.
1316+
> ... CNOT 0 1
1317+
> ... H 0
1318+
> ... M 0 1
1319+
> ...
1320+
> ... # Both measurements should be False under noiseless execution.
1321+
> ... DETECTOR rec[-1]
1322+
> ... DETECTOR rec[-2]
1323+
> ... ''')
1324+
> >>> explained_errors = circuit.explain_detector_error_model_errors(
1325+
> ... dem_filter=stim.DetectorErrorModel('error(1) D0 D1'),
1326+
> ... reduce_to_one_representative_error=True,
1327+
> ... )
1328+
> >>> print(explained_errors[0].circuit_error_locations[0])
1329+
> CircuitErrorLocation {
1330+
> flipped_pauli_product: Y0
1331+
> Circuit location stack trace:
1332+
> (after 0 TICKs)
1333+
> at instruction #3 (DEPOLARIZE1) in the circuit
1334+
> at target #1 of the instruction
1335+
> resolving to DEPOLARIZE1(0.01) 0
1336+
> }
1337+
> ```
1338+
12851339
### `stim.Circuit.flattened_operations(self) -> list`<a name="stim.Circuit.flattened_operations"></a>
12861340
> ```
12871341
> Flattens the circuit's operations into a list.
@@ -1402,6 +1456,56 @@
14021456
> OBSERVABLE_INCLUDE(0) rec[-1]
14031457
> ```
14041458
1459+
### `stim.Circuit.get_detector_coordinates(self, only: object = None) -> Dict[int, List[float]]`<a name="stim.Circuit.get_detector_coordinates"></a>
1460+
> ```
1461+
> Returns the coordinate metadata of detectors in the circuit.
1462+
>
1463+
> Args:
1464+
> only: Defaults to None (meaning include all detectors). A list of detector indices to include in the
1465+
> result. Detector indices beyond the end of the detector error model of the circuit cause an error.
1466+
>
1467+
> Returns:
1468+
> A dictionary mapping integers (detector indices) to lists of floats (coordinates).
1469+
> A dictionary mapping detector indices to lists of floats.
1470+
> Detectors with no specified coordinate data are mapped to an empty tuple.
1471+
> If `only` is specified, then `set(result.keys()) == set(only)`.
1472+
>
1473+
> Examples:
1474+
> >>> import stim
1475+
> >>> circuit = stim.Circuit('''
1476+
> ... M 0
1477+
> ... DETECTOR rec[-1]
1478+
> ... DETECTOR(1, 2, 3) rec[-1]
1479+
> ... REPEAT 3 {
1480+
> ... DETECTOR(42) rec[-1]
1481+
> ... SHIFT_COORDS(100)
1482+
> ... }
1483+
> ... ''')
1484+
> >>> circuit.get_detector_coordinates()
1485+
> {0: [], 1: [1.0, 2.0, 3.0], 2: [42.0], 3: [142.0], 4: [242.0]}
1486+
> >>> circuit.get_detector_coordinates(only=[1])
1487+
> {1: [1.0, 2.0, 3.0]}
1488+
> ```
1489+
1490+
### `stim.Circuit.get_final_qubit_coordinates(self, List[float]]`<a name="stim.Circuit.get_final_qubit_coordinates"></a>
1491+
> ```
1492+
> Returns the coordinate metadata of qubits in the circuit.
1493+
>
1494+
> If a qubit's coordinates are specified multiple times, only the last specified coordinates are returned.
1495+
>
1496+
> Returns:
1497+
> A dictionary mapping qubit indices (integers) to coordinates (lists of floats).
1498+
> Qubits that never had their coordinates specified are not included in the result.
1499+
>
1500+
> Examples:
1501+
> >>> import stim
1502+
> >>> circuit = stim.Circuit('''
1503+
> ... QUBIT_COORDS(1, 2, 3) 1
1504+
> ... ''')
1505+
> >>> circuit.get_final_qubit_coordinates()
1506+
> {1: [1.0, 2.0, 3.0]}
1507+
> ```
1508+
14051509
### `stim.Circuit.num_detectors`<a name="stim.Circuit.num_detectors"></a>
14061510
> ```
14071511
> Counts the number of bits produced when sampling the circuit's detectors.
@@ -1494,7 +1598,7 @@
14941598
> 6
14951599
> ```
14961600
1497-
### `stim.Circuit.shortest_graphlike_error(self, *, ignore_ungraphlike_errors: bool = False, canonicalize_circuit_errors: bool = False) -> List[stim.MatchedError]`<a name="stim.Circuit.shortest_graphlike_error"></a>
1601+
### `stim.Circuit.shortest_graphlike_error(self, *, ignore_ungraphlike_errors: bool = False, canonicalize_circuit_errors: bool = False) -> List[stim.ExplainedError]`<a name="stim.Circuit.shortest_graphlike_error"></a>
14981602
> ```
14991603
> Finds a minimum sized set of graphlike errors that produce an undetected logical error.
15001604
>
@@ -1541,7 +1645,7 @@
15411645
> ... rounds=10,
15421646
> ... distance=7,
15431647
> ... before_round_data_depolarization=0.01)
1544-
> >>> len(circuit.shortest_graphlike_error(decompose_errors=True))
1648+
> >>> len(circuit.shortest_graphlike_error())
15451649
> 7
15461650
> ```
15471651
@@ -2715,6 +2819,33 @@
27152819
> True
27162820
> ```
27172821
2822+
### `stim.DetectorErrorModel.get_detector_coordinates(self, only: object = None) -> Dict[int, List[float]]`<a name="stim.DetectorErrorModel.get_detector_coordinates"></a>
2823+
> ```
2824+
> Returns the coordinate metadata of detectors in the detector error model.
2825+
>
2826+
> Args:
2827+
> only: Defaults to None (meaning include all detectors). A list of detector indices to include in the
2828+
> result. Detector indices beyond the end of the detector error model cause an error.
2829+
>
2830+
> Returns:
2831+
> A dictionary mapping integers (detector indices) to lists of floats (coordinates).
2832+
> Detectors with no specified coordinate data are mapped to an empty tuple.
2833+
> If `only` is specified, then `set(result.keys()) == set(only)`.
2834+
>
2835+
> Examples:
2836+
> >>> import stim
2837+
> >>> dem = stim.DetectorErrorModel('''
2838+
> ... error(0.25) D0 D1
2839+
> ... detector(1, 2, 3) D1
2840+
> ... shift_detectors(5) 1
2841+
> ... detector(1, 2) D2
2842+
> ... ''')
2843+
> >>> dem.get_detector_coordinates()
2844+
> {0: [], 1: [1.0, 2.0, 3.0], 2: [], 3: [6.0, 2.0]}
2845+
> >>> dem.get_detector_coordinates(only=[1])
2846+
> {1: [1.0, 2.0, 3.0]}
2847+
> ```
2848+
27182849
### `stim.DetectorErrorModel.num_detectors`<a name="stim.DetectorErrorModel.num_detectors"></a>
27192850
> ```
27202851
> Counts the number of detectors (e.g. `D2`) in the error model.
@@ -2868,6 +2999,29 @@
28682999
> 7
28693000
> ```
28703001
3002+
### `stim.ExplainedError.__init__(self, *, dem_error_terms: List[stim.DemTargetWithCoords], circuit_error_locations: List[stim.CircuitErrorLocation]) -> None`<a name="stim.ExplainedError.__init__"></a>
3003+
> ```
3004+
> Creates a stim.ExplainedError.
3005+
> ```
3006+
3007+
### `stim.ExplainedError.circuit_error_locations`<a name="stim.ExplainedError.circuit_error_locations"></a>
3008+
> ```
3009+
> The locations of circuit errors that produce the symptoms in dem_error_terms.
3010+
>
3011+
> Note: if this list contains a single entry, it may be because a result
3012+
> with a single representative error was requested (as opposed to all possible
3013+
> errors).
3014+
>
3015+
> Note: if this list is empty, it may be because there was a DEM error decomposed
3016+
> into parts where one of the parts is impossible to make on its own from a single
3017+
> circuit error.
3018+
> ```
3019+
3020+
### `stim.ExplainedError.dem_error_terms`<a name="stim.ExplainedError.dem_error_terms"></a>
3021+
> ```
3022+
> The detectors and observables flipped by this error mechanism.
3023+
> ```
3024+
28713025
### `stim.FlippedMeasurement.__init__(self, *, record_index: int, observable: object) -> None`<a name="stim.FlippedMeasurement.__init__"></a>
28723026
> ```
28733027
> Creates a stim.FlippedMeasurement.
@@ -2975,29 +3129,6 @@
29753129
> Returns the actual gate target as a `stim.GateTarget`.
29763130
> ```
29773131
2978-
### `stim.MatchedError.__init__(self, *, dem_error_terms: List[stim.DemTargetWithCoords], circuit_error_locations: List[stim.CircuitErrorLocation]) -> None`<a name="stim.MatchedError.__init__"></a>
2979-
> ```
2980-
> Creates a stim.MatchedError.
2981-
> ```
2982-
2983-
### `stim.MatchedError.circuit_error_locations`<a name="stim.MatchedError.circuit_error_locations"></a>
2984-
> ```
2985-
> The locations of circuit errors that produce the symptoms in dem_error_terms.
2986-
>
2987-
> Note: if this list contains a single entry, it may be because a result
2988-
> with a single representative error was requested (as opposed to all possible
2989-
> errors).
2990-
>
2991-
> Note: if this list is empty, it may be because there was a DEM error decomposed
2992-
> into parts where one of the parts is impossible to make on its own from a single
2993-
> circuit error.
2994-
> ```
2995-
2996-
### `stim.MatchedError.dem_error_terms`<a name="stim.MatchedError.dem_error_terms"></a>
2997-
> ```
2998-
> The detectors and observables flipped by this error mechanism.
2999-
> ```
3000-
30013132
### `stim.PauliString.__add__(self, rhs: stim.PauliString) -> stim.PauliString`<a name="stim.PauliString.__add__"></a>
30023133
> ```
30033134
> Returns the tensor product of two Pauli strings.

0 commit comments

Comments
 (0)