From ddcf5b96e2a1098cc2bd1cbaadc8f76437ee8aa1 Mon Sep 17 00:00:00 2001 From: "dekel.meirom" Date: Wed, 15 Sep 2021 12:12:22 +0300 Subject: [PATCH 1/6] enable resonator as component --- qiskit_experiments/framework/base_analysis.py | 12 ++-- test/fake_resonator_experiment.py | 56 +++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 test/fake_resonator_experiment.py diff --git a/qiskit_experiments/framework/base_analysis.py b/qiskit_experiments/framework/base_analysis.py index adfe2cf831..0bc59c8a21 100644 --- a/qiskit_experiments/framework/base_analysis.py +++ b/qiskit_experiments/framework/base_analysis.py @@ -18,7 +18,7 @@ from qiskit.exceptions import QiskitError -from qiskit_experiments.database_service.device_component import Qubit +from qiskit_experiments.database_service.device_component import Qubit, Resonator from qiskit_experiments.framework import Options from qiskit_experiments.framework.experiment_data import ExperimentData from qiskit_experiments.framework.analysis_result_data import AnalysisResultData @@ -73,12 +73,16 @@ def run( ) # Get experiment device components + experiment_components = [] if "physical_qubits" in experiment_data.metadata: experiment_components = [ Qubit(qubit) for qubit in experiment_data.metadata["physical_qubits"] - ] - else: - experiment_components = [] + ] + if "resonators" in experiment_data.metadata: + experiment_components.extend([ + Resonator(resonator) for resonator in experiment_data.metadata["resonators"] + ]) + # Get analysis options analysis_options = self._default_options() diff --git a/test/fake_resonator_experiment.py b/test/fake_resonator_experiment.py new file mode 100644 index 0000000000..5d2eb1091a --- /dev/null +++ b/test/fake_resonator_experiment.py @@ -0,0 +1,56 @@ +# 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. + +"""Fake experiment using resonator instead of qubits for testing.""" + +from typing import Iterable, Optional, Tuple, List, Dict +from qiskit_experiments.framework import BaseExperiment, Options, BaseAnalysis, AnalysisResultData + +from qiskit.providers import Backend +from qiskit.circuit import QuantumCircuit + +class FakeResonatorAnalysis(BaseAnalysis): + # pylint: disable=arguments-differ + def _run_analysis( + self, + experiment_data, + ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]: + return [], None + + +class FakeResonatorExperiment(BaseExperiment): + """ + An experiment to show how to use resonators instead of qubits + """ + + @classmethod + def _default_experiment_options(cls) -> Options: + """ + Add resonators to the experiment options + """ + options = super()._default_experiment_options() + options.resonators = [] + return options + + def __init__( + self, + resonators: Iterable[int]): + super().__init__([]) + + # Set experiment options + self.set_experiment_options(resonators=resonators) + + def circuits(self, backend: Optional[Backend] = None): + circ = QuantumCircuit(1, 1) + circ.measure(0, 0) + + return [circ] \ No newline at end of file From 0d29713f0c23264714a37498cc001ba0332290f3 Mon Sep 17 00:00:00 2001 From: "dekel.meirom" Date: Wed, 29 Sep 2021 11:19:12 +0300 Subject: [PATCH 2/6] add resonator test --- qiskit_experiments/framework/base_experiment.py | 2 +- test/database_service/test_db_analysis_result.py | 16 ++++++++++++++++ test/fake_resonator_experiment.py | 14 +++++++++----- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/qiskit_experiments/framework/base_experiment.py b/qiskit_experiments/framework/base_experiment.py index 4240ae91c1..e6161ba1f3 100644 --- a/qiskit_experiments/framework/base_experiment.py +++ b/qiskit_experiments/framework/base_experiment.py @@ -353,7 +353,7 @@ def _metadata(self) -> Dict[str, any]: "job_metadata": [], } # Add additional metadata if subclasses specify it - for key, val in self._additional_metadata(): + for key, val in self._additional_metadata().items(): metadata[key] = val return metadata diff --git a/test/database_service/test_db_analysis_result.py b/test/database_service/test_db_analysis_result.py index 85a62f14af..5f31d77355 100644 --- a/test/database_service/test_db_analysis_result.py +++ b/test/database_service/test_db_analysis_result.py @@ -18,8 +18,11 @@ import json import numpy as np +import unittest from qiskit.test import QiskitTestCase +from test.fake_resonator_experiment import FakeResonatorExperiment, FakeResonatorAnalysis +from test.fake_backend import FakeBackend from qiskit_experiments.database_service import DbAnalysisResultV1 as DbAnalysisResult from qiskit_experiments.database_service.device_component import Qubit, Resonator, to_component from qiskit_experiments.database_service.database_service import DatabaseServiceV1 @@ -156,3 +159,16 @@ def test_to_component(self): r1 = to_component("R1") self.assertIsInstance(r1, Resonator) self.assertEqual("R1", str(r1)) + + def test_resonator_experiment(self): + """Test creating an experiment consisting only resonator components""" + resonator_exp = FakeResonatorExperiment(resonators=[0,1]) + resonator_data = resonator_exp.run(FakeBackend()) + resonator_data.block_for_results() + analysis_res = resonator_data._analysis_results + for key in analysis_res._container.keys(): + device_components = analysis_res._container[key].device_components + self.assertIsInstance(device_components[0], Resonator) + self.assertEqual("R0", str(device_components[0])) + self.assertIsInstance(device_components[1], Resonator) + self.assertEqual("R1", str(device_components[1])) diff --git a/test/fake_resonator_experiment.py b/test/fake_resonator_experiment.py index 5d2eb1091a..27cdf18c96 100644 --- a/test/fake_resonator_experiment.py +++ b/test/fake_resonator_experiment.py @@ -17,6 +17,7 @@ from qiskit.providers import Backend from qiskit.circuit import QuantumCircuit +from qiskit.test import QiskitTestCase class FakeResonatorAnalysis(BaseAnalysis): # pylint: disable=arguments-differ @@ -24,7 +25,10 @@ def _run_analysis( self, experiment_data, ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]: - return [], None + return [AnalysisResultData( + "ResonatorTest", + 0 + )], None class FakeResonatorExperiment(BaseExperiment): @@ -32,6 +36,8 @@ class FakeResonatorExperiment(BaseExperiment): An experiment to show how to use resonators instead of qubits """ + __analysis_class__ = FakeResonatorAnalysis + @classmethod def _default_experiment_options(cls) -> Options: """ @@ -50,7 +56,5 @@ def __init__( self.set_experiment_options(resonators=resonators) def circuits(self, backend: Optional[Backend] = None): - circ = QuantumCircuit(1, 1) - circ.measure(0, 0) - - return [circ] \ No newline at end of file + """return empty circuits for test""" + return [] From 123f9467b40cdf7dc769fea1ee48c96ac1c693a0 Mon Sep 17 00:00:00 2001 From: "dekel.meirom" Date: Wed, 29 Sep 2021 11:41:39 +0300 Subject: [PATCH 3/6] fix lint errors --- .../test_db_analysis_result.py | 8 +++---- test/fake_resonator_experiment.py | 24 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/test/database_service/test_db_analysis_result.py b/test/database_service/test_db_analysis_result.py index 5f31d77355..35ea48e26c 100644 --- a/test/database_service/test_db_analysis_result.py +++ b/test/database_service/test_db_analysis_result.py @@ -16,13 +16,12 @@ from unittest import mock import json +from test.fake_resonator_experiment import FakeResonatorExperiment +from test.fake_backend import FakeBackend import numpy as np -import unittest from qiskit.test import QiskitTestCase -from test.fake_resonator_experiment import FakeResonatorExperiment, FakeResonatorAnalysis -from test.fake_backend import FakeBackend from qiskit_experiments.database_service import DbAnalysisResultV1 as DbAnalysisResult from qiskit_experiments.database_service.device_component import Qubit, Resonator, to_component from qiskit_experiments.database_service.database_service import DatabaseServiceV1 @@ -162,12 +161,13 @@ def test_to_component(self): def test_resonator_experiment(self): """Test creating an experiment consisting only resonator components""" - resonator_exp = FakeResonatorExperiment(resonators=[0,1]) + resonator_exp = FakeResonatorExperiment(resonators=[0, 1]) resonator_data = resonator_exp.run(FakeBackend()) resonator_data.block_for_results() analysis_res = resonator_data._analysis_results for key in analysis_res._container.keys(): device_components = analysis_res._container[key].device_components + self.assertEqual(len(device_components), 2) self.assertIsInstance(device_components[0], Resonator) self.assertEqual("R0", str(device_components[0])) self.assertIsInstance(device_components[1], Resonator) diff --git a/test/fake_resonator_experiment.py b/test/fake_resonator_experiment.py index 27cdf18c96..b8f38758f8 100644 --- a/test/fake_resonator_experiment.py +++ b/test/fake_resonator_experiment.py @@ -12,23 +12,20 @@ """Fake experiment using resonator instead of qubits for testing.""" -from typing import Iterable, Optional, Tuple, List, Dict +from typing import Iterable, Optional, Tuple, List +from qiskit.providers import Backend from qiskit_experiments.framework import BaseExperiment, Options, BaseAnalysis, AnalysisResultData -from qiskit.providers import Backend -from qiskit.circuit import QuantumCircuit -from qiskit.test import QiskitTestCase class FakeResonatorAnalysis(BaseAnalysis): + """ + Simple analysis to test experiment using resonators instead of qubits + """ # pylint: disable=arguments-differ def _run_analysis( - self, - experiment_data, + self, experiment_data, ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]: - return [AnalysisResultData( - "ResonatorTest", - 0 - )], None + return [AnalysisResultData("ResonatorTest", 0)], None class FakeResonatorExperiment(BaseExperiment): @@ -47,14 +44,15 @@ def _default_experiment_options(cls) -> Options: options.resonators = [] return options - def __init__( - self, - resonators: Iterable[int]): + def __init__(self, resonators: Iterable[int]): super().__init__([]) # Set experiment options self.set_experiment_options(resonators=resonators) + def _additional_metadata(self): + return {"resonators": self.experiment_options.resonators} + def circuits(self, backend: Optional[Backend] = None): """return empty circuits for test""" return [] From 4273bfb0ccd9888add0c5f0b97ae236613afb2e2 Mon Sep 17 00:00:00 2001 From: "dekel.meirom" Date: Wed, 29 Sep 2021 11:54:53 +0300 Subject: [PATCH 4/6] fix more lint errors --- qiskit_experiments/framework/base_analysis.py | 15 +++++---------- test/fake_resonator_experiment.py | 1 + 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/qiskit_experiments/framework/base_analysis.py b/qiskit_experiments/framework/base_analysis.py index 0bc59c8a21..f89cc871aa 100644 --- a/qiskit_experiments/framework/base_analysis.py +++ b/qiskit_experiments/framework/base_analysis.py @@ -48,11 +48,7 @@ class BaseAnalysis(ABC): def _default_options(cls) -> Options: return Options() - def run( - self, - experiment_data: ExperimentData, - **options, - ) -> ExperimentData: + def run(self, experiment_data: ExperimentData, **options,) -> ExperimentData: """Run analysis and update ExperimentData with analysis result. Args: @@ -77,12 +73,11 @@ def run( if "physical_qubits" in experiment_data.metadata: experiment_components = [ Qubit(qubit) for qubit in experiment_data.metadata["physical_qubits"] - ] + ] if "resonators" in experiment_data.metadata: - experiment_components.extend([ - Resonator(resonator) for resonator in experiment_data.metadata["resonators"] - ]) - + experiment_components.extend( + [Resonator(resonator) for resonator in experiment_data.metadata["resonators"]] + ) # Get analysis options analysis_options = self._default_options() diff --git a/test/fake_resonator_experiment.py b/test/fake_resonator_experiment.py index b8f38758f8..de3139fde0 100644 --- a/test/fake_resonator_experiment.py +++ b/test/fake_resonator_experiment.py @@ -21,6 +21,7 @@ class FakeResonatorAnalysis(BaseAnalysis): """ Simple analysis to test experiment using resonators instead of qubits """ + # pylint: disable=arguments-differ def _run_analysis( self, experiment_data, From dd2de686cd9d71e0a6e0cdf3eb4611f0c83d6899 Mon Sep 17 00:00:00 2001 From: "dekel.meirom" Date: Wed, 29 Sep 2021 12:09:53 +0300 Subject: [PATCH 5/6] fix black version --- qiskit_experiments/framework/base_analysis.py | 6 +++++- test/fake_resonator_experiment.py | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/qiskit_experiments/framework/base_analysis.py b/qiskit_experiments/framework/base_analysis.py index f89cc871aa..13aa37e541 100644 --- a/qiskit_experiments/framework/base_analysis.py +++ b/qiskit_experiments/framework/base_analysis.py @@ -48,7 +48,11 @@ class BaseAnalysis(ABC): def _default_options(cls) -> Options: return Options() - def run(self, experiment_data: ExperimentData, **options,) -> ExperimentData: + def run( + self, + experiment_data: ExperimentData, + **options, + ) -> ExperimentData: """Run analysis and update ExperimentData with analysis result. Args: diff --git a/test/fake_resonator_experiment.py b/test/fake_resonator_experiment.py index de3139fde0..acb9e96448 100644 --- a/test/fake_resonator_experiment.py +++ b/test/fake_resonator_experiment.py @@ -24,7 +24,8 @@ class FakeResonatorAnalysis(BaseAnalysis): # pylint: disable=arguments-differ def _run_analysis( - self, experiment_data, + self, + experiment_data, ) -> Tuple[List[AnalysisResultData], List["matplotlib.figure.Figure"]]: return [AnalysisResultData("ResonatorTest", 0)], None From 29c0bfd8fda798eb8e11b3a189db7dedc3b0960b Mon Sep 17 00:00:00 2001 From: "dekel.meirom" Date: Thu, 31 Mar 2022 14:17:08 +0300 Subject: [PATCH 6/6] fix lint errors --- test/database_service/test_db_analysis_result.py | 8 +++----- test/fake_resonator_experiment.py | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/test/database_service/test_db_analysis_result.py b/test/database_service/test_db_analysis_result.py index 3c70202372..078577c059 100644 --- a/test/database_service/test_db_analysis_result.py +++ b/test/database_service/test_db_analysis_result.py @@ -13,16 +13,14 @@ # pylint: disable=missing-docstring """Test AnalysisResult.""" -from test.base import QiskitExperimentsTestCase from unittest import mock import json -from test.fake_resonator_experiment import FakeResonatorExperiment -from test.fake_backend import FakeBackend - import math +from test.base import QiskitExperimentsTestCase +from test.fake_resonator_experiment import FakeResonatorExperiment import numpy as np - +from qiskit_experiments.test.fake_backend import FakeBackend from qiskit_experiments.database_service import DbAnalysisResultV1 as DbAnalysisResult from qiskit_experiments.database_service.device_component import Qubit, Resonator, to_component from qiskit_experiments.database_service.database_service import DatabaseServiceV1 diff --git a/test/fake_resonator_experiment.py b/test/fake_resonator_experiment.py index acb9e96448..d56aa3c9a8 100644 --- a/test/fake_resonator_experiment.py +++ b/test/fake_resonator_experiment.py @@ -12,8 +12,7 @@ """Fake experiment using resonator instead of qubits for testing.""" -from typing import Iterable, Optional, Tuple, List -from qiskit.providers import Backend +from typing import Iterable, Tuple, List from qiskit_experiments.framework import BaseExperiment, Options, BaseAnalysis, AnalysisResultData @@ -55,6 +54,6 @@ def __init__(self, resonators: Iterable[int]): def _additional_metadata(self): return {"resonators": self.experiment_options.resonators} - def circuits(self, backend: Optional[Backend] = None): + def circuits(self): """return empty circuits for test""" return []