From 73d0a03c87baef50400594d85b3f67b6ae40266b Mon Sep 17 00:00:00 2001 From: Helena Zhang Date: Mon, 16 Oct 2023 11:22:52 -0400 Subject: [PATCH] Update `HamiltonianGate` path and add tolerance to `PulseBackend` (#1280) ### Summary After `qiskit.extensions` was deprecated in https://github.com/Qiskit/qiskit/pull/10725, this PR updates the path of `HamiltonianGate` so tests against Qiskit main pass again. This also adds `atol` and `rtol` tolerance parameters to `PulseBackend` for speeding up slow tests. --- qiskit_experiments/test/__init__.py | 1 - qiskit_experiments/test/pulse_backend.py | 17 +++++++++++++++++ ...hamiltonian-experiment-7f47c51d26941f16.yaml | 2 +- test/library/calibration/test_half_angle.py | 2 +- test/library/calibration/test_rabi.py | 17 +++++++++-------- .../library/calibration/test_rough_amplitude.py | 4 ++-- .../library/calibration/test_rough_frequency.py | 6 ++++-- .../test_cross_resonance_hamiltonian.py | 8 +++++++- .../test_multi_state_discrimination.py | 4 ++-- 9 files changed, 43 insertions(+), 18 deletions(-) diff --git a/qiskit_experiments/test/__init__.py b/qiskit_experiments/test/__init__.py index 609dbdec96..41df7bfee5 100644 --- a/qiskit_experiments/test/__init__.py +++ b/qiskit_experiments/test/__init__.py @@ -37,7 +37,6 @@ MockIQParallelBackend T2HahnBackend NoisyDelayAerBackend - SingleTransmonTestBackend Helpers ======= diff --git a/qiskit_experiments/test/pulse_backend.py b/qiskit_experiments/test/pulse_backend.py index 963f5deb3b..84acf9f7cd 100644 --- a/qiskit_experiments/test/pulse_backend.py +++ b/qiskit_experiments/test/pulse_backend.py @@ -72,6 +72,8 @@ def __init__( dt: float = 0.1 * 1e-9, solver_method="RK23", seed: int = 0, + atol: float = None, + rtol: float = None, **kwargs, ): """Initialize a backend with model information. @@ -85,6 +87,8 @@ def __init__( methods. Defaults to "RK23". seed: An optional seed given to the random number generator. If this argument is not set then the seed defaults to 0. + atol: Absolute tolerance during solving. + rtol: Relative tolerance during solving. """ from qiskit_dynamics import Solver @@ -109,6 +113,12 @@ def __init__( self.solver_method = solver_method + self.solve_kwargs = {} + if atol: + self.solve_kwargs["atol"] = atol + if rtol: + self.solve_kwargs["rtol"] = rtol + self.static_hamiltonian = static_hamiltonian self.hamiltonian_operators = hamiltonian_operators self.static_dissipators = static_dissipators @@ -339,6 +349,7 @@ def solve(self, schedule: Union[ScheduleBlock, Schedule], qubits: Tuple[int]) -> t_eval=[time_f], signals=signal, method=self.solver_method, + **self.solve_kwargs, ).y[0] return unitary @@ -454,6 +465,8 @@ def __init__( lambda_2: float = 0.8e9, gamma_1: float = 1e4, noise: bool = True, + atol: float = None, + rtol: float = None, **kwargs, ): """Initialise backend with hamiltonian parameters @@ -466,6 +479,8 @@ def __init__( gamma_1: Relaxation rate (1/T1) for 1-0. Defaults to 1e4. noise: Defaults to True. If True then T1 dissipation is included in the pulse-simulation. The strength is given by ``gamma_1``. + atol: Absolute tolerance during solving. + rtol: Relative tolerance during solving. """ from qiskit_dynamics.pulse import InstructionToSignals @@ -509,6 +524,8 @@ def __init__( rwa_cutoff_freq=1.9 * qubit_frequency, rwa_carrier_freqs=[qubit_frequency], evaluation_mode=evaluation_mode, + atol=atol, + rtol=rtol, **kwargs, ) diff --git a/releasenotes/notes/0.3/cleanup-cr-hamiltonian-experiment-7f47c51d26941f16.yaml b/releasenotes/notes/0.3/cleanup-cr-hamiltonian-experiment-7f47c51d26941f16.yaml index 4828ae44c6..a05dcc704a 100644 --- a/releasenotes/notes/0.3/cleanup-cr-hamiltonian-experiment-7f47c51d26941f16.yaml +++ b/releasenotes/notes/0.3/cleanup-cr-hamiltonian-experiment-7f47c51d26941f16.yaml @@ -6,5 +6,5 @@ upgrade: setting backend for just checking experiment sequence. The sequence with actual parameters is generated after the backend is set. In addition, now experiments can take ``cr_gate`` in the constractor which is ``Gate`` type subclass taking a single parameter (flat-top width). - If one inputs a :class:`~qiskit.extensions.hamiltonian_gate.HamiltonianGate` subclass with + If one inputs a :class:`~qiskit.circuit.library.HamiltonianGate` subclass with cross resonance Hamiltonian, experiment can be simulated with Aer QASM simulator. diff --git a/test/library/calibration/test_half_angle.py b/test/library/calibration/test_half_angle.py index 40ae7b655d..7e6d704636 100644 --- a/test/library/calibration/test_half_angle.py +++ b/test/library/calibration/test_half_angle.py @@ -32,7 +32,7 @@ def setUp(self): super().setUp() library = FixedFrequencyTransmon() - self.backend = SingleTransmonTestBackend(noise=False) + self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) self.cals = Calibrations.from_backend(self.backend, libraries=[library]) def test_amp_parameter_error(self): diff --git a/test/library/calibration/test_rabi.py b/test/library/calibration/test_rabi.py index 7708e64cfd..962b3abd92 100644 --- a/test/library/calibration/test_rabi.py +++ b/test/library/calibration/test_rabi.py @@ -34,17 +34,18 @@ class TestRabiEndToEnd(QiskitExperimentsTestCase): """Test the rabi experiment.""" - def setUp(self): + @classmethod + def setUpClass(cls): """Setup the tests.""" - super().setUp() + super().setUpClass() - self.qubit = 0 + cls.qubit = 0 with pulse.build(name="x") as sched: - pulse.play(pulse.Drag(160, Parameter("amp"), 40, 0.4), pulse.DriveChannel(self.qubit)) + pulse.play(pulse.Drag(160, Parameter("amp"), 40, 0.4), pulse.DriveChannel(cls.qubit)) - self.sched = sched - self.backend = SingleTransmonTestBackend(noise=False) + cls.sched = sched + cls.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) # pylint: disable=no-member def test_rabi_end_to_end(self): @@ -101,7 +102,7 @@ def setUp(self): super().setUp() self.qubit = 0 - self.backend = SingleTransmonTestBackend(noise=False) + self.backend = SingleTransmonTestBackend(noise=False, atol=1e-4) self.anharmonicity = self.backend.anharmonicity with pulse.build(name="x") as sched: with pulse.frequency_offset(self.anharmonicity, pulse.DriveChannel(self.qubit)): @@ -115,7 +116,7 @@ def setUp(self): def test_ef_rabi_end_to_end(self): """Test the EFRabi experiment end to end.""" - test_tol = 0.01 + test_tol = 0.05 # Note that the backend is not sophisticated enough to simulate an e-f # transition so we run the test with a tiny frequency shift, still driving the e-g transition. diff --git a/test/library/calibration/test_rough_amplitude.py b/test/library/calibration/test_rough_amplitude.py index ebc933298a..7618757f5c 100644 --- a/test/library/calibration/test_rough_amplitude.py +++ b/test/library/calibration/test_rough_amplitude.py @@ -32,7 +32,7 @@ def setUp(self): super().setUp() library = FixedFrequencyTransmon() - self.backend = SingleTransmonTestBackend(noise=False) + self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) self.cals = Calibrations.from_backend(self.backend, libraries=[library]) def test_circuits(self): @@ -107,7 +107,7 @@ def setUpClass(cls): library = FixedFrequencyTransmon() - cls.backend = SingleTransmonTestBackend(noise=False) + cls.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) cls.cals = Calibrations.from_backend(cls.backend, libraries=[library]) # Add some pulses on the 1-2 transition. diff --git a/test/library/calibration/test_rough_frequency.py b/test/library/calibration/test_rough_frequency.py index 3b32ad3d26..930cce1814 100644 --- a/test/library/calibration/test_rough_frequency.py +++ b/test/library/calibration/test_rough_frequency.py @@ -28,7 +28,7 @@ class TestRoughFrequency(QiskitExperimentsTestCase): def setUp(self): """Setup the tests.""" super().setUp() - self.backend = SingleTransmonTestBackend(noise=False) + self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) def test_init(self): """Test that initialization.""" @@ -53,7 +53,9 @@ def test_update_calibrations(self): freq01 = BackendData(self.backend).drive_freqs[0] - backend_5mhz = SingleTransmonTestBackend(qubit_frequency=freq01 + 5e6, noise=False) + backend_5mhz = SingleTransmonTestBackend( + qubit_frequency=freq01 + 5e6, noise=False, atol=1e-3 + ) library = FixedFrequencyTransmon() cals = Calibrations.from_backend(self.backend, libraries=[library]) diff --git a/test/library/characterization/test_cross_resonance_hamiltonian.py b/test/library/characterization/test_cross_resonance_hamiltonian.py index 1df5c80aae..540c0e0dc4 100644 --- a/test/library/characterization/test_cross_resonance_hamiltonian.py +++ b/test/library/characterization/test_cross_resonance_hamiltonian.py @@ -21,7 +21,13 @@ from ddt import ddt, data, unpack from qiskit import QuantumCircuit, pulse, qpy, quantum_info as qi from qiskit.providers.fake_provider import FakeBogotaV2 -from qiskit.extensions.hamiltonian_gate import HamiltonianGate + +# TODO: remove old path after we stop supporting the relevant version of Qiskit +try: + from qiskit.circuit.library.hamiltonian_gate import HamiltonianGate +except ModuleNotFoundError: + from qiskit.extensions.hamiltonian_gate import HamiltonianGate + from qiskit_aer import AerSimulator from qiskit_experiments.library.characterization import cr_hamiltonian diff --git a/test/library/characterization/test_multi_state_discrimination.py b/test/library/characterization/test_multi_state_discrimination.py index 861e987917..36990bb884 100644 --- a/test/library/characterization/test_multi_state_discrimination.py +++ b/test/library/characterization/test_multi_state_discrimination.py @@ -49,7 +49,7 @@ def setUp(self): """Setup test variables.""" super().setUp() - self.backend = SingleTransmonTestBackend(noise=False) + self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) # Build x12 schedule self.qubit = 0 @@ -94,7 +94,7 @@ def test_discrimination_analysis(self, n_states): fidelity = exp_data.analysis_results("fidelity").value - self.assertGreaterEqual(fidelity, 0.96) + self.assertGreaterEqual(fidelity, 0.93) # check that the discriminator differentiates n different states discrim_lbls = exp_data.analysis_results("discriminator_config").value["attributes"][