diff --git a/qiskit_experiments/test/__init__.py b/qiskit_experiments/test/__init__.py index f031a6a8fb..519e407bdc 100644 --- a/qiskit_experiments/test/__init__.py +++ b/qiskit_experiments/test/__init__.py @@ -37,8 +37,11 @@ MockIQParallelBackend T2HahnBackend NoisyDelayAerBackend +<<<<<<< HEAD PulseBackend SingleTransmonTestBackend +======= +>>>>>>> 73d0a03 (Update `HamiltonianGate` path and add tolerance to `PulseBackend` (#1280)) Helpers ======= diff --git a/qiskit_experiments/test/pulse_backend.py b/qiskit_experiments/test/pulse_backend.py index ad77616238..9356a93054 100644 --- a/qiskit_experiments/test/pulse_backend.py +++ b/qiskit_experiments/test/pulse_backend.py @@ -73,6 +73,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. @@ -86,6 +88,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. """ super().__init__( None, @@ -108,6 +112,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 @@ -338,6 +348,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 @@ -452,6 +463,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 @@ -464,6 +477,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. """ qubit_frequency_02 = 2 * qubit_frequency + anharmonicity ket0 = np.array([[1, 0, 0]]).T @@ -505,6 +520,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 new file mode 100644 index 0000000000..7e6d704636 --- /dev/null +++ b/test/library/calibration/test_half_angle.py @@ -0,0 +1,62 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2023. +# +# 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 rough amplitude calibration experiment classes.""" + +from test.base import QiskitExperimentsTestCase + +from qiskit import pulse +from qiskit.circuit import Parameter + +from qiskit_experiments.exceptions import CalibrationError +from qiskit_experiments.calibration_management.basis_gate_library import FixedFrequencyTransmon +from qiskit_experiments.calibration_management import Calibrations +from qiskit_experiments.library import HalfAngleCal +from qiskit_experiments.test.pulse_backend import SingleTransmonTestBackend + + +class TestHalfAngleCal(QiskitExperimentsTestCase): + """A class to test the half angle calibration experiments.""" + + def setUp(self): + """Setup the tests.""" + super().setUp() + library = FixedFrequencyTransmon() + + self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) + self.cals = Calibrations.from_backend(self.backend, libraries=[library]) + + def test_amp_parameter_error(self): + """Test that setting cal_parameter_name to amp raises an error""" + with self.assertRaises(CalibrationError): + HalfAngleCal([0], self.cals, cal_parameter_name="amp") + + def test_angle_parameter_missing_error(self): + """Test that default cal_parameter_name with no matching parameter raises an error""" + cals_no_angle = Calibrations() + dur = Parameter("dur") + amp = Parameter("amp") + sigma = Parameter("σ") + beta = Parameter("β") + drive = pulse.DriveChannel(Parameter("ch0")) + + with pulse.build(name="sx") as sx: + pulse.play(pulse.Drag(dur, amp, sigma, beta), drive) + + cals_no_angle.add_schedule(sx, num_qubits=1) + with self.assertRaises(CalibrationError): + HalfAngleCal([0], cals_no_angle) + + def test_circuits_roundtrip_serializable(self): + """Test circuits serialization of the experiment.""" + exp = HalfAngleCal([0], self.cals, backend=self.backend) + self.assertRoundTripSerializable(exp._transpiled_circuits()) diff --git a/test/library/calibration/test_rabi.py b/test/library/calibration/test_rabi.py index 5c2321d56a..f171a1da07 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): @@ -100,7 +101,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)): @@ -114,7 +115,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 575d8ee2ac..3c8788026e 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): @@ -100,8 +100,13 @@ def setUp(self): library = FixedFrequencyTransmon() +<<<<<<< HEAD self.backend = SingleTransmonTestBackend(noise=False) self.cals = Calibrations.from_backend(self.backend, libraries=[library]) +======= + cls.backend = SingleTransmonTestBackend(noise=False, atol=1e-3) + cls.cals = Calibrations.from_backend(cls.backend, libraries=[library]) +>>>>>>> 73d0a03 (Update `HamiltonianGate` path and add tolerance to `PulseBackend` (#1280)) # Add some pulses on the 1-2 transition. d0 = pulse.DriveChannel(0) diff --git a/test/library/calibration/test_rough_frequency.py b/test/library/calibration/test_rough_frequency.py index 3c77a52739..f30df6eb87 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 ffa9c76d14..08c11f2346 100644 --- a/test/library/characterization/test_cross_resonance_hamiltonian.py +++ b/test/library/characterization/test_cross_resonance_hamiltonian.py @@ -20,7 +20,13 @@ from ddt import ddt, data, unpack from qiskit import QuantumCircuit, pulse, 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 508299cd75..1a8211a920 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 @@ -97,7 +97,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"][