Skip to content

Fix --loopsum for amplitudes with an imaginary part (#22) - #65

Merged
alan23273850 merged 3 commits into
fmlab-iis:mainfrom
ondrik:fix-loopsum-imag
Oct 21, 2026
Merged

alan23273850 merged 3 commits into
fmlab-iis:mainfrom
ondrik:fix-loopsum-imag

Conversation

@ondrik

@ondrik ondrik commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #22.

The bug

With --loopsum, every amplitude is replaced by a variable v encoded as vR + i·vI. After the fix point, eval_symbol puts the real amplitudes back in. It bound vI to FiveTuple::imag(), which is i·Im(x) and not the real number Im(x). The term's coefficient already carries the i, so it contributed i·i·Im(x) = −Im(x), and every summarized iteration ran on Re(x) − Im(x) instead of x. Any loop whose iterations see a complex amplitude gave wrong states. These come from a complex precondition or from gates like s, t, y or sdg in the body. The error changed ver verdicts in both directions.

The fix

src/loop_summarization.cc: bind vI to imag() rotated a quarter turn clockwise, which multiplies it by −i and gives Im(x). clockwise() is part of the is_complex concept, so this doesn't depend on the FiveTuple representation.

I left FiveTuple::imag() alone. The HSL imag(...) function also uses it and has the same i·Im(x) quirk, but changing that would change how existing .hsl files are read, so it should get its own PR.

Test

A new unit test, for_loop_summarization_complex_amplitudes, runs each loop both unrolled and summarized and requires exactly the same printed set of states:

Precondition Loop body Iterations
(|0⟩ + i|1⟩)/√2 (the issue's example) h 1
|0⟩ h; t 3
|1⟩ s 2
(|00⟩ + e^{iπ/4}|11⟩)/√2 y; h; cz; tdg 3

All four fail without the fix and pass with it. The existing GroverFor test still passes, and ctest passes (2/2).

I also checked against the CLI:

  • The issue's ver example now gives [OK] / [failed] with --loopsum, the same as without it.
  • (H·T)^n on |0⟩ for n = 1, 2, 3, 4 and 8 matches unrolling exactly. Before the fix, every n ≥ 2 was wrong and not even normalised.

Not fixed here: --loopsum hangs on multi-state preconditions

While testing, I found that --loopsum never finishes when the precondition contains more than one state, for example {|0>, |1>} with a single x. The same happens on main without this change. It is filed as #66.

🤖 Generated with Claude Code

https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY

A loop-summarization variable v is encoded as vR + i·vI, so vI must be
bound to the real number Im(x). eval_symbol bound it to
FiveTuple::imag(), which is i·Im(x), so every summarized iteration ran
on Re(x) - Im(x) instead of x. Rotate the value a quarter turn
clockwise (multiply by -i) to get Im(x).

Add a unit test that runs four loops both unrolled and summarized and
requires the same printed states: the issue's example, (T·H)^3 on |0>,
S·S on |1>, and a two-qubit loop with Y, H, CZ and T†. All four fail
without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY
@alan23273850
alan23273850 merged commit 3d92eb3 into fmlab-iis:main Oct 21, 2026
12 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.

--loopsum computes wrong amplitudes when a loop iteration receives an amplitude with a nonzero imaginary part

2 participants