Skip to content

Rework NamedTensorOperator around output/input pairing#222

Merged
mtfishman merged 6 commits into
mainfrom
mf/operator-input-output
Jul 21, 2026
Merged

Rework NamedTensorOperator around output/input pairing#222
mtfishman merged 6 commits into
mainfrom
mf/operator-input-output

Conversation

@mtfishman

@mtfishman mtfishman commented Jul 15, 2026

Copy link
Copy Markdown
Member

Summary

Reworks NamedTensorOperator to describe an operator as a wrapped tensor plus a pairing of its dimension names into an output side and an input side, renaming the codomainnames/domainnames accessors to outputnames/inputnames. The rename frees codomain/domain for the tensor's own structural split, which is separate from the operator's output/input pairing.

The pairing is now stored as two equal-length name vectors over the wrapped tensor instead of a Bijection. Lookups are a linear findfirst, which is faster than hashing for the handful of paired legs an operator carries and drops the OrderedCollections dependency. outputname/inputname look up a wire's other end, with a three-argument get-style form that returns a supplied default when a name is unpaired (so a caller can write inputname(op, i, i) for "the other end of the wire, or i itself") and a two-argument form that throws instead.

apply(x, y) applies x to y, landing x's inputs on y's outputs (or a plain state's legs) and relabeling each consumed output of x back to its input, so the result sits on x's input space. Applying an operator to a state gives a state and applying it to another operator gives an operator, with a disjoint part of x tensored in. check_apply rejects landing an input of x on an input of y. apply_dag is removed, since the dagger application is apply(adjoint(x), y).

product(a, b) composes operators on matching sites: a name that is an input of both operands is welded through a fresh bond so the site composes, while dangling names such as batch and Kraus dimensions contract the way * contracts them. The rule that keeps a product well defined is factored into check_product: a wire of a and a wire of b must either be the same wire, which welds, or share no name, which stays independent. Connecting two operators end to end through a shared bond is left to *, which already returns the composed operator.

Priming is demoted from a pairing mechanism to a naming convenience. The pairing is explicit data, so prime/noprime survive only as name generators for constructing operators, and any pair of distinct names describes a wire equally well.

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.23%. Comparing base (412dfa9) to head (83e5c9a).

Files with missing lines Patch % Lines
src/namedtensoroperator.jl 85.71% 16 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #222      +/-   ##
==========================================
+ Coverage   76.90%   77.23%   +0.32%     
==========================================
  Files          29       29              
  Lines        1706     1713       +7     
==========================================
+ Hits         1312     1323      +11     
+ Misses        394      390       -4     
Flag Coverage Δ
docs 27.19% <38.73%> (+0.82%) ⬆️

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

☔ View full report in Codecov by Harness.
📢 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.

Rename the operator's dimension-name accessors from codomainnames/domainnames
to outputnames/inputnames, and store the pairing as two equal-length name
vectors over the wrapped tensor instead of a Bijection (linear findfirst is
faster than hashing for the few paired legs an operator carries, and it drops
the OrderedCollections dependency). Add outputname/inputname get-style wire
lookups, express apply as a contraction followed by an output-to-input relabel,
and define product as composition on matching sites, gated by check_product.
Add two-argument `outputname(a, i)` / `inputname(a, i)` that return the paired
name and throw a clear `ArgumentError` when `i` is unpaired, alongside the
three-argument get-style forms that return a supplied default.
Rework `apply` so applying an operator to another operator returns an operator:
`x`'s inputs land on `y`'s outputs, each consumed output of `x` is relabeled back
to its input, and uncontracted structure passes through, with a disjoint part of
`x` tensored in. Applying to a bare state still returns a state, and `check_apply`
rejects landing an input of `x` on an input of `y`. Remove `apply_dag`, which was
unused. The dagger application is `apply(adjoint(x), y)`.
The Hermitian square-root operator forms (`project_hermitian`, `sqrth_safe`,
`invsqrth_safe`, `sqrth_invsqrth_safe`) landed on `main` after this branch and
still used the old `codomainnames`/`domainnames` accessors. Rename them to
`outputnames`/`inputnames` so they resolve against the reworked operator interface.
@mtfishman
mtfishman force-pushed the mf/operator-input-output branch from 2c39c72 to f0a11b3 Compare July 20, 2026 22:31
The operator methods return a `Vector{DimName}`, so the plain-tensor fallback
returning a tuple was inconsistent. Return `DimName[]` so both always give a
Vector, and drop the now-redundant `collect` from the accessor docstrings.
`apply`'s `See also` linked `[`product`](@ref)`, but `product` is internal
(unexported and undocumented), so Documenter cannot resolve the reference and the
docs build fails. Remove it. The remaining `See also` links all point to
documented names.
@mtfishman mtfishman changed the title [WIP] Rework NamedTensorOperator around output/input pairing Rework NamedTensorOperator around output/input pairing Jul 21, 2026
@mtfishman
mtfishman marked this pull request as ready for review July 21, 2026 18:21
@mtfishman
mtfishman enabled auto-merge (squash) July 21, 2026 18:21
@mtfishman
mtfishman merged commit 06900c4 into main Jul 21, 2026
26 of 28 checks passed
@mtfishman
mtfishman deleted the mf/operator-input-output branch July 21, 2026 18:41
mtfishman added a commit to ITensor/ITensorNetworksNext.jl that referenced this pull request Jul 21, 2026
## Summary

Builds ITensorNetworksNext against ITensorBase v0.13
(ITensor/ITensorBase.jl#222), which reworks
`NamedTensorOperator` around an output/input name pairing. Renames the
`domainnames` accessor to `inputnames` in the belief-propagation apply
path.

The Ising-network generator inserted each bond matrix with `apply` on an
operator whose shared leg was its output. The reworked `apply` preserves
a state's names and only contracts an operator's input, so it now
rejects that usage. The old `apply` had degraded to a plain contraction
in that case anyway, so this replaces it with the direct named
contraction it was really doing, leaving the generated network and the
Ising free-energy checks unchanged.
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