Skip to content

Commit 1efe91b

Browse files
authored
Add stim.{CircuitInstruction,DemInstruction}.target_groups (#812)
Fixes #811
1 parent 51b29e3 commit 1efe91b

19 files changed

Lines changed: 693 additions & 93 deletions

doc/python_api_reference_vDev.md

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ API references for stable versions are kept on the [stim github wiki](https://gi
8282
- [`stim.CircuitInstruction.gate_args_copy`](#stim.CircuitInstruction.gate_args_copy)
8383
- [`stim.CircuitInstruction.name`](#stim.CircuitInstruction.name)
8484
- [`stim.CircuitInstruction.num_measurements`](#stim.CircuitInstruction.num_measurements)
85+
- [`stim.CircuitInstruction.target_groups`](#stim.CircuitInstruction.target_groups)
8586
- [`stim.CircuitInstruction.targets_copy`](#stim.CircuitInstruction.targets_copy)
8687
- [`stim.CircuitRepeatBlock`](#stim.CircuitRepeatBlock)
8788
- [`stim.CircuitRepeatBlock.__eq__`](#stim.CircuitRepeatBlock.__eq__)
@@ -123,6 +124,7 @@ API references for stable versions are kept on the [stim github wiki](https://gi
123124
- [`stim.DemInstruction.__repr__`](#stim.DemInstruction.__repr__)
124125
- [`stim.DemInstruction.__str__`](#stim.DemInstruction.__str__)
125126
- [`stim.DemInstruction.args_copy`](#stim.DemInstruction.args_copy)
127+
- [`stim.DemInstruction.target_groups`](#stim.DemInstruction.target_groups)
126128
- [`stim.DemInstruction.targets_copy`](#stim.DemInstruction.targets_copy)
127129
- [`stim.DemInstruction.type`](#stim.DemInstruction.type)
128130
- [`stim.DemRepeatBlock`](#stim.DemRepeatBlock)
@@ -3664,6 +3666,25 @@ def instruction_targets(
36643666
"""Within the error instruction, which may have hundreds of
36653667
targets, which specific targets were being executed to
36663668
produce the error.
3669+
3670+
Examples:
3671+
>>> import stim
3672+
>>> err = stim.Circuit('''
3673+
... R 0
3674+
... TICK
3675+
... Y_ERROR(0.125) 0
3676+
... M 0
3677+
... OBSERVABLE_INCLUDE(0) rec[-1]
3678+
... ''').shortest_graphlike_error()
3679+
>>> targets = err[0].circuit_error_locations[0].instruction_targets
3680+
>>> targets == stim.CircuitTargetsInsideInstruction(
3681+
... gate='Y_ERROR',
3682+
... args=[0.125],
3683+
... target_range_start=0,
3684+
... target_range_end=1,
3685+
... targets_in_range=(stim.GateTargetWithCoords(0, []),),
3686+
... )
3687+
True
36673688
"""
36683689
```
36693690

@@ -3917,6 +3938,17 @@ def gate_args_copy(
39173938
For noisy gates this typically a list of probabilities.
39183939
For OBSERVABLE_INCLUDE it's a singleton list containing the logical observable
39193940
index.
3941+
3942+
Examples:
3943+
>>> import stim
3944+
>>> instruction = stim.CircuitInstruction('X_ERROR', [2, 3], [0.125])
3945+
>>> instruction.gate_args_copy()
3946+
[0.125]
3947+
3948+
>>> instruction.gate_args_copy() == instruction.gate_args_copy()
3949+
True
3950+
>>> instruction.gate_args_copy() is instruction.gate_args_copy()
3951+
False
39203952
"""
39213953
```
39223954

@@ -3961,6 +3993,52 @@ def num_measurements(
39613993
"""
39623994
```
39633995

3996+
<a name="stim.CircuitInstruction.target_groups"></a>
3997+
```python
3998+
# stim.CircuitInstruction.target_groups
3999+
4000+
# (in class stim.CircuitInstruction)
4001+
def target_groups(
4002+
self,
4003+
) -> List[List[stim.GateTarget]]:
4004+
"""Splits the instruction's targets into groups depending on the type of gate.
4005+
4006+
Single qubit gates like H get one group per target.
4007+
Two qubit gates like CX get one group per pair of targets.
4008+
Pauli product gates like MPP get one group per combined product.
4009+
4010+
Returns:
4011+
A list of groups of targets.
4012+
4013+
Examples:
4014+
>>> import stim
4015+
>>> for g in stim.Circuit('H 0 1 2')[0].target_groups():
4016+
... print(repr(g))
4017+
[stim.GateTarget(0)]
4018+
[stim.GateTarget(1)]
4019+
[stim.GateTarget(2)]
4020+
4021+
>>> for g in stim.Circuit('CX 0 1 2 3')[0].target_groups():
4022+
... print(repr(g))
4023+
[stim.GateTarget(0), stim.GateTarget(1)]
4024+
[stim.GateTarget(2), stim.GateTarget(3)]
4025+
4026+
>>> for g in stim.Circuit('MPP X0*Y1*Z2 X5*X6')[0].target_groups():
4027+
... print(repr(g))
4028+
[stim.target_x(0), stim.target_y(1), stim.target_z(2)]
4029+
[stim.target_x(5), stim.target_x(6)]
4030+
4031+
>>> for g in stim.Circuit('DETECTOR rec[-1] rec[-2]')[0].target_groups():
4032+
... print(repr(g))
4033+
[stim.target_rec(-1)]
4034+
[stim.target_rec(-2)]
4035+
4036+
>>> for g in stim.Circuit('CORRELATED_ERROR(0.1) X0 Y1')[0].target_groups():
4037+
... print(repr(g))
4038+
[stim.target_x(0), stim.target_y(1)]
4039+
"""
4040+
```
4041+
39644042
<a name="stim.CircuitInstruction.targets_copy"></a>
39654043
```python
39664044
# stim.CircuitInstruction.targets_copy
@@ -3970,6 +4048,17 @@ def targets_copy(
39704048
self,
39714049
) -> List[stim.GateTarget]:
39724050
"""Returns a copy of the targets of the instruction.
4051+
4052+
Examples:
4053+
>>> import stim
4054+
>>> instruction = stim.CircuitInstruction('X_ERROR', [2, 3], [0.125])
4055+
>>> instruction.targets_copy()
4056+
[stim.GateTarget(2), stim.GateTarget(3)]
4057+
4058+
>>> instruction.targets_copy() == instruction.targets_copy()
4059+
True
4060+
>>> instruction.targets_copy() is instruction.targets_copy()
4061+
False
39734062
"""
39744063
```
39754064

@@ -5335,6 +5424,42 @@ def args_copy(
53355424
"""
53365425
```
53375426

5427+
<a name="stim.DemInstruction.target_groups"></a>
5428+
```python
5429+
# stim.DemInstruction.target_groups
5430+
5431+
# (in class stim.DemInstruction)
5432+
def target_groups(
5433+
self,
5434+
) -> List[List[stim.DemTarget]]:
5435+
"""Returns a copy of the instruction's targets, split by target separators.
5436+
5437+
When a detector error model instruction contains a suggested decomposition,
5438+
its targets contain separators (`stim.DemTarget("^")`). This method splits the
5439+
targets into groups based the separators, similar to how `str.split` works.
5440+
5441+
Returns:
5442+
A list of groups of targets.
5443+
5444+
Examples:
5445+
>>> import stim
5446+
>>> dem = stim.DetectorErrorModel('''
5447+
... error(0.01) D0 D1 ^ D2
5448+
... error(0.01) D0 L0
5449+
... error(0.01)
5450+
... ''')
5451+
5452+
>>> dem[0].target_groups()
5453+
[[stim.DemTarget('D0'), stim.DemTarget('D1')], [stim.DemTarget('D2')]]
5454+
5455+
>>> dem[1].target_groups()
5456+
[[stim.DemTarget('D0'), stim.DemTarget('L0')]]
5457+
5458+
>>> dem[2].target_groups()
5459+
[[]]
5460+
"""
5461+
```
5462+
53385463
<a name="stim.DemInstruction.targets_copy"></a>
53395464
```python
53405465
# stim.DemInstruction.targets_copy
@@ -8928,7 +9053,7 @@ class GateTarget:
89289053
>>> circuit[0].targets_copy()[0]
89299054
stim.GateTarget(0)
89309055
>>> circuit[0].targets_copy()[1]
8931-
stim.GateTarget(stim.target_inv(1))
9056+
stim.target_inv(1)
89329057
"""
89339058
```
89349059

doc/stim.pyi

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2846,6 +2846,25 @@ class CircuitErrorLocation:
28462846
"""Within the error instruction, which may have hundreds of
28472847
targets, which specific targets were being executed to
28482848
produce the error.
2849+
2850+
Examples:
2851+
>>> import stim
2852+
>>> err = stim.Circuit('''
2853+
... R 0
2854+
... TICK
2855+
... Y_ERROR(0.125) 0
2856+
... M 0
2857+
... OBSERVABLE_INCLUDE(0) rec[-1]
2858+
... ''').shortest_graphlike_error()
2859+
>>> targets = err[0].circuit_error_locations[0].instruction_targets
2860+
>>> targets == stim.CircuitTargetsInsideInstruction(
2861+
... gate='Y_ERROR',
2862+
... args=[0.125],
2863+
... target_range_start=0,
2864+
... target_range_end=1,
2865+
... targets_in_range=(stim.GateTargetWithCoords(0, []),),
2866+
... )
2867+
True
28492868
"""
28502869
@property
28512870
def stack_frames(
@@ -3001,6 +3020,17 @@ class CircuitInstruction:
30013020
For noisy gates this typically a list of probabilities.
30023021
For OBSERVABLE_INCLUDE it's a singleton list containing the logical observable
30033022
index.
3023+
3024+
Examples:
3025+
>>> import stim
3026+
>>> instruction = stim.CircuitInstruction('X_ERROR', [2, 3], [0.125])
3027+
>>> instruction.gate_args_copy()
3028+
[0.125]
3029+
3030+
>>> instruction.gate_args_copy() == instruction.gate_args_copy()
3031+
True
3032+
>>> instruction.gate_args_copy() is instruction.gate_args_copy()
3033+
False
30043034
"""
30053035
@property
30063036
def name(
@@ -3029,10 +3059,60 @@ class CircuitInstruction:
30293059
>>> stim.CircuitInstruction('HERALDED_ERASE', [0]).num_measurements
30303060
1
30313061
"""
3062+
def target_groups(
3063+
self,
3064+
) -> List[List[stim.GateTarget]]:
3065+
"""Splits the instruction's targets into groups depending on the type of gate.
3066+
3067+
Single qubit gates like H get one group per target.
3068+
Two qubit gates like CX get one group per pair of targets.
3069+
Pauli product gates like MPP get one group per combined product.
3070+
3071+
Returns:
3072+
A list of groups of targets.
3073+
3074+
Examples:
3075+
>>> import stim
3076+
>>> for g in stim.Circuit('H 0 1 2')[0].target_groups():
3077+
... print(repr(g))
3078+
[stim.GateTarget(0)]
3079+
[stim.GateTarget(1)]
3080+
[stim.GateTarget(2)]
3081+
3082+
>>> for g in stim.Circuit('CX 0 1 2 3')[0].target_groups():
3083+
... print(repr(g))
3084+
[stim.GateTarget(0), stim.GateTarget(1)]
3085+
[stim.GateTarget(2), stim.GateTarget(3)]
3086+
3087+
>>> for g in stim.Circuit('MPP X0*Y1*Z2 X5*X6')[0].target_groups():
3088+
... print(repr(g))
3089+
[stim.target_x(0), stim.target_y(1), stim.target_z(2)]
3090+
[stim.target_x(5), stim.target_x(6)]
3091+
3092+
>>> for g in stim.Circuit('DETECTOR rec[-1] rec[-2]')[0].target_groups():
3093+
... print(repr(g))
3094+
[stim.target_rec(-1)]
3095+
[stim.target_rec(-2)]
3096+
3097+
>>> for g in stim.Circuit('CORRELATED_ERROR(0.1) X0 Y1')[0].target_groups():
3098+
... print(repr(g))
3099+
[stim.target_x(0), stim.target_y(1)]
3100+
"""
30323101
def targets_copy(
30333102
self,
30343103
) -> List[stim.GateTarget]:
30353104
"""Returns a copy of the targets of the instruction.
3105+
3106+
Examples:
3107+
>>> import stim
3108+
>>> instruction = stim.CircuitInstruction('X_ERROR', [2, 3], [0.125])
3109+
>>> instruction.targets_copy()
3110+
[stim.GateTarget(2), stim.GateTarget(3)]
3111+
3112+
>>> instruction.targets_copy() == instruction.targets_copy()
3113+
True
3114+
>>> instruction.targets_copy() is instruction.targets_copy()
3115+
False
30363116
"""
30373117
class CircuitRepeatBlock:
30383118
"""A REPEAT block from a circuit.
@@ -4172,6 +4252,35 @@ class DemInstruction:
41724252
>>> instruction.args_copy() is instruction.args_copy()
41734253
False
41744254
"""
4255+
def target_groups(
4256+
self,
4257+
) -> List[List[stim.DemTarget]]:
4258+
"""Returns a copy of the instruction's targets, split by target separators.
4259+
4260+
When a detector error model instruction contains a suggested decomposition,
4261+
its targets contain separators (`stim.DemTarget("^")`). This method splits the
4262+
targets into groups based the separators, similar to how `str.split` works.
4263+
4264+
Returns:
4265+
A list of groups of targets.
4266+
4267+
Examples:
4268+
>>> import stim
4269+
>>> dem = stim.DetectorErrorModel('''
4270+
... error(0.01) D0 D1 ^ D2
4271+
... error(0.01) D0 L0
4272+
... error(0.01)
4273+
... ''')
4274+
4275+
>>> dem[0].target_groups()
4276+
[[stim.DemTarget('D0'), stim.DemTarget('D1')], [stim.DemTarget('D2')]]
4277+
4278+
>>> dem[1].target_groups()
4279+
[[stim.DemTarget('D0'), stim.DemTarget('L0')]]
4280+
4281+
>>> dem[2].target_groups()
4282+
[[]]
4283+
"""
41754284
def targets_copy(
41764285
self,
41774286
) -> List[Union[int, stim.DemTarget]]:
@@ -6976,7 +7085,7 @@ class GateTarget:
69767085
>>> circuit[0].targets_copy()[0]
69777086
stim.GateTarget(0)
69787087
>>> circuit[0].targets_copy()[1]
6979-
stim.GateTarget(stim.target_inv(1))
7088+
stim.target_inv(1)
69807089
"""
69817090
def __eq__(
69827091
self,

file_lists/test_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
src/stim.test.cc
22
src/stim/circuit/circuit.test.cc
3+
src/stim/circuit/circuit_instruction.test.cc
34
src/stim/circuit/gate_decomposition.test.cc
45
src/stim/circuit/gate_target.test.cc
56
src/stim/cmd/command_analyze_errors.test.cc

0 commit comments

Comments
 (0)