From 06b0bdffc39d530bb7ed6cb7ebb12c434cef1c6d Mon Sep 17 00:00:00 2001 From: David McKay Date: Fri, 27 Sep 2024 03:12:02 -0400 Subject: [PATCH] fit lint errors, upgrade pylint, fix tomo bug --- .../framework/base_experiment.py | 38 ++++++++++--------- .../framework/experiment_data.py | 32 ++++++++-------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/qiskit_experiments/framework/base_experiment.py b/qiskit_experiments/framework/base_experiment.py index 7dd8b715cb..551fcce58c 100644 --- a/qiskit_experiments/framework/base_experiment.py +++ b/qiskit_experiments/framework/base_experiment.py @@ -23,6 +23,7 @@ from qiskit.exceptions import QiskitError from qiskit.qobj.utils import MeasLevel from qiskit.providers.options import Options +from qiskit_ibm_runtime import SamplerV2 as Sampler from qiskit_experiments.framework import BackendData from qiskit_experiments.framework.store_init_args import StoreInitArgs from qiskit_experiments.framework.base_analysis import BaseAnalysis @@ -30,8 +31,6 @@ from qiskit_experiments.framework.configs import ExperimentConfig from qiskit_experiments.database_service import Qubit -from qiskit_ibm_runtime import SamplerV2 as Sampler - class BaseExperiment(ABC, StoreInitArgs): """Abstract base class for experiments.""" @@ -42,7 +41,7 @@ def __init__( analysis: Optional[BaseAnalysis] = None, backend: Optional[Backend] = None, experiment_type: Optional[str] = None, - use_sampler: Options[bool] = False + use_sampler: Options[bool] = False, ): """Initialize the experiment object. @@ -218,6 +217,7 @@ def run( it contains one. timeout: Time to wait for experiment jobs to finish running before cancelling. + use_sampler: Use the SamplerV2 to run the experiment run_options: backend runtime options used for circuit execution. Returns: @@ -359,29 +359,31 @@ def _run_jobs(self, circuits: List[QuantumCircuit], **run_options) -> List[Job]: if self._use_sampler: sampler = Sampler(self.backend) - #have to hand set some of these options - #see https://docs.quantum.ibm.com/api/qiskit-ibm-runtime/qiskit_ibm_runtime.options.SamplerExecutionOptionsV2 - if 'init_qubits' in run_options: - sampler.options.execution.init_qubits = run_options['init_qubits'] - if 'rep_delay' in run_options: - sampler.options.execution.rep_delay = run_options['rep_delay'] - if 'meas_level' in run_options: - if run_options['meas_level'] == 2: + # have to hand set some of these options + # see https://docs.quantum.ibm.com/api/qiskit-ibm-runtime + # /qiskit_ibm_runtime.options.SamplerExecutionOptionsV2 + if "init_qubits" in run_options: + sampler.options.execution.init_qubits = run_options["init_qubits"] + if "rep_delay" in run_options: + sampler.options.execution.rep_delay = run_options["rep_delay"] + if "meas_level" in run_options: + if run_options["meas_level"] == 2: sampler.options.execution.meas_type = "classified" - elif run_options['meas_level'] == 1: - if 'meas_return' in run_options: - if run_options['meas_return'] == 'avg': + elif run_options["meas_level"] == 1: + if "meas_return" in run_options: + if run_options["meas_return"] == "avg": sampler.options.execution.meas_type = "avg_kerneled" else: sampler.options.execution.meas_type = "kerneled" else: - #assume this is what is wanted if no meas return specified + # assume this is what is wanted if no meas return specified sampler.options.execution.meas_type = "kerneled" else: - raise QiskitError('Only meas level 1 + 2 supported by sampler') + raise QiskitError("Only meas level 1 + 2 supported by sampler") - - jobs = [sampler.run(circs, shots=run_options.get('shots', None)) for circs in job_circuits] + jobs = [ + sampler.run(circs, shots=run_options.get("shots", None)) for circs in job_circuits + ] else: jobs = [self.backend.run(circs, **run_options) for circs in job_circuits] diff --git a/qiskit_experiments/framework/experiment_data.py b/qiskit_experiments/framework/experiment_data.py index 93628e9b03..8c2662e892 100644 --- a/qiskit_experiments/framework/experiment_data.py +++ b/qiskit_experiments/framework/experiment_data.py @@ -38,6 +38,7 @@ from qiskit.exceptions import QiskitError from qiskit.providers import Job, Backend, Provider from qiskit.utils.deprecation import deprecate_arg +from qiskit.primitives import BitArray, SamplerPubResult from qiskit_ibm_experiment import ( IBMExperimentService, @@ -45,6 +46,7 @@ AnalysisResultData as AnalysisResultDataclass, ResultQuality, ) + from qiskit_experiments.framework.json import ExperimentEncoder, ExperimentDecoder from qiskit_experiments.database_service.utils import ( plot_to_svg_bytes, @@ -68,8 +70,6 @@ from .containers.figure_data import FigureData, FigureType -from qiskit.primitives import BitArray, SamplerPubResult - if TYPE_CHECKING: # There is a cyclical dependency here, but the name needs to exist for # Sphinx on Python 3.9+ to link type hints correctly. The gating on @@ -987,8 +987,8 @@ def _add_result_data(self, result: Result, job_id: Optional[str] = None) -> None job_id: The id of the job the result came from. If `None`, the job id in `result` is used. """ - if hasattr(result, 'results'): - #backend run results + if hasattr(result, "results"): + # backend run results if job_id is None: job_id = result.job_id if job_id not in self._jobs: @@ -1011,9 +1011,9 @@ def _add_result_data(self, result: Result, job_id: Optional[str] = None) -> None data["meas_return"] = expr_result.meas_return self._result_data.append(data) else: - #sampler results + # sampler results if job_id is None: - raise QiskitError('job_id must be provided, not available in the sampler result') + raise QiskitError("job_id must be provided, not available in the sampler result") if job_id not in self._jobs: self._jobs[job_id] = None self.job_ids.append(job_id) @@ -1022,22 +1022,22 @@ def _add_result_data(self, result: Result, job_id: Optional[str] = None) -> None # Sampler results are a list for i, _ in enumerate(result): data = {} - #convert to a Sampler Pub Result (can remove this later when the bug is fixed) + # convert to a Sampler Pub Result (can remove this later when the bug is fixed) testres = SamplerPubResult(result[i].data, result[i].metadata) data["job_id"] = job_id - if type(testres.data[next(iter(testres.data))]) is BitArray: - #bit results so has counts + if isinstance(testres.data[next(iter(testres.data))], BitArray): + # bit results so has counts data["meas_level"] = 2 - data["meas_return"] = 'avg' - #join the data + data["meas_return"] = "avg" + # join the data data["counts"] = testres.join_data(testres.data.keys()).get_counts() - #number of shots + # number of shots data["shots"] = testres.data[next(iter(testres.data))].num_shots else: - raise QiskitError("Sampler with meas level 1 support TBD") - - data["metadata"] = testres.metadata['circuit_metadata'] - + raise QiskitError("Sampler with meas level 1 support TBD") + + data["metadata"] = testres.metadata["circuit_metadata"] + self._result_data.append(data) def _retrieve_data(self):