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

Qiskit Pulse migration to Dynamics #365

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

arthurostrauss
Copy link
Contributor

Summary

This PR is a first step towards Qiskit Pulse migration to Qiskit Dynamics.

I

Details and comments

t contains:

  • A full migration of all qiskit.pulse files into the pulse module of Dynamics, with their imports passing from qiskit.pulse to qiskit_dynamics.pulse
  • All the tests of the pulse module present in Qiskit, now migrated to the pulse tests of Dynamics (I removed one that had to do with Qobj at pulse level, I'm not sure what is the future for such interface in Qiskit core)
  • A full migration of qiskit.scheduler module, contained within pulse module of Dynamics.
  • A new Python file called update_circuit, called upon import of qiskit_dynamics.pulse, whose purpose is to dynamically add properties and methods to the QuantumCircuit object that enable the recovery of the pulse level features (e.g. calibrations, op_start_times, add_calibration...). It also copies and overrides the assign_parameters , compose, and copy_empty_like methods of the original QuantumCircuit object, as current versions of those methods involve updating the calibrations of the circuit. We could maintain them in the future by just catching the latest implementation in Qiskit core and adding the piece dealing with custom calibrations. This editing of the original class occurs only if the concerned attributes are not present (meaning that Qiskit 2.0 and above is used).

@nkanazawa1989
Copy link
Contributor

See Qiskit/qiskit#13063 also

Copy link
Contributor

@nkanazawa1989 nkanazawa1989 left a comment

Choose a reason for hiding this comment

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

Thanks for migration of the pulse module! This is great job :)

I removed one that had to do with Qobj at pulse level, I'm not sure what is the future for such interface in Qiskit core

This should be fine because Qiskit Dynamics doesn't require wire format. These are missing components in the PR:

  • Please write release note
  • Please also migrate the visualization module (qiskit.visualization.pulse_v2)

May main concern is usage of monkey patch as I wrote in the comments below.


r"""
===========================
Pulse (:mod:`qiskit.pulse`)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is not rendered as a module documentation. You also need to update Sphinx API docs configuration.
https://github.com/qiskit-community/qiskit-dynamics/blob/main/docs/apidocs/index.rst

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure how to proceed for this. I have modified the Python file to make it more coherent as a whole but did not touch the docs yet.

qiskit_dynamics/pulse/parser.py Outdated Show resolved Hide resolved
@@ -22,7 +22,7 @@
import numpy as np
import sympy as sym

from qiskit.pulse import (
from qiskit_dynamics.pulse import (
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be great if you can directly convert ScheduleBlock into Signal to remove the legacy Schedule along with this module. Of course this is not the scope of this PR. Just keep it in mind :)

Perhaps we can move pulse_to_signals under transforms submodule.

test/dynamics/pulse/test_builder.py Outdated Show resolved Hide resolved
test/dynamics/pulse/test_parser.py Outdated Show resolved Hide resolved
if name:
cpy.name = name
return cpy
if not hasattr(QuantumCircuit, "calibrations"):
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think monkey patch is not right approach because of following reasons:

  • Monkey patch is a temporary solution and should not be permanent. Qiskit core decided to drop these methods permanently.

  • This hack affects not only QiskitDynamics but also other packages such as add-ons using QuantumCircuit object. These packages are not aware of the hack and might cause unexpected interactions (edge cases). This is almost unmanageable.

  • If someone wants to write new package with the calibration feature, it's difficult to know when this monkey patch is applied. One may need to write hasattr(circ, "calibrations") every time, but this is very cumbersome.

  • If you transpile this patched circuit object, the output is the same QuantumCircuit type but ._calibrations data is lost because the dag to circuit conversion doesn't care the calibration data. From the end user viewpoint, this behavior looks a bug. But we don't have bandwidth to maintain the custom transpile infrastructure.

Instead of using monkey patch, I would define an explicit subclass with multiple inheritance not to tightly couple calibration data to the core data model of QuantumCircuit.

For example:

from qiskit.circuit import QuantumCircuit
from functools import wraps

class Calibration:

    @wraps(QuantumCircuit.__init__)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.calibrations = {}

    @wraps(QuantumCircuit.assign_parameters)
    def assign_parameters(self, *args, **kwargs):
        super().assign_parameters(*args, **kwargs)
        ... # implement assign logic

class CalibratedCircuit(Calibration, QuantumCircuit):

    @classmethod
    def from_circuit(cls, circuit):
        new_circ = circuit.copy()
        new_circ.__class__ = cls
        new_circ.calibrations = {}
        return new_circ

With this, the signature of transpile is

transpile(QuantumCircuit|CalibratedCircuit) -> QuantumCircuit

and user can notice transpile doesn't support calibration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for this review. I like the proposed solution. However, wouldn't there be a way to replicate the Analysis and Transformation passes that were introduced in the scheduling stage, and add them as plugins of the DynamicsBackend object? I was moreover wondering if those custom backend plugins as described here (https://docs.quantum.ibm.com/api/qiskit/transpiler_plugins) could be automatically called when using transpile() over the backend. If yes, then we could just adapt the case of the transpilation pipeline to take the plugins from the backend, checking for calibrations (we would therefore check that the type of the input is a CalibratedCircuit. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants