From 3c53f5a7b5a34ac3a3e633459ebf2899a327adfc Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Thu, 11 Nov 2021 17:42:53 +0200 Subject: [PATCH 01/16] Readout angle experiment --- .../framework/composite/composite_analysis.py | 9 +++++++++ qiskit_experiments/library/__init__.py | 2 ++ qiskit_experiments/library/characterization/__init__.py | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/qiskit_experiments/framework/composite/composite_analysis.py b/qiskit_experiments/framework/composite/composite_analysis.py index 33bdf9e931..28f8e9fa75 100644 --- a/qiskit_experiments/framework/composite/composite_analysis.py +++ b/qiskit_experiments/framework/composite/composite_analysis.py @@ -13,6 +13,7 @@ Composite Experiment Analysis class. """ +import numpy as np from typing import List, Dict from qiskit.result import marginal_counts from qiskit_experiments.framework import BaseAnalysis, ExperimentData, AnalysisResultData @@ -160,6 +161,14 @@ def _marginalize_data(self, composite_data: List[Dict]) -> List[Dict]: sub_data["counts"] = marginal_counts(datum["counts"], composite_clbits[i]) else: sub_data["counts"] = datum["counts"] + print("hey", datum) + if "memory" in datum: + if composite_clbits is not None: + print(composite_clbits) + print(np.array(datum["memory"])[composite_clbits[i]]) + sub_data["memory"] = (np.array(datum["memory"])[composite_clbits[i]]).tolist() + else: + sub_data["memory"] = datum["memory"] marginalized_data[index].append(sub_data) # Sort by index diff --git a/qiskit_experiments/library/__init__.py b/qiskit_experiments/library/__init__.py index b23ab5e9ef..a1fb5ea92b 100644 --- a/qiskit_experiments/library/__init__.py +++ b/qiskit_experiments/library/__init__.py @@ -70,6 +70,7 @@ ~characterization.Rabi ~characterization.EFRabi ~characterization.RamseyXY + ~characterization.ReadoutAngle .. _calibration: @@ -129,6 +130,7 @@ class instance to manage parameters and pulse schedules. FineXAmplitude, FineSXAmplitude, RamseyXY, + ReadoutAngle ) from .randomized_benchmarking import StandardRB, InterleavedRB from .tomography import StateTomography, ProcessTomography diff --git a/qiskit_experiments/library/characterization/__init__.py b/qiskit_experiments/library/characterization/__init__.py index c583f03dd3..8464d83d86 100644 --- a/qiskit_experiments/library/characterization/__init__.py +++ b/qiskit_experiments/library/characterization/__init__.py @@ -36,6 +36,7 @@ FineSXAmplitude RamseyXY RoughDrag + ReadoutAngle Analysis @@ -48,6 +49,7 @@ T1Analysis T2RamseyAnalysis CrossResonanceHamiltonianAnalysis + ReadoutAngleAnalysis """ @@ -64,3 +66,5 @@ from .fine_amplitude import FineAmplitude, FineXAmplitude, FineSXAmplitude from .ramsey_xy import RamseyXY from .drag import RoughDrag +from .readout_angle import ReadoutAngle +from .readout_angle_analysis import ReadoutAngleAnalysis From 4db958100301a544bac6c63e726d75c08422b1f6 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Thu, 11 Nov 2021 17:44:12 +0200 Subject: [PATCH 02/16] readout angle files --- .../library/characterization/readout_angle.py | 98 +++++++++++++++++++ .../readout_angle_analysis.py | 39 ++++++++ test/test_readout_angle.py | 82 ++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 qiskit_experiments/library/characterization/readout_angle.py create mode 100644 qiskit_experiments/library/characterization/readout_angle_analysis.py create mode 100644 test/test_readout_angle.py diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py new file mode 100644 index 0000000000..6ad5b4a63a --- /dev/null +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -0,0 +1,98 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +""" +Readout Angle Experiment class. +""" + +from typing import List, Optional, Union +import numpy as np + +from qiskit.circuit import QuantumCircuit +from qiskit.qobj.utils import MeasLevel +from qiskit.providers.backend import Backend +from qiskit.test.mock import FakeBackend + +from qiskit_experiments.framework import BaseExperiment, Options, fix_class_docs +from qiskit_experiments.library.characterization.readout_angle_analysis import ReadoutAngleAnalysis + + +@fix_class_docs +class ReadoutAngle(BaseExperiment): + r""" + Readout angle experiment class + + # section: overview + + Design and analyze experiments for estimating readout angle of the qubit. + + Each experiment consists of the following steps: + + 1. Circuits generation: two circuits, the first circuit measures the qubit + in the ground state, the second circuit sets the qubit in the excited state + and measures it. Measurements are in level 1 (kerneled). + + 2. Backend execution: actually running the circuits on the device + (or a simulator that supports level 1 measurements). + + 3. Analysis of results: return the average of the centers of the two angles. + + """ + + __analysis_class__ = ReadoutAngleAnalysis + + @classmethod + def _default_run_options(cls) -> Options: + """Default run options.""" + options = super()._default_run_options() + + options.meas_level = MeasLevel.KERNELED + options.meas_return = "avg" + + return options + + def __init__( + self, + qubit: int, + backend: Optional[Backend] = None, + ): + """ + Initialize the readout angle experiment class + + Args: + qubit: the qubit whose readout angle is to be estimated + backend: Optional, the backend to run the experiment on. + """ + # Initialize base experiment + super().__init__([qubit], backend=backend) + + def circuits(self) -> List[QuantumCircuit]: + """ + Return a list of experiment circuits + + Returns: + The experiment circuits + """ + circ0 = QuantumCircuit(1, 1) + circ0.measure(0, 0) + + circ1 = QuantumCircuit(1, 1) + circ1.x(0) + circ1.measure(0, 0) + + for i, circ in enumerate([circ0, circ1]): + circ.metadata = { + "experiment_type": self._type, + "qubit": self.physical_qubits[0], + "xval": i, + } + + return [circ0, circ1] diff --git a/qiskit_experiments/library/characterization/readout_angle_analysis.py b/qiskit_experiments/library/characterization/readout_angle_analysis.py new file mode 100644 index 0000000000..5716d9a61d --- /dev/null +++ b/qiskit_experiments/library/characterization/readout_angle_analysis.py @@ -0,0 +1,39 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +""" +Readout Angle Analysis class. +""" + +import numpy as np + +from qiskit_experiments.framework import BaseAnalysis, AnalysisResultData + + +class ReadoutAngleAnalysis(BaseAnalysis): + def _run_analysis(self, experiment_data, **kwargs): + print("hi", experiment_data.data(0)) + center0 = complex(*experiment_data.data(0)["memory"][0]) + center1 = complex(*experiment_data.data(1)["memory"][0]) + print(center0, center1) + + angle = (np.angle(center0) + np.angle(center1)) / 2 + if np.abs(np.angle(center0) - np.angle(center1)) > np.pi: + angle += np.pi + + analysis_results = [AnalysisResultData( + name="ReadoutAngle", + value=angle + )] + + print(analysis_results[0]) + return analysis_results, [] + diff --git a/test/test_readout_angle.py b/test/test_readout_angle.py new file mode 100644 index 0000000000..e6fe725d68 --- /dev/null +++ b/test/test_readout_angle.py @@ -0,0 +1,82 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2021. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +""" +Test readout angle experiment +""" + +import numpy as np + +from qiskit.test import QiskitTestCase +from qiskit_experiments.framework import ExperimentData, ParallelExperiment +from qiskit_experiments.library import ReadoutAngle +from qiskit_experiments.library.characterization import ReadoutAngleAnalysis +from qiskit_experiments.test.mock_iq_backend import MockIQBackend + +class ReadoutAngleBackend(MockIQBackend): + def _compute_probability(self, circ): + return 1 - circ.metadata["xval"] + +class TestReadoutAngle(QiskitTestCase): + """ + Test the readout angle experiment + """ + + def test_readout_angle_end2end(self): + """ + Test readout angle experiment using a simulator. + """ + backend = ReadoutAngleBackend(iq_cluster_centers=(5.0, 5.0, -3.0, 3.0)) + exp = ReadoutAngle(0) + expdata = exp.run(backend, shots=100000).block_for_results() + res = expdata.analysis_results(0) + self.assertAlmostEqual(res.value, np.pi/2, places=2) + + def test_readout_angle_parallel(self): + """ + Test parallel experiments of readout angle using a simulator. + """ + backend = ReadoutAngleBackend(iq_cluster_centers=(5.0, 5.0, -3.0, 3.0)) + exp2 = ReadoutAngle(2) + exp0 = ReadoutAngle(0) + parexp = ParallelExperiment([exp2, exp0]) + expdata = parexp.run(backend, shots=100000).block_for_results() + + for i in range(2): + res = expdata.child_data(i).analysis_results(0) + self.assertAlmostEqual(res, np.pi/2, places=2) + + def test_t1_parallel_different_analysis_options(self): + """ + Test parallel experiments of T1 using a simulator, for the case where + the sub-experiments have different analysis options + """ + + t1 = 25 + delays = list(range(1, 40, 3)) + + exp0 = T1(0, delays) + exp0.set_analysis_options(p0={"tau": 30}) + exp1 = T1(1, delays) + exp1.set_analysis_options(p0={"tau": 1000000}) + + par_exp = ParallelExperiment([exp0, exp1]) + res = par_exp.run(T1Backend([t1, t1])) + res.block_for_results() + + sub_res = [] + for i in range(2): + sub_res.append(res.child_data(i).analysis_results("T1")) + + self.assertEqual(sub_res[0].quality, "good") + self.assertAlmostEqual(sub_res[0].value.value, t1, delta=3) + self.assertEqual(sub_res[1].quality, "bad") + From 8486d352f75b22f979e2bfb28579f4cfa04d86eb Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 10:15:48 +0200 Subject: [PATCH 03/16] removed fix_class_docs --- qiskit_experiments/library/characterization/readout_angle.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py index 6ad5b4a63a..d734183f60 100644 --- a/qiskit_experiments/library/characterization/readout_angle.py +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -21,11 +21,10 @@ from qiskit.providers.backend import Backend from qiskit.test.mock import FakeBackend -from qiskit_experiments.framework import BaseExperiment, Options, fix_class_docs +from qiskit_experiments.framework import BaseExperiment, Options from qiskit_experiments.library.characterization.readout_angle_analysis import ReadoutAngleAnalysis -@fix_class_docs class ReadoutAngle(BaseExperiment): r""" Readout angle experiment class From 5a749dbbbabf79726f7bc3b1f85a2b8b5e88e9c3 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 12:40:50 +0200 Subject: [PATCH 04/16] bug fix in composite save --- qiskit_experiments/framework/experiment_data.py | 9 ++++++--- test/test_t1.py | 9 +++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/qiskit_experiments/framework/experiment_data.py b/qiskit_experiments/framework/experiment_data.py index 4831a8a8ce..bfaa650a47 100644 --- a/qiskit_experiments/framework/experiment_data.py +++ b/qiskit_experiments/framework/experiment_data.py @@ -142,13 +142,16 @@ def save(self) -> None: data.verbose = original_verbose def save_metadata(self) -> None: - # Copy child experiment IDs to metadata - if self._child_data: - self._metadata["child_data_ids"] = self._child_data.keys() super().save_metadata() for data in self.child_data(): data.save_metadata() + def _save_experiment_metadata(self): + # Copy child experiment IDs to metadata + if self._child_data: + self._metadata["child_data_ids"] = self._child_data.keys() + super()._save_experiment_metadata() + @classmethod def load(cls, experiment_id: str, service: DatabaseService) -> ExperimentData: expdata = DbExperimentData.load(experiment_id, service) diff --git a/test/test_t1.py b/test/test_t1.py index b939308dfd..74f2d63c30 100644 --- a/test/test_t1.py +++ b/test/test_t1.py @@ -78,6 +78,15 @@ def test_t1_parallel(self): self.assertEqual(sub_res.quality, "good") self.assertAlmostEqual(sub_res.value.value, t1[i], delta=3) + res.service = FakeService() + res.save() + loaded_data = ExperimentData.load(res.experiment_id, res.service) + + for i in range(2): + sub_res = res.child_data(i).analysis_results("T1") + sub_loaded = loaded_data.child_data(i).analysis_results("T1") + self.assertEqual(repr(sub_res), repr(sub_loaded)) + def test_t1_parallel_different_analysis_options(self): """ Test parallel experiments of T1 using a simulator, for the case where From af1e6180ede842300459bc5512429cf5d380b343 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 15:32:18 +0200 Subject: [PATCH 05/16] removed debug prints --- qiskit_experiments/framework/base_experiment.py | 7 +++++++ .../framework/composite/composite_analysis.py | 3 --- .../library/characterization/readout_angle_analysis.py | 3 --- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/qiskit_experiments/framework/base_experiment.py b/qiskit_experiments/framework/base_experiment.py index af73003eaa..484fbdf56a 100644 --- a/qiskit_experiments/framework/base_experiment.py +++ b/qiskit_experiments/framework/base_experiment.py @@ -264,7 +264,12 @@ def run( # Generate and transpile circuits transpile_opts = copy.copy(experiment.transpile_options.__dict__) transpile_opts["initial_layout"] = list(experiment.physical_qubits) + print("transpile options:", transpile_opts) + transpile_opts.pop("timing_constraints", {}) + transpile_opts.pop("scheduling_method", {}) + print("transpile options:", transpile_opts) circuits = transpile(experiment.circuits(), experiment.backend, **transpile_opts) + print("circuit after compliation:", circuits[0]) experiment._postprocess_transpiled_circuits(circuits, **run_options) # Run jobs @@ -331,8 +336,10 @@ def _run_jobs(self, circuits: List[QuantumCircuit], **run_options) -> List[BaseJ for circs in job_circuits: if isinstance(self.backend, LegacyBackend): qobj = assemble(circs, backend=self.backend, **run_options) + print("legacy", qobj) job = self.backend.run(qobj) else: + print("not legacy", circs[0]) job = self.backend.run(circs, **run_options) jobs.append(job) return jobs diff --git a/qiskit_experiments/framework/composite/composite_analysis.py b/qiskit_experiments/framework/composite/composite_analysis.py index 57a1501a17..9b2a3a576c 100644 --- a/qiskit_experiments/framework/composite/composite_analysis.py +++ b/qiskit_experiments/framework/composite/composite_analysis.py @@ -160,11 +160,8 @@ def _marginalize_data(self, composite_data: List[Dict]) -> List[Dict]: sub_data["counts"] = marginal_counts(datum["counts"], composite_clbits[i]) else: sub_data["counts"] = datum["counts"] - print("hey", datum) if "memory" in datum: if composite_clbits is not None: - print(composite_clbits) - print(np.array(datum["memory"])[composite_clbits[i]]) sub_data["memory"] = (np.array(datum["memory"])[composite_clbits[i]]).tolist() else: sub_data["memory"] = datum["memory"] diff --git a/qiskit_experiments/library/characterization/readout_angle_analysis.py b/qiskit_experiments/library/characterization/readout_angle_analysis.py index 5716d9a61d..095cf26d5e 100644 --- a/qiskit_experiments/library/characterization/readout_angle_analysis.py +++ b/qiskit_experiments/library/characterization/readout_angle_analysis.py @@ -20,10 +20,8 @@ class ReadoutAngleAnalysis(BaseAnalysis): def _run_analysis(self, experiment_data, **kwargs): - print("hi", experiment_data.data(0)) center0 = complex(*experiment_data.data(0)["memory"][0]) center1 = complex(*experiment_data.data(1)["memory"][0]) - print(center0, center1) angle = (np.angle(center0) + np.angle(center1)) / 2 if np.abs(np.angle(center0) - np.angle(center1)) > np.pi: @@ -34,6 +32,5 @@ def _run_analysis(self, experiment_data, **kwargs): value=angle )] - print(analysis_results[0]) return analysis_results, [] From d88eceb9caa79f8268ab0f93818dd823d3415af8 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 15:33:16 +0200 Subject: [PATCH 06/16] moved location of analysis file --- .../characterization/{ => analysis}/readout_angle_analysis.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename qiskit_experiments/library/characterization/{ => analysis}/readout_angle_analysis.py (100%) diff --git a/qiskit_experiments/library/characterization/readout_angle_analysis.py b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py similarity index 100% rename from qiskit_experiments/library/characterization/readout_angle_analysis.py rename to qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py From a2aa28b65ce0129f1901827f9cf8a3008b6604ff Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 15:34:19 +0200 Subject: [PATCH 07/16] removed the parallel test --- test/test_readout_angle.py | 40 -------------------------------------- 1 file changed, 40 deletions(-) diff --git a/test/test_readout_angle.py b/test/test_readout_angle.py index e6fe725d68..f087497f45 100644 --- a/test/test_readout_angle.py +++ b/test/test_readout_angle.py @@ -40,43 +40,3 @@ def test_readout_angle_end2end(self): res = expdata.analysis_results(0) self.assertAlmostEqual(res.value, np.pi/2, places=2) - def test_readout_angle_parallel(self): - """ - Test parallel experiments of readout angle using a simulator. - """ - backend = ReadoutAngleBackend(iq_cluster_centers=(5.0, 5.0, -3.0, 3.0)) - exp2 = ReadoutAngle(2) - exp0 = ReadoutAngle(0) - parexp = ParallelExperiment([exp2, exp0]) - expdata = parexp.run(backend, shots=100000).block_for_results() - - for i in range(2): - res = expdata.child_data(i).analysis_results(0) - self.assertAlmostEqual(res, np.pi/2, places=2) - - def test_t1_parallel_different_analysis_options(self): - """ - Test parallel experiments of T1 using a simulator, for the case where - the sub-experiments have different analysis options - """ - - t1 = 25 - delays = list(range(1, 40, 3)) - - exp0 = T1(0, delays) - exp0.set_analysis_options(p0={"tau": 30}) - exp1 = T1(1, delays) - exp1.set_analysis_options(p0={"tau": 1000000}) - - par_exp = ParallelExperiment([exp0, exp1]) - res = par_exp.run(T1Backend([t1, t1])) - res.block_for_results() - - sub_res = [] - for i in range(2): - sub_res.append(res.child_data(i).analysis_results("T1")) - - self.assertEqual(sub_res[0].quality, "good") - self.assertAlmostEqual(sub_res[0].value.value, t1, delta=3) - self.assertEqual(sub_res[1].quality, "bad") - From 79d531954670e0f2a88234183e4ed8a480d934a9 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 15:35:53 +0200 Subject: [PATCH 08/16] black --- .../framework/composite/composite_analysis.py | 4 +++- qiskit_experiments/library/__init__.py | 2 +- .../characterization/analysis/readout_angle_analysis.py | 6 +----- .../library/characterization/readout_angle.py | 4 ++-- test/test_readout_angle.py | 5 +++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/qiskit_experiments/framework/composite/composite_analysis.py b/qiskit_experiments/framework/composite/composite_analysis.py index 9b2a3a576c..2202cba19f 100644 --- a/qiskit_experiments/framework/composite/composite_analysis.py +++ b/qiskit_experiments/framework/composite/composite_analysis.py @@ -162,7 +162,9 @@ def _marginalize_data(self, composite_data: List[Dict]) -> List[Dict]: sub_data["counts"] = datum["counts"] if "memory" in datum: if composite_clbits is not None: - sub_data["memory"] = (np.array(datum["memory"])[composite_clbits[i]]).tolist() + sub_data["memory"] = ( + np.array(datum["memory"])[composite_clbits[i]] + ).tolist() else: sub_data["memory"] = datum["memory"] marginalized_data[index].append(sub_data) diff --git a/qiskit_experiments/library/__init__.py b/qiskit_experiments/library/__init__.py index 8cc5f04d14..d243b7670d 100644 --- a/qiskit_experiments/library/__init__.py +++ b/qiskit_experiments/library/__init__.py @@ -136,7 +136,7 @@ class instance to manage parameters and pulse schedules. FineXAmplitude, FineSXAmplitude, RamseyXY, - ReadoutAngle + ReadoutAngle, ) from .randomized_benchmarking import StandardRB, InterleavedRB from .tomography import StateTomography, ProcessTomography diff --git a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py index 095cf26d5e..c292f47ba7 100644 --- a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py +++ b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py @@ -27,10 +27,6 @@ def _run_analysis(self, experiment_data, **kwargs): if np.abs(np.angle(center0) - np.angle(center1)) > np.pi: angle += np.pi - analysis_results = [AnalysisResultData( - name="ReadoutAngle", - value=angle - )] + analysis_results = [AnalysisResultData(name="ReadoutAngle", value=angle)] return analysis_results, [] - diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py index d734183f60..ff477ca679 100644 --- a/qiskit_experiments/library/characterization/readout_angle.py +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -52,10 +52,10 @@ class ReadoutAngle(BaseExperiment): def _default_run_options(cls) -> Options: """Default run options.""" options = super()._default_run_options() - + options.meas_level = MeasLevel.KERNELED options.meas_return = "avg" - + return options def __init__( diff --git a/test/test_readout_angle.py b/test/test_readout_angle.py index f087497f45..d6875e3499 100644 --- a/test/test_readout_angle.py +++ b/test/test_readout_angle.py @@ -21,10 +21,12 @@ from qiskit_experiments.library.characterization import ReadoutAngleAnalysis from qiskit_experiments.test.mock_iq_backend import MockIQBackend + class ReadoutAngleBackend(MockIQBackend): def _compute_probability(self, circ): return 1 - circ.metadata["xval"] + class TestReadoutAngle(QiskitTestCase): """ Test the readout angle experiment @@ -38,5 +40,4 @@ def test_readout_angle_end2end(self): exp = ReadoutAngle(0) expdata = exp.run(backend, shots=100000).block_for_results() res = expdata.analysis_results(0) - self.assertAlmostEqual(res.value, np.pi/2, places=2) - + self.assertAlmostEqual(res.value, np.pi / 2, places=2) From 605cd48f8270cec4a63922606868783e8f478ce2 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 16:00:50 +0200 Subject: [PATCH 09/16] lint --- qiskit_experiments/framework/base_experiment.py | 7 ------- .../framework/composite/composite_analysis.py | 2 +- qiskit_experiments/library/characterization/__init__.py | 1 - .../characterization/analysis/readout_angle_analysis.py | 4 ++++ .../library/characterization/readout_angle.py | 7 +++---- test/test_readout_angle.py | 9 +++++---- test/test_t1.py | 9 --------- 7 files changed, 13 insertions(+), 26 deletions(-) diff --git a/qiskit_experiments/framework/base_experiment.py b/qiskit_experiments/framework/base_experiment.py index 484fbdf56a..af73003eaa 100644 --- a/qiskit_experiments/framework/base_experiment.py +++ b/qiskit_experiments/framework/base_experiment.py @@ -264,12 +264,7 @@ def run( # Generate and transpile circuits transpile_opts = copy.copy(experiment.transpile_options.__dict__) transpile_opts["initial_layout"] = list(experiment.physical_qubits) - print("transpile options:", transpile_opts) - transpile_opts.pop("timing_constraints", {}) - transpile_opts.pop("scheduling_method", {}) - print("transpile options:", transpile_opts) circuits = transpile(experiment.circuits(), experiment.backend, **transpile_opts) - print("circuit after compliation:", circuits[0]) experiment._postprocess_transpiled_circuits(circuits, **run_options) # Run jobs @@ -336,10 +331,8 @@ def _run_jobs(self, circuits: List[QuantumCircuit], **run_options) -> List[BaseJ for circs in job_circuits: if isinstance(self.backend, LegacyBackend): qobj = assemble(circs, backend=self.backend, **run_options) - print("legacy", qobj) job = self.backend.run(qobj) else: - print("not legacy", circs[0]) job = self.backend.run(circs, **run_options) jobs.append(job) return jobs diff --git a/qiskit_experiments/framework/composite/composite_analysis.py b/qiskit_experiments/framework/composite/composite_analysis.py index 2202cba19f..fd083d0f9c 100644 --- a/qiskit_experiments/framework/composite/composite_analysis.py +++ b/qiskit_experiments/framework/composite/composite_analysis.py @@ -13,8 +13,8 @@ Composite Experiment Analysis class. """ -import numpy as np from typing import List, Dict +import numpy as np from qiskit.result import marginal_counts from qiskit_experiments.framework import BaseAnalysis, ExperimentData, AnalysisResultData from qiskit_experiments.database_service.device_component import Qubit diff --git a/qiskit_experiments/library/characterization/__init__.py b/qiskit_experiments/library/characterization/__init__.py index 6b597c3d2c..0ef25e07a9 100644 --- a/qiskit_experiments/library/characterization/__init__.py +++ b/qiskit_experiments/library/characterization/__init__.py @@ -84,5 +84,4 @@ from .ramsey_xy import RamseyXY from .drag import RoughDrag from .readout_angle import ReadoutAngle -from .readout_angle_analysis import ReadoutAngleAnalysis from .fine_drag import FineDrag, FineXDrag, FineSXDrag diff --git a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py index c292f47ba7..19b1e69a46 100644 --- a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py +++ b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py @@ -19,6 +19,10 @@ class ReadoutAngleAnalysis(BaseAnalysis): + """ + A class to analyze readout angle experiments + """ + # pylint: disable=unused-argument def _run_analysis(self, experiment_data, **kwargs): center0 = complex(*experiment_data.data(0)["memory"][0]) center1 = complex(*experiment_data.data(1)["memory"][0]) diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py index ff477ca679..0ff03491f7 100644 --- a/qiskit_experiments/library/characterization/readout_angle.py +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -13,16 +13,15 @@ Readout Angle Experiment class. """ -from typing import List, Optional, Union -import numpy as np +from typing import List, Optional from qiskit.circuit import QuantumCircuit from qiskit.qobj.utils import MeasLevel from qiskit.providers.backend import Backend -from qiskit.test.mock import FakeBackend from qiskit_experiments.framework import BaseExperiment, Options -from qiskit_experiments.library.characterization.readout_angle_analysis import ReadoutAngleAnalysis +from qiskit_experiments.library.characterization.analysis.readout_angle_analysis import \ + ReadoutAngleAnalysis class ReadoutAngle(BaseExperiment): diff --git a/test/test_readout_angle.py b/test/test_readout_angle.py index d6875e3499..8adae2579e 100644 --- a/test/test_readout_angle.py +++ b/test/test_readout_angle.py @@ -16,15 +16,16 @@ import numpy as np from qiskit.test import QiskitTestCase -from qiskit_experiments.framework import ExperimentData, ParallelExperiment from qiskit_experiments.library import ReadoutAngle -from qiskit_experiments.library.characterization import ReadoutAngleAnalysis from qiskit_experiments.test.mock_iq_backend import MockIQBackend class ReadoutAngleBackend(MockIQBackend): - def _compute_probability(self, circ): - return 1 - circ.metadata["xval"] + """ + Mock IQ backend tailored to the readout angle test + """ + def _compute_probability(self, circuit): + return 1 - circuit.metadata["xval"] class TestReadoutAngle(QiskitTestCase): diff --git a/test/test_t1.py b/test/test_t1.py index 74f2d63c30..b939308dfd 100644 --- a/test/test_t1.py +++ b/test/test_t1.py @@ -78,15 +78,6 @@ def test_t1_parallel(self): self.assertEqual(sub_res.quality, "good") self.assertAlmostEqual(sub_res.value.value, t1[i], delta=3) - res.service = FakeService() - res.save() - loaded_data = ExperimentData.load(res.experiment_id, res.service) - - for i in range(2): - sub_res = res.child_data(i).analysis_results("T1") - sub_loaded = loaded_data.child_data(i).analysis_results("T1") - self.assertEqual(repr(sub_res), repr(sub_loaded)) - def test_t1_parallel_different_analysis_options(self): """ Test parallel experiments of T1 using a simulator, for the case where From b243f3d0e613f3034ab48578d3c1f023e54b29d8 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 16:04:11 +0200 Subject: [PATCH 10/16] black --- .../characterization/analysis/readout_angle_analysis.py | 1 + qiskit_experiments/library/characterization/readout_angle.py | 5 +++-- test/test_readout_angle.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py index 19b1e69a46..9f11006eb1 100644 --- a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py +++ b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py @@ -22,6 +22,7 @@ class ReadoutAngleAnalysis(BaseAnalysis): """ A class to analyze readout angle experiments """ + # pylint: disable=unused-argument def _run_analysis(self, experiment_data, **kwargs): center0 = complex(*experiment_data.data(0)["memory"][0]) diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py index 0ff03491f7..94fd2ffd9a 100644 --- a/qiskit_experiments/library/characterization/readout_angle.py +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -20,8 +20,9 @@ from qiskit.providers.backend import Backend from qiskit_experiments.framework import BaseExperiment, Options -from qiskit_experiments.library.characterization.analysis.readout_angle_analysis import \ - ReadoutAngleAnalysis +from qiskit_experiments.library.characterization.analysis.readout_angle_analysis import ( + ReadoutAngleAnalysis, +) class ReadoutAngle(BaseExperiment): diff --git a/test/test_readout_angle.py b/test/test_readout_angle.py index 8adae2579e..8b332601e8 100644 --- a/test/test_readout_angle.py +++ b/test/test_readout_angle.py @@ -24,6 +24,7 @@ class ReadoutAngleBackend(MockIQBackend): """ Mock IQ backend tailored to the readout angle test """ + def _compute_probability(self, circuit): return 1 - circuit.metadata["xval"] From cbe890cc74ea2c2f1c756c862d94b25e62e5a97d Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 16:10:25 +0200 Subject: [PATCH 11/16] lint --- qiskit_experiments/library/characterization/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit_experiments/library/characterization/__init__.py b/qiskit_experiments/library/characterization/__init__.py index 0ef25e07a9..f7f57afcf7 100644 --- a/qiskit_experiments/library/characterization/__init__.py +++ b/qiskit_experiments/library/characterization/__init__.py @@ -71,6 +71,7 @@ T2RamseyAnalysis, T1Analysis, CrossResonanceHamiltonianAnalysis, + ReadoutAngleAnalysis ) from .t1 import T1 From 25990b38babbce2b8c0f267abbaf9c32194cb319 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 16:11:49 +0200 Subject: [PATCH 12/16] black --- qiskit_experiments/library/characterization/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit_experiments/library/characterization/__init__.py b/qiskit_experiments/library/characterization/__init__.py index f7f57afcf7..00680c5fa6 100644 --- a/qiskit_experiments/library/characterization/__init__.py +++ b/qiskit_experiments/library/characterization/__init__.py @@ -71,7 +71,7 @@ T2RamseyAnalysis, T1Analysis, CrossResonanceHamiltonianAnalysis, - ReadoutAngleAnalysis + ReadoutAngleAnalysis, ) from .t1 import T1 From 46c3f04bb94b1772ae578762b3a9578ceb307656 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 16:42:59 +0200 Subject: [PATCH 13/16] update init file --- qiskit_experiments/library/characterization/analysis/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit_experiments/library/characterization/analysis/__init__.py b/qiskit_experiments/library/characterization/analysis/__init__.py index 02f2aeec27..9d52c65770 100644 --- a/qiskit_experiments/library/characterization/analysis/__init__.py +++ b/qiskit_experiments/library/characterization/analysis/__init__.py @@ -21,3 +21,4 @@ from .t2ramsey_analysis import T2RamseyAnalysis from .t1_analysis import T1Analysis from .cr_hamiltonian_analysis import CrossResonanceHamiltonianAnalysis +from .readout_angle_analysis import ReadoutAngleAnalysis From e8d6473dd5e4fc05c29e07bd349eee4e4fe0b4ca Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Mon, 15 Nov 2021 16:56:57 +0200 Subject: [PATCH 14/16] docs --- qiskit_experiments/library/characterization/readout_angle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py index 94fd2ffd9a..d0e8a199b9 100644 --- a/qiskit_experiments/library/characterization/readout_angle.py +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -36,8 +36,8 @@ class ReadoutAngle(BaseExperiment): Each experiment consists of the following steps: 1. Circuits generation: two circuits, the first circuit measures the qubit - in the ground state, the second circuit sets the qubit in the excited state - and measures it. Measurements are in level 1 (kerneled). + in the ground state, the second circuit sets the qubit in the excited state + and measures it. Measurements are in level 1 (kerneled). 2. Backend execution: actually running the circuits on the device (or a simulator that supports level 1 measurements). From efba207727dd827301f9cc7b8574dff7ff85ea3e Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Tue, 16 Nov 2021 14:41:44 +0200 Subject: [PATCH 15/16] release notes --- releasenotes/notes/readout-angle-4d3be1d584ba5ac1.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 releasenotes/notes/readout-angle-4d3be1d584ba5ac1.yaml diff --git a/releasenotes/notes/readout-angle-4d3be1d584ba5ac1.yaml b/releasenotes/notes/readout-angle-4d3be1d584ba5ac1.yaml new file mode 100644 index 0000000000..5e0bd32925 --- /dev/null +++ b/releasenotes/notes/readout-angle-4d3be1d584ba5ac1.yaml @@ -0,0 +1,4 @@ +--- +features: + - | + A new readout angle experiment. The experiment computes the average of the angles of the IQ clusters of the ground and excited states. From 4529137b00f484633a9619c0086bbbaa00ec7102 Mon Sep 17 00:00:00 2001 From: Yael Ben-Haim Date: Thu, 18 Nov 2021 09:26:11 +0200 Subject: [PATCH 16/16] addressing review comments --- .../analysis/readout_angle_analysis.py | 18 +++++++++++++----- .../library/characterization/readout_angle.py | 8 ++++++-- test/test_readout_angle.py | 8 +++++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py index 9f11006eb1..b850ed1f49 100644 --- a/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py +++ b/qiskit_experiments/library/characterization/analysis/readout_angle_analysis.py @@ -25,13 +25,21 @@ class ReadoutAngleAnalysis(BaseAnalysis): # pylint: disable=unused-argument def _run_analysis(self, experiment_data, **kwargs): - center0 = complex(*experiment_data.data(0)["memory"][0]) - center1 = complex(*experiment_data.data(1)["memory"][0]) + angles = [] + for i in range(2): + center = complex(*experiment_data.data(i)["memory"][0]) + angles.append(np.angle(center)) - angle = (np.angle(center0) + np.angle(center1)) / 2 - if np.abs(np.angle(center0) - np.angle(center1)) > np.pi: + angle = (angles[0] + angles[1]) / 2 + if (np.abs(angles[0] - angles[1])) % (2 * np.pi) > np.pi: angle += np.pi - analysis_results = [AnalysisResultData(name="ReadoutAngle", value=angle)] + analysis_results = [ + AnalysisResultData( + name="ReadoutAngle", + value=angle, + extra={"angle_ground": angles[0], "angle_excited": angles[1]}, + ) + ] return analysis_results, [] diff --git a/qiskit_experiments/library/characterization/readout_angle.py b/qiskit_experiments/library/characterization/readout_angle.py index d0e8a199b9..25a694110e 100644 --- a/qiskit_experiments/library/characterization/readout_angle.py +++ b/qiskit_experiments/library/characterization/readout_angle.py @@ -32,6 +32,9 @@ class ReadoutAngle(BaseExperiment): # section: overview Design and analyze experiments for estimating readout angle of the qubit. + The readout angle is the average of two angles: the angle of the IQ + cluster center of the ground state, and the angle of the IQ cluster center + of the excited state. Each experiment consists of the following steps: @@ -40,9 +43,10 @@ class ReadoutAngle(BaseExperiment): and measures it. Measurements are in level 1 (kerneled). 2. Backend execution: actually running the circuits on the device - (or a simulator that supports level 1 measurements). + (or a simulator that supports level 1 measurements). The backend returns + the cluster centers of the ground and excited states. - 3. Analysis of results: return the average of the centers of the two angles. + 3. Analysis of results: return the average of the angles of the two centers. """ diff --git a/test/test_readout_angle.py b/test/test_readout_angle.py index 8b332601e8..3f75f3fb65 100644 --- a/test/test_readout_angle.py +++ b/test/test_readout_angle.py @@ -42,4 +42,10 @@ def test_readout_angle_end2end(self): exp = ReadoutAngle(0) expdata = exp.run(backend, shots=100000).block_for_results() res = expdata.analysis_results(0) - self.assertAlmostEqual(res.value, np.pi / 2, places=2) + self.assertAlmostEqual(res.value % (2 * np.pi), np.pi / 2, places=2) + + backend = ReadoutAngleBackend(iq_cluster_centers=(5.0, 5.0, 0, -3.0)) + exp = ReadoutAngle(0) + expdata = exp.run(backend, shots=100000).block_for_results() + res = expdata.analysis_results(0) + self.assertAlmostEqual(res.value % (2 * np.pi), 15 * np.pi / 8, places=2)