Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e2992f0
* Added the restless mix-in to the init for documentation.
eggerdj Apr 29, 2022
1716aee
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj May 4, 2022
f406c30
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj May 13, 2022
cba70ea
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Jun 8, 2022
c944772
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Jul 7, 2022
2fa0251
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Jul 8, 2022
f94be94
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Aug 15, 2022
9fdb84f
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Oct 6, 2022
187bb33
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Oct 10, 2022
5593342
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Oct 12, 2022
c6106db
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Oct 14, 2022
4b39095
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Oct 25, 2022
93f1180
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Oct 26, 2022
ca0f59e
Merge branch 'Qiskit:main' into main
eggerdj Nov 1, 2022
5afc28f
Merge branch 'main' of github.com:eggerdj/qiskit-experiments
eggerdj Nov 1, 2022
7716463
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Nov 2, 2022
b2e9db2
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Nov 22, 2022
7d44612
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Dec 14, 2022
9000df0
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Dec 14, 2022
9262f96
Merge branch 'main' of github.com:Qiskit/qiskit-experiments
eggerdj Jan 10, 2023
d385010
Merge branch 'Qiskit:main' into main
eggerdj May 13, 2023
63f8869
Merge branch 'main' of github.com:Qiskit-Extensions/qiskit-experiments
eggerdj Jun 14, 2023
33d1c50
* Remove special variables from the Calibrations
eggerdj Jun 14, 2023
d522382
* Clean-up meas_freq and drive_freq variables.
eggerdj Jun 14, 2023
e1a7380
* Add missing cal_parameter_name in init
eggerdj Jun 15, 2023
d88e6b4
* Simplified parameters without schedule
eggerdj Jun 15, 2023
10567f2
* lint
eggerdj Jun 15, 2023
015ced4
* Align tests to changes
eggerdj Jun 15, 2023
ea6a454
Update releasenotes/notes/params_without_schedule-20555d98875a626b.yaml
eggerdj Jun 19, 2023
7d8a6ed
* Simplified interface.
eggerdj Jun 19, 2023
c4ad955
Merge branch 'main' into remove_reserved_vars
eggerdj Jun 20, 2023
48d693a
Update qiskit_experiments/calibration_management/calibrations.py
eggerdj Jun 20, 2023
813ed84
* Deprecation of meas_freq.
eggerdj Jun 20, 2023
95ac7cd
* black
eggerdj Jun 20, 2023
395c1f8
Update qiskit_experiments/calibration_management/calibrations.py
nkanazawa1989 Jun 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class BasisGateLibrary(ABC, Mapping):
# Location where default parameter values are stored. These may be updated at construction.
__default_values__ = {}

# Parameters that do not belong to a schedule, a set of names
__parameters_without_schedule__ = set()

