tech-debt-backlog §7.10: simplify Q-R scaffolding in below-atol guard test - #134
Conversation
… test Replace the two np.linalg.qr calls plus U_oracle @ S_oracle @ Vh_oracle product in test_below_atol_discard_does_not_raise with a one-liner M = np.diag([1.0, 0.5, 1e-12, 0.0]).astype(complex). A diagonal matrix has its diagonal entries as its singular values by inspection, so the prescribed [1.0, 0.5, 1e-12, 0] spectrum lands by construction with no randomness and no sanity assertion. The CNOT inverse-permutation that follows is unitary so it preserves singular values through to _apply_cnot's SVD step — pin unchanged. Audit clarified the surface: the Q-R block lives in the below-atol test (lines 336-345), not in test_rank_three_input_raises_with_named_discard (which already uses a seeded Gaussian directly and keeps its oracle SVD intact). ~10 lines deleted, 1 added. Full suite: 1282 passed, 8 skipped. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jascal
left a comment
There was a problem hiding this comment.
Code Review — Claude Sonnet 4.6
Verdict: LGTM — correct, well-scoped refactor. Recommend merge after a one-line comment tweak (non-blocking).
A clean tech-debt simplification: the RNG + dual-QR scaffolding in test_below_atol_discard_does_not_raise is replaced with a single M = np.diag([1.0, 0.5, 1e-12, 0.0]).astype(complex). I traced the math and ran the suite — both confirm equivalence.
Correctness ✅
I verified the round-trip end to end against _apply_cnot (q_orca/compiler/mps_contract.py:129):
- A diagonal
(4,4)matrix has|diagonal entries|as its singular values, soM's spectrum is exactly[1.0, 0.5, 1e-12, 0.0]— identical to the oldU_oracle @ S_oracle @ Vh_oracle(unitary · diag · unitary is an SVD). The guard only inspects the spectrum, so the construction is faithful. - The test plays
Mas the post-CNOT tensorT2, reverse-applies the CNOT swap to getT, then SVD-factorsTkeeping all 4 singular values — soA_c @ A_treconstructsTexactly. - Inside
_apply_cnot, the forward CNOT permutation (mps_contract.py:148-151) is the exact inverse of the test's pre-swap, so it lands back onMbit-for-bit (modulo ~1e-15 round-off). The guard atmps_contract.py:163-166then seesdiscarded = [1e-12, 0.0],max_discarded = 1e-12 < atol 1e-10→ no raise. Theshape[2] == 2/shape[0] == 2asserts hold (chi = min(2, 4) = 2).
The pinned third singular value (1e-12) sits ~3 orders above the intermediate-SVD round-off floor (~1e-15) and ~2 orders below the guard's atol (1e-10), so the test keeps a healthy margin on both sides — it remains robust, not brittle, after the change.
One nit — comment precision (non-blocking)
The new comment reads:
The CNOT inverse-permutation below is unitary, so the singular values propagate through to
_apply_cnot's SVD step unchanged.
The conclusion is correct (the guard does see M's spectrum), but the stated reason is loose. The inverse-CNOT step is a permutation of tensor entries, i.e. a row-dependent column swap on the reshaped (4,4) — that is not a unitary left/right multiplication and does not preserve the matrix's singular values (indeed T's own spectrum differs from M's). The reason the guard recovers M's spectrum is that the test pre-applies the exact inverse of _apply_cnot's permutation and the intermediate full-rank SVD factoring is exact — so the forward permutation reconstructs M, not that singular values are invariant under the swap. Suggest something like:
# We pre-apply the inverse of _apply_cnot's CNOT swap; the full-rank SVD
# factoring below is exact, so _apply_cnot's forward swap reconstructs M
# and SVDs its [1.0, 0.5, 1e-12, 0] spectrum. (The permutation reshuffles
# entries, so it does NOT itself preserve the matrix's singular values.)Code is correct either way — this is purely about not leaving a future reader with a wrong mental model.
Test coverage ✅
The behavior under test (sub-atol discard stays silent) is preserved exactly; this is a refactor, not new behavior, so no new edge cases are warranted. Nicely, the two sibling tests (test_rank_two_input_passes_through_cleanly, test_rank_three_input_raises_with_named_discard) are left untouched, keeping their distinct construction styles.
Lint / tests ✅
.venv/bin/ruff check tests/test_concept_gram_mps_contraction.py→ All checks passed. (The 18 repo-wide ruff errors are all pre-existing in other files —test_verifier.pyE402, etc. — and are not introduced or touched by this PR.)pytest tests/test_concept_gram_mps_contraction.py::TestApplyCnotBondTruncationGuard -v→ 3 passed.pytest tests/test_concept_gram_mps_contraction.py -q→ 39 passed, 1 skipped.pytest -q(full suite) → 1282 passed, 8 skipped — matches the PR's claim exactly.
Security / performance
N/A (test-only). Mild plus: the new version drops 4 RNG seeds + 2 QR decompositions, so it's marginally faster and fully deterministic-by-construction rather than deterministic-by-fixed-seed.
What looks good
- The surface audit in
tasks.mdis exemplary: it caught that the task pointed at the wrong test (test_rank_three_input_raises_with_named_discard) and documented that the Q-R block actually lived intest_below_atol_discard_does_not_raise, then took the simpler path. That's the right way to handle a mislabeled backlog item. - Net
-10 / +1with a clearer comment block, and thetasks.md[ ] → [x]flip plus rationale keeps the backlog honest.
This review was posted automatically by Claude Sonnet 4.6.
#138) Three [XS] follow-ups, all surface-only wording fixes from prior PR review logs. - §7.27 — fix the line citation in §7.22's resolution note. `examples/hybrid-bridge/README.md:60` → :59. `2·asin√0.85 ≈ 2.346` actually sits on line 59 of that file; the PR #129 reviewer flagged the off-by-one and it persisted in the merged backlog body. - §7.28 — replace "class-level docstring" with "leading `#` comment on the class" in §7.12's resolution note. Verified against tests/test_mcp_server.py:181-188: the §7.12 rationale lives in a contiguous `#` comment block immediately above the `@pytest.mark.skip`, not a docstring (no `"""…"""` exists on the class). The prior wording would mislead a future reader using `pydoc` / `__doc__` to find it. - §7.29 — rewrite the below-atol-guard test's spectrum-recovery comment. PR #134's "CNOT inverse-permutation is unitary, so singular values propagate unchanged" framing was loose — an entry permutation is a row-dependent column swap that does not in general preserve a *reshaped* matrix's spectrum. New comment references the actual chain that does: exact inverse swap of _apply_cnot's forward swap, then a `full_matrices=False` SVD with every singular value kept (no truncation), so the reconstruction is exact and _apply_cnot's downstream SVD sees the singular values of M itself. Bundled because all three are XS doc-nits from review logs, matching the §§7.21–7.24 (PR #129), §§7.16/7.17 (PR #135), and §§7.18/7.19 (PR #137) bundling precedent. `pytest -q`: 1282 passed, 8 skipped (the §7.29 test fixture stays green; the §7.27/§7.28 edits are tasks.md-only and not referenced by any test). Tasks marked `[x]` with closing notes per §6.1. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
openspec/changes/tech-debt-backlog/tasks.md(PR tech-debt-backlog §7.5: defensive rank-≤2 guard in _apply_cnot #73 review nit: "simplify unusedU_oracle/Vh_oraclesetup in test 3").np.linalg.qrcalls andM = U_oracle @ S_oracle @ Vh_oracleproduct intest_below_atol_discard_does_not_raise(tests/test_concept_gram_mps_contraction.py) with a one-lineM = np.diag([1.0, 0.5, 1e-12, 0.0]).astype(complex).(4, 4)matrix has its diagonal entries as its singular values, so the prescribed[1.0, 0.5, 1e-12, 0]spectrum lands by construction — no randomness, no Q-R unitaries, no sanity assertion needed. The downstream CNOT inverse-permutation is unitary and preserves singular values through to_apply_cnot's SVD step (the existing inline comment already noted this invariance).TestApplyCnotBondTruncationGuardare unchanged — rank-2 pass-through and rank-3 raise keep their seeded-Gaussian construction and oracle-SVD magnitude pin respectively.Surface audit
The task body pointed at
test_rank_three_input_raises_with_named_discard, but the Q-R block actually lives intest_below_atol_discard_does_not_raise(lines 336-345). The rank-3 raise test already uses a seeded Gaussian directly and pins the discarded magnitude against an oracle SVD — nothing to simplify there.Test plan
pytest tests/test_concept_gram_mps_contraction.py::TestApplyCnotBondTruncationGuard -v— all 3 guard tests pass (rank-2 pass-through, rank-3 raise, below-atol silent).pytest tests/test_concept_gram_mps_contraction.py -q— 39 passed, 1 skipped (file-wide regression).pytest -q— full suite green at 1282 passed, 8 skipped.🤖 Generated with Claude Code