Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QPY schedule serialization #7300

Merged
merged 42 commits into from
Jun 23, 2022

Conversation

nkanazawa1989
Copy link
Contributor

@nkanazawa1989 nkanazawa1989 commented Nov 23, 2021

Summary

This PR adds qiskit.qpy that covers qpy serialization of both QuantumCircuit and ScheduleBlock which is requirement of Qiskit Experiments.

Details and comments

Currently only basic component for MVP

from qiskit import pulse, circuit
from qiskit.qpy.objects.schedules import _write_instruction, _read_instruction
import io

freq = circuit.Parameter("freq")
ch = circuit.Parameter("ch0")
inst = pulse.SetFrequency(freq, pulse.DriveChannel(ch))

container = io.BytesIO()
_write_instruction(container, inst)

container.seek(0)
container.read() # b'\x00\x0c\x00\x00\x00\x02SetFrequencyp\x00\x00\x00\x00\x00\x00\x00\x16\x00\x04\x84\xc4\x06\x13\x0e(G\x1d\x8b\xd0\xf3\xc9D\xd7\x1dXfreqd\x00\x00\x00\x00\x00\x00\x00&\x00\x0cp\x00\x15DriveChannel\x00\x03R\x89\xb3\xf3x2G\xbe\x86\xf8\xddX\xea\xcbe\x85ch0'

container.seek(0)
read_inst = _read_instruction(container); read_inst  # SetFrequency(freq, DriveChannel(ch0))

inst == read_inst  # True

Because in pulse schedule representation (in contrast to QuantumCircuit), parameterizable operand values exit across multiple layers from alignment context parameter to pulse values. To eliminate boilerplate code in each layer, parameter value serialization logic is isolated without changing data structure so that it can be reused.

TODO

  • ScheduleBlock serialization
  • Frame change instructions () serialization
  • Play serialization
  • [ ] Call serialization
  • Context serialization
  • [ ] Discriminator/Kernel serialization
  • Circuit QPY migration
  • Unittest
  • Documentation
  • release note

QuantumCircuit.calibrations field serialization will be done in follow-up.

@nkanazawa1989 nkanazawa1989 added mod: qpy Related to QPY serialization mod: pulse Related to the Pulse module labels Nov 23, 2021
@coveralls
Copy link

coveralls commented Nov 23, 2021

Pull Request Test Coverage Report for Build 2545753902

  • 645 of 699 (92.27%) changed or added relevant lines in 11 files are covered.
  • 6 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.08%) to 84.377%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/qpy/binary_io/circuits.py 71 72 98.61%
qiskit/pulse/transforms/alignments.py 43 45 95.56%
qiskit/qpy/binary_io/schedules.py 162 164 98.78%
qiskit/qpy/common.py 50 54 92.59%
qiskit/qpy/interface.py 38 42 90.48%
qiskit/qpy/binary_io/value.py 53 65 81.54%
qiskit/qpy/type_keys.py 201 230 87.39%
Files with Coverage Reduction New Missed Lines %
qiskit/pulse/transforms/alignments.py 3 93.79%
qiskit/qpy/common.py 3 91.03%
Totals Coverage Status
Change from base Build 2545752111: 0.08%
Covered Lines: 55498
Relevant Lines: 65774

💛 - Coveralls


def _write_measure_processor(file_obj, data):
name = data.name.encode("utf8")
params = json.dumps(data.params, separators=(",", ":")).encode("utf8")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume parameters of Kernel and Discriminator are a free-form but json serializable dictionary (i.e. no numpy, no parameter, etc...). However I've never seen actual spec of these objects. @taalexander do you have any information?


def _parse_custom_instruction(custom_instructions, gate_name, params):
(type_str, num_qubits, num_clbits, definition) = custom_instructions[gate_name]
if type_str == "i":
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TypeKey enum strategy doesn't work here because i is also used for Integer (because key is not scoped). This logic imperfection looks bit awkward (but removing enum makes pulse qpy code really hard to read because there are many kinds of operand classes).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we want to have a custom instruction table type key enum defined in this module too? They're circuit specific but likely will grow more over time as we have special custom circuit operations with different representations that are needed. For example QPY v3 added a "p" here for PauliEvolutionGate

@nkanazawa1989 nkanazawa1989 marked this pull request as ready for review November 30, 2021 13:28
@nkanazawa1989 nkanazawa1989 requested a review from a team as a code owner November 30, 2021 13:29
@nkanazawa1989 nkanazawa1989 force-pushed the feature/schedule-serialization branch 2 times, most recently from da0715b to 1f836c4 Compare June 22, 2022 05:37
@nkanazawa1989 nkanazawa1989 force-pushed the feature/schedule-serialization branch from 1f836c4 to 7c9f829 Compare June 22, 2022 05:46
@mtreinish mtreinish linked an issue Jun 22, 2022 that may be closed by this pull request
mtreinish
mtreinish previously approved these changes Jun 22, 2022
Copy link
Member

