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
7 changes: 7 additions & 0 deletions qiskit/pulse/calibration_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ def __init__(self, arguments: Optional[Sequence[str]] = None):

Args:
arguments: User provided argument names for this entry, if parameterized.

Raises:
PulseError: When `arguments` is not a sequence of string.
"""
if arguments and not all(isinstance(arg, str) for arg in arguments):
raise PulseError(f"Arguments must be name of parameters. Not {arguments}.")
if arguments:
arguments = list(arguments)
self._user_arguments = arguments

self._definition = None
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
fixes:
- |
An edge case of pickle :class:`.InstructionScheduleMap` with
non-picklable iterable ``arguments`` is supported.
When :meth:`InstructionScheduleMap.add` is called with
``arguments``, this method typecasts the user value to a python list
to guarantee the added entry is picklable.
For example, a user may supply a python dict keys as ``arguments``.
This also guarantees parallel transpile works with such a custom
instruction schedule map, where the map object is pickled and
distributed to every parallel threads.
25 changes: 25 additions & 0 deletions test/python/pulse/test_instruction_schedule_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,31 @@ def test_instmap_picklable(self):

self.assertEqual(instmap, deser_instmap)

def test_instmap_picklable_with_arguments(self):
"""Test instmap pickling with an edge case.

This test attempts to pickle instmap with custom entry,
in which arguments are provided by users in the form of
python dict key object that is not picklable.
"""
instmap = FakeAthens().defaults().instruction_schedule_map

param1 = Parameter("P1")
param2 = Parameter("P2")
sched = Schedule()
sched.insert(0, Play(Constant(100, param1), DriveChannel(0)), inplace=True)
sched.insert(0, Play(Constant(100, param2), DriveChannel(1)), inplace=True)
to_assign = {"P1": 0.1, "P2": 0.2}

# Note that dict keys is not picklable
# Instmap should typecast it into list to pickle itself.
instmap.add("custom", (0, 1), sched, arguments=to_assign.keys())

ser_obj = pickle.dumps(instmap)
deser_instmap = pickle.loads(ser_obj)

self.assertEqual(instmap, deser_instmap)

def test_check_backend_provider_cals(self):
"""Test if schedules provided by backend provider is distinguishable."""
instmap = FakeOpenPulse2Q().defaults().instruction_schedule_map
Expand Down