Skip to content

Fix mixed control values in qjit capture - #10356

Open
JerryChen97 wants to merge 9 commits into
mainfrom
fix-captured-dynamic-control-values
Open

JerryChen97 wants to merge 9 commits into
mainfrom
fix-captured-dynamic-control-values

Conversation

@JerryChen97

@JerryChen97 JerryChen97 commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Context

Under qp.qjit(capture=True, skip_preprocess=True), qp.ctrl mishandles control_values that mix Python Booleans with traced values. Depending on the input form, PennyLane can select the wrong array interface, attempt to call bool() on a tracer, or store a tracer in static primitive metadata.

Changes

  • Infer the array interface from all control values.

  • Preserve traced values when normalizing tuples.

  • Pass all callable control values as Boolean operands:

    ctrl_transform(*consts, *args, *control_wires, *control_values, ...)
    
  • Remove the static control_values primitive parameter.

  • Update the primitive implementation, interpreter, tape conversion, and regression tests.

The public qp.ctrl API is unchanged.

Compatibility and landing plan

This changes the internal capture contract for callable controls. PennyLane and Catalyst therefore need coordinated updates; either new implementation is incompatible with the other repository's previous representation.

Proposed order:

  1. Land qp.ctrl of qfuncs keeps work_wire_type #10355 with PennyLaneAI/catalyst#3366.
  2. Rebase and land this change with its matching Catalyst update and compatible dependency pins.

PennyLaneAI/catalyst#3350 and PennyLaneAI/catalyst#3365 address separate decomposition issues and are outside this PR's scope.

Validation

  • 20 targeted PennyLane tests passed, covering static and dynamic operand layouts, primitive execution, interpreter forwarding, tape conversion, dynamic shapes, constants, and mixed operator-instance lists.
  • 21 targeted Catalyst tests passed with the matching local change, including the four reported cases for both runtime Boolean values against default.qubit, plus static and nested controls.
  • Catalyst SSA FileCheck passed, including its existing static-control checks.
  • TestDeviceLevelSpecs.test_complex has a temporary strict xfail limited to the old Catalyst handler's missing-control_values error. It was verified as XFAIL with the upstream handler, strict XPASS with the companion change, and passing with the companion change under --runxfail. The marker can be removed once a compatible Catalyst nightly is available.
  • PennyLane source and test Pylint, formatting, tach check, and git diff --check passed. tach reported three pre-existing unused-ignore warnings.
  • Full local test suites were not run.

Related issue

[sc-133997]

AI assistance: Prepared with AI assistance at the contributor's request. Human review remains in progress.

@JerryChen97 JerryChen97 added the WIP 🚧 Work-in-progress label Oct 19, 2026
@codecov

codecov Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.44%. Comparing base (956370f) to head (c5f3118).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #10356   +/-   ##
=======================================
  Coverage   99.44%   99.44%           
=======================================
  Files         617      617           
  Lines       68037    68044    +7     
=======================================
+ Hits        67656    67664    +8     
+ Misses        381      380    -1     

☔ View full report in Codecov by Harness.
📢 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.

@JerryChen97 JerryChen97 self-assigned this Oct 20, 2026
@JerryChen97 JerryChen97 removed the WIP 🚧 Work-in-progress label Oct 20, 2026
@JerryChen97 JerryChen97 changed the title WIP: Fix mixed control values in qjit capture Fix mixed control values in qjit capture Oct 20, 2026
@JerryChen97 JerryChen97 added the review-ready 👌 PRs which are ready for review by someone from the core team. label Oct 20, 2026
Comment thread doc/releases/changelog-dev.md Outdated
Comment thread pennylane/ops/op_math/controlled.py Outdated
control_values = [bool(control_values)]
elif isinstance(control_values, tuple):
control_values = [bool(v) for v in control_values]
control_values = [v if math.is_abstract(v) else bool(v) for v in control_values]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we convert to a bool dtype here to handle things like control_values=(0,1) which would default to int?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@paul0403 paul0403 left a comment

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.

LGTM from primitive invar/param perspective, approving pending on Christina's comments

@JerryChen97
JerryChen97 requested a review from albi3ro October 20, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-ready 👌 PRs which are ready for review by someone from the core team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants