Skip to content

Commit c83a214

Browse files
coruscatingmergify[bot]
authored andcommitted
Update HamiltonianGate path and add tolerance to PulseBackend (#1280)
### Summary After `qiskit.extensions` was deprecated in Qiskit/qiskit#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. (cherry picked from commit 73d0a03) # Conflicts: # qiskit_experiments/test/__init__.py # test/library/calibration/test_half_angle.py # test/library/calibration/test_rough_amplitude.py
1 parent 62d75a1 commit c83a214

File tree

9 files changed

+111
-15
lines changed

9 files changed

+111
-15
lines changed

qiskit_experiments/test/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@
3737
MockIQParallelBackend
3838
T2HahnBackend
3939
NoisyDelayAerBackend
40+
<<<<<<< HEAD
4041
PulseBackend
4142
SingleTransmonTestBackend
43+
=======
44+
>>>>>>> 73d0a03 (Update `HamiltonianGate` path and add tolerance to `PulseBackend` (#1280))
4245
4346
Helpers
4447
=======

qiskit_experiments/test/pulse_backend.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ def __init__(
7373
dt: float = 0.1 * 1e-9,
7474
solver_method="RK23",
7575
seed: int = 0,
76+
atol: float = None,
77+
rtol: float = None,
7678
**kwargs,
7779
):
7880
"""Initialize a backend with model information.
@@ -86,6 +88,8 @@ def __init__(
8688
methods. Defaults to "RK23".
8789
seed: An optional seed given to the random number generator. If this argument is not
8890
set then the seed defaults to 0.
91+
atol: Absolute tolerance during solving.
92+
rtol: Relative tolerance during solving.
8993
"""
9094
super().__init__(
9195
None,
@@ -108,6 +112,12 @@ def __init__(
108112

109113
self.solver_method = solver_method
110114

115+
self.solve_kwargs = {}
116+
if atol:
117+
self.solve_kwargs["atol"] = atol
118+
if rtol:
119+
self.solve_kwargs["rtol"] = rtol
120+
111121
self.static_hamiltonian = static_hamiltonian
112122
self.hamiltonian_operators = hamiltonian_operators
113123
self.static_dissipators = static_dissipators
@@ -338,6 +348,7 @@ def solve(self, schedule: Union[ScheduleBlock, Schedule], qubits: Tuple[int]) ->
338348
t_eval=[time_f],
339349
signals=signal,
340350
method=self.solver_method,
351+
**self.solve_kwargs,
341352
).y[0]
342353

343354
return unitary
@@ -452,6 +463,8 @@ def __init__(
452463
lambda_2: float = 0.8e9,
453464
gamma_1: float = 1e4,
454465
noise: bool = True,
466+
atol: float = None,
467+
rtol: float = None,
455468
**kwargs,
456469
):
457470
"""Initialise backend with hamiltonian parameters
@@ -464,6 +477,8 @@ def __init__(
464477
gamma_1: Relaxation rate (1/T1) for 1-0. Defaults to 1e4.
465478
noise: Defaults to True. If True then T1 dissipation is included in the pulse-simulation.
466479
The strength is given by ``gamma_1``.
480+
atol: Absolute tolerance during solving.
481+
rtol: Relative tolerance during solving.
467482
"""
468483
qubit_frequency_02 = 2 * qubit_frequency + anharmonicity
469484
ket0 = np.array([[1, 0, 0]]).T
@@ -505,6 +520,8 @@ def __init__(
505520
rwa_cutoff_freq=1.9 * qubit_frequency,
506521
rwa_carrier_freqs=[qubit_frequency],
507522
evaluation_mode=evaluation_mode,
523+
atol=atol,
524+
rtol=rtol,
508525
**kwargs,
509526
)
510527

releasenotes/notes/0.3/cleanup-cr-hamiltonian-experiment-7f47c51d26941f16.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ upgrade:
66
setting backend for just checking experiment sequence. The sequence with actual parameters
77
is generated after the backend is set. In addition, now experiments can take ``cr_gate``
88
in the constractor which is ``Gate`` type subclass taking a single parameter (flat-top width).
9-
If one inputs a :class:`~qiskit.extensions.hamiltonian_gate.HamiltonianGate` subclass with
9+
If one inputs a :class:`~qiskit.circuit.library.HamiltonianGate` subclass with
1010
cross resonance Hamiltonian, experiment can be simulated with Aer QASM simulator.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# This code is part of Qiskit.
2+
#
3+
# (C) Copyright IBM 2023.
4+
#
5+
# This code is licensed under the Apache License, Version 2.0. You may
6+
# obtain a copy of this license in the LICENSE.txt file in the root directory
7+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8+
#
9+
# Any modifications or derivative works of this code must retain this
10+
# copyright notice, and modified files need to carry a notice indicating
11+
# that they have been altered from the originals.
12+
13+
"""Test rough amplitude calibration experiment classes."""
14+
15+
from test.base import QiskitExperimentsTestCase
16+
17+
from qiskit import pulse
18+
from qiskit.circuit import Parameter
19+
20+
from qiskit_experiments.exceptions import CalibrationError
21+
from qiskit_experiments.calibration_management.basis_gate_library import FixedFrequencyTransmon
22+
from qiskit_experiments.calibration_management import Calibrations
23+
from qiskit_experiments.library import HalfAngleCal
24+
from qiskit_experiments.test.pulse_backend import SingleTransmonTestBackend
25+
26+
27+
class TestHalfAngleCal(QiskitExperimentsTestCase):
28+
"""A class to test the half angle calibration experiments."""
29+
30+
def setUp(self):
31+
"""Setup the tests."""
32+
super().setUp()
33+
library = FixedFrequencyTransmon()
34+
35+
self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3)
36+
self.cals = Calibrations.from_backend(self.backend, libraries=[library])
37+
38+
def test_amp_parameter_error(self):
39+
"""Test that setting cal_parameter_name to amp raises an error"""
40+
with self.assertRaises(CalibrationError):
41+
HalfAngleCal([0], self.cals, cal_parameter_name="amp")
42+
43+
def test_angle_parameter_missing_error(self):
44+
"""Test that default cal_parameter_name with no matching parameter raises an error"""
45+
cals_no_angle = Calibrations()
46+
dur = Parameter("dur")
47+
amp = Parameter("amp")
48+
sigma = Parameter("σ")
49+
beta = Parameter("β")
50+
drive = pulse.DriveChannel(Parameter("ch0"))
51+
52+
with pulse.build(name="sx") as sx:
53+
pulse.play(pulse.Drag(dur, amp, sigma, beta), drive)
54+
55+
cals_no_angle.add_schedule(sx, num_qubits=1)
56+
with self.assertRaises(CalibrationError):
57+
HalfAngleCal([0], cals_no_angle)
58+
59+
def test_circuits_roundtrip_serializable(self):
60+
"""Test circuits serialization of the experiment."""
61+
exp = HalfAngleCal([0], self.cals, backend=self.backend)
62+
self.assertRoundTripSerializable(exp._transpiled_circuits())

test/library/calibration/test_rabi.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,18 @@
3434
class TestRabiEndToEnd(QiskitExperimentsTestCase):
3535
"""Test the rabi experiment."""
3636

37-
def setUp(self):
37+
@classmethod
38+
def setUpClass(cls):
3839
"""Setup the tests."""
39-
super().setUp()
40+
super().setUpClass()
4041

41-
self.qubit = 0
42+
cls.qubit = 0
4243

4344
with pulse.build(name="x") as sched:
44-
pulse.play(pulse.Drag(160, Parameter("amp"), 40, 0.4), pulse.DriveChannel(self.qubit))
45+
pulse.play(pulse.Drag(160, Parameter("amp"), 40, 0.4), pulse.DriveChannel(cls.qubit))
4546

46-
self.sched = sched
47-
self.backend = SingleTransmonTestBackend(noise=False)
47+
cls.sched = sched
48+
cls.backend = SingleTransmonTestBackend(noise=False, atol=1e-3)
4849

4950
# pylint: disable=no-member
5051
def test_rabi_end_to_end(self):
@@ -100,7 +101,7 @@ def setUp(self):
100101
super().setUp()
101102

102103
self.qubit = 0
103-
self.backend = SingleTransmonTestBackend(noise=False)
104+
self.backend = SingleTransmonTestBackend(noise=False, atol=1e-4)
104105
self.anharmonicity = self.backend.anharmonicity
105106
with pulse.build(name="x") as sched:
106107
with pulse.frequency_offset(self.anharmonicity, pulse.DriveChannel(self.qubit)):
@@ -114,7 +115,7 @@ def setUp(self):
114115
def test_ef_rabi_end_to_end(self):
115116
"""Test the EFRabi experiment end to end."""
116117

117-
test_tol = 0.01
118+
test_tol = 0.05
118119

119120
# Note that the backend is not sophisticated enough to simulate an e-f
120121
# transition so we run the test with a tiny frequency shift, still driving the e-g transition.

test/library/calibration/test_rough_amplitude.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def setUp(self):
3232
super().setUp()
3333
library = FixedFrequencyTransmon()
3434

35-
self.backend = SingleTransmonTestBackend(noise=False)
35+
self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3)
3636
self.cals = Calibrations.from_backend(self.backend, libraries=[library])
3737

3838
def test_circuits(self):
@@ -100,8 +100,13 @@ def setUp(self):
100100

101101
library = FixedFrequencyTransmon()
102102

103+
<<<<<<< HEAD
103104
self.backend = SingleTransmonTestBackend(noise=False)
104105
self.cals = Calibrations.from_backend(self.backend, libraries=[library])
106+
=======
107+
cls.backend = SingleTransmonTestBackend(noise=False, atol=1e-3)
108+
cls.cals = Calibrations.from_backend(cls.backend, libraries=[library])
109+
>>>>>>> 73d0a03 (Update `HamiltonianGate` path and add tolerance to `PulseBackend` (#1280))
105110

106111
# Add some pulses on the 1-2 transition.
107112
d0 = pulse.DriveChannel(0)

test/library/calibration/test_rough_frequency.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class TestRoughFrequency(QiskitExperimentsTestCase):
2828
def setUp(self):
2929
"""Setup the tests."""
3030
super().setUp()
31-
self.backend = SingleTransmonTestBackend(noise=False)
31+
self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3)
3232

3333
def test_init(self):
3434
"""Test that initialization."""
@@ -53,7 +53,9 @@ def test_update_calibrations(self):
5353

5454
freq01 = BackendData(self.backend).drive_freqs[0]
5555

56-
backend_5mhz = SingleTransmonTestBackend(qubit_frequency=freq01 + 5e6, noise=False)
56+
backend_5mhz = SingleTransmonTestBackend(
57+
qubit_frequency=freq01 + 5e6, noise=False, atol=1e-3
58+
)
5759

5860
library = FixedFrequencyTransmon()
5961
cals = Calibrations.from_backend(self.backend, libraries=[library])

test/library/characterization/test_cross_resonance_hamiltonian.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@
2020
from ddt import ddt, data, unpack
2121
from qiskit import QuantumCircuit, pulse, quantum_info as qi
2222
from qiskit.providers.fake_provider import FakeBogotaV2
23-
from qiskit.extensions.hamiltonian_gate import HamiltonianGate
23+
24+
# TODO: remove old path after we stop supporting the relevant version of Qiskit
25+
try:
26+
from qiskit.circuit.library.hamiltonian_gate import HamiltonianGate
27+
except ModuleNotFoundError:
28+
from qiskit.extensions.hamiltonian_gate import HamiltonianGate
29+
2430
from qiskit_aer import AerSimulator
2531
from qiskit_experiments.library.characterization import cr_hamiltonian
2632

test/library/characterization/test_multi_state_discrimination.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def setUp(self):
4949
"""Setup test variables."""
5050
super().setUp()
5151

52-
self.backend = SingleTransmonTestBackend(noise=False)
52+
self.backend = SingleTransmonTestBackend(noise=False, atol=1e-3)
5353

5454
# Build x12 schedule
5555
self.qubit = 0
@@ -97,7 +97,7 @@ def test_discrimination_analysis(self, n_states):
9797

9898
fidelity = exp_data.analysis_results("fidelity").value
9999

100-
self.assertGreaterEqual(fidelity, 0.96)
100+
self.assertGreaterEqual(fidelity, 0.93)
101101

102102
# check that the discriminator differentiates n different states
103103
discrim_lbls = exp_data.analysis_results("discriminator_config").value["attributes"][

0 commit comments

Comments
 (0)