Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 2 additions & 11 deletions docs/tutorials/calibrating_armonk.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
"outputs": [],
"source": [
"library = FixedFrequencyTransmon(default_values={\"duration\": 320})\n",
"cals = Calibrations.from_backend(backend, library)"
"cals = Calibrations.from_backend(backend, libraries=[library])"
]
},
{
Expand Down Expand Up @@ -900,16 +900,7 @@
"execution_count": 27,
"id": "317994db",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/daniel/Documents/IBM/qiskit/qiskit-experiments/qiskit_experiments/calibration_management/calibrations.py:1333: UserWarning: Schedules are only saved in text format. They cannot be re-loaded.\n",
" warnings.warn(\"Schedules are only saved in text format. They cannot be re-loaded.\")\n"
]
}
],
"outputs": [],
"source": [
"cals.save(file_type=\"csv\", overwrite=True, file_prefix=\"Armonk\")"
]
Expand Down
94 changes: 63 additions & 31 deletions qiskit_experiments/calibration_management/calibrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,25 @@ def __init__(
coupling_map: Optional[List[List[int]]] = None,
control_channel_map: Optional[Dict[Tuple[int, ...], List[ControlChannel]]] = None,
library: Optional[Union[BasisGateLibrary, List[BasisGateLibrary]]] = None,
libraries: Optional[List[BasisGateLibrary]] = None,
add_parameter_defaults: bool = True,
backend_name: Optional[str] = None,
backend_version: Optional[str] = None,
):
"""Initialize the calibrations.

Calibrations can be initialized from a basis gate library, i.e. a subclass of
Calibrations can be initialized from a list of basis gate libraries, i.e. a subclass of
:class:`BasisGateLibrary`. As example consider the following code:

.. code-block:: python

cals = Calibrations(
library=FixedFrequencyTransmon(
basis_gates=["x", "sx"],
default_values={duration: 320}
)
libraries=[
FixedFrequencyTransmon(
basis_gates=["x", "sx"],
default_values={duration: 320}
)
]
)

Args:
Expand All @@ -99,27 +102,41 @@ def __init__(
keys are tuples of qubits and the values are a list of ControlChannels
that correspond to the qubits in the keys. If a control_channel_map is given
then the qubits must be in the coupling_map.
library: A library instance from which to get template schedules to register as well
as default parameter values.
library (deprecated): A library instance from which to get template schedules to
register as well as default parameter values.
libraries: A list of library instance from which to get template schedules to register
as well as default parameter values.
add_parameter_defaults: A boolean to indicate weather the default parameter values of
the given library should be used to populate the calibrations. By default this
the given libraries should be used to populate the calibrations. By default this
value is True but can be set to false when deserializing a calibrations object.
backend_name: The name of the backend that these calibrations are attached to.
backend_version: The version of the backend that these calibrations are attached to.

Raises:
NotImplementedError: if a list of libraries is given. This will be implemented in
the future.
CalibrationError: if both library and libraries are given. Note that library will be
removed in future versions.

"""
self._backend_name = backend_name
self._backend_version = backend_version

