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

Start deprecation of complex parameters in Qiskit Pulse [2] #9897

Merged
merged 15 commits into from
Apr 4, 2023

Conversation

TsafrirA
Copy link
Collaborator

@TsafrirA TsafrirA commented Apr 3, 2023

Summary

This PR starts the deprecation process of complex parameters in Qiskit Pulse, by raising a PendingDeprecationWarning when one assigns a complex value to ParameterExpression in any Pulse object.

This PR replaces PR #9735 which produced inconsistent warnings (issue #9837) and was reverted.

Details and comments

PR #9002 began the deprecation of the last complex parameters in Qiskit Pulse (namely the amp parameter of pulses in the SymbolicPulse library). Complex values in ParameterExpression have caused issues in the past (for example #9187), and it seems likely that eventually complex values will be phased out. With #9002 in place, we can therefore begin heading in this direction and deprecate the use of complex parameters.

To avoid the problems identified in #9837, the caching of format_parameter_value was removed.

Sidenote

It was debated whether or not other pulse-related formatting functions (see here and here) should be merged into a single warning-yielding formatting function in the global qiskit utils (avoiding circular imports). Eventually, it was decided that this not necessary - often calibration retrieval doesn't support complex values to be begin with (see here), making the warning unnecessary and even misleading. Furthermore, the pulse utils formatting function introduces rounding, which is currently not implemented in the other formatting functions. While such rounding is important, it was decided it should not be done in this PR.

@TsafrirA TsafrirA requested review from a team, eggerdj and wshanks as code owners April 3, 2023 10:58
@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

@coveralls
Copy link

coveralls commented Apr 3, 2023

Pull Request Test Coverage Report for Build 4596529943

  • 4 of 4 (100.0%) changed or added relevant lines in 2 files are covered.
  • 6 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.03%) to 85.412%

Files with Coverage Reduction New Missed Lines %
qiskit/extensions/quantum_initializer/squ.py 2 80.0%
crates/accelerate/src/sabre_swap/layer.rs 4 97.32%
Totals Coverage Status
Change from base Build 4588217505: 0.03%
Covered Lines: 67474
Relevant Lines: 78998

💛 - Coveralls

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 finding the correct logic to do deprecation. I think we can unify format functions after we drop this complex value support (likely conditional branch for complex value is just redundant for other inline format functions, as it is not allowed at circuit level). Let's keep logical change minimum for this PR.

@@ -65,6 +64,19 @@ def format_parameter_value(
evaluated = float(evaluated.real)
if evaluated.is_integer():
evaluated = int(evaluated)
else:
warnings.warn(
Copy link
Contributor

Choose a reason for hiding this comment

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

@Eric-Arellano Can we use your deprecation decorator for this case? Seems like predicate is good place to do type check, but writing try-except logic inside lambda function looks bit ugly.

Copy link
Collaborator

@Eric-Arellano Eric-Arellano Apr 3, 2023

Choose a reason for hiding this comment

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

Hello! Indeed, this is a great case of using @deprecate_arg with predicate and deprecation_description.

In Python, a lambda is simply shorthand for writing a normal def function. They result in the same function object. So, here, you would create a function like this:

def _is_deprecated_operand(operand: ParameterExpression) -> bool:
   ...

Then, predicate=_is_deprecated_operand, without parantheses.

You will unfortunately need to duplicate some code because _is_deprecated_operand can only return the bool and it will not set the evaluated argument for you. So, you still need the code in this function body to set evaluated. You could get fancy and DRY that with yet another helper function -- but also this is temporary code and maybe not a big deal to duplicate

--

Here's an example of what to set deprecation_description to:

https://github.com/Qiskit/qiskit-terra/blob/6a946cf47886c3d6de4b52c98c3bacbda0d35df8/qiskit/synthesis/evolution/suzuki_trotter.py#L54-L64

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is what I'm thinking of as an alternative. But writing another function for just checking type seems too much overhead, and indeed inlining the warning is much simpler. I know your decorator properly updates API docs. Does it make sense to suppress exception here?
https://github.com/Qiskit/qiskit-terra/blob/6a946cf47886c3d6de4b52c98c3bacbda0d35df8/qiskit/utils/deprecation.py#L291-L292

Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this function is not added to toctree and we don't have motivation for using decorator for the API doc update.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But writing another function for just checking type seems too much overhead

What's the overhead? Code readability?

Note that this function is not added to toctree and we don't have motivation for using decorator for the API doc update.

The decorator has two benefits:

  1. Update the docstring for the function so that it shows up in API docs and help(my_func) in REPLs/Jupyter
  2. Standardize the message

Copy link
Contributor

@nkanazawa1989 nkanazawa1989 Apr 3, 2023

Choose a reason for hiding this comment

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

Yeah readability and maintenance overhead. We need to implement quite similar conditional branch in two separate functions. e.g.

def _is_deprecated_operand(operand, decimal):
    try:
        evaluated = complex(operand)
        evaluated = np.round(evaluated, decimals=decimal)
        return not np.isreal(evaluated)
    except TypeError:
        return False

@deprecate_arg(
   ...,
   predicate=_is_deprecated_operand,
)
def format_parameter_value(operand, decimal):
    try:
        operand = complex(operand)
        evaluated = np.round(evaluated, decimals=decimal)
        if np.isreal(evaluated):
            ...
    except TypeError:
        return operand

This doesn't seem to me like readable and efficient (because it evaluates symbolic expression twice). Also we cannot pass decimal to the predicate function because this line ignores *args.
https://github.com/Qiskit/qiskit-terra/blob/751fa46947aa1cc581b0fc25673236e396397b0f/qiskit/utils/deprecation.py#L169-L177

Again, this function is not exposed to end-users and documentation doesn't become good motivation for us, though standardization of error massage is worth considering (I'm basically a big fan of this decorator). Currently I tend to approve this PR as it is if you don't have strong objection. It would be great in future if the deprecate util could support such (edge) case more efficiently.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Again, this function is not exposed to end-users and documentation doesn't become good motivation for us, though standardization of error massage is worth considering

Here's the standard format:

https://github.com/Qiskit/qiskit-terra/blob/751fa46947aa1cc581b0fc25673236e396397b0f/test/python/utils/test_deprecation.py#L152-L155

You'd want to change the first part of the first sentence to say something like

Passing a complex to the argument arg5 in the function blah is pending...

--

Currently I tend to approve this PR as it is if you don't have strong objection.

No objections from me to approve the PR as is :) The main thing I care about is docs having the deprecations, which isn't relevant here.

