Source code for quantum_launcher.routines.qiskit_routines.backends.utils

 1from typing import TypeVar
 2from qiskit import QuantumCircuit, transpile
 3from qiskit.providers.backend import BackendV1, BackendV2
 4from qiskit.primitives import BackendSamplerV2, BackendEstimatorV2
 5from qiskit_ibm_runtime import EstimatorV2, SamplerV2
 6
 7
 8AUTO_TRANSPILE_SAMPLER_TYPE = TypeVar('AUTO_TRANSPILE_SAMPLER_TYPE', BackendSamplerV2, SamplerV2)
 9AUTO_TRANSPILE_ESTIMATOR_TYPE = TypeVar('AUTO_TRANSPILE_ESTIMATOR_TYPE', BackendEstimatorV2, EstimatorV2)
10
11
12def _get_transpiled_pubs(pubs: list[tuple | QuantumCircuit], backend: BackendV1 | BackendV2, optimization_level: int = 2) -> list[tuple | QuantumCircuit]:
13    new_pubs = []
14    for pub in pubs:
15        if isinstance(pub, QuantumCircuit):
16            pub = transpile(pub, backend, optimization_level=optimization_level)
17        elif isinstance(pub, tuple):
18            pub = (transpile(pub[0], backend, optimization_level=optimization_level), *pub[1:])
19        new_pubs.append(pub)
20    return new_pubs
21
22
23def _assign_sampler_pubs(pubs: list[tuple | QuantumCircuit]) -> list[QuantumCircuit]:
24    new_pubs = []
25    for pub in pubs:
26        if isinstance(pub, tuple):
27            qc, *params = pub
28            pub = qc.assign_parameters(*params)
29        new_pubs.append(pub)
30    return new_pubs
31
32
33def _assign_estimator_pubs(pubs: list[tuple]) -> list[tuple]:
34    new_pubs = []
35    for pub in pubs:
36        if len(pub) > 2:
37            qc, observable, *params = pub
38            pub = (qc.assign_parameters(*params), observable)
39        new_pubs.append(pub)
40    return new_pubs
41
42
[docs] 43def set_sampler_auto_run_behavior(sampler: AUTO_TRANSPILE_SAMPLER_TYPE, auto_transpile: bool = False, auto_transpile_level: int = 2, auto_assign: bool = False) -> AUTO_TRANSPILE_SAMPLER_TYPE: 44 """ 45 Set chosen automatic behavior on a sampler instance. 46 47 Args: 48 sampler (AUTO_TRANSPILE_SAMPLER_TYPE): Compatible sampler instance 49 auto_transpile (bool, optional): Whether to automatically transpile to the samplers backend. Defaults to False. 50 auto_transpile_level (int, optional): What level of optimization to set. Defaults to 2. 51 auto_assign (bool, optional): Whether to automatically assign parameters in case of parameterized circuits. Defaults to False. 52 53 Returns: 54 AUTO_TRANSPILE_SAMPLER_TYPE: Same instance with modified run() method. 55 """ 56 func = sampler.run 57 58 def run_wrapper(pubs, *args, shots: int | None = None): 59 if auto_transpile: 60 pubs = _get_transpiled_pubs(pubs, sampler._backend, optimization_level=auto_transpile_level) 61 if auto_assign: 62 pubs = _assign_sampler_pubs(pubs) 63 64 return func(pubs, *args, shots=shots) 65 66 sampler.run = run_wrapper 67 return sampler
68 69
[docs] 70def set_estimator_auto_run_behavior(estimator: AUTO_TRANSPILE_ESTIMATOR_TYPE, auto_transpile: bool = False, auto_transpile_level: int = 2, auto_assign: bool = False) -> AUTO_TRANSPILE_ESTIMATOR_TYPE: 71 """ 72 Set chosen automatic behavior on a estimator instance. 73 74 Args: 75 estimator (AUTO_TRANSPILE_ESTIMATOR_TYPE): Compatible estimator instance 76 auto_transpile (bool, optional): Whether to automatically transpile to the estimators backend. Defaults to False. 77 auto_transpile_level (int, optional): What level of optimization to set. Defaults to 2. 78 auto_assign (bool, optional): Whether to automatically assign parameters in case of parameterized circuits. Defaults to False. 79 80 Returns: 81 AUTO_TRANSPILE_ESTIMATOR_TYPE: Same instance with modified run() method. 82 """ 83 func = estimator.run 84 85 def run_wrapper(pubs, *args, precision: float | None = None): 86 if auto_transpile: 87 pubs = _get_transpiled_pubs(pubs, estimator._backend, optimization_level=auto_transpile_level) 88 if auto_assign: 89 pubs = _assign_estimator_pubs(pubs) 90 return func(pubs, *args, precision=precision) 91 estimator.run = run_wrapper 92 return estimator