Nicole 0.4.1 — Relative Squared Discarded Weight in SVD
Release Date: September 20, 2026
Version 0.4.1 redefines the "discarded_weight" diagnostic reported by svd(..., requires_info=True). It was previously the raw sum of truncated singular values; it is now the relative squared weight ‖T − T_trunc‖²/‖T‖², the fractional squared 2-norm lost by truncation, which is the quantity conventionally used to monitor truncation error in DMRG and related algorithms. For SU(2) tensors, each reduced singular value is weighted by the dimension of its irrep so that the reported value is the physical norm loss in the full state space. Alongside this, the package metadata is updated with new author and maintainer contact information. The call signature and return structure of svd are unchanged.
🔧 API Changes
"discarded_weight" is now a relative squared weight
svd(T, axis, trunc=..., requires_info=True) returns an info dict whose "discarded_weight" entry previously accumulated Σ_dropped s — the plain sum of singular values removed by "thresh" and "nkeep" truncation. This quantity has no fixed scale (it grows with ‖T‖) and is not the norm-loss measure that truncation error analyses actually use. It is now defined as
discarded_weight = (Σ_q d_q Σ_dropped s²) / (Σ_q d_q Σ_all s²)
where the outer sum runs over left charge sectors q and d_q = irrep_dim(q) is the multiplicity of that sector in the full state space. The denominator equals T.norm()**2, so the result lies in [0, 1) and is exactly 1 − ‖T_trunc‖²/‖T‖². A value of 1e-8 therefore means the truncated tensor differs from the original by a relative 2-norm error of 1e-4.
Implementation details:
- The untruncated spectrum of each sector is accumulated into the denominator before any truncation mask is applied, so the normalization is always against the full tensor.
- Under
"thresh"truncation, the squared weight of masked-out singular values is accumulated per sector; under global"nkeep"truncation, the per-sector multiplicity is recovered from the charge stored alongside each singular value in the global sort. - For Abelian groups
d_q = 1and the formula reduces to the plain relative squared sum. For SU(2), each reduced singular value stands ford_qdegenerate Schmidt values, and the factor is required for the weighted spectrum to reproduceT.norm()**2. - The multiplicity factor weights the reported value only. It does not enter the
"thresh"or"nkeep"truncation criteria, since alld_qSchmidt vectors of a multiplet share the same singular value and are kept or dropped together. - An identically-zero tensor has no spectrum to lose and reports
0.0instead of dividing by zero.
Both the extra accumulation and the multiplicity lookup are gated on requires_info=True, so calls without it pay no additional cost.
Package metadata
The author email in pyproject.toml is updated to c.zhang@ideogenesis.ai, and a maintainers entry for Ideogenesis AI <developer@ideogenesis.ai> is added.
📖 Documentation
docs/api/decomposition/svd.mdnow states the[0, 1)range and the‖T − T_trunc‖²/‖T‖²definition of"discarded_weight", and adds a note on the irrep-dimension factor for generic symmetry groups.docs/examples/operations/decomposition-examples.mdexplains that the reported weight is relative and squared, with a worked interpretation of what1e-8means in terms of 2-norm error. The example output is printed in scientific notation to suit the new scale.- The
svddocstring gains a Notes paragraph giving the formula and the role ofd_q. - The documentation hero image is refreshed.
🧪 Test Suite (1635 tests)
- 1625 tests pass, 10 skipped (CUDA-only tests on a CUDA-less CI runner)
- 5 existing
infotests intests/operations/test_factorize.py(nkeep,thresh, combined, multi-block) are updated to assert the relative squared weight against the full and truncatedS_dictspectra - 3 new tests in
tests/operations/test_factorize.py:test_svd_info_discarded_weight_boundedchecks that the reported value lies in[0, 1)test_svd_info_matches_reconstruction_normrebuildsT_trunc = U · S · Vhviadecompand assertsdiscarded_weight == 1 − ‖T_trunc‖²/‖T‖²directly from the definitiontest_svd_su2_discarded_weight_multiplicityverifies for an SU(2) tensor that theirrep_dim-weighted full spectrum reproducesT.norm()**2, and that the reported value matches the reconstruction norm loss undernkeeptruncation
📊 Statistics
Code Changes
- 8 commits since v0.4.0
- 6 files changed: 111 insertions, 26 deletions
- Source module touched:
src/nicole/decomp.py - Test module touched:
tests/operations/test_factorize.py - Documentation touched:
docs/api/decomposition/svd.md,docs/examples/operations/decomposition-examples.md,docs/images/hero.png - Metadata touched:
pyproject.toml
✅ Compatibility
Breaking Changes: The numerical meaning of info["discarded_weight"] returned by svd(..., requires_info=True) has changed. Code that compared it against an absolute threshold calibrated to the old sum-of-singular-values definition must be recalibrated to the relative squared scale in [0, 1). The svd signature, the shape of the return tuple, the info dict keys, and all truncation behavior are unchanged; U, S_dict, and Vh are bit-for-bit identical to v0.4.0. Calls without requires_info=True are unaffected.
Requirements:
- Python ≥ 3.11
- PyTorch ≥ 2.5
- Yuzuha ≥ 0.1.5
📝 Notes
The relative squared definition is the standard truncation-error measure in tensor-network algorithms: the sum of discarded squared Schmidt values is the squared distance between the original and truncated states, and normalizing by ‖T‖² makes it independent of the overall scale of the tensor. For SU(2) tensors, the singular values obtained from the block-wise SVD are reduced: each one stands for a full multiplet of 2j + 1 degenerate Schmidt values, so the irrep-dimension factor is needed for the squared spectrum to add up to ‖T‖². Omitting it would systematically undercount the weight carried by higher-spin sectors.