Skip to content

Clarify the purpose of execute() function and deprecate transpile kwargs#7888

Closed
mtreinish wants to merge 9 commits into
Qiskit:mainfrom
mtreinish:deprecate-legacy-execute
Closed

Clarify the purpose of execute() function and deprecate transpile kwargs#7888
mtreinish wants to merge 9 commits into
Qiskit:mainfrom
mtreinish:deprecate-legacy-execute

Conversation

@mtreinish
Copy link
Copy Markdown
Member

Summary

This commit updates the documentation of the execute() function to
clarify its purpose and intent. The execute() function is provided as a
higher level abstraction and convenience function for use cases where
you just want to execute a circuit and not worry about how it gets
compiled for a particular backend. The set of options the function is
minimal by design because it should just be about running circuits with
no options needed and if you need to exert more control over the
compilation you should use transpile() and backend.run() together
instead. As part of this a large number of legacy kwargs defined on the
function are deprecated as they are mostly holdovers from before the
purpose of the function was clear and really are just needless
duplication of transpile(), schedule(), and assemble() (even though this
isn't used anymore after #7886).

Details and comments

Closes #7640

This commit updates the documentation of the execute() function to
clarify its purpose and intent. The execute() function is provided as a
higher level abstraction and convenience function for use cases where
you just want to execute a circuit and not worry about how it gets
compiled for a particular backend. The set of options the function is
minimal by design because it should just be about running circuits with
no options needed and if you need to exert more control over the
compilation you should use transpile() and backend.run() together
instead. As part of this a large number of legacy kwargs defined on the
function are deprecated as they are mostly holdovers from before the
purpose of the function was clear and really are just needless
duplication of transpile(), schedule(), and assemble() (even though this
isn't used anymore after Qiskit#7886).

Closes Qiskit#7640
@mtreinish mtreinish requested a review from a team as a code owner April 4, 2022 21:21
@mtreinish mtreinish added the Changelog: Deprecated Add a "Deprecated" entry in the GitHub Release changelog. label Apr 4, 2022
@mtreinish mtreinish added this to the 0.21 milestone Apr 4, 2022
Comment thread qiskit/execute_function.py Outdated
DEPRECATED: Properties returned by a backend, including information on gate
errors, readout errors, qubit coherence times, etc. Find a backend
that provides this information with:
``backend.properties()``
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Below this line, how come initial_layout got to stay non-deprecated? That feels like a transpiler option as well, perhaps?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was on the fence about it. It felt like maybe high level enough to say run this circuit on these qubits. But, I agree it's probably better to deprecate it here too and rely on transpile() if you need this.

Comment on lines +338 to +346
if shots is not None:
if not hasattr(backend.options, "shots"):
warnings.warn(
"The shots argument is deprecated as of Qiskit Terra 0.21.0, "
"and will be removed in a future release. The backend you are running on does "
"not support setting the number of shots so this option will have no effect.",
DeprecationWarning,
stacklevel=2,
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If the shots keyword is deprecated, I think we need the warning in both paths? It'll just have a different message. (Similar comment for memory and seed_simulator as well.)

On the other hand, shots may be one of the few options that could still be appropriate for execute.

edit: I just saw the extra comment in the release note about the first point here. In this case, perhaps we might want to make the distinction in the docstring as well, since at the moment the documentation looks the same for a completely deprecated argument.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sure, I'll update the docstring some more. I honestly just got annoyed/overwhelmed by all the options here (you might notice the deprecation warnings get a bit less detailed the further down you go).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, I totally understand that - there's hundreds of them.

Comment thread releasenotes/notes/deprecate-legacy-execute-args-b607c5e85ed2d073.yaml Outdated
Co-authored-by: Jake Lishman <jake@binhbar.com>
@jakelishman
Copy link
Copy Markdown
Member

I suspect we may need to invest a bit of time updating tutorials and other documentation after this - I feel like we probably have a fair amount of extant code on qiskit.org that uses execute.

Comment on lines +462 to +479
if scheduling_method is not None:
warnings.warn(
"The scheduling_method argument is deprecated as of Qiskit Terra 0.21.0, "
"and will be removed in a future release. If you require scheduling your circuit "
"prior to execution you should use the :func:`~.schedule` function explicitly with "
"prior to running the circuit.",
DeprecationWarning,
stacklevel=2,
)
if init_qubits is not None:
warnings.warn(
"The init_qubits argument is deprecated as of Qiskit Terra 0.21.0, "
"and will be removed in a future release. If you require scheduling your circuit "
"prior to execution you should use the :func:`~.schedule` function explicitly with "
"prior to running the circuit.",
DeprecationWarning,
stacklevel=2,
)
Copy link
Copy Markdown
Member

@1ucian0 1ucian0 Apr 19, 2022

Choose a reason for hiding this comment

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

Users with several arguments in execute will a lot get a lot of warning (maybe flooding the terminal?). I suggest this style:

Suggested change
if scheduling_method is not None:
warnings.warn(
"The scheduling_method argument is deprecated as of Qiskit Terra 0.21.0, "
"and will be removed in a future release. If you require scheduling your circuit "
"prior to execution you should use the :func:`~.schedule` function explicitly with "
"prior to running the circuit.",
DeprecationWarning,
stacklevel=2,
)
if init_qubits is not None:
warnings.warn(
"The init_qubits argument is deprecated as of Qiskit Terra 0.21.0, "
"and will be removed in a future release. If you require scheduling your circuit "
"prior to execution you should use the :func:`~.schedule` function explicitly with "
"prior to running the circuit.",
DeprecationWarning,
stacklevel=2,
)
if init_qubits is not None:
deprecated_arg.append('init_qubits')
if scheduling_method is not None:
deprecated_arg.append('scheduling_method')
if deprecated_arg:
warnings.warn(
"The following arguments are deprecated as of Qiskit Terra 0.21.0, "
"and will be removed in a future release: {", ".join(deprecated_arg)}. If you require scheduling your circuit "
"prior to execution you should use the :func:`~.schedule` function explicitly with "
"prior to running the circuit.",
DeprecationWarning,
stacklevel=2,
)

@mtreinish mtreinish modified the milestones: 0.21, 0.22 Jun 14, 2022
@mtreinish mtreinish modified the milestones: 0.22, 0.23.0 Sep 27, 2022
@mtreinish mtreinish changed the title Clarify the purpose of execute() function Clarify the purpose of execute() function and deprecate transpile kwargs Jan 9, 2023
Copy link
Copy Markdown
Member

@kdk kdk left a comment

Choose a reason for hiding this comment

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

I'm highly in favor of cleaning up the execute interface, but I think I still have some reservations about deprecating all the kwargs and directing users to use a combination of transpiler/schedule/backend.run. There are often cases where a user wants to set one option e.g. shots or initial_layout and this approach asks users to add more boilerplate to achieve the same end.

I wonder if there's a middle ground which might ease the transition. Something like allowing execute to accept {transpile,schedule,runtime}_options objects which can then be passed to their respective functions. This would help to remove the large number of kwargs on execute, help users understand the machinery behind execute and where those options will be applied, and will align better with the defined Options interfaces on the primitives.

Comment thread releasenotes/notes/deprecate-legacy-execute-args-b607c5e85ed2d073.yaml Outdated
Comment thread qiskit/execute_function.py Outdated
@mtreinish
Copy link
Copy Markdown
Member Author

I'm highly in favor of cleaning up the execute interface, but I think I still have some reservations about deprecating all the kwargs and directing users to use a combination of transpiler/schedule/backend.run. There are often cases where a user wants to set one option e.g. shots or initial_layout and this approach asks users to add more boilerplate to achieve the same end.

This is actually a bit of the confusion with the current state of execute() imo. backend.run() options will still work as expected so things like shots will work fine if the backend supports. What is being deprecated are hard coded options around things that are the domain of other parts of the stack and leaving execute() as just the lightweight wrapper for backend.run(transpile(qc, backend)) we've been treating it as for the past several years (but not documenting). My intent with this was to keep the undeprecated options as generic for all execution and if you need something more advanced you need to drop down to the more specific functions. So tl;dr setting shots via execute() isn't being deprecated but having a hard coded option named shots is even if the backend doesn't support setting shots.

I wonder if there's a middle ground which might ease the transition. Something like allowing execute to accept {transpile,schedule,runtime}_options objects which can then be passed to their respective functions. This would help to remove the large number of kwargs on execute, help users understand the machinery behind execute and where those options will be applied, and will align better with the defined Options interfaces on the primitives.

Heh, the Options object in the ibm runtime primitives is loosely based on what we did in BackendV1's run interface (it's also specific to ibm runtime's interface and is not part of the common interface defined in terra). Personally I don't like the dict of kwargs approach because it's hard to validate and document clearly all the fields and it never really works with autocomplete or code inspection. What I feel is the best spot for execute() is to have it really be the abstraction where you don't care at all about the compilation you just have a circuit and want it to run on the backend. There are a minimal set of high level transpile() and schedule() (although there really aren't any for schedule() options that influence the high level operation of the compiler functions (which basically just means optimization_level) and anything more sophisticated users should drop down to the compiler directly because they're doing something more advanced. I could see an argument for initial_layout being left intact though, because it's like saying run my circuit on qubits 1, 2, and 3 which seems to fit in that.

@mtreinish
Copy link
Copy Markdown
Member Author

although there really aren't any for schedule() options that influence the high level operation of the compiler functions (which basically just means optimization_level) and anything more sophisticated users should drop down to the compiler directly because they're doing something more advanced. I could see an argument for initial_layout being left intact though, because it's like saying run my circuit on qubits 1, 2, and 3 which seems to fit in that.

Heh, I actually need to remember my own PR (granted it has been ~8 months since I looked at it in detail). The options allowed that are passed through to transpile() with this are optimization_level, initial_layout, and seed_transpiler I viewed all those as high level enough for the scope I was trying to define more clearly here. Anything outside that set users will need to use transpile() directly.

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 3953571855

  • 26 of 47 (55.32%) changed or added relevant lines in 1 file are covered.
  • 11 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.05%) to 84.823%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/execute_function.py 26 47 55.32%
Files with Coverage Reduction New Missed Lines %
qiskit/pulse/library/waveform.py 3 91.67%
src/vf2_layout.rs 8 86.44%
Totals Coverage Status
Change from base Build 3953361416: -0.05%
Covered Lines: 65970
Relevant Lines: 77774

💛 - Coveralls

@kdk kdk modified the milestones: 0.24.0, 0.25.0 Apr 6, 2023
@1ucian0 1ucian0 modified the milestones: 0.25.0, 0.45.0 Jul 10, 2023
@mtreinish mtreinish closed this Sep 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Changelog: Deprecated Add a "Deprecated" entry in the GitHub Release changelog.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

qiskit.execute() does not use the scheduling_method argument

5 participants