-
Notifications
You must be signed in to change notification settings - Fork 557
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
Implement qml.breakpoint()
and initial integration with Pdb
#5600
Conversation
Hello. You may have forgotten to update the changelog!
|
[sc-62243] |
Open Questions:
|
qml.breakpoint()
and initial integration with Pdb
qml.breakpoint()
and initial integration with Pdb
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #5600 +/- ##
==========================================
- Coverage 99.68% 99.67% -0.01%
==========================================
Files 416 416
Lines 39105 38432 -673
==========================================
- Hits 38981 38307 -674
- Misses 124 125 +1 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Jaybsoni!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
qml.breakpoint()
pauses execution ✔️- Tested the commands while debugging (list, next, continue, quit) and they all worked fine. ✔️ One note here: hitting next at the return statement of the circuit puts us into PL internals, but I think that's fine.
- Can access internal and external variables from the debugging context ✔️
- Can queue additional operations ✔️
Pending for next PRs:
- qml.debugging.state()
- qml.debugging.expval()
- qml.debugging.tape()
I think we can keep this open and merge other PRs into this branch. Having the docs will especially help with PR reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat stuff, @Jaybsoni! I left a few minor comments and suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No blockers to merging from me! Thanks @Jaybsoni!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Jaybsoni, looks good to me.
def __init__(self, *args, **kwargs): | ||
"""Initialize the debugger, and set custom prompt string.""" | ||
super().__init__(*args, **kwargs) | ||
self.prompt = "[pldb]: " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this be mutable, or could it be defined via property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there value in making the prompt mutable? I think it's OK for this to be hidden state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be mutable, I can re-define it as a property. It should be internal anyways
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, Pdb complains if we implement it as a property. Leaving it as is.
class PLDB(pdb.Pdb): | ||
"""Custom debugging class integrated with Pdb.""" | ||
|
||
__active_dev = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__active_dev = None | |
__active_dev : Optional[qml.devices.Device] = None |
Trying to get better about type-hints throughout pennylane. Helps specify things a little bit more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what the PennyLane coding standards say, but in Python 3.9+ you can use:
__active_dev = None | |
__active_dev: qml.devices.Device | None = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll be supporting 3.9 till after the next release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. I mean that if we don't support Python 3.8 or lower, we can use the |
syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried adding the type hint, but its causing circular import issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to get around that issue by using
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pennylane.devices import Device
but I'm sure we can leave that as a future enhancement.
# Before constructing the tape, we pass the device to the | ||
# debugger to ensure they are compatible if there are any | ||
# breakpoints in the circuit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So is this just for checking compatibility? If so, do we need to use a context with an enter-exit just for checking validity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I think having a "is this device compatible with breakpoints" function makes sense although I'm not sure it would be too useful here (unless we know ahead of time that the current circuit has a breakpoint).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's the key, we don't need to do validation checks if there are no breakpoints in the circuit. Furthermore, we use the device to execute measurements (see the following PR), so we do need the context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, @Jaybsoni! 🚀
I especially think the skip
change adds good value.
def __init__(self, *args, **kwargs): | ||
"""Initialize the debugger, and set custom prompt string.""" | ||
super().__init__(*args, **kwargs) | ||
self.prompt = "[pldb]: " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there value in making the prompt mutable? I think it's OK for this to be hidden state.
Co-authored-by: Mikhail Andrenkov <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing the feedback, @Jaybsoni! 🚀
class PLDB(pdb.Pdb): | ||
"""Custom debugging class integrated with Pdb.""" | ||
|
||
__active_dev = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to get around that issue by using
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pennylane.devices import Device
but I'm sure we can leave that as a future enhancement.
Context:
Part of the effort to add more tools for algorithmic debugging of quantum circuits with PennyLane. In this PR we introduce the
qml.breakpoint()
function which allows users to insert breakpoints into their quantum workflow and enter a debugging context (via Pdb) to step through their quantum functions.Description of the Change: