Skip to content

feat(mps): linear-combination SRC apply and SRC-based rounding - #493

Merged
ultimatile merged 5 commits into
mainfrom
feat/469-src-extensions
Jul 20, 2026
Merged

feat(mps): linear-combination SRC apply and SRC-based rounding#493
ultimatile merged 5 commits into
mainfrom
feat/469-src-extensions

Conversation

@ultimatile

@ultimatile ultimatile commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

Extends successive randomized compression (SRC, arXiv:2504.06475) with the two extensions tracked as phase 3 of #469: a linear-combination apply computing $\eta \approx \sum_t c_t\, H_t \psi_t$ in one right-to-left sweep with each site's Gaussian block shared across the terms, and adaptive MPS rounding that runs the SRC sweep against a per-call identity MPO. Sharing the Gaussians is a correctness requirement, not an optimization: the coefficient-weighted sum of the terms' sketches is then exactly the sketch of the summed operand, so the paper's single-pair guarantees (exactness with probability one at the representable rank, validity of the leave-one-out error estimate) transfer verbatim — with independent per-term draws a cancelling sum would sketch as nonzero. Closes #492.

Changes

  • crates/ariadnetor-mps/src/apply/successive_randomized.rs — the sweep core generalizes to a multi-term kernel: one sketch-environment store and one cap (the running right environment closing a term's remaining network against the assembled output basis) per term, one shared incremental QR and stopping test over the summed sketch panels (the per-round blocks of sketch columns), coefficients entering only the panel summation and the deterministic site assembly — never the caps, which the shared basis projects at every later site. The single-pair kernel behind ApplyMethod::SuccessiveRandomized becomes a coefficient-one wrapper whose output is bit-identical to the previous implementation at equal seeds. Environment machinery and term-list handling split into the env.rs / terms.rs submodules.
  • Zero-weighted terms are validated, then pruned before the sweep, so a non-finite element in a disabled term cannot poison the result; an all-zero coefficient list yields the bond-dimension-1 zero state (zero center site, right-isometric basis sites off-center).
  • crates/ariadnetor-mps/src/types.rsMpo::identity (dense $(1, d, d, 1)$ delta sites) and the SumTerm term alias.
  • crates/ariadnetor-mps/src/dispatch.rs + dispatch/entries.rs — new sealed-trait methods with panicking block-sparse arms, the public free function apply_sum_successive_randomized, and the inherent in-place Mps::round_successive_randomized; the multi-arg free functions move to dispatch/entries.rs.
  • crates/ariadnetor-algorithms/benches/mpo_mps_apply.rs — a two-term Heisenberg sum arm in the existing case grid (reachability of the new entry; no performance claim).

Impact

New public surface in ariadnetor-mps: apply_sum_successive_randomized, SumTerm, Mpo::identity, and Mps::round_successive_randomized, plus the two sealed-trait methods backing them. Existing entry points keep their signatures and numerical output. ApplyError docs now enumerate the new SRC-based reporters of NonFinite alongside ApplyMethod::SuccessiveRandomized.

Test plan

  • Single-term bit-identity against the pre-existing apply_with_method entry with ApplyMethod::SuccessiveRandomized at the same seed, pinning both the RNG-stream preservation of the shared-Gaussian refactor and the coefficient-one arithmetic bypass.
  • Two-term sums against densified per-term lossless references: exact rank (f64), adaptive tolerance, complex coefficients, single-site chains, and a non-unit single-term coefficient.
  • Cancelling sum resolves to the zero state via the sweep's zero-norm early exit (an identically zero summed sketch is the case that makes Gaussian sharing a correctness requirement); a zero coefficient disables a poisoned term; all-zero coefficients return a structurally right-isometric zero state.
  • Rounding compresses redundant bonds to within one adaptive growth step (sketch_increment) of the rank bound set by the state-space dimensions on each side of the cut, preserves the state, and returns Mixed { center: 0 } with right-canonical sites.
  • Block-sparse and validation panics for both new entries; Mpo::identity invariance under a lossless apply and its zero-dimension panic.
  • cargo make gate green (fmt-check, clippy -D warnings over all targets, workspace tests and doctests); rustdoc with -D warnings clean.

Notes

  • Dense-only, like the single-pair method: the block-sparse arms panic, and the sector-preserving sketch is tracked as phase 4 of Successive randomized compression (SRC) for MPO-MPS apply #469.
  • Rounding deliberately reuses the general apply path through a per-call identity MPO; a specialized bond-dimension-1 kernel would shave a factor of the physical dimension off the environment recursion and remains a later optimization if rounding ever dominates a profile.

Plan-vs-actual delta

Everything in #492's Scope landed; the deltas are additions.

Scope additions:

  • Zero-coefficient handling: zero-weighted terms are validated, then pruned before the sweep, and an all-zero coefficient list returns the bond-dimension-1 zero state. Without pruning, a disabled term's non-finite element would poison the summed sketch panel through 0 * inf; the pruning matches the paper authors' companion implementation (TNrandNLA).
  • The zero state's off-center sites are normalized basis tensors rather than zero tensors, keeping the stamped Mixed { center: 0 } structurally true — zero tensors are not isometries, and Mps::truncate trusts the stamped form and skips re-canonicalization (the all-zero test now asserts right-isometry).
  • Saturating arithmetic in the summed rank caps, from this PR's review thread: an overflowed sum would wrap to a small cap and silently truncate ranks.
  • The SumTerm public alias, replacing the raw term-slice tuple type that clippy's type_complexity lint rejects in signatures.
  • File splits beyond the plan: terms.rs (term validation / pruning / combiner) and dispatch/entries.rs (the pre-existing free functions), keeping every source file within the committed line-count hook's limit (scripts/check-file-lines.sh; 600 lines for non-test sources).
  • Test-helper consolidation: relative_frobenius / with_site_scaled promoted to the shared helpers module; make_identity_mpo now delegates to Mpo::identity.
  • An entry-side empty-chain assert in rounding, so the panic names the called method rather than the identity constructor it delegates to.

Scope subtractions: none. The Out of scope set is unchanged — the identity-specialized kernel, the MPO-free linear combination, and block-sparse support all remain deferred to #469.

Acceptance recalibration: "rounding reduces inflated bonds" holds, but the adaptive sweep only observes rank deficiency one sketch_increment after the bond has grown past the true rank, so the final bond can exceed that rank by up to one increment. The rounding test therefore pins the bond to within one sketch_increment of the dimension-counting rank bound (tested with sketch_increment = 1), together with the clamp of the output bond to the site's fused row count, rather than pinning the exact rank.

Generalize the successive-randomized-compression sweep to a
coefficient-weighted sum of MPO-MPS products, sharing each site's
Gaussian block across terms (a correctness requirement: the summed
panel is then exactly the sketch of the summed operand). Per-term
environment stores and caps; one shared incremental QR and stopping
test; coefficients enter only the panel summation and the deterministic
site assembly, with a coefficient-one bypass keeping the single-pair
wrapper bit-identical to the previous kernel. Zero-weighted terms are
pruned up front and an all-zero coefficient list yields the
bond-dimension-1 zero state.

New public surface: apply_sum_successive_randomized, the SumTerm alias,
Mpo::identity (dense delta sites), and the in-place
Mps::round_successive_randomized, which rounds a state adaptively by
running the SRC sweep against a per-call identity MPO. Block-sparse
arms panic with the existing dense-only wording.

The kernel module splits its environment machinery (env.rs) and
term-list handling (terms.rs) into submodules, and the dispatch free
functions move to dispatch/entries.rs.
The all-zero-coefficient fast path returned every site as a zero tensor
while claiming Mixed { center: 0 }; zero off-center sites are not
right-isometries, and downstream consumers (truncate among them) trust
the canonical-form metadata and skip re-canonicalization. Only the
center site is zero now; off-center sites are normalized basis tensors,
so the claimed form holds structurally while the state stays zero.
Qualify the ApplyMethod intra-doc link that broke when dispatch.rs
stopped importing the enum, add round_successive_randomized to the
inherent-method inventory in lib.rs, and update the bench module doc's
arm count for the new sum arm.
Add the SRC sum free function and the rounding inherent method to the
MpsOps trait doc's forwarding inventory, and document the reachable
zero-physical-dimension panic that rounding inherits from the identity
MPO construction.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the dense successive randomized compression (SRC) MPO–MPS apply path to support coefficient-weighted sums of multiple MPO–MPS terms in a single shared-Gaussian right-to-left sweep, and adds SRC-based adaptive in-place MPS rounding implemented via applying a per-call identity MPO.

Changes:

  • Generalize the SRC sweep core to a multi-term kernel with shared Gaussian sketch blocks, per-term environments/caps, and coefficient-weighted panel/site assembly.
  • Introduce new public API surface: apply_sum_successive_randomized, SumTerm, Mpo::identity, and Mps::round_successive_randomized, plus sealed-trait dispatch wiring.
  • Add comprehensive tests for multi-term correctness (including cancellation/zero-coefficient behavior) and rounding, and extend the existing apply benchmark with a two-term “sum” arm.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
crates/ariadnetor-mps/tests/mps/helpers.rs Adds dense relative-error helper and a generic site-scaling helper; updates identity MPO test helper to call Mpo::identity.
crates/ariadnetor-mps/tests/mps/apply_successive_randomized.rs Refactors existing SRC tests to reuse new helpers (relative_frobenius, with_site_scaled).
crates/ariadnetor-mps/tests/mps/apply_src_sum.rs New test suite covering SRC sum apply + SRC-based rounding + validation panics.
crates/ariadnetor-mps/tests/mps.rs Registers the new apply_src_sum test module.
crates/ariadnetor-mps/src/types.rs Adds SumTerm alias, implements Mpo::identity, and updates ApplyError/SRC param docs for new SRC entry points.
crates/ariadnetor-mps/src/lib.rs Re-exports the new public entry apply_sum_successive_randomized and SumTerm; documents round_successive_randomized as inherent.
crates/ariadnetor-mps/src/dispatch/entries.rs New module holding multi-arg public free functions, including apply_sum_successive_randomized.
crates/ariadnetor-mps/src/dispatch.rs Adds sealed-trait entrypoints for sum apply + rounding; wires new entries module; implements dense and block-sparse (panic) arms.
crates/ariadnetor-mps/src/apply/successive_randomized/env.rs New module for per-term environment storage and sketch-panel contraction, supporting shared-Gaussian multi-term recursion.
crates/ariadnetor-mps/src/apply/successive_randomized/terms.rs New module for term validation, zero-coefficient pruning, and coefficient-weighted tensor summation with single-term bypass.
crates/ariadnetor-mps/src/apply/successive_randomized.rs Refactors SRC sweep into multi-term kernel and restores single-term behavior via coefficient-one wrapper/bypass.
crates/ariadnetor-mps/src/apply/mod.rs Re-exports the new dense sum-SRC kernel from the apply module.
crates/ariadnetor-algorithms/benches/mpo_mps_apply.rs Adds a “sum” benchmark arm to exercise the new sum entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ariadnetor-mps/src/apply/successive_randomized.rs
Comment thread crates/ariadnetor-mps/src/apply/successive_randomized.rs
Comment thread crates/ariadnetor-mps/tests/mps/helpers.rs
The multi-term rank caps (default max_dim and the per-site left-rank
sum) now use saturating arithmetic: a wrapped sum would masquerade as a
small cap and silently truncate ranks, while saturation pins at
effectively unbounded. The test-side relative-error helper asserts a
nonzero reference norm instead of returning inf/NaN.

Copilot AI left a comment

Copy link
Copy Markdown

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 13 out of 13 changed files in this pull request and generated no new comments.

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.

Phase 3: linear-combination SRC apply and SRC-based adaptive MPS rounding

2 participants