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

Deprecate Pulse package and dependencies #13164

Merged
merged 31 commits into from
Oct 23, 2024
Merged

Conversation

eliarbel
Copy link
Contributor

Summary

This PR deprecates the Pulse package and any non-pulse package code within Qiskit that uses it.

Closes #13063

Details and comments

@eliarbel eliarbel added Changelog: Deprecation Include in "Deprecated" section of changelog mod: pulse Related to the Pulse module labels Sep 17, 2024
@eliarbel eliarbel added this to the 1.3.0 milestone Sep 17, 2024
@wshanks wshanks mentioned this pull request Sep 18, 2024
@coveralls
Copy link

coveralls commented Sep 23, 2024

Pull Request Test Coverage Report for Build 11468453533

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 416 of 440 (94.55%) changed or added relevant lines in 74 files are covered.
  • 39 unchanged lines in 6 files lost coverage.
  • Overall coverage increased (+0.1%) to 88.67%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/dagcircuit/dagdependency.py 9 10 90.0%
qiskit/transpiler/passes/scheduling/base_scheduler.py 1 2 50.0%
qiskit/pulse/library/symbolic_pulses.py 20 24 83.33%
qiskit/transpiler/passes/calibration/rzx_builder.py 26 31 83.87%
qiskit/transpiler/passes/scheduling/dynamical_decoupling.py 2 7 28.57%
crates/circuit/src/dag_circuit.rs 43 51 84.31%
Files with Coverage Reduction New Missed Lines %
qiskit/transpiler/passes/scheduling/dynamical_decoupling.py 1 78.46%
qiskit/transpiler/target.py 1 94.05%
crates/accelerate/src/two_qubit_decompose.rs 1 92.09%
crates/circuit/src/imports.rs 2 77.78%
crates/qasm2/src/lex.rs 4 92.48%
crates/qasm2/src/parse.rs 30 97.15%
Totals Coverage Status
Change from base Build 11411236768: 0.1%
Covered Lines: 74896
Relevant Lines: 84466

💛 - Coveralls

Added deprecations in `dag_circuit.rs`
Added more deprecations in `builder.py`
Fixed some deprecations comments
This commit adds `warnings.catch_warnings` blocks to some methods which
are not directly deprecated but otherwise use classes or methods which
are being deprecated. Adding this filter to specific methods which are
used in common workflow, e.g. transpilation and for which we don't want
pulse deprecations to be emitted if pulse is not used directly by the user.
@eliarbel
Copy link
Contributor Author

I think this PR is ready for review now as it contains all the deprecations, unit-test assertions, warning filtering and release notes I thought we should have for deprecating the pulse package. A couple notes worth highlighting and getting feedback on:

  1. I've introduced a few deprecation decorators, specifically for pulse, located in qiskit.utils.deprecate_pulse.py. The aim of these decorators is to reuse deprecations messages and overall reduce code clutter due to the deprecation code in many places.
  2. For unit test classes which interact heavily with pulse (e.g. all test cases in test/python/pulse) I used a new class level decorator which is used to suppress all deprecation warnings issued by pulse classes and methods. Same goes for calibration builder passes.
  3. warnings.catch_warnings is used in several places which are called in common workflows such as transpile and working with Target. The motivation being is to prevent pulse-related deprecation from being emitted in cases where the user code does not call deprecated pulse APIs directly.

@eliarbel eliarbel marked this pull request as ready for review October 14, 2024 21:15
Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Thanks @eliarbel!! This was a very large task to tackle. I added a few suggestions regarding deprecation messages and the filtering strategy. As for the use of custom decorators to reduce code repetition, we don't commonly do it but I see how in this case they are handy. Technically, as long as they don't show up in the docs, they wouldn't be part of the documented interface, so we would be able to remove them in 2.0 without issues.

qiskit/utils/deprecate_pulse.py Outdated Show resolved Hide resolved
qiskit/utils/deprecate_pulse.py Show resolved Hide resolved
Comment on lines +66 to +90
def ignore_pulse_deprecation_warnings(func):
"""Ignore deprecation warnings emitted from the pulse package"""

@functools.wraps(func)
def wrapper(*args, **kwargs):
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", category=DeprecationWarning, message="The (.*) ``qiskit.pulse"
)
return func(*args, **kwargs)

return wrapper


def decorate_test_methods(decorator):
"""Put a given decorator on all the decorated class methods whose name starts with `test_`"""

def cls_wrapper(cls):
for attr in dir(cls):
if attr.startswith("test_") and callable(object.__getattribute__(cls, attr)):
setattr(cls, attr, decorator(object.__getattribute__(cls, attr)))

return cls

return cls_wrapper
Copy link
Contributor

Choose a reason for hiding this comment

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

In my experience, we usually tackle these large deprecations adding filters to the qiskit test base class rather than defining a custom decorator for this:

qiskit/test/utils/base.py

Lines 171 to 177 in fbfe738

