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

Allow standard qml.cond usage of qml.cond(pred, qml.some_gate)(*args, **kwargs) in qjit #1232

Open
wants to merge 22 commits into
base: v0.9.0-rc
Choose a base branch
from

Conversation

paul0403
Copy link
Contributor

@paul0403 paul0403 commented Oct 25, 2024

Context:
The standard qml.cond usage for single gates fails with qjit:

@qjit
@qml.qnode(dev)
def func(x, y):
    qml.cond(x == 42, qml.Hadamard)(wires=0)
    qml.cond(y == 37, qml.Hadamard)(wires=0)
    return qml.probs()

print(func(42, 37), func(42, 2))
TypeError: Conditional 'True' function is not allowed to have any arguments

While users can work around this by using catalyst.cond syntax, it is a bit incovenient.

Moreover, the fewer code changes required to qjit a pennylane circuit, the better. Since qml.cond just aliases to catalyst.cond within qjit, we should make sure qjit does not reject any valid plain pennylane use patterns.

Description of the Change:
The error arises because the conditional branch functions are not allowed to have arguments. This is because the CondCallable class's __call__() method does not take any arguments.

While we do not want to change the overarching design of CondCallable, we can make a new class that inherits from it, which specifically deals with the case where the conditional branch function is a pennylane gate (like qml.Hadamard, ...).

This new class, named CondCallableSingleGateHandler, has a __call__() method that can take in arbitrary args and kwargs. The class creates a wrapper conditional function taking in no arguments and sends the wrapper to the usual CondCallable, but the body of the wrapper calls the actual conditional branch function that is passed in. This allows us to perform the conditional branch function with arguments.

Benefits:
The standard usage qml.cond(predicate, qml.some_gate)(*args, **kwargs) works within qjit.

Related GitHub Issues: closes #449

[sc-55079]

@paul0403 paul0403 requested review from willjmax and a team October 25, 2024 17:28
@paul0403 paul0403 requested a review from josh146 October 25, 2024 17:35
@paul0403 paul0403 changed the title Allow standard qml.cond usage of qml.cond(pred, qml.some_gate)(*args, wires=...) Allow standard qml.cond usage of qml.cond(pred, qml.some_gate)(*args, wires=...) in qjit Oct 25, 2024
@paul0403 paul0403 changed the title Allow standard qml.cond usage of qml.cond(pred, qml.some_gate)(*args, wires=...) in qjit Allow standard qml.cond usage of qml.cond(pred, qml.some_gate)(*args, **kwargs) in qjit Oct 25, 2024
@paul0403 paul0403 marked this pull request as ready for review October 25, 2024 17:55
Copy link

codecov bot commented Oct 25, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.97%. Comparing base (71b43c7) to head (e339f97).

Additional details and impacted files
@@            Coverage Diff             @@
##           v0.9.0-rc    #1232   +/-   ##
==========================================
  Coverage      97.96%   97.97%           
==========================================
  Files             77       77           
  Lines          11278    11318   +40     
  Branches         976      981    +5     
==========================================
+ Hits           11049    11089   +40     
  Misses           180      180           
  Partials          49       49           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@paul0403 paul0403 added this to the v0.9.0 milestone Oct 25, 2024
Copy link
Contributor

@joeycarter joeycarter left a comment

Choose a reason for hiding this comment

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

Looks good @paul0403, thanks! 🚀

I only have a few minor suggestions. I was also wondering if you could comment on the fact that the else_if and otherwise methods in CondCallable also restrict their inputs to be functions without arguments. For example, would this be allowed/supported?

qml.cond(x > 42, qml.RY, qml.RX)(0.7, wires=0)

doc/releases/changelog-dev.md Outdated Show resolved Hide resolved
frontend/catalyst/api_extensions/control_flow.py Outdated Show resolved Hide resolved
Copy link
Contributor

@rmoyard rmoyard left a comment

Choose a reason for hiding this comment

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

Thanks it looks good, just one question 👍

@paul0403
Copy link
Contributor Author

Looks good @paul0403, thanks! 🚀

I only have a few minor suggestions. I was also wondering if you could comment on the fact that the else_if and otherwise methods in CondCallable also restrict their inputs to be functions without arguments. For example, would this be allowed/supported?

qml.cond(x > 42, qml.RY, qml.RX)(0.7, wires=0)

Good catch! I'll add the other conditional branches.

@paul0403 paul0403 changed the base branch from main to v0.9.0-rc October 28, 2024 17:05
Copy link
Contributor

Hello. You may have forgotten to update the changelog!
Please edit doc/releases/changelog-dev.md on your branch with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

@willjmax
Copy link

Thanks for this! This gets us one step closer to making PennyLane's iterative_qpe operation QJIT compatible. The remaining issue is that catalyst.cond does not accept MeasurementValue type for the input conditional. I opened an issue addressing this #1237.

@paul0403
Copy link
Contributor Author

Looks good @paul0403, thanks! 🚀

I only have a few minor suggestions. I was also wondering if you could comment on the fact that the else_if and otherwise methods in CondCallable also restrict their inputs to be functions without arguments. For example, would this be allowed/supported?

qml.cond(x > 42, qml.RY, qml.RX)(0.7, wires=0)

Done, now all three branches (true, false, sequence of else_ifs) are all supported

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.

The new qml.cond does not work on single gates
4 participants