@mtreinish mtreinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, thanks for the quick fixes. I left a few questions inline about the size of certain fields. I don't think it's a blocker at all (I'm going to tag as automerge) the choices you made are reasonable but I wanted to just raise the question so we have it in the review log, primarily because if we do need to bump any we'll have to bump the QPY version.

@@ -155,8 +154,49 @@
CUSTOM_CIRCUIT_INST_DEF_PACK = "!H1cII?Q"
CUSTOM_CIRCUIT_INST_DEF_SIZE = struct.calcsize(CUSTOM_CIRCUIT_INST_DEF_PACK)

# CALIBRATION
CALIBRATION = namedtuple("CALIBRATION", ["num_cals"])
CALIBRATION_PACK = "!I"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how many calibrations are typical on a circuit, this sets the upper bound at 2**32 which is probably sufficient but I'm wondering if we want to allow more or less.


# CALIBRATION_DEF
CALIBRATION_DEF = namedtuple("CALIBRATION_DEF", ["name_size", "num_qubits", "num_params", "type"])
CALIBRATION_DEF_PACK = "!III1c"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here as above we're limiting the calibration name, number of qubits, and number of parameters to 2**32. I think that's reasonable but maybe too high.

"amp_limited",
],
)
SYMBOLIC_PULSE_PACK = "!HHHH?"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This limits the number of bytes to the envelope, constraints, and valid amp conditions size to 2**16 bytes. I know they're zlib compressed but do you have as sense for how large these can get?


# MAP_ITEM
MAP_ITEM = namedtuple("MAP_ITEM", ["key_size", "type", "size"])
MAP_ITEM_PACK = "!H1cH"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we can have keys more than 2*16 characters?

@mtreinish mtreinish added Changelog: Deprecation Include in "Deprecated" section of changelog Changelog: New Feature Include in the "Added" section of the changelog automerge labels Jun 22, 2022
@mergify mergify bot merged commit c650341 into Qiskit:main Jun 23, 2022
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Jul 3, 2022
The support for serializing SymbolicPulse objects using QPY was added in
PR Qiskit#7300 and has been released as part of 0.21.0. However, the
documentation for the SymbolicPulse class had a note saying the QPY
support was pending. This was necessary when the SymbolicPulse class was
added in Qiskit#7821 because it was unclear when we'd be able to add the QPY
support. But, Qiskit#7300 was updated and merged soon after Qiskit#7821, but we
neglected to remove that note. This commit corrects the oversight and
removes the stale note.
mergify bot added a commit that referenced this pull request Jul 4, 2022
The support for serializing SymbolicPulse objects using QPY was added in
PR #7300 and has been released as part of 0.21.0. However, the
documentation for the SymbolicPulse class had a note saying the QPY
support was pending. This was necessary when the SymbolicPulse class was
added in #7821 because it was unclear when we'd be able to add the QPY
support. But, #7300 was updated and merged soon after #7821, but we
neglected to remove that note. This commit corrects the oversight and
removes the stale note.

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
mergify bot pushed a commit that referenced this pull request Jul 4, 2022
The support for serializing SymbolicPulse objects using QPY was added in
PR #7300 and has been released as part of 0.21.0. However, the
documentation for the SymbolicPulse class had a note saying the QPY
support was pending. This was necessary when the SymbolicPulse class was
added in #7821 because it was unclear when we'd be able to add the QPY
support. But, #7300 was updated and merged soon after #7821, but we
neglected to remove that note. This commit corrects the oversight and
removes the stale note.

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 47c7c27)
mergify bot added a commit that referenced this pull request Jul 4, 2022
…#8292)

The support for serializing SymbolicPulse objects using QPY was added in
PR #7300 and has been released as part of 0.21.0. However, the
documentation for the SymbolicPulse class had a note saying the QPY
support was pending. This was necessary when the SymbolicPulse class was
added in #7821 because it was unclear when we'd be able to add the QPY
support. But, #7300 was updated and merged soon after #7821, but we
neglected to remove that note. This commit corrects the oversight and
removes the stale note.

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
(cherry picked from commit 47c7c27)

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
rathishcholarajan added a commit to rathishcholarajan/qiskit-ibm-runtime that referenced this pull request Jul 5, 2022
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>
rathishcholarajan added a commit to Qiskit/qiskit-ibm-runtime that referenced this pull request Jul 5, 2022
* Copy Qiskit/qiskit#8055

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

* Copy qpy changes from Qiskit/qiskit#8093

Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>

* Copy Qiskit/qiskit#8200

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

* Copy of Qiskit/qiskit#7300

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>

* Copy of Qiskit/qiskit#8235

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: Naoki Kanazawa <nkanazawa1989@gmail.com>
@nkanazawa1989 nkanazawa1989 deleted the feature/schedule-serialization branch November 25, 2022 02:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Deprecation Include in "Deprecated" section of changelog Changelog: New Feature Include in the "Added" section of the changelog mod: pulse Related to the Pulse module mod: qpy Related to QPY serialization
Projects
None yet
Development

Successfully merging this pull request may close these issues.

qpy serialization for pulse schedule
7 participants