Skip to content

Fix controlled CU QPY serialization - #16665

Open
TSS99 wants to merge 2 commits into
Qiskit:mainfrom
TSS99:fix-controlled-cu-qpy
Open

Fix controlled CU QPY serialization#16665
TSS99 wants to merge 2 commits into
Qiskit:mainfrom
TSS99:fix-controlled-cu-qpy

Conversation

@TSS99

@TSS99 TSS99 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #11686. A circuit containing a controlled CUGate (for example
CUGate(...).control()) crashed on qpy.load with
TypeError: label expects a string or None.

Cause

CUGate carries four parameters (θ, φ, λ, γ), but its base gate is a
three-parameter UGate. When another control was added, the generic control
helper kept the three-parameter UGate as the base while the resulting
controlled gate exposed all four CUGate parameters. On reload QPY rebuilt the
base as UGate(θ, φ, λ, γ), passing the fourth value γ into the label
argument.

Fix

For a controlled CUGate, the base gate now explicitly represents
e^{iγ}·U(θ, φ, λ) (a UGate with a global phase of γ), so it genuinely has
four parameters. QPY round-trips it and the circuit operator is preserved.

Tests

  • test_controlled_cu_gate in test_circuit_load_from_qpy.py – QPY round-trip
    of a controlled CUGate.
  • test_controlled_cugate_base_gate_includes_global_phase in
    test_controlled_gate.py – the base gate equals e^{iγ}·U(θ, φ, λ).

AI/LLM disclosure

  • I didn't use LLM tooling, or only used it privately.
  • I used the following tools to understand this PR: Claude and ChatGPT

@TSS99
TSS99 requested a review from a team as a code owner July 26, 2026 17:07
@TSS99
TSS99 requested a review from alexanderivrii July 26, 2026 17:07
@qiskit-bot qiskit-bot added the Community PR PRs from contributors that are not 'members' of the Qiskit repo label Jul 26, 2026
@qiskit-bot

Copy link
Copy Markdown
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

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

  • @Qiskit/terra-core
  • @mtreinish

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

This can't be the cleanest way to go about the stated fix: it's neither a change to the CUGate class, nor to QPY. The CUGate/ControlledGate subclass relationship is somehow different to other gates: either that should be fixed directly (which probably has a myriad backwards compatibility concerns), or QPY needs a direct fix.

Certainly, modifying the generic backing of Gate.control (very indirectly) and not the ostensibly problematic CUGate.control is not the answer here.

@github-project-automation github-project-automation Bot moved this to Waiting for contributor in Contributor Monitoring Jul 26, 2026
@TSS99

TSS99 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

@jakelishman , Thanks for the feedback! I've updated CUGate.control to handle the CU-specific base gate and reverted _add_control.py back to its original generic implementation. Both the controlled-CU base-gate and QPY round-trip regression tests are now passing.

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

Labels

Community PR PRs from contributors that are not 'members' of the Qiskit repo

Projects

Status: Waiting for contributor

Development

Successfully merging this pull request may close these issues.

TypeError: label expects a string or None when loading a circuit using default label

3 participants