Skip to content

[Bug][QDP] Align Iris GPU training path with sibling pipelines (real dtype + leaf weights)#1412

Merged
ryankert01 merged 2 commits into
apache:mainfrom
ryankert01:fix-iris-complex-dtype
Jul 10, 2026
Merged

[Bug][QDP] Align Iris GPU training path with sibling pipelines (real dtype + leaf weights)#1412
ryankert01 merged 2 commits into
apache:mainfrom
ryankert01:fix-iris-complex-dtype

Conversation

@ryankert01

@ryankert01 ryankert01 commented Jun 26, 2026

Copy link
Copy Markdown
Member

Related Issues

Closes #1160

Changes

  • Bug fix

Why

The Iris amplitude-encoding GPU training path (_run_training_gpu) had
drifted from its sibling pipelines (mnist_amplitude.py, svhn_iqp.py)
in two ways, both of which break it:

  1. Complex dtype leaks into trainable params/labels (issue [need triage] we cast from complex64 to real value everytime #1160).
    dtype = encoded_train.dtype is complex64/complex128 from the QDP
    amplitude encoding. That complex dtype was inherited by the weights
    (used as qml.Rot angles), the bias, and the ±1 labels — all of
    which must be real.

  2. Non-leaf weight tensor. weights = 0.01 * torch.randn(..., requires_grad=True)
    is a non-leaf tensor (the multiply has a grad_fn), so
    torch.optim.SGD rejects it with can't optimize a non-leaf Tensor,
    crashing the path before training starts.

Both are already handled correctly in the sibling pipelines; Iris was
simply not aligned.

How

Mirror the siblings:

  • Derive a real dtype: real_dtype = torch.float64 if encoded_train.dtype == torch.complex128 else torch.float32, used for weights, bias and labels (encoded state vector stays complex for StatePrep).
  • Initialise weights as a leaf: (0.01 * torch.randn(...)).detach().requires_grad_(True).

Split into two commits so each fix can be reviewed independently.

Verification

qumat_qdp / lightning.gpu / CUDA were not available in my environment,
so I exercised the real _run_training_gpu directly on CPU with
default.qubit and a synthetic complex64 state-vector batch (stubbing
the unused qumat_qdp import). Before/after:

weights dtype optimizer training
before complex64 rejects (non-leaf) crashes
after float32 accepts (leaf) runs 10 epochs, returns results

Note: this confirms the code path executes with correct real dtypes and
gradients flow
; it does not validate model accuracy (synthetic input, not
real QDP-encoded Iris). End-to-end accuracy validation still needs the
qumat_qdp extension + a CUDA/lightning.gpu stack.

Checklist

  • Added or updated unit tests for all changes
  • Added or updated documentation for all changes

No automated tests exist for these benchmark pipelines (the GPU path needs CUDA + lightning.gpu); verified manually as described above.

@ryankert01 ryankert01 requested a review from 400Ping as a code owner June 26, 2026 18:28
@ryankert01 ryankert01 changed the title [Bug][QDP] Use real dtype for weights/labels in Iris GPU training path [Bug][QDP] Align Iris GPU training path with sibling pipelines (real dtype + leaf weights) Jun 26, 2026
@ryankert01 ryankert01 force-pushed the fix-iris-complex-dtype branch from bfdf141 to ae1863f Compare June 26, 2026 18:58
@ryankert01 ryankert01 requested review from Copilot and rich7420 June 26, 2026 18:59

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ryankert01 ryankert01 requested a review from Copilot July 10, 2026 05:03
The GPU training path in iris_amplitude.py derived its dtype directly
from the QDP-encoded state vector (`dtype = encoded_train.dtype`), which
is complex64/complex128. That complex dtype was then inherited by the
trainable weights (used as qml.Rot rotation angles), the bias, and the
±1 labels — all of which must be real-valued.

Mirror the existing pattern in mnist_amplitude.py and svhn_iqp.py: map
complex128 -> float64 and otherwise use float32 for weights, bias and
labels, while keeping the encoded state vector complex for StatePrep.

Fixes apache#1160
`weights = 0.01 * torch.randn(..., requires_grad=True)` produces a
non-leaf tensor (the multiply has a grad_fn), so torch.optim.SGD rejects
it with "can't optimize a non-leaf Tensor" and the GPU path crashes
before training starts.

Use the same idiom as mnist_amplitude.py and svhn_iqp.py:
`(0.01 * torch.randn(...)).detach().requires_grad_(True)`, which yields a
proper leaf parameter the optimizer accepts.

Found while verifying the dtype fix in the previous commit: with both
fixes the GPU training path runs end to end (default.qubit, complex64
state-vector input) and weights/bias/labels are real-valued.

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@ryankert01 ryankert01 merged commit 35a8526 into apache:main Jul 10, 2026
4 checks passed
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.

[need triage] we cast from complex64 to real value everytime

2 participants