13
13
# limitations under the License.
14
14
"""Abstract base class for things sampling quantum circuits."""
15
15
16
- import abc
17
16
import collections
18
17
from typing import Dict , FrozenSet , List , Optional , Sequence , Tuple , TYPE_CHECKING , Union
19
18
19
+ import duet
20
20
import pandas as pd
21
21
22
- from cirq import ops , protocols , study
22
+ from cirq import ops , protocols , study , value
23
23
from cirq .work .observable_measurement import (
24
24
measure_observables ,
25
25
RepetitionsStoppingCriteria ,
31
31
import cirq
32
32
33
33
34
- class Sampler (metaclass = abc . ABCMeta ):
34
+ class Sampler (metaclass = value . ABCMetaImplementAnyOneOf ):
35
35
"""Something capable of sampling quantum circuits. Simulator or hardware."""
36
36
37
37
def run (
@@ -177,7 +177,19 @@ def sample(
177
177
178
178
return pd .concat (results )
179
179
180
- @abc .abstractmethod
180
+ def _run_sweep_impl (
181
+ self , program : 'cirq.AbstractCircuit' , params : 'cirq.Sweepable' , repetitions : int = 1
182
+ ) -> Sequence ['cirq.Result' ]:
183
+ """Implements run_sweep using run_sweep_async"""
184
+ return duet .run (self .run_sweep_async , program , params , repetitions )
185
+
186
+ async def _run_sweep_async_impl (
187
+ self , program : 'cirq.AbstractCircuit' , params : 'cirq.Sweepable' , repetitions : int = 1
188
+ ) -> Sequence ['cirq.Result' ]:
189
+ """Implements run_sweep_async using run_sweep"""
190
+ return self .run_sweep (program , params = params , repetitions = repetitions )
191
+
192
+ @value .alternative (requires = 'run_sweep_async' , implementation = _run_sweep_impl )
181
193
def run_sweep (
182
194
self , program : 'cirq.AbstractCircuit' , params : 'cirq.Sweepable' , repetitions : int = 1
183
195
) -> Sequence ['cirq.Result' ]:
@@ -200,6 +212,7 @@ def run_sweep(
200
212
Result list for this run; one for each possible parameter resolver.
201
213
"""
202
214
215
+ @value .alternative (requires = 'run_sweep' , implementation = _run_sweep_async_impl )
203
216
async def run_sweep_async (
204
217
self , program : 'cirq.AbstractCircuit' , params : 'cirq.Sweepable' , repetitions : int = 1
205
218
) -> Sequence ['cirq.Result' ]:
@@ -217,13 +230,12 @@ async def run_sweep_async(
217
230
Returns:
218
231
Result list for this run; one for each possible parameter resolver.
219
232
"""
220
- return self .run_sweep (program , params = params , repetitions = repetitions )
221
233
222
234
def run_batch (
223
235
self ,
224
236
programs : Sequence ['cirq.AbstractCircuit' ],
225
- params_list : Optional [List ['cirq.Sweepable' ]] = None ,
226
- repetitions : Union [int , List [int ]] = 1 ,
237
+ params_list : Optional [Sequence ['cirq.Sweepable' ]] = None ,
238
+ repetitions : Union [int , Sequence [int ]] = 1 ,
227
239
) -> Sequence [Sequence ['cirq.Result' ]]:
228
240
"""Runs the supplied circuits.
229
241
@@ -263,6 +275,34 @@ def run_batch(
263
275
ValueError: If length of `programs` is not equal to the length
264
276
of `params_list` or the length of `repetitions`.
265
277
"""
278
+ params_list , repetitions = self ._normalize_batch_args (programs , params_list , repetitions )
279
+ return [
280
+ self .run_sweep (circuit , params = params , repetitions = repetitions )
281
+ for circuit , params , repetitions in zip (programs , params_list , repetitions )
282
+ ]
283
+
284
+ async def run_batch_async (
285
+ self ,
286
+ programs : Sequence ['cirq.AbstractCircuit' ],
287
+ params_list : Optional [Sequence ['cirq.Sweepable' ]] = None ,
288
+ repetitions : Union [int , Sequence [int ]] = 1 ,
289
+ ) -> Sequence [Sequence ['cirq.Result' ]]:
290
+ """Runs the supplied circuits.
291
+
292
+ This is an asynchronous version of `run_batch`; see full docs there.
293
+ """
294
+ params_list , repetitions = self ._normalize_batch_args (programs , params_list , repetitions )
295
+ return [
296
+ await self .run_sweep_async (circuit , params = params , repetitions = repetitions )
297
+ for circuit , params , repetitions in zip (programs , params_list , repetitions )
298
+ ]
299
+
300
+ def _normalize_batch_args (
301
+ self ,
302
+ programs : Sequence ['cirq.AbstractCircuit' ],
303
+ params_list : Optional [Sequence ['cirq.Sweepable' ]] = None ,
304
+ repetitions : Union [int , Sequence [int ]] = 1 ,
305
+ ) -> Tuple [Sequence ['cirq.Sweepable' ], Sequence [int ]]:
266
306
if params_list is None :
267
307
params_list = [None ] * len (programs )
268
308
if len (programs ) != len (params_list ):
@@ -277,10 +317,7 @@ def run_batch(
277
317
'len(programs) and len(repetitions) must match. '
278
318
f'Got { len (programs )} and { len (repetitions )} .'
279
319
)
280
- return [
281
- self .run_sweep (circuit , params = params , repetitions = repetitions )
282
- for circuit , params , repetitions in zip (programs , params_list , repetitions )
283
- ]
320
+ return params_list , repetitions
284
321
285
322
def sample_expectation_values (
286
323
self ,
0 commit comments