It would be great in future if the deprecate util could support such (edge) case more efficiently.

Hm, idea: #9902

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks @Eric-Arellano for the detailed explanation!

@nkanazawa1989 nkanazawa1989 added this pull request to the merge queue Apr 4, 2023
Merged via the queue into Qiskit:main with commit 2ebf81e Apr 4, 2023
giacomoRanieri pushed a commit to giacomoRanieri/qiskit-terra that referenced this pull request Apr 16, 2023
)

* Add warning and update tests

* Release notes

* Move warning to all Pulse objects.

* Fix releasenote typo

* Move warning to format_parameter_value

* Remove cache to insure warning

* Lint
github-merge-queue bot pushed a commit to qiskit-community/qiskit-experiments that referenced this pull request May 9, 2023
### Summary
This PR aims to remove the use of complex amplitude for `SymbolicPulse`
in calibration experiments. Most notable changes are to the
`HalfAngleCal` experiment and the `FixedFrquencyTransmon` library. With
these changes, support of complex values in general raises a
`PendingDeprecationWarning`.

### Details and comments
Qiskit Terra recently changed the representation of `SymbolicPulse` from
complex amplitude to (`amp`,`angle`). Once the deprecation is completed,
some calibration experiments will fail. Additionally, assignment of
complex parameters in general has caused problems recently (See
Qiskit-Terra issue
[9187](Qiskit/qiskit#9187)), and is also
being phased out (See Qiskit-Terra PR
[9735](Qiskit/qiskit#9735)).

Most calibration experiments are oblivious to these changes, with the
exception of `HalfAngleCal` and `RoughAmplitudeCal`. The library
`FixedFrequencyTransmon` also has to conform with the new
representation.

To create as little breaking changes as possible, the following were
changed:

- `FixedFrequencyTransmon` library was converted to the new
representation. All experiments will work as they have been with it.
- `RoughAmplitudeCal` was changed such that it will work for both real
or complex `amp`, without changing the type of the value.
- `HalfAngleCal` was changed to calibrate 'angle' instead of the complex
amplitude. A user which uses the `FixedFrequencyTransmon` library will
experience no change (except for the added parameters). A user which
uses custom built schedules will experience an error. To simplify the
transition, most likely scenarios (schedule with no `angle` parameter,
`cal_parameter_name="amp"`) will raise an informative error with
explanation about the needed changes.

A `PendingDeprecationWarning` is raised with every initialization of
`ParameterValue` with complex type value (which also covers addition of
parameter value to a calibration). Note that Qiskit-Terra PR
[9897](Qiskit/qiskit#9897) will also raise
a warning from the Terra side, for all assignment of complex parameters.

Handling of loaded calibrations which do not conform to the new
representation will be sorted out once PR #1120 is merged, as it
introduces a major change in calibration loading.

---------

Co-authored-by: Naoki Kanazawa <[email protected]>
Co-authored-by: Will Shanks <[email protected]>
Co-authored-by: Daniel J. Egger <[email protected]>
king-p3nguin pushed a commit to king-p3nguin/qiskit-terra that referenced this pull request May 22, 2023
)

* Add warning and update tests

* Release notes

* Move warning to all Pulse objects.

* Fix releasenote typo

* Move warning to format_parameter_value

* Remove cache to insure warning

* Lint
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.

5 participants