Skip to content

[Frontend] Split QFuncPlxprInterpreter into SubroutineInterpreter #1787

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

Merged

Conversation

erick-xanadu
Copy link
Contributor

@erick-xanadu erick-xanadu commented Jun 5, 2025

Context: A quantum subroutine and the quantum kernel's entry point have almost everything in common. The only differences are:

  • the kernel's entry point will define the quantum register as one of the first few instructions in its body, while the quantum subroutine the quantum register will be passed in as a parameter.
  • the kernel's entry point will deallocate the quantum register as one if its last few instruction in its body, while the quantum subroutine will return the most recently updated value of the quantum register.
  • the kernel's entry point will deallocate the device as one of its last few instruction in its body.

Description of the Change: Move all the semantics of the quantum instructions except the setup and teardown method's for QFuncPlxprInterpreter into SubroutineInterpreter.

Benefits: Avoid code duplication once support for subroutines are added in the frontend.

Copy link

codecov bot commented Jun 5, 2025

Codecov Report

Attention: Patch coverage is 93.75000% with 1 line in your changes missing coverage. Please review.

Project coverage is 96.61%. Comparing base (d23b9c3) to head (9e9e852).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
frontend/catalyst/from_plxpr.py 93.75% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1787      +/-   ##
==========================================
- Coverage   96.61%   96.61%   -0.01%     
==========================================
  Files          82       82              
  Lines        9260     9265       +5     
  Branches      875      875              
==========================================
+ Hits         8947     8951       +4     
- Misses        254      255       +1     
  Partials       59       59              

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@dime10 dime10 left a comment

Choose a reason for hiding this comment

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

This is a sensible change!

One thing I'm wondering about is whether we should make it a hard assumption that subroutines always take in the entire register. It is the most generic option, and also what we do with control flow, but ultimately this is quite heavy handed. Take for example a decomposition scenario. For a single qubit operation, a decomposition subroutine would be much more effective (to the overall IR) if it only accepted and produced that single qubit.

I'm not saying the register couldn't be a safe fallback, but maybe we should just be careful in baking that in as a hard assumption.

Copy link
Contributor

github-actions bot commented Jun 6, 2025

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.

@erick-xanadu
Copy link
Contributor Author

erick-xanadu commented Jun 6, 2025

I'm not saying the register couldn't be a safe fallback, but maybe we should just be careful in baking that in as a hard assumption.

Yes, I agree with this, but it is going to be difficult to implement without a new interface. There's stopping a user to just say "wire=some_number".

I've thought about alternative interfaces like if a subroutine is annotated with wire parameters, then do not pass the register.

@subroutine
def foo(w0 : Wire, w1: Wire) # (can only manipulate these wires)

But then it becomes impossible to have control flow in the subroutine because we need the register for control flow. Ideally the control flow should also only pass wires.

This also may get weird with dynamic qubits.

My prefer UI is exposing value qubits to the user. I.e.,

@subroutine
def foo(q0: Qubit, q1: Qubit):
  q0, q1 = qml.CNOT(q0, q1)
  return q0, q1

@dime10
Copy link
Contributor

dime10 commented Jun 6, 2025

But then it becomes impossible to have control flow in the subroutine because we need the register for control flow.

I don't think this is necessarily true, with the exception of maybe the frontend? At least in MLIR I feel like I have written examples of control flow around qubits. EDIT: Ah you're focused on the frontend here, yeah that's true, but see below.

But even if we assume that it is, this should be easy (and desirable!) to change.

@dime10
Copy link
Contributor

dime10 commented Jun 6, 2025

There's stopping a user to just say "wire=some_number".

Not sure I follow here, do you have an example?

I think the UI you're showing looks good!

@erick-xanadu
Copy link
Contributor Author

erick-xanadu commented Jun 6, 2025

@dime10

def foo(wire0: Wire, wire1: Wire):
  assert wire0 != 45 and wire1 != 45
  qml.Hadamard(45)
  qml.CNOT(wire0, wire1)

Sorry I meant "there's nothing stopping a user to just say wire=some_number"

@dime10
Copy link
Contributor

dime10 commented Jun 6, 2025

@dime10

def foo(wire0: Wire, wire1: Wire):
  assert wire0 != 45 and wire1 != 45
  qml.Hadamard(45)
  qml.CNOT(wire0, wire1)

Sorry I meant "there's nothing stopping a user to just say wire=some_number"

Got it! I might need to think about it some more, especially as there are different scenarios to consider (e.g. a user writing a subroutine, an internal transform that replaces one piece of code with another, a user transform, ...).

Thanks!

@erick-xanadu erick-xanadu force-pushed the eochoa/2025-06-05/just-the-changes-to-the-plxpr-interpreter branch from c7c3bc0 to 0f20608 Compare June 11, 2025 16:04
@erick-xanadu erick-xanadu merged commit 2c0917c into main Jun 11, 2025
37 of 38 checks passed
@erick-xanadu erick-xanadu deleted the eochoa/2025-06-05/just-the-changes-to-the-plxpr-interpreter branch June 11, 2025 17:39
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.

2 participants