Skip to content

Fix sx resynthesis of negative angles in CommutativeCancellation#16599

Merged
alexanderivrii merged 3 commits into
Qiskit:mainfrom
jakelishman:fix-commutative-cancellation-sxdg
Jul 20, 2026
Merged

Fix sx resynthesis of negative angles in CommutativeCancellation#16599
alexanderivrii merged 3 commits into
Qiskit:mainfrom
jakelishman:fix-commutative-cancellation-sxdg

Conversation

@jakelishman

Copy link
Copy Markdown
Member

% maintains the sign of the left operand, so 0..(num_sx as i64 % 4) is an empty iterator for non-positive num_sx. If the calculated rotation angle was negative (such as from a chain of sxdg), non-identity, and we go down the sx-like synthesis path, we would miscompile.

This is a minimal fix to be backport stable, rather than a greater reworking.

Introduced in 91081cc: Add additional Z and X rotation gate handling to CommutativeCancellation (#16191)

Fix #16594

AI/LLM disclosure

  • I didn't use LLM tooling, or only used it privately.
  • I used the following tool to help write this PR description:
  • I used the following tool to generate or modify code:

`%` maintains the sign of the left operand, so `0..(num_sx as i64 % 4)`
is an empty iterator for non-positive `num_sx`.  If the calculated
rotation angle was negative (such as from a chain of `sxdg`),
non-identity, and we go down the `sx`-like synthesis path, we would
miscompile.

This is a minimal fix to be backport stable, rather than a greater
reworking.

Introduced in 91081cc: Add additional Z and X rotation gate handling
to CommutativeCancellation (Qiskit#16191)
@jakelishman jakelishman added this to the 2.5.1 milestone Jul 17, 2026
@jakelishman
jakelishman requested a review from a team as a code owner July 17, 2026 09:45
@jakelishman
jakelishman requested a review from Cryoris July 17, 2026 09:45
@jakelishman jakelishman added stable backport potential Make Mergify open a backport PR to the most recent stable branch on merge. Changelog: Fixed Add a "Fixed" entry in the GitHub Release changelog. mod: transpiler Issues and PRs related to Transpiler labels Jul 17, 2026
@qiskit-bot

Copy link
Copy Markdown
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@alexanderivrii alexanderivrii 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.

Thanks for the fix! One super-minor comment inline.

Comment on lines +984 to +996
def test_negative_x_rotations(self):
qcs, expecteds = [], []
for num_sxdg in (2, 3, 4):
qc = QuantumCircuit(1)
for _ in range(num_sxdg):
qc.sxdg(0)
qcs.append(qc)
expected = qc.copy_empty_like()
for _ in range(4 - num_sxdg):
expected.sx(0)
expecteds.append(expected)
pass_ = CommutativeCancellation(["sx", "rz"])
self.assertEqual([pass_(qc) for qc in qcs], expecteds)

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.

Nitpick: it might be nice to split this into separate tests using @ddt.data. That said, I don't feel strongly about it and am happy to merge as is.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done in 49ee46d.

@alexanderivrii alexanderivrii 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.

Thanks!

@alexanderivrii
alexanderivrii added this pull request to the merge queue Jul 20, 2026
@ShellyGarion

Copy link
Copy Markdown
Member

Thanks for the quick fix!
My main concern that that "%" is used in many places. Hopefully, in these case it should handle only positive numbers.
Should all these places be inspected in a follow-up?

Merged via the queue into Qiskit:main with commit 33d90a9 Jul 20, 2026
27 checks passed
@jakelishman
jakelishman deleted the fix-commutative-cancellation-sxdg branch July 20, 2026 09:57
@jakelishman

Copy link
Copy Markdown
Member Author

Shelly: sounds like it's worth a quick scan, sure. % is guaranteed to be fine if it's acting on unsigned data types, and in general the behaviour of Rust-space % on negative left-hand sides is fine (though not in this case), it's just different to Python's decision, so not always what's expected when code's been ported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Changelog: Fixed Add a "Fixed" entry in the GitHub Release changelog. mod: transpiler Issues and PRs related to Transpiler stable backport potential Make Mergify open a backport PR to the most recent stable branch on merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CommutativeCancellation cancels an sxdg·sxdg pair that equals X, giving wrong results at optimization_level ≥ 2

4 participants