def __init__(
self,
basis_gates: Optional[List[str]] = None,
Expand Down Expand Up @@ -204,12 +207,18 @@ class FixedFrequencyTransmon(BasisGateLibrary):
The amplitude of the ``sx`` and ``sy`` pulses is half the provided value.
- angle: The phase of the complex amplitude of the pulses.

Parameters without schedule:
- meas_freq: frequency of the measurement drives.
- drive_freq: frequency of the qubit drives.

Note that the β and amp parameters may be linked between the x and y as well as between
the sx and sy pulses. All pulses share the same duration and σ parameters.
"""

__default_values__ = {"duration": 160, "amp": 0.5, "β": 0.0, "angle": 0.0}

__parameters_without_schedule__ = {"meas_freq", "drive_freq"}

def __init__(
self,
basis_gates: Optional[List[str]] = None,
Expand Down
53 changes: 33 additions & 20 deletions qiskit_experiments/calibration_management/calibrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ class Calibrations:
ScheduleBlock are supported.
"""

# The name of the parameter under which the qubit frequencies are registered.
__drive_freq_parameter__ = "drive_freq"

# The name of the parameter under which the readout frequencies are registered.
__readout_freq_parameter__ = "meas_freq"

def __init__(
self,
coupling_map: Optional[List[List[int]]] = None,
Expand Down Expand Up @@ -153,7 +147,6 @@ def __init__(
libraries = [libraries]

for lib in libraries:

# Add the basis gates
for gate in lib.basis_gates:
self.add_schedule(lib[gate], num_qubits=lib.num_qubits(gate))
Expand All @@ -163,19 +156,17 @@ def __init__(
for param_conf in lib.default_values():
self.add_parameter_value(*param_conf, update_inst_map=False)

# Add the parameters that do not belong to a schedule.
for param_name in lib.__parameters_without_schedule__:
self._register_parameter(Parameter(param_name), tuple())

# This internal parameter is False so that if a schedule is added after the
# init it will be set to True and serialization will raise an error.
self._has_manually_added_schedule = False

# Instruction schedule map variables and support variables.
self._inst_map = InstructionScheduleMap()

# Use the same naming convention as in backend.defaults()
self.drive_freq = Parameter(self.__drive_freq_parameter__)
self.meas_freq = Parameter(self.__readout_freq_parameter__)
self._register_parameter(self.drive_freq, ())
self._register_parameter(self.meas_freq, ())

# Backends with a single qubit may not have a coupling map.
self._coupling_map = coupling_map if coupling_map is not None else []

Expand All @@ -187,6 +178,28 @@ def __init__(
# Push the schedules to the instruction schedule map.
self.update_inst_map()

@property
@deprecate_func(
is_property=True,
since="0.6",
package_name="qiskit-experiments",
additional_msg="The drive_freq is moved to FixedFrequencyTransmon basis gate library.",
)
def drive_freq(self):
"""Parameter object for qubit drive frequency."""
return self._parameter_map.get(("drive_freq", (), None), None)

@property
@deprecate_func(
is_property=True,
since="0.6",
package_name="qiskit-experiments",
additional_msg="The meas_freq is moved to FixedFrequencyTransmon basis gate library.",
)
def meas_freq(self):
"""Parameter object for qubit measure frequency."""
return self._parameter_map.get(("meas_freq", (), None), None)

def _check_consistency(self):
"""Check that the attributes defined in self are consistent.

Expand Down Expand Up @@ -237,7 +250,7 @@ def from_backend(
libraries: A list of libraries from which to get template schedules to register as
well as default parameter values.
add_parameter_defaults: A boolean to indicate whether the default parameter values of
the given library should be used to populate the calibrations. By default this
the given library should be used to populate the calibrations. By default, this
value is ``True``.

Returns:
Expand All @@ -260,11 +273,13 @@ def from_backend(
)

if add_parameter_defaults:
for qubit, freq in enumerate(backend_data.drive_freqs):
cals.add_parameter_value(freq, cals.drive_freq, qubit, update_inst_map=False)
if ("drive_freq", (), None) in cals._parameter_map:
for qubit, freq in enumerate(backend_data.drive_freqs):
cals.add_parameter_value(freq, "drive_freq", qubit, update_inst_map=False)

for meas, freq in enumerate(backend_data.meas_freqs):
cals.add_parameter_value(freq, cals.meas_freq, meas, update_inst_map=False)
if ("meas_freq", (), None) in cals._parameter_map:
for meas, freq in enumerate(backend_data.meas_freqs):
cals.add_parameter_value(freq, "meas_freq", meas, update_inst_map=False)

# Update the instruction schedule map after adding all parameter values.
cals.update_inst_map()
Expand Down Expand Up @@ -449,7 +464,6 @@ def _get_full_qubits_of_schedule(
"""
for key, circuit_inst_num_qubits in self._schedules_qubits.items():
if key.schedule == schedule_name:

if len(partial_qubits) == circuit_inst_num_qubits:
return [partial_qubits]

Expand Down Expand Up @@ -888,7 +902,6 @@ def _get_channel_index(self, qubits: Tuple[int, ...], chan: PulseChannel) -> int

# Control channels name example ch1.0$1
if isinstance(chan, ControlChannel):

channel_index_parts = chan.index.name[2:].split("$")
qubit_channels = channel_index_parts[0]

Expand Down
7 changes: 2 additions & 5 deletions qiskit_experiments/calibration_management/update_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def update(
calibrations: Calibrations,
exp_data: ExperimentData,
result_index: Optional[int] = None,
parameter: str = None,
parameter: str = "drive_freq",
group: str = "default",
fit_parameter: Optional[str] = None,
**options,
Expand All @@ -163,16 +163,13 @@ def update(
exp_data: The experiment data from which to update.
result_index: The result index to use which defaults to -1.
parameter: The name of the parameter to update. If None is given this will default
to :code:`calibrations.__qubit_freq_parameter__`.
to `drive_freq`.
group: The calibrations group to update. Defaults to "default."
options: Trailing options.
fit_parameter: The name of the fit parameter in the analysis result. This will default
to the class variable :code:`__fit_parameter__` if not given.

"""
if parameter is None:
parameter = calibrations.__drive_freq_parameter__

super().update(
calibrations=calibrations,
exp_data=exp_data,
Expand Down
9 changes: 6 additions & 3 deletions qiskit_experiments/library/calibration/fine_frequency_cal.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def __init__(
physical_qubits: Sequence[int],
calibrations: Calibrations,
backend: Optional[Backend] = None,
cal_parameter_name: Optional[str] = "drive_freq",
delay_duration: Optional[int] = None,
repetitions: List[int] = None,
auto_update: bool = True,
Expand All @@ -54,11 +55,13 @@ def __init__(
fine frequency calibration.
calibrations: The calibrations instance with the schedules.
backend: Optional, the backend to run the experiment on.
cal_parameter_name: The name of the parameter to update in the calibrations.
This defaults to `drive_freq`.
delay_duration: The duration of the delay at :math:`n=1`. If this value is
not given then the duration of the gate named ``gate_name`` in the
calibrations will be used.
auto_update: Whether or not to automatically update the calibrations. By
default this variable is set to True.
auto_update: Whether to automatically update the calibrations or not. By
default, this variable is set to True.
gate_name: This argument is only needed if ``delay_duration`` is None. This
should be the name of a valid schedule in the calibrations.
"""
Expand All @@ -72,7 +75,7 @@ def __init__(
schedule_name=None,
repetitions=repetitions,
backend=backend,
cal_parameter_name=calibrations.__drive_freq_parameter__,
cal_parameter_name=cal_parameter_name,
auto_update=auto_update,
)

Expand Down
5 changes: 4 additions & 1 deletion qiskit_experiments/library/calibration/frequency_cal.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(
physical_qubits: Sequence[int],
calibrations: Calibrations,
backend: Optional[Backend] = None,
cal_parameter_name: Optional[str] = "drive_freq",
delays: Optional[List] = None,
osc_freq: float = 2e6,
auto_update: bool = True,
Expand All @@ -46,6 +47,8 @@ def __init__(
frequency calibration.
calibrations: The calibrations instance with the schedules.
backend: Optional, the backend to run the experiment on.
cal_parameter_name: The name of the parameter to update in the calibrations.
This defaults to `drive_freq`.
delays: The list of delays that will be scanned in the experiment, in seconds.
osc_freq: A frequency shift in Hz that will be applied by means of
a virtual Z rotation to increase the frequency of the measured oscillation.
Expand All @@ -58,7 +61,7 @@ def __init__(
backend=backend,
delays=delays,
osc_freq=osc_freq,
cal_parameter_name=calibrations.__drive_freq_parameter__,
cal_parameter_name=cal_parameter_name,
auto_update=auto_update,
)

Expand Down
4 changes: 4 additions & 0 deletions qiskit_experiments/library/calibration/rough_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(
backend: Optional[Backend] = None,
auto_update: bool = True,
absolute: bool = True,
cal_parameter_name: Optional[str] = "drive_freq",
):
"""See :class:`.QubitSpectroscopy` for detailed documentation.

Expand All @@ -53,6 +54,8 @@ def __init__(
automatically update the frequency in the calibrations.
absolute: Boolean to specify if the frequencies are absolute or relative to the
qubit frequency in the backend.
cal_parameter_name: The name of the parameter to update in the calibrations.
This defaults to `drive_freq`.

Raises:
QiskitError: If there are less than three frequency shifts.
Expand All @@ -66,6 +69,7 @@ def __init__(
absolute=absolute,
updater=Frequency,
auto_update=auto_update,
cal_parameter_name=cal_parameter_name,
)

def _attach_calibrations(self, circuit: QuantumCircuit):
Expand Down
11 changes: 11 additions & 0 deletions releasenotes/notes/params_without_schedule-20555d98875a626b.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
upgrade:
- |
The variables `__drive_freq_parameter__` and `__readout_freq_parameter__`
have been removed from `Calibrations`. These variables were given special
treatment which is inconsistent with the framework. To replace them a
mechanism to define and add parameters without a schedule has been added to
the basis gate library. This has the added benefit of making the API of
frequency calibration experiments more consistent with the other calibration
experiments. Calibration developers can now add parameters to their library that are not
attached to a schedule in a meaningful way.
8 changes: 3 additions & 5 deletions test/calibration/test_calibrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,12 @@ def test_remove_schedule(self):
self.cals.add_schedule(sched, num_qubits=1)

self.assertEqual(len(self.cals.schedules()), 4)
self.assertEqual(len(self.cals.parameters), 9)
self.assertEqual(len(self.cals.parameters), 7)

self.cals.remove_schedule(sched)

self.assertEqual(len(self.cals.schedules()), 3)
self.assertEqual(len(self.cals.parameters), 8)
self.assertEqual(len(self.cals.parameters), 6)
for param in [self.sigma, self.amp_xp, self.amp_x90p, self.amp_y90p, self.beta]:
self.assertTrue(param in self.cals.parameters)

Expand Down Expand Up @@ -323,7 +323,7 @@ def test_from_backend(self):
"""Test that when generating calibrations from backend
the data is passed correctly"""
backend = FakeBelemV2()
cals = Calibrations.from_backend(backend)
cals = Calibrations.from_backend(backend, libraries=[FixedFrequencyTransmon()])
with self.assertWarns(DeprecationWarning):
config_args = cals.config()["kwargs"]
control_channel_map_size = len(config_args["control_channel_map"].chan_map)
Expand Down Expand Up @@ -565,8 +565,6 @@ def test_default_schedules(self):
self.sigma,
self.beta,
self.duration,
self.cals.drive_freq,
self.cals.meas_freq,
}
self.assertEqual(len(set(self.cals.parameters.keys())), len(expected))

Expand Down
2 changes: 1 addition & 1 deletion test/calibration/test_setup_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def test_standard_single_qubit_gates(self):
self.assertListEqual(library.basis_gates, ["x", "y", "sx", "sy"])

def test_unlinked_parameters(self):
"""Test the we get schedules with unlinked parameters."""
"""Test that we get schedules with unlinked parameters."""

library = FixedFrequencyTransmon(link_parameters=False)

Expand Down
7 changes: 4 additions & 3 deletions test/calibration/test_update_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from qiskit_experiments.library import QubitSpectroscopy
from qiskit_experiments.calibration_management.calibrations import Calibrations
from qiskit_experiments.calibration_management.update_library import Frequency
from qiskit_experiments.calibration_management.basis_gate_library import FixedFrequencyTransmon
from qiskit_experiments.test.mock_iq_backend import MockIQBackend
from qiskit_experiments.test.mock_iq_helpers import MockIQSpectroscopyHelper as SpectroscopyHelper

Expand Down Expand Up @@ -55,7 +56,7 @@ def test_frequency(self):
self.assertEqual(result.quality, "good")

# Test the integration with the Calibrations
cals = Calibrations.from_backend(FakeAthensV2())
self.assertNotEqual(cals.get_parameter_value(cals.__drive_freq_parameter__, qubit), value)
cals = Calibrations.from_backend(FakeAthensV2(), libraries=[FixedFrequencyTransmon()])
self.assertNotEqual(cals.get_parameter_value("drive_freq", qubit), value)
Frequency.update(cals, exp_data)
self.assertEqual(cals.get_parameter_value(cals.__drive_freq_parameter__, qubit), value)
self.assertEqual(cals.get_parameter_value("drive_freq", qubit), value)
4 changes: 2 additions & 2 deletions test/library/calibration/test_fine_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ def test_calibration_version(self):
fine_freq = FineFrequencyCal([0], self.cals, backend)
armonk_freq = BackendData(FakeArmonkV2()).drive_freqs[0]

freq_before = self.cals.get_parameter_value(self.cals.__drive_freq_parameter__, 0)
freq_before = self.cals.get_parameter_value("drive_freq", 0)

self.assertAlmostEqual(freq_before, armonk_freq)

expdata = fine_freq.run()
self.assertExperimentDone(expdata)

freq_after = self.cals.get_parameter_value(self.cals.__drive_freq_parameter__, 0)
freq_after = self.cals.get_parameter_value("drive_freq", 0)

# Test equality up to 10kHz on a 100 kHz shift
self.assertAlmostEqual(freq_after, armonk_freq + exp_helper.freq_shift, delta=1e4)
Expand Down
2 changes: 1 addition & 1 deletion test/library/calibration/test_ramsey_xy.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_update_calibrations(self):

tol = 1e4 # 10 kHz resolution

freq_name = self.cals.__drive_freq_parameter__
freq_name = "drive_freq"

# Check qubit frequency before running the cal
f01 = self.cals.get_parameter_value(freq_name, 0)
Expand Down
4 changes: 2 additions & 2 deletions test/library/calibration/test_rough_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_update_calibrations(self):
library = FixedFrequencyTransmon()
cals = Calibrations.from_backend(self.backend, libraries=[library])

prev_freq = cals.get_parameter_value(cals.__drive_freq_parameter__, (0,))
prev_freq = cals.get_parameter_value("drive_freq", (0,))
self.assertEqual(prev_freq, freq01)

frequencies = np.linspace(freq01 - 10.0e6, freq01 + 10.0e6, 11)
Expand All @@ -69,7 +69,7 @@ def test_update_calibrations(self):
self.assertExperimentDone(expdata)

# Check the updated frequency which should be shifted by 5MHz.
post_freq = cals.get_parameter_value(cals.__drive_freq_parameter__, (0,))
post_freq = cals.get_parameter_value("drive_freq", (0,))
self.assertTrue(abs(post_freq - freq01 - 5e6) < 1e6)

def test_experiment_config(self):
Expand Down