Skip to content

Commit

Permalink
Add support for saving/loading calibration parameters without schedules
Browse files Browse the repository at this point in the history
5b6fa06 added support for saving and
loading `Calibrations` objects with a JSON format that preserved
calibrated gate schedules. However, it did not capture and restore the
`Parameter` objects for calibration parameters (like `drive_freq`) which
were not associated with a schedule. This commit adds support for these
parameters by adding an entry to the serialization model that holds a
placeholder `QuantumCircuit` with the parameters attached to placeholder
instructions. `ExperimentEncoder` can serialize `QuantumCircuit` to qpy
and so supports this format. Using a placeholder circuit like this is
the only supported way to serialize `Parameter` objects. An alternative
approach would be to store and retrieve the hidden attributes of the
`Parameter` objects directly.
  • Loading branch information
wshanks committed Jan 16, 2024
1 parent be220b2 commit d337439
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
30 changes: 29 additions & 1 deletion qiskit_experiments/calibration_management/save_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@

from dataclasses import dataclass, field, asdict
from datetime import datetime
from typing import List, Dict, Any
from typing import List, Dict, Any, Tuple

from qiskit import QuantumCircuit
from qiskit.circuit import Instruction, Parameter
from qiskit.pulse import ScheduleBlock

from .calibrations import Calibrations
Expand Down Expand Up @@ -118,6 +120,14 @@ class CalibrationModelV1:
parameters: List[ParameterModelV1] = field(default_factory=list)
"""List of calibrated pulse parameters."""

schedule_free_parameters: QuantumCircuit = field(default_factory=lambda: QuantumCircuit(1))
"""Placeholder circuit for parameters not associated with a schedule
The circuit contains placeholder instructions which have the Parameter
objects attached and operate on the qubits that the parameter is associated
with in the calibrations.
"""

schema_version: str = "1.0"
"""Version of this data model. This must be static."""

Expand Down Expand Up @@ -177,13 +187,26 @@ def calibrations_to_dict(
sched_obj.metadata.update(qubit_metadata)
sched_entries.append(sched_obj)

max_qubit = max(
(max(k.qubits or (0,)) for k in cals._parameter_map if k.schedule is None),
default=0,
)
schedule_free_parameters = QuantumCircuit(max_qubit + 1)
for sched_key, param in cals._parameter_map.items():
if sched_key.schedule is None:
schedule_free_parameters.append(
Instruction("parameter_container", len(sched_key.qubits), 0, [param]),
sched_key.qubits,
)

model = CalibrationModelV1(
backend_name=cals.backend_name,
backend_version=cals.backend_version,
device_coupling_graph=getattr(cals, "_coupling_map"),
control_channel_map=ControlChannelMap(getattr(cals, "_control_channel_map")),
schedules=sched_entries,
parameters=data_entries,
schedule_free_parameters=schedule_free_parameters,
)

return asdict(model)
Expand Down Expand Up @@ -257,6 +280,11 @@ def calibrations_from_dict(
schedule=param.schedule,
update_inst_map=False,
)

for instruction in model.schedule_free_parameters.data:
for param in instruction.operation.params:
cals._register_parameter(param, instruction.qubits)

cals.update_inst_map()

return cals
3 changes: 0 additions & 3 deletions test/calibration/test_calibrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1692,9 +1692,6 @@ def test_save_load_library_csv(self):
BackendData(backend).drive_freqs[0],
)

# Expected to fail because json calibration loading does not support
# restoring Parameter objects
@unittest.expectedFailure
def test_save_load_library(self):
"""Test that we can load and save a library.
Expand Down

0 comments on commit d337439

Please sign in to comment.