Skip to content

Fix Box.truncation discarding requested dims for array-backed boxes - #34

Draft
giodefelice-agents wants to merge 2 commits into
mainfrom
claude/wizardly-hopper-3spxen
Draft

giodefelice-agents wants to merge 2 commits into
mainfrom
claude/wizardly-hopper-3spxen

Conversation

@giodefelice-agents

Copy link
Copy Markdown
Collaborator

Closes #28, flagged for 🌙 Evening on memory#16's board. No verbatim human prompt — TODO.md quotes the issue instead, per the discopy#513/#514 precedent for self-contained bug+fix pairs.

The bug

Box.truncation's array branch built its result with Dim(2) ** len(dom/cod) unconditionally, ignoring the input_dims/output_dims its caller (Diagram.to_tensor) asks it to build against. That's correct for bit/qubit wires (always dimension 2) but silently wrong for any array-backed box with a mode/qmode wire above cutoff two — reproduced both symptoms from #28:

  • a state (dom=Ty()) with a 3-entry array over one mode wire raised ValueError: cannot reshape array of size 3 into shape (2,)
  • an endomorphism over one mode wire with a 3×3 array reported Dim(2) -> Dim(2) instead of Dim(3) -> Dim(3), then raised on eval()

determine_output_dimensions had the matching bug for the empty-dom case: it returned input_dims unchanged, which is [] for a state, so there was nothing to derive the codomain from.

The fix

Box.array_wire_dims and Box.array_truncation (public, no leading underscore, per STYLE.md's no-secrets rule — matches the pattern #29 is applying elsewhere) compute per-wire dimensions: bit wires stay fixed at 2, mode wires take the requested input_dims/output_dims. determine_output_dimensions falls back to the array's own shape when dom is empty, since that's the only case with no input to derive the codomain from. A size mismatch between the array and the requested dims now raises ValueError loudly instead of building a tensor.Box whose declared type doesn't match its data (the "worth deciding" question #28 raised — resolved in favour of the loud error).

Two per wire stays correct for bit/qubit, so nothing changes for the boxes that already used this path (zx.H, zx.SWAP — both override truncation directly and never reach the array branch anyway).

Tests

test/test_box_truncation.py — both #28 repro symptoms fixed and asserted, bit wires still fixed at 2 with no explicit dims, and the array/dims mismatch now raises.

Verification


Generated by Claude Code

claude added 2 commits August 4, 2026 20:39
Closes #28. `Box.truncation`'s array branch built its result with
`Dim(2) ** len(dom/cod)` unconditionally, ignoring the input_dims/
output_dims callers ask it to build against -- correct for bit/qubit
wires (always dimension 2) but silently wrong for any array-backed
box with a mode/qmode wire above cutoff two. determine_output_dimensions
had the matching bug for the empty-dom (state) case, where there is no
input to derive the codomain from.

Box.array_wire_dims and Box.array_truncation (public, no leading
underscore, per STYLE.md's no-secrets rule) compute per-wire dims from
the requested input_dims/output_dims, falling back to the array's own
shape when dom is empty, and raise loudly on a size mismatch instead of
building a tensor.Box whose declared type does not match its data.

[x] @evening-2026-08-04 21:05
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.

Box.truncation ignores the requested dimensions for array-backed boxes

2 participants