# Safe to remove once `FakeBackend` is removed (2.0)
warnings.filterwarnings(
"ignore", # If "default", it floods the CI output
category=DeprecationWarning,
message=r".*from_backend using V1 based backend is deprecated as of Aer 0.15*",
module="qiskit.providers.fake_provider.fake_backend",
)
. It is less granular than your approach (in the sense that we don't control which tests have raised these filtered warnings) but I think it makes the removal process smoother. This is not standardized and it probably will depend a bit on who you ask.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a tradeoff here... It seems that the preferred way in Qiskit to handle deprecation warnings in testing is by using unittest.assertWarns and that QiskitTestCase-level filtering is meant to be used mainly for messages emitted by 3rd party packages or otherwise in very special circumstances like deprecating a key core element which makes the use of assertWarns really problematic.
In this case, I wanted to avoid putting assertWarns everywhere in test/python/pulse but still use it on deprecated functions outside of Pulse like QuantumCircuit.calibrations. So I took a hybrid approach where I used the @decorate_test_methods(ignore_pulse_deprecation_warnings) only in test/python/pulse and test/python/visualization_v2 which both are being deprecated as a whole, as well as on the calibration builder passes in test/python/transpiler which are being deprecated as well. I like this balance but I'm open to other views or ideas about how to achieve this in a different way.
BTW, FWIW, these decorators are useful as markers for things to be removed in 2.0.

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
@eliarbel
Copy link
Contributor Author

Here is the result of a performance comparison of Qiskit benchmarks, showing only the change w.r.t the default ASV factor. There isn't a clear trend and I'm curious about what these changes mean really. Anyway for now I think we should wait a bit until the PR is stable and then rerun this and decide whether or not it's worthwhile to dive into this in more detail.

Change Before [54fe09b] After [f78a957] Ratio Benchmark (Parameter)
- 138±0.7μs 106±0.5μs 0.77 circuit_construction.CircuitConstructionBench.time_circuit_copy(14, 8192)
- 1.68±0.07ms 1.05±0.04ms 0.63 circuit_construction.CliffordSynthesis.time_clifford_synthesis(10)
+ 1.02±0.02ms 1.69±0.2ms 1.65 mapping_passes.PassBenchmarks.time_dense_layout(14, 1024)
+ 3.62±0ms 3.99±0.03ms 1.1 mapping_passes.PassBenchmarks.time_layout_2q_distance(14, 1024)
+ 1.15±0.01ms 1.27±0ms 1.1 mapping_passes.PassBenchmarks.time_layout_2q_distance(5, 1024)
+ 471±1ms 525±0.5ms 1.12 passes.MultipleBasisPassBenchmarks.time_basis_translator(14, 1024, ['rx', 'ry', 'rz', 'r', 'rxx', 'id'])
+ 667±3ms 748±2ms 1.12 passes.MultipleBasisPassBenchmarks.time_basis_translator(20, 1024, ['rx', 'ry', 'rz', 'r', 'rxx', 'id'])
+ 158±0.4ms 174±0.1ms 1.1 passes.MultipleBasisPassBenchmarks.time_basis_translator(5, 1024, ['rx', 'ry', 'rz', 'r', 'rxx', 'id'])
+ 312±2ms 344±6ms 1.1 quantum_info.RandomCliffordBench.time_random_clifford('5,1000')
- 16.3±0.4ms 5.60±0.4ms 0.34 quantum_volume.QuantumVolumeBenchmark.time_ibmq_backend_transpile(1, 'translator')
- 18.1±1ms 6.35±0.05ms 0.35 transpiler_benchmarks.TranspilerBenchSuite.time_single_gate_compile
+ 54.9±0.9ms 77.6±6ms 1.41 transpiler_qualitative.TranspilerQualitativeBench.time_transpile_time_cnt3_5_180(0, 'sabre', 'sabre')

@eliarbel eliarbel requested a review from ElePT October 17, 2024 09:31
ElePT
ElePT previously approved these changes Oct 17, 2024
Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Overall, the deprecation looks good, and I think it is in a mergeable state. The only missing point I think could be improved is my previous comment on adding a link to Qiskit Dynamics for the deprecated pulse dependencies. I suggested always mentioning the link for simplicity (even for dependencies that are not being ported to Dynamics), but of course having a dedicated decorator for the elements that are being ported would be even better. I don't think it's a deal breaker though, so I will approve, and can re-approve if you decide to implement the suggestion.

@ElePT
Copy link
Contributor

ElePT commented Oct 17, 2024

And regarding the benchmarks, I see what you mean, and in my experience the variability of the asv results is quite high, which makes certain improvements difficult to track (I have seen this with Unitary Synthesis, where the tests that didn't run it would also change quite a lot when benchmarking the PR).

@eliarbel
Copy link
Contributor Author

The only missing point I think could be improved is my previous comment on adding a link to Qiskit Dynamics for the deprecated pulse dependencies.

Thanks @ElePT . I have implemented your suggestion already but haven't pushed it yet since I'm waiting for input from @nkanazawa1989 and @DanPuzzuoli regarding the exact dependencies which should be moved to Dynamics. Putting the list here so we can discuss in a wider forum if needed:

qiskit.compiler.schedule()
qiskit.compiler.sequence()
qiskit.scheduler.schedule_circuit()
qiskit.scheduler.sequence()
qiskit.scheduler.ScheduleConfig
qiskit.scheduler.methods.as_soon_as_possible()
qiskit.scheduler.methods.as_late_as_possible()
qiskit.visualization.pulse_v2.draw()

The inner class `TestAddCalibration` in `test_transpiler.py::TestTranspilerParallel` calls a deprecated functionality.
In an attempt to use `self.assertWarns` inside the inner class, a reference to the outer
class was stored as a class attribute of `TestAddCalibration`.  dill got confused as to how to serialize
the outer class which derives from `QiskitTestCase`. So switched to using `warnings.catch_warnnigs`
instead in the inner class to avoid this reference of the outer class in the serialized inner class.
Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Thanks a lot! I agree with the changes, the PR is good to go, I just had one tiny final comment.

qiskit/utils/deprecate_pulse.py Outdated Show resolved Hide resolved
@ElePT ElePT added this pull request to the merge queue Oct 23, 2024
Merged via the queue into Qiskit:main with commit 056f286 Oct 23, 2024
16 checks passed
raynelfss added a commit to raynelfss/qiskit that referenced this pull request Oct 29, 2024
- Use `QuantumCircuit._has_calibration_for()` when trying to obtain calibrations from a `QuantumCircuit` due to the deprecation of the `Pulse` package.
github-merge-queue bot pushed a commit that referenced this pull request Oct 31, 2024
…Rust. (#13237)

* Initial: Move the rest of the `BasisTranslator` to Rust.

Fixes Port `BasisTranslator` to Rust #12246

This is the final act of the efforts to move the `BasisTranslator` transpiler pass into Rust. With many of the parts of this pass already living in Rust, the following commits attempt to bring in the final changes to allow complete operation of this pass in the Rust space (with of course some interaction with Python.)

Methodology:
The way this works is by keeping the original `BasisTranslator` python class, and have it store the rust-space counterpart (now called `CoreBasisTranslator`) which will perform all of the operations leveraging the existent Rust API's available for the `Target` (#12292), `EquivalenceLibrary`(#12585) and the `BasisTranslator` methods `basis_search` (#12811) and `compose_transforms`(#13137).

All of the inner methods will have private visibility and will not be accessible to `Python` as they're intended to be internal by design.

By removing the extra layers of conversion we should be seeing a considerable speed-up, alongside all of the other incremental improvements we have made.

Changes:

- Add the pyo3 class/struct `BasisTranslator` that will contain allof the main data used by the transpiler pass to perform its operation.
- Convert the `target_basis` into a set manually from python before sending it into the Rust space.
- Remove the exposure of `basis_search` and `compose_transforms` to python.
- Change `basis_search` so that it accepts references to `HashSet` instances instead of accepting a `HashSet<&str>` instance.
- Change inner method's visibility for `basis_search` and `compose_transform` modules in rust.
- Expose the exception imports from `Target` to the `accelerate` crate.
- Expose `DAGCircuit::copy_empty_like` to the rest of the crates.
- Remove all of the unused imports in the Python-side `BasisTranslator`.

Blockers:
- [ ] #12811

* Fix: Redundancies with serialization methods
- Remove extra copies of `target`, `target_basis`, `equiv_lib`, and `min_qubits`.
- Remove unnecessary mutability in `apply_transforms` and `replace_node`.

* Refactor: Remove `BasisTranslator` struct, use pymethod.
- Using this method avoids the creation of a datastructure in rust and the overhead of deserializing rust structures which can be overly slow due to multiple cloning. With this update, since the `BasisTranslator` never mutates, it is better to not store anything in Rust.

* Lint: Ignore too_many_args flag from clippy on `basis_translator::run()`

* Fix: Remove redundant clone

* Fix: Leverage using `unwrap_operation` when taking op_nodes from the dag.
- Add function signature in `base_run`.

* Update crates/accelerate/src/basis/basis_translator/mod.rs

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>

* Adapt to #13164
- Use `QuantumCircuit._has_calibration_for()` when trying to obtain calibrations from a `QuantumCircuit` due to the deprecation of the `Pulse` package.

---------

Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
eliarbel added a commit to eliarbel/qiskit that referenced this pull request Nov 3, 2024
This commit deprecates `inst_map` in `PassManagerConfig.__init__`. It should have
been part of the pulse deprecation PR Qiskit#13164 but I somehow missed to covere it. We're
already in our feature freeze period for version 1.3 but since this is not a new feature
but rather an addendum to the pulse deprecation PR  we should squeeze this in as well.
github-merge-queue bot pushed a commit that referenced this pull request Nov 4, 2024
This commit deprecates `inst_map` in `PassManagerConfig.__init__`. It should have
been part of the pulse deprecation PR #13164 but I somehow missed to covere it. We're
already in our feature freeze period for version 1.3 but since this is not a new feature
but rather an addendum to the pulse deprecation PR  we should squeeze this in as well.
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 mod: pulse Related to the Pulse module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deprecate pulse module and related functionality for removal in 2.0
4 participants