Balanced gram_eigh_full convention, add one and operator-construction primitives#177
Open
mtfishman wants to merge 7 commits into
Open
Balanced gram_eigh_full convention, add one and operator-construction primitives#177mtfishman wants to merge 7 commits into
mtfishman wants to merge 7 commits into
Conversation
Switch gram_eigh_full and gram_eigh_full_with_pinv from A ≈ X' * X to A ≈ X * X', i.e. X = V * sqrt(D) instead of sqrt(D) * V'. This matches the convention used by eigh and SVD (factor on the left, with codomain axes leading and a trailing rank axis), so the output of gram_eigh_full can be right-multiplied into a tensor in the operator's input space without an axis-order swap. The companion left inverse Y from gram_eigh_full_with_pinv now satisfies Y * X ≈ I on the rank subspace (it was a right inverse under the old convention).
Mirrors the existing factorization API (qr/svd/eigen/gram_eigh_full):
a layered dispatch chain accepting labels, perm-tuples, biperms, or
Val{ndims_codomain}, all funneling into a canonical worker that
matricizes, calls MatrixAlgebraKit.one!, and unmatricizes. The
result sits in canonical (codomain, domain) order.
Not exported, since exporting would clash with the implicit Base.one.
Qualify as `TensorAlgebra.one(A, ...)`.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #177 +/- ##
==========================================
- Coverage 80.61% 80.03% -0.58%
==========================================
Files 24 26 +2
Lines 1011 1037 +26
==========================================
+ Hits 815 830 +15
- Misses 196 207 +11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Allows callers to supply codomain and domain axes in the same direction. Storage axes become `(codomain..., conj.(domain)...)`, baking the bra/ket flip into the primitive instead of pushing it onto every caller.
mtfishman
added a commit
to ITensor/NamedDimsArrays.jl
that referenced
this pull request
Jun 2, 2026
`TensorAlgebra.similar_map` now flips the domain direction itself when laying out storage (ITensor/TensorAlgebra.jl#177), so the wrapper passes both sides in the same direction and lets the primitive handle the bra/ket flip.
`projectto!(dest, src) -> dest` orthogonally projects `src` onto the representable subspace of `dest`, in place. Magnitude-blind and tolerance-free: the non-representable component is dropped unconditionally. `checked_projectto!(dest, src; atol, rtol) -> dest` runs the projection and then verifies via `isapprox(src, dest)`, throwing on tolerance violations. The default `projectto!` falls through to `copyto!`, which is correct for dense backends where the representable subspace is everything. Block-structured backends (`AbelianGradedArray`, `FusionTensor`) overload it to copy only the symmetry-allowed entries. This pairs with `similar_map` to give a uniform "allocate then project" idiom for operator constructors across backends, mirroring the standard `copyto!(similar(...), src)` pattern but with backend-aware projection in place of faithful copy. Co-authored-by: Claude <noreply@anthropic.com>
…ppers The data-bearing sibling of `similar_map` / `zeros_map`: allocate via `similar_map` and project `raw` in via `projectto!`. `checked_project_map` is the same on top of `checked_projectto!`, throwing if the discarded weight exceeds the tolerance. Co-authored-by: Claude <noreply@anthropic.com>
Unmatricize `S` so all three SVD outputs share one backend. Previously `S` came back as the matricized form from `MatrixAlgebra.svd!!`, while `U` and `Vᴴ` went through `unmatricize`, leaving downstream consumers with mixed backends (`FusedGradedMatrix` for `S`, the unmatricized backend for the others). `S` now uses `tuplemortar(((axes(U, 2),), (axes(Vᴴ, 1),)))` as its 1+1 axis pair.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Flips
gram_eigh_fullfrom the right-Gram (A ≈ X' * X) convention to the balanced left form (A ≈ X * X'), whereX = V * sqrt(D)is the symmetric eigendecomposition with the square-root absorbed into the eigenvector matrix. The returned factorXnow carries the codomain axes followed by a trailing rank axis, matching the layout of the eigendecomposition'sVand the SVD'sU, and parallel to the L-form of Cholesky. The companiongram_eigh_full_with_pinvnow returns a left inverseYsuch thatY * X ≈ Ion the rank subspace.Also adds
TensorAlgebra.one(A, codomain, domain)for constructing an identity operator tensor with the same shape asA, with the layered dispatch chain (labels, perm tuples, biperms,Val{ndims_codomain}) used by the other factorizations. Not exported because exporting would clash withBase.one. Qualify asTensorAlgebra.one(...).Adds
TensorAlgebra.similar_map(prototype, [T,] codomain_axes, domain_axes)for allocating an array shaped as a linear map with axes(codomain_axes..., domain_axes...). This is the primitiveNamedDimsArrays.similar_operatorwill route through (ITensor/NamedDimsArrays.jl#229), so a backend only needs to overloadsimilar_mapto plug into the named-axis wrapper.Adds
projectto!(dest, src)andchecked_projectto!(dest, src; atol, rtol)for orthogonal projection of a source array into the representable subspace ofdest.projectto!drops the non-representable component without looking at its size.checked_projectto!runs the projection and verifies the discarded weight viaisapprox, throwing on tolerance violations. The defaultprojectto!falls through tocopyto!, correct for dense backends where everything is representable.AbelianGradedArray(inGradedArrays.jl) overloads it to copy only symmetry-allowed entries.Pairs
similar_mapwithprojectto!asproject_map(raw, cod, dom) = projectto!(similar_map(raw, cod, dom), raw), the data-bearing sibling of the_mapallocator family.checked_project_mapis the same on top ofchecked_projectto!. Operator constructors call the checked variant by default.The
gram_eigh_fullconvention change is technically breaking, but the function was introduced very recently and has no known downstream users, so this lands as a patch bump (0.9.5).