Skip to content

Fix bug in exp_pauli qubit concatenation#4064

Merged
sacpis merged 2 commits intoNVIDIA:mainfrom
huaweil-nv:fix/exp-pauli-operator-precedence
Mar 2, 2026
Merged

Fix bug in exp_pauli qubit concatenation#4064
sacpis merged 2 commits intoNVIDIA:mainfrom
huaweil-nv:fix/exp-pauli-operator-precedence

Conversation

@huaweil-nv
Copy link
Collaborator

Description

Fix a Python operator precedence bug in PyKernel.exp_pauli() where individual qubits (RefType) are silently dropped when a quantum register (VeqType) is also provided.
The + operator has higher precedence than the ternary if/else expression in Python, so:

[quantumVal] if quantumVal is not None else [] + qubitsList

is parsed as:

[quantumVal] if quantumVal is not None else ([] + qubitsList)

This means when quantumVal is not None, the result is [quantumVal] alone — qubitsList is discarded entirely. The fix adds parentheses to ensure qubitsList is always concatenated:

([quantumVal] if quantumVal is not None else []) + qubitsList

How to reproduce:

import cudaq

kernel = cudaq.make_kernel()
qreg = kernel.qalloc(2)
q_extra = kernel.qalloc()
kernel.exp_pauli(1.0, qreg, q_extra, 'XXX')

print(kernel)

Before fix: The generated IR shows q_extra allocated but never used. exp_pauli operates on veq<2> (2 qubits) despite the 3-qubit Pauli word "XXX":

%0 = quake.alloca !quake.veq<2>
%1 = quake.alloca !quake.ref
quake.exp_pauli (%cst) %0 to "XXX" : (f64, !quake.veq<2>) -> ()

After fix: quake.concat correctly merges the register and the individual qubit into veq<3>:

%0 = quake.alloca !quake.veq<2>
%1 = quake.alloca !quake.ref
%2 = quake.concat %0, %1 : (!quake.veq<2>, !quake.ref) -> !quake.veq<3>
quake.exp_pauli (%cst) %2 to "XXX" : (f64, !quake.veq<3>) -> ()

@huaweil-nv huaweil-nv requested review from 1tnguyen and sacpis March 2, 2026 08:54
@copy-pr-bot
Copy link

copy-pr-bot bot commented Mar 2, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

In `PyKernel.exp_pauli()`, the `+` operator binds tighter than the
ternary `if/else`, causing `qubitsList` to be silently dropped when
`quantumVal` is not None. Add parentheses to ensure individual qubits
are always concatenated with the register.

Signed-off-by: huaweil <huaweil@nvidia.com>
@huaweil-nv huaweil-nv force-pushed the fix/exp-pauli-operator-precedence branch from f62bfef to 784b17f Compare March 2, 2026 09:33
Copy link
Collaborator

@sacpis sacpis left a comment

Choose a reason for hiding this comment

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

LGTM. Thansk @huaweil-nv.

@sacpis
Copy link
Collaborator

sacpis commented Mar 2, 2026

/ok to test c06e3be

Command Bot: Processing...

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

Merged via the queue into NVIDIA:main with commit 3cb2034 Mar 2, 2026
206 checks passed
github-actions bot pushed a commit that referenced this pull request Mar 2, 2026
@sacpis sacpis added this to the release 0.14.0 milestone Mar 2, 2026
@bettinaheim bettinaheim changed the title Fix operator precedence bug in exp_pauli qubit concatenation Fix bug in exp_pauli qubit concatenation Mar 11, 2026
@bettinaheim bettinaheim added the bug fix To be listed under Bug Fixes in the release notes label Mar 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug fix To be listed under Bug Fixes in the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants