Skip to content

[WIP] Named-operator constructors, projection verbs, and balanced gram_eigh_full#229

Draft
mtfishman wants to merge 9 commits into
mainfrom
mf/gram-eigh-balanced
Draft

[WIP] Named-operator constructors, projection verbs, and balanced gram_eigh_full#229
mtfishman wants to merge 9 commits into
mainfrom
mf/gram-eigh-balanced

Conversation

@mtfishman
Copy link
Copy Markdown
Member

@mtfishman mtfishman commented Jun 2, 2026

Summary

  • Base.one(::AbstractNamedDimsOperator) and Base.one(::AbstractNamedDimsArray, codomain, domain)
  • similar_operator(prototype, [T,] axes, [codomain_names,] domain_names), routed through TensorAlgebra.similar_map
  • Random.randn! and Random.rand! on AbstractNamedDimsOperator
  • Base.conj(::AbstractNamedUnitRange), forwarded through the underlying range so graded-axis conjugation flips sector arrows
  • gram_eigh_full aligned with the balanced convention from Balanced gram_eigh_full convention, add one and operator-construction primitives TensorAlgebra.jl#177
  • domain(::Bijection) returns a Base.KeySet, so equal-pair Bijections compare equal
  • Base.conj, Base.:* / Base.:/ by a scalar, and LinearAlgebra.normalize on AbstractNamedDimsArray, routed through denamed to avoid the broadcast-scalar-indexing path
  • TensorAlgebra.projectto! and TensorAlgebra.checked_projectto! forwarded to the underlying storage

TODO

  • Drop the [sources] pin on TensorAlgebra once the matching version (0.9.5) registers.

mtfishman added 3 commits June 1, 2026 23:57
Match TensorAlgebra's switch to A ≈ X * X' for gram_eigh_full:
relabel X with the domain dimension names (rank trailing) so it
mirrors V_R from eigh. The companion left inverse Y from
gram_eigh_full_with_pinv likewise carries the domain names with
the rank axis leading.

Pin the matching TensorAlgebra branch via [sources] until that
patch is registered.
- `Base.one(::AbstractNamedDimsArray, codomain, domain)` and
  `Base.one(::AbstractNamedDimsOperator)` build identity-shaped named
  arrays/operators by dispatching to `TensorAlgebra.one` on the
  underlying raw storage. The result sits in canonical
  (codomain, domain) name order.
- `similar_operator(prototype, [T,] axes, [codomain_names,] domain_names)`
  allocates an operator with the user-supplied side as the domain and
  the codomain derived by `conj`-ing the domain axes; codomain names
  default to fresh `randname` outputs. Exported.
- `Random.randn!` / `Random.rand!` peel down to the concrete storage,
  working around the ITensor `eltype(::Type) === Any` issue.
Previously `domain(::Bijection)` returned `values(::OrderedDict)`, a
`Base.ValueIterator` that compares by object identity. Switching it to
`keys` of the reverse dict gives a `Base.KeySet` whose `==` matches
elementwise, so `domainnames(op1) == domainnames(op2)` does what one
would expect.

The two dicts are constructed from the same pairs in the same order, so
`codomain(b)[i]` and `domain(b)[i]` remain in lock-step positional
order.

Also reworks the `Base.one` docstring examples to use `apply` (which
renames the codomain back to the domain), replacing the matricize +
identity-matrix check that's better suited to tests than docs.
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 31.37255% with 35 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.10%. Comparing base (39c2806) to head (c224d98).

Files with missing lines Patch % Lines
src/nameddimsoperator.jl 15.38% 22 Missing ⚠️
src/abstractnameddimsarray.jl 14.28% 12 Missing ⚠️
src/abstractnamedunitrange.jl 0.00% 1 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (39c2806) and HEAD (c224d98). Click for more details.

HEAD has 13 uploads less than BASE
Flag BASE (39c2806) HEAD (c224d98)
docs 2 1
12 0
Additional details and impacted files
@@             Coverage Diff             @@
##             main     #229       +/-   ##
===========================================
- Coverage   71.77%   25.10%   -46.68%     
===========================================
  Files          20       19        -1     
  Lines         992     1000        +8     
===========================================
- Hits          712      251      -461     
- Misses        280      749      +469     
Flag Coverage Δ
docs 25.10% <31.37%> (+1.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Centralizes the linear-map allocation primitive in TensorAlgebra so backends only need to overload `similar_map`, while `similar_operator` keeps the named-axis wrapping.

Also drops the redundant `[sources.TensorAlgebra]` pin from `docs/`, `examples/`, and `test/Project.toml`; the workspace root `Project.toml` already pins the upstream feature branch for all subprojects.
@mtfishman mtfishman changed the title [WIP] Named-operator constructors; align with balanced gram_eigh_full [WIP] Named-operator constructors, align with balanced gram_eigh_full Jun 2, 2026
mtfishman added 2 commits June 2, 2026 11:20
`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.
Without this, `Base.conj(::AbstractArray{<:Real})` short-circuits on a `NamedUnitRange` (element type `NamedInteger{Int, Name}` is a `Real` subtype) and returns the wrapper unchanged — never touching the inner range. That's a no-op for plain ranges but wrong for graded axes, where the inner conj needs to flip sector arrows.
mtfishman and others added 3 commits June 2, 2026 16:59
`Base.conj`, `Base.:*(::, ::Number)`, `Base.:/(::, ::Number)`, and `LinearAlgebra.normalize` are overloaded for `AbstractNamedDimsArray` to delegate to the underlying array rather than the default broadcast path. Broadcast on a `NamedDimsArrayStyle` reaches into the storage via scalar `getindex`, which is unsupported on block-structured arrays such as `AbelianGradedArray` (and would round-trip through scalar slots even when the storage could handle the op block-wise).

`denamed(a, inds)` also short-circuits when the requested order already matches `dimnames(a)`, returning `denamed(a)` directly. The previous path always wrapped in a `PermutedDimsArray` for the identity permutation, which hid the storage type from downstream dispatch (`LinearAlgebra.dot` is the visible case).

Co-authored-by: Claude <noreply@anthropic.com>
`TensorAlgebra.projectto!(::AbstractNamedDimsArray, ::AbstractArray)` delegates to the underlying-storage `projectto!`, so a named operator allocated via `similar_map(prototype, T, named_codomain, named_domain)` can be filled from raw dense data uniformly across backends. The named layer doesn't need to know which storage the named array wraps.

Co-authored-by: Claude <noreply@anthropic.com>
Mirrors the existing `projectto!` forwarder, so backend specializations (e.g. `AbelianGradedArray`'s materialize-and-compare check) are reachable through the named layer with their tolerance defaults intact.

Co-authored-by: Claude <noreply@anthropic.com>
@mtfishman mtfishman changed the title [WIP] Named-operator constructors, align with balanced gram_eigh_full [WIP] Named-operator constructors, projection verbs, and balanced gram_eigh_full Jun 2, 2026
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.

1 participant