Skip to content

Commit b0519b3

Browse files
authored
Convert cirq.Result to ABC and add ResultDict implementation (#4806)
This converts cirq.Result into an abstract base class which defines the interface provided by measurement result objects. We introduce a new class cirq.ResultDict which is the default implementation of this result type, based on a dict mapping string keys to array data. This will allow us to provide alternate implementations as needed, for example a result type that is based on a DataFrame and only converts to measurement dict on demand (cf #4774), or a result type that is based on experimental data (such as raw IQ data) and allows accessing this raw data while also converting to the standard measurements dict on demand (see #3868 for other possible Result implementations). Making this separation will also simplify the implementation of repeated measurement keys (#4274), since it will allow us to define the new interface for accessing data from repeated keys separately from the implementation of how this data is stored. Review: @95-martin-orion
1 parent 2c795d2 commit b0519b3

31 files changed

+502
-148
lines changed

Diff for: cirq-aqt/cirq_aqt/aqt_sampler.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ def run_sweep(
208208
)
209209
results = results.astype(bool)
210210
res_dict = {meas_name: results}
211-
trial_results.append(cirq.Result(params=param_resolver, measurements=res_dict))
211+
trial_results.append(cirq.ResultDict(params=param_resolver, measurements=res_dict))
212212
return trial_results
213213

214214

Diff for: cirq-core/cirq/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@
470470
flatten,
471471
flatten_with_params,
472472
flatten_with_sweep,
473+
ResultDict,
473474
Linspace,
474475
ListSweep,
475476
ParamDictType,

Diff for: cirq-core/cirq/contrib/quantum_volume/quantum_volume_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def test_sample_heavy_set():
7070

7171
sampler = Mock(spec=cirq.Simulator)
7272
# Construct a result that returns "1", "2", "3", "0"
73-
result = cirq.Result(
73+
result = cirq.ResultDict(
7474
params=cirq.ParamResolver({}),
7575
measurements={'mock': np.array([[0, 1], [1, 0], [1, 1], [0, 0]])},
7676
)
@@ -94,7 +94,7 @@ def test_sample_heavy_set_with_parity():
9494
# bitstring "10" is valid and heavy. The second "01" is valid and not
9595
# heavy. The third and fourth bitstrings "11" and "00" are not valid and
9696
# dropped.
97-
result = cirq.Result(
97+
result = cirq.ResultDict(
9898
params=cirq.ParamResolver({}),
9999
measurements={
100100
'0': np.array([[1], [0]]),

Diff for: cirq-core/cirq/json_resolver_cache.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ def _parallel_gate_op(gate, qubits):
144144
'TensoredConfusionMatrices': cirq.TensoredConfusionMatrices,
145145
'RepetitionsStoppingCriteria': cirq.work.RepetitionsStoppingCriteria,
146146
'ResetChannel': cirq.ResetChannel,
147-
'Result': cirq.Result,
147+
'Result': cirq.ResultDict, # Keep support for Cirq < 0.14.
148+
'ResultDict': cirq.ResultDict,
148149
'Rx': cirq.Rx,
149150
'Ry': cirq.Ry,
150151
'Rz': cirq.Rz,
@@ -158,7 +159,7 @@ def _parallel_gate_op(gate, qubits):
158159
'SympyCondition': cirq.SympyCondition,
159160
'TaggedOperation': cirq.TaggedOperation,
160161
'TiltedSquareLattice': cirq.TiltedSquareLattice,
161-
'TrialResult': cirq.Result, # keep support for Cirq < 0.11.
162+
'TrialResult': cirq.ResultDict, # keep support for Cirq < 0.11.
162163
'TwoQubitGateTabulation': cirq.TwoQubitGateTabulation,
163164
'_UnconstrainedDevice': cirq.devices.unconstrained_device._UnconstrainedDevice,
164165
'VarianceStoppingCriteria': cirq.work.VarianceStoppingCriteria,

Diff for: cirq-core/cirq/protocols/json_test_data/Result.repr

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[True, True, False, True, False], [False, True, True, False, False], [True, False, True, False, True]], dtype=bool)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int16)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int32)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint16)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint32)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint64)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8), 'n': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)})]
+297
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
[
2+
{
3+
"cirq_type": "ResultDict",
4+
"params": {
5+
"cirq_type": "ParamResolver",
6+
"param_dict": [
7+
[
8+
{
9+
"cirq_type": "sympy.Symbol",
10+
"name": "a"
11+
},
12+
0.5
13+
]
14+
]
15+
},
16+
"measurements": {
17+
"m": {
18+
"packed_digits": "d32a",
19+
"binary": true,
20+
"dtype": "bool",
21+
"shape": [
22+
3,
23+
5
24+
]
25+
}
26+
}
27+
},
28+
{
29+
"cirq_type": "ResultDict",
30+
"params": {
31+
"cirq_type": "ParamResolver",
32+
"param_dict": [
33+
[
34+
{
35+
"cirq_type": "sympy.Symbol",
36+
"name": "a"
37+
},
38+
0.5
39+
]
40+
]
41+
},
42+
"measurements": {
43+
"m": {
44+
"packed_digits": "d32a",
45+
"binary": true,
46+
"dtype": "uint8",
47+
"shape": [
48+
3,
49+
5
50+
]
51+
}
52+
}
53+
},
54+
{
55+
"cirq_type": "ResultDict",
56+
"params": {
57+
"cirq_type": "ParamResolver",
58+
"param_dict": [
59+
[
60+
{
61+
"cirq_type": "sympy.Symbol",
62+
"name": "a"
63+
},
64+
0.5
65+
]
66+
]
67+
},
68+
"measurements": {
69+
"m": {
70+
"packed_digits": "934e554d5059010076007b276465736372273a20277c6931272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000102030405060708",
71+
"binary": false,
72+
"dtype": "int8",
73+
"shape": [
74+
3,
75+
3
76+
]
77+
}
78+
}
79+
},
80+
{
81+
"cirq_type": "ResultDict",
82+
"params": {
83+
"cirq_type": "ParamResolver",
84+
"param_dict": [
85+
[
86+
{
87+
"cirq_type": "sympy.Symbol",
88+
"name": "a"
89+
},
90+
0.5
91+
]
92+
]
93+
},
94+
"measurements": {
95+
"m": {
96+
"packed_digits": "934e554d5059010076007b276465736372273a20273c6932272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000001000200030004000500060007000800",
97+
"binary": false,
98+
"dtype": "int16",
99+
"shape": [
100+
3,
101+
3
102+
]
103+
}
104+
}
105+
},
106+
{
107+
"cirq_type": "ResultDict",
108+
"params": {
109+
"cirq_type": "ParamResolver",
110+
"param_dict": [
111+
[
112+
{
113+
"cirq_type": "sympy.Symbol",
114+
"name": "a"
115+
},
116+
0.5
117+
]
118+
]
119+
},
120+
"measurements": {
121+
"m": {
122+
"packed_digits": "934e554d5059010076007b276465736372273a20273c6934272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000000000100000002000000030000000400000005000000060000000700000008000000",
123+
"binary": false,
124+
"dtype": "int32",
125+
"shape": [
126+
3,
127+
3
128+
]
129+
}
130+
}
131+
},
132+
{
133+
"cirq_type": "ResultDict",
134+
"params": {
135+
"cirq_type": "ParamResolver",
136+
"param_dict": [
137+
[
138+
{
139+
"cirq_type": "sympy.Symbol",
140+
"name": "a"
141+
},
142+
0.5
143+
]
144+
]
145+
},
146+
"measurements": {
147+
"m": {
148+
"packed_digits": "934e554d5059010076007b276465736372273a20273c6938272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000000000000000001000000000000000200000000000000030000000000000004000000000000000500000000000000060000000000000007000000000000000800000000000000",
149+
"binary": false,
150+
"dtype": "int64",
151+
"shape": [
152+
3,
153+
3
154+
]
155+
}
156+
}
157+
},
158+
{
159+
"cirq_type": "ResultDict",
160+
"params": {
161+
"cirq_type": "ParamResolver",
162+
"param_dict": [
163+
[
164+
{
165+
"cirq_type": "sympy.Symbol",
166+
"name": "a"
167+
},
168+
0.5
169+
]
170+
]
171+
},
172+
"measurements": {
173+
"m": {
174+
"packed_digits": "934e554d5059010076007b276465736372273a20277c7531272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000102030405060708",
175+
"binary": false,
176+
"dtype": "uint8",
177+
"shape": [
178+
3,
179+
3
180+
]
181+
}
182+
}
183+
},
184+
{
185+
"cirq_type": "ResultDict",
186+
"params": {
187+
"cirq_type": "ParamResolver",
188+
"param_dict": [
189+
[
190+
{
191+
"cirq_type": "sympy.Symbol",
192+
"name": "a"
193+
},
194+
0.5
195+
]
196+
]
197+
},
198+
"measurements": {
199+
"m": {
200+
"packed_digits": "934e554d5059010076007b276465736372273a20273c7532272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000001000200030004000500060007000800",
201+
"binary": false,
202+
"dtype": "uint16",
203+
"shape": [
204+
3,
205+
3
206+
]
207+
}
208+
}
209+
},
210+
{
211+
"cirq_type": "ResultDict",
212+
"params": {
213+
"cirq_type": "ParamResolver",
214+
"param_dict": [
215+
[
216+
{
217+
"cirq_type": "sympy.Symbol",
218+
"name": "a"
219+
},
220+
0.5
221+
]
222+
]
223+
},
224+
"measurements": {
225+
"m": {
226+
"packed_digits": "934e554d5059010076007b276465736372273a20273c7534272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000000000100000002000000030000000400000005000000060000000700000008000000",
227+
"binary": false,
228+
"dtype": "uint32",
229+
"shape": [
230+
3,
231+
3
232+
]
233+
}
234+
}
235+
},
236+
{
237+
"cirq_type": "ResultDict",
238+
"params": {
239+
"cirq_type": "ParamResolver",
240+
"param_dict": [
241+
[
242+
{
243+
"cirq_type": "sympy.Symbol",
244+
"name": "a"
245+
},
246+
0.5
247+
]
248+
]
249+
},
250+
"measurements": {
251+
"m": {
252+
"packed_digits": "934e554d5059010076007b276465736372273a20273c7538272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000000000000000001000000000000000200000000000000030000000000000004000000000000000500000000000000060000000000000007000000000000000800000000000000",
253+
"binary": false,
254+
"dtype": "uint64",
255+
"shape": [
256+
3,
257+
3
258+
]
259+
}
260+
}
261+
},
262+
{
263+
"cirq_type": "ResultDict",
264+
"params": {
265+
"cirq_type": "ParamResolver",
266+
"param_dict": [
267+
[
268+
{
269+
"cirq_type": "sympy.Symbol",
270+
"name": "a"
271+
},
272+
0.5
273+
]
274+
]
275+
},
276+
"measurements": {
277+
"m": {
278+
"packed_digits": "d32a",
279+
"binary": true,
280+
"dtype": "uint8",
281+
"shape": [
282+
3,
283+
5
284+
]
285+
},
286+
"n": {
287+
"packed_digits": "934e554d5059010076007b276465736372273a20273c6938272c2027666f727472616e5f6f72646572273a2046616c73652c20277368617065273a2028332c2033292c207d202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200a000000000000000001000000000000000200000000000000030000000000000004000000000000000500000000000000060000000000000007000000000000000800000000000000",
288+
"binary": false,
289+
"dtype": "int64",
290+
"shape": [
291+
3,
292+
3
293+
]
294+
}
295+
}
296+
}
297+
]
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[True, True, False, True, False], [False, True, True, False, False], [True, False, True, False, True]], dtype=bool)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int16)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int32)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint16)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint32)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint64)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8), 'n': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)})]
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[True, True, False, True, False], [False, True, True, False, False], [True, False, True, False, True]], dtype=np.bool)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int8)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int16)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int32)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint8)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint16)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint32)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint64)}), cirq.Result(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8), 'n': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)})]
1+
[cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[True, True, False, True, False], [False, True, True, False, False], [True, False, True, False, True]], dtype=np.bool)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int16)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int32)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint8)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint16)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint32)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.uint64)}), cirq.ResultDict(params=cirq.ParamResolver({sympy.Symbol('a'): 0.5}), measurements={'m': np.array([[1, 1, 0, 1, 0], [0, 1, 1, 0, 0], [1, 0, 1, 0, 1]], dtype=np.uint8), 'n': np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=np.int64)})]

Diff for: cirq-core/cirq/sim/clifford/stabilizer_sampler.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def run_sweep(
4848
resolved_circuit,
4949
repetitions=repetitions,
5050
)
51-
results.append(cirq.Result(params=param_resolver, measurements=measurements))
51+
results.append(cirq.ResultDict(params=param_resolver, measurements=measurements))
5252
return results
5353

5454
def _run(self, circuit: 'cirq.AbstractCircuit', repetitions: int) -> Dict[str, np.ndarray]:

0 commit comments

Comments
 (0)