Source code for qlauncher.routines.qiskit.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_sampler_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 _get_transpiled_estimator_pubs(pubs: list[tuple], backend: BackendV1 | BackendV2, optimization_level: int = 2) -> list[tuple | QuantumCircuit]:
 24    new_pubs = []
 25    for pub in pubs:
 26        circuit, operator, *args = pub
 27        transp_circ: QuantumCircuit = transpile(circuit, backend, optimization_level=optimization_level)
 28        transp_op = operator.apply_layout(transp_circ.layout, num_qubits=transp_circ.num_qubits)
 29        pub = (transp_circ, transp_op, *args)
 30        new_pubs.append(pub)
 31    return new_pubs
 32
 33
 34def _assign_sampler_pubs(pubs: list[tuple | QuantumCircuit]) -> list[QuantumCircuit]:
 35    new_pubs = []
 36    for pub in pubs:
 37        if isinstance(pub, tuple):
 38            qc, *params = pub
 39            pub = qc.assign_parameters(*params)
 40        new_pubs.append(pub)
 41    return new_pubs
 42
 43
 44def _assign_estimator_pubs(pubs: list[tuple]) -> list[tuple]:
 45    new_pubs = []
 46    for pub in pubs:
 47        if len(pub) > 2:
 48            qc, observable, *params = pub
 49            pub = (qc.assign_parameters(*params), observable)
 50        new_pubs.append(pub)
 51    return new_pubs
 52
 53
[docs] 54def 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: 55 """ 56 Set chosen automatic behavior on a sampler instance. 57 58 Args: 59 sampler (AUTO_TRANSPILE_SAMPLER_TYPE): Compatible sampler instance 60 auto_transpile (bool, optional): Whether to automatically transpile to the samplers backend. Defaults to False. 61 auto_transpile_level (int, optional): What level of optimization to set. Defaults to 2. 62 auto_assign (bool, optional): Whether to automatically assign parameters in case of parameterized circuits. Defaults to False. 63 64 Returns: 65 AUTO_TRANSPILE_SAMPLER_TYPE: Same instance with modified run() method. 66 """ 67 func = sampler.run 68 69 def run_wrapper(pubs, *args, shots: int | None = None): 70 if auto_transpile: 71 pubs = _get_transpiled_sampler_pubs(pubs, sampler._backend, optimization_level=auto_transpile_level) 72 if auto_assign: 73 pubs = _assign_sampler_pubs(pubs) 74 75 return func(pubs, *args, shots=shots) 76 77 sampler.run = run_wrapper 78 return sampler
79 80
[docs] 81def 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: 82 """ 83 Set chosen automatic behavior on a estimator instance. 84 85 Args: 86 estimator (AUTO_TRANSPILE_ESTIMATOR_TYPE): Compatible estimator instance 87 auto_transpile (bool, optional): Whether to automatically transpile to the estimators backend. Defaults to False. 88 auto_transpile_level (int, optional): What level of optimization to set. Defaults to 2. 89 auto_assign (bool, optional): Whether to automatically assign parameters in case of parameterized circuits. Defaults to False. 90 91 Returns: 92 AUTO_TRANSPILE_ESTIMATOR_TYPE: Same instance with modified run() method. 93 """ 94 func = estimator.run 95 96 def run_wrapper(pubs, *args, precision: float | None = None): 97 if auto_transpile: 98 pubs = _get_transpiled_estimator_pubs(pubs, estimator._backend, optimization_level=auto_transpile_level) 99 if auto_assign: 100 pubs = _assign_estimator_pubs(pubs) 101 return func(pubs, *args, precision=precision) 102 estimator.run = run_wrapper 103 return estimator