if isinstance(library, list):
raise NotImplementedError(
"Passing a list of libraries from which to instantiate "
"will be supported in future releases."
if library:
warnings.warn(
"library has been deprecated, please provide `libraries` instead."
"The `library` argument along with this warning will be removed "
"in Qiskit Experiments 0.4.",
DeprecationWarning,
stacklevel=2,
)

if libraries:
raise CalibrationError("Cannot supply both library and libraries.")

if not isinstance(library, list):
libraries = [library]
else:
libraries = library

# Mapping between qubits and their control channels.
self._control_channel_map = control_channel_map if control_channel_map else {}

Expand Down Expand Up @@ -149,18 +166,18 @@ def __init__(
self._hash_to_counter_map = {}
self._parameter_counter = 0

self._library = None
if library is not None:
self._library = library
self._libraries = libraries
if libraries is not None:
for lib in libraries:

# Add the basis gates
for gate in library.basis_gates:
self.add_schedule(library[gate], num_qubits=library.num_qubits(gate))
# Add the basis gates
for gate in lib.basis_gates:
self.add_schedule(lib[gate], num_qubits=lib.num_qubits(gate))

# Add the default values
if add_parameter_defaults:
for param_conf in library.default_values():
self.add_parameter_value(*param_conf, update_inst_map=False)
# Add the default values
if add_parameter_defaults:
for param_conf in lib.default_values():
self.add_parameter_value(*param_conf, update_inst_map=False)

# 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.
Expand Down Expand Up @@ -220,6 +237,7 @@ def from_backend(
cls,
backend: Backend,
library: Optional[BasisGateLibrary] = None,
libraries: Optional[List[BasisGateLibrary]] = None,
add_parameter_defaults: bool = True,
) -> "Calibrations":
"""Create an instance of Calibrations from a backend.
Expand All @@ -228,8 +246,10 @@ def from_backend(
backend: A backend instance from which to extract the qubit and readout frequencies
(which will be added as first guesses for the corresponding parameters) as well
as the coupling map.
library: A library instance from which to get template schedules to register as well
as default parameter values.
library: A library or list thereof from which to get template schedules to register as
well as default parameter values.
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
value is ``True``.
Expand All @@ -246,6 +266,7 @@ def from_backend(
getattr(backend.configuration(), "coupling_map", []),
getattr(backend.configuration(), "control_channels", None),
library,
libraries,
add_parameter_defaults,
backend_name,
getattr(backend, "version", None),
Expand All @@ -264,9 +285,20 @@ def from_backend(
return cals

@property
def library(self) -> Optional[BasisGateLibrary]:
"""Return the name of the library, e.g. for experiment metadata."""
return self._library
def libraries(self) -> Optional[List[BasisGateLibrary]]:
"""Return the libraries used to initialize the calibrations."""
return self._libraries

@property
def library(self) -> Optional[List[BasisGateLibrary]]:
"""Return the libraries used to initialize the calibrations."""
warnings.warn(
"library has been deprecated, use libraries instead."
"This warning will be removed with backport in Qiskit Experiments 0.4.",
DeprecationWarning,
stacklevel=2,
)
return self._libraries

def _get_operated_qubits(self) -> Dict[int, List[int]]:
"""Get a dict describing qubit couplings.
Expand Down Expand Up @@ -1609,7 +1641,7 @@ def __eq__(self, other: "Calibrations") -> bool:
- The backends have the same name.
- The backends have the same version.
- The calibrations contain the same schedules.
- The stored paramters have the same values.
- The stored parameters have the same values.
"""
if self.backend_name != other.backend_name:
return False
Expand Down Expand Up @@ -1654,7 +1686,7 @@ def config(self) -> Dict[str, Any]:
kwargs = {
"coupling_map": self._coupling_map,
"control_channel_map": ControlChannelMap(self._control_channel_map),
"library": self.library,
"libraries": self.libraries,
"add_parameter_defaults": False, # the parameters will be added outside of the init
"backend_name": self._backend_name,
"backend_version": self._backend_version,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
deprecations:
- |
The library argument to :class:`.Calibrations` has been deprecated in favour
of a new argument called libraries.
2 changes: 1 addition & 1 deletion test/calibration/experiments/test_drag.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def setUp(self):
library = FixedFrequencyTransmon()

self.backend = DragBackend(gate_name="Drag(x)")
self.cals = Calibrations.from_backend(self.backend, library)
self.cals = Calibrations.from_backend(self.backend, libraries=[library])
self.test_tol = 0.05

def test_update(self):
Expand Down
2 changes: 1 addition & 1 deletion test/calibration/experiments/test_fine_amplitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def setUp(self):
library = FixedFrequencyTransmon()

self.backend = MockFineAmp(-np.pi * 0.07, np.pi, "xp")
self.cals = Calibrations.from_backend(self.backend, library)
self.cals = Calibrations.from_backend(self.backend, libraries=[library])

def test_cal_options(self):
"""Test that the options are properly propagated."""
Expand Down
2 changes: 1 addition & 1 deletion test/calibration/experiments/test_fine_drag.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def setUp(self):
library = FixedFrequencyTransmon()

self.backend = FineDragTestBackend()
self.cals = Calibrations.from_backend(self.backend, library)
self.cals = Calibrations.from_backend(self.backend, libraries=[library])

def test_experiment_config(self):
"""Test converting to and from config works"""
Expand Down
2 changes: 1 addition & 1 deletion test/calibration/experiments/test_fine_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def setUp(self):

self.inst_map.add("sx", 0, sx_sched)

self.cals = Calibrations.from_backend(FakeArmonk(), FixedFrequencyTransmon())
self.cals = Calibrations.from_backend(FakeArmonk(), libraries=[FixedFrequencyTransmon()])

@data(-0.5e6, -0.1e6, 0.1e6, 0.5e6)
def test_end_to_end(self, freq_shift):
Expand Down
2 changes: 1 addition & 1 deletion test/calibration/experiments/test_ramsey_xy.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def setUp(self):
super().setUp()

library = FixedFrequencyTransmon()
self.cals = Calibrations.from_backend(FakeArmonk(), library)
self.cals = Calibrations.from_backend(FakeArmonk(), libraries=[library])

def test_end_to_end(self):
"""Test that we can run on a mock backend and perform a fit.
Expand Down
4 changes: 2 additions & 2 deletions test/calibration/experiments/test_rough_amplitude.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def setUp(self):
library = FixedFrequencyTransmon()

self.backend = FakeArmonk()
self.cals = Calibrations.from_backend(self.backend, library)
self.cals = Calibrations.from_backend(self.backend, libraries=[library])

def test_circuits(self):
"""Test the quantum circuits."""
Expand Down Expand Up @@ -86,7 +86,7 @@ def setUp(self):
library = FixedFrequencyTransmon()

self.backend = FakeArmonk()
self.cals = Calibrations.from_backend(self.backend, library)
self.cals = Calibrations.from_backend(self.backend, libraries=[library])

# Add some pulses on the 1-2 transition.
d0 = pulse.DriveChannel(0)
Expand Down
2 changes: 1 addition & 1 deletion test/calibration/experiments/test_rough_frequency.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_update_calibrations(self):
backend.defaults().qubit_freq_est = [freq01, freq01]

library = FixedFrequencyTransmon(basis_gates=["x", "sx"])
cals = Calibrations.from_backend(FakeArmonk(), library=library)
cals = Calibrations.from_backend(FakeArmonk(), libraries=[library])

prev_freq = cals.get_parameter_value(cals.__drive_freq_parameter__, (0,))
self.assertEqual(prev_freq, freq01)
Expand Down
Loading