diff --git a/qiskit_experiments/curve_analysis/curve_analysis.py b/qiskit_experiments/curve_analysis/curve_analysis.py index 09949ba329..66e86a96ad 100644 --- a/qiskit_experiments/curve_analysis/curve_analysis.py +++ b/qiskit_experiments/curve_analysis/curve_analysis.py @@ -21,13 +21,12 @@ import inspect import warnings from abc import ABC -from typing import Any, Dict, List, Tuple, Callable, Union, Optional +from typing import Dict, List, Tuple, Callable, Union, Optional import numpy as np import uncertainties from uncertainties import unumpy as unp -from qiskit.providers import Backend from qiskit.utils import detach_prefix from qiskit_experiments.curve_analysis.curve_data import ( CurveData, @@ -256,6 +255,9 @@ def __init__(self): #: List[CurveData]: Processed experiment data set. self.__processed_data_set = list() + #: List[int]: Index of physical qubits + self._physical_qubits = None + @classmethod def _fit_params(cls) -> List[str]: """Return a list of fitting parameters. @@ -701,6 +703,10 @@ def _data( raise AnalysisError(f"Specified series {series_name} is not defined in this analysis.") + @property + def _num_qubits(self) -> int: + return len(self._physical_qubits) + def _run_analysis( self, experiment_data: ExperimentData ) -> Tuple[List[AnalysisResultData], List["pyplot.Figure"]]: @@ -732,9 +738,7 @@ def _run_analysis( # get experiment metadata try: - physical_qubits = experiment_data.metadata["physical_qubits"] - setattr(self, "_physical_qubits", physical_qubits) - setattr(self, "_num_qubits", len(physical_qubits)) + self._physical_qubits = experiment_data.metadata["physical_qubits"] except AttributeError: pass diff --git a/qiskit_experiments/library/randomized_benchmarking/interleaved_rb_experiment.py b/qiskit_experiments/library/randomized_benchmarking/interleaved_rb_experiment.py index 02bec38083..e4c6679563 100644 --- a/qiskit_experiments/library/randomized_benchmarking/interleaved_rb_experiment.py +++ b/qiskit_experiments/library/randomized_benchmarking/interleaved_rb_experiment.py @@ -143,9 +143,11 @@ def _set_interleaved_element(self, interleaved_element): ) ) from error + @classmethod def _default_experiment_options(cls) -> Options: options = super()._default_experiment_options() - # Computation of EPG is not necessary for IRB. This will drastically reduce overhead of ops counting. + # Computation of EPG is not necessary for IRB. + # This will drastically reduce overhead of ops counting. options.gate_error_ratio = "skip" return options diff --git a/qiskit_experiments/library/randomized_benchmarking/rb_analysis.py b/qiskit_experiments/library/randomized_benchmarking/rb_analysis.py index fe14e00ae7..af361c5128 100644 --- a/qiskit_experiments/library/randomized_benchmarking/rb_analysis.py +++ b/qiskit_experiments/library/randomized_benchmarking/rb_analysis.py @@ -194,7 +194,11 @@ def _extra_database_entry(self, fit_data: curve.FitData) -> List[AnalysisResultD ) # Calculate EPG - if self.options.gate_error_ratio != "skip": + + if ( + self.options.gate_counts_per_clifford is not None + and self.options.gate_error_ratio != "skip" + ): num_qubits = len(self._physical_qubits) if num_qubits == 1: @@ -244,7 +248,8 @@ def _run_analysis( # This could return errorneous error ratio. # Deprecation warning is triggered on RBUtils. gate_error_ratio = RBUtils.get_error_dict_from_backend( - backend=experiment_data.backend, qubits=experiment_data.metadata["physical_qubits"], + backend=experiment_data.backend, + qubits=experiment_data.metadata["physical_qubits"], ) self.set_options(gate_error_ratio=gate_error_ratio) diff --git a/qiskit_experiments/library/randomized_benchmarking/rb_experiment.py b/qiskit_experiments/library/randomized_benchmarking/rb_experiment.py index ea5ab10ddf..6dcc12631b 100644 --- a/qiskit_experiments/library/randomized_benchmarking/rb_experiment.py +++ b/qiskit_experiments/library/randomized_benchmarking/rb_experiment.py @@ -12,7 +12,7 @@ """ Standard RB Experiment class. """ -from typing import Union, Iterable, Optional, List, Sequence, Dict +from typing import Union, Iterable, Optional, List, Sequence from collections import defaultdict import numpy as np @@ -24,7 +24,7 @@ from qiskit.circuit import Gate from qiskit.providers.backend import Backend -from qiskit_experiments.framework import BaseExperiment, ParallelExperiment, Options +from qiskit_experiments.framework import BaseExperiment, Options from qiskit_experiments.framework.restless_mixin import RestlessMixin from .rb_analysis import RBAnalysis from .clifford_utils import CliffordUtils @@ -124,15 +124,17 @@ def _default_experiment_options(cls) -> Options: used to initialize ``numpy.random.default_rng`` when generating circuits. The ``default_rng`` will be initialized with this seed value everytime :meth:`circuits` is called. - gate_error_ratio (Union[str, Dict[Tuple[int, str], float]]): The assumption of error ratio of - basis gates constituting RB Clifford sequences. When this value is set, - the error per gate (EPG) values are computed from the estimated error per Clifford (EPC) parameter - in the RB analysis. This value defaults to "default". When explicit gate error ratio is not - provided, a gate error ratio dictionary of typical basis gates for superconducting processor is + gate_error_ratio (Union[str, Dict[Tuple[int, str], float]]): The assumption of error ratio + of basis gates constituting RB Clifford sequences. When this value is set, + the error per gate (EPG) values are computed from the estimated + error per Clifford (EPC) parameter in the RB analysis. + This value defaults to "default". When explicit gate error ratio is not provided, + a gate error ratio dictionary of typical basis gates for superconducting processor is implicitly created and set, i.e. ``(sx, x, rz)`` for single qubit RB, - and ``(cx, )`` for two qubit RB. No default gate definition for more than three qubit RB. + and ``(cx, )`` for two qubit RB. + No default gate definition for more than three qubit RB. The dictionary is keyed on a tuple of qubit index and string label of instruction. - Defined instruction should appear in the basis gates configurations in the transpile options. + Defined instructions should appear in the ``basis_gates`` in the transpile options. If this value is set to ``"skip"``, the computation of EPG values is skipped. """ options = super()._default_experiment_options() @@ -228,6 +230,7 @@ def _generate_circuit( circuits.append(rb_circ) return circuits + @classmethod def _default_transpile_options(cls) -> Options: options = super()._default_experiment_options() @@ -256,14 +259,13 @@ def _finalize(self): if gate_error_ratio != "skip": - gates_in_estimates = set( - q_gate_tup[1] for q_gate_tup in gate_error_ratio.keys() - ) + gates_in_estimates = set(q_gate_tup[1] for q_gate_tup in gate_error_ratio.keys()) # Validate if assumed gates are a part to basis gates in the transpile options basis_gates = set(self.transpile_options.basis_gates) if not basis_gates.issuperset(gates_in_estimates): raise ValueError( - f"Assumed gates {gates_in_estimates} is not valid subset of basis gates {basis_gates}." + f"Assumed gates {gates_in_estimates} is not valid " + f"subset of basis gates {basis_gates}." ) # Directly copy the value to experiment data metadata via instance state