Skip to content

Add ITensorNetworkOperator and QuadraticFormNetwork data structures - #195

Draft
jack-dunham wants to merge 18 commits into
mainfrom
jd/quadraticform
Draft

jack-dunham wants to merge 18 commits into
mainfrom
jd/quadraticform

Conversation

@jack-dunham

@jack-dunham jack-dunham commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Adds QuadraticFormNetwork for ⟨ψ|O|ψ⟩, and changes the vertex data of the norm and quadratic-form networks from lazy tensor products to Gramian objects.

  • NormNetwork and QuadraticFormNetwork share a supertype, AbstractBilinearFormNetwork, in src/bilinearforms/. ketnetwork, operatornetwork and branetwork return the layers. The bra layer is a BraView whose tensors are built on access.
  • ITensorNetworkOperator is a tensor network with a pairing of output and input index names, made with operator(tn, outputnames, inputnames). Each output has to sit on the same vertex as its input.
  • nn[v] and qf[v] return a NormGramian or QuadraticFormGramian. It holds the ket tensor, the operator at that vertex for a quadratic form, and the ket-to-bra name map. kettensor, bratensor and operatortensor read the layers, and the bra is only built when asked for. Gramians define inds, names and axes, so linkinds, siteinds etc. work on these networks.
  • contract_network and contraction_order split each Gramian into its layer tensors, so the contraction order can absorb messages into the ket before joining it to the bra. This replaces factor_tensors.

Breaking:

  • The eltype of NormNetwork and QuadraticFormNetwork is now the Gramian type.
  • Removed factor_tensors, indmap, KetView, OperatorView, and the two-argument accessors such as kettensor(bn, v). Use kettensor(bn[v]) instead.
  • subgraph doesn't work on these networks yet.

@ITensorBot

ITensorBot commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Your PR no longer requires formatting changes. Thank you for your contribution!

@codecov

codecov Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.62500% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.86%. Comparing base (b22c27f) to head (f9bdc22).

Files with missing lines Patch % Lines
src/bilinearforms/abstractbilinearformnetwork.jl 79.16% 10 Missing ⚠️
src/itensornetworkoperator.jl 79.54% 9 Missing ⚠️
src/bilinearforms/normnetwork.jl 87.50% 2 Missing ⚠️
src/bilinearforms/quadraticformnetwork.jl 93.93% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #195      +/-   ##
==========================================
- Coverage   87.19%   82.86%   -4.33%     
==========================================
  Files          16       16              
  Lines         687      782      +95     
==========================================
+ Hits          599      648      +49     
- Misses         88      134      +46     
Flag Coverage Δ
docs 0.00% <0.00%> (ø)

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.

Comment thread src/itensornetworkoperator.jl Outdated
struct ITensorNetworkOperator{T, V, I, P <: AbstractITensorNetwork{T, V}} <:
AbstractITensorNetwork{T, V}
parent::P
outputnames::Vector{I}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Consider fast lookup of this.

Comment thread src/bilinearforms/bilinearformnetworkview.jl Outdated
@jack-dunham
jack-dunham force-pushed the jd/quadraticform branch 2 times, most recently from 39c3212 to 3457ed5 Compare September 28, 2026 19:38
jack-dunham and others added 17 commits September 29, 2026 10:47
`QuadraticFormNetwork` represents `⟨tn|op|tn⟩` lazily, with an operator layer
between the bra and ket layers. A ket index name is renamed in the bra layer
when it is a link name or appears in the operator's `inputnames`, so a ket index
the operator does not act on still contracts straight onto the bra.
`operatortensor` renames each operator output name to the bra name of the input
name it is paired with, leaving the input names to meet the ket. The constructor
throws unless `vertices(operator)` and `vertices(ket)` are set-equal.

`AbstractBilinearFormNetwork` is the new supertype of `NormNetwork` and
`QuadraticFormNetwork`. A subtype implements `braname`, `kettensor` and, where it
has an operator layer, `operatortensor`; `bratensor`, `conj_bratensor` and
`indmap` are defined once in terms of those, so the two concrete files now share
them instead of each carrying a copy. `AbstractBilinearFormNetworkView` does the
same for `KetView`, `BraView` and the new `OperatorView`: each implements
`Base.parent` and `get_vertex_data`, and takes its graph structure, assignment
and mutability from the parent network.

`test/test_quadraticformnetwork.jl` covers the name map, the three views, and
three contractions: an identity operator layer reproduces
`contract_network(NormNetwork(tn))`, a random on-site product operator matches a
dense `⟨ψ|O|ψ⟩` reference, and a `2I` layer on three vertices scales the norm by
8.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The five files are byte-identical at their new paths; only the `include` paths in
`src/ITensorNetworksNext.jl` change. `src/normnetworkview.jl` becomes
`bilinearformnetworkview.jl`, since it now holds the views of both `NormNetwork`
and `QuadraticFormNetwork`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`OperatorView` now accepts any `AbstractBilinearFormNetwork` rather than only a
`QuadraticFormNetwork`, and a second constructor throws an `ArgumentError` for a
`NormNetwork`, which reports the reason rather than surfacing a `MethodError`.

A `NormNetwork` maps every site index name to itself in its bra layer, so an
identity operator between the layers would need its output name to equal its
input name, and `ITensor` rejects that: "Dimension names must be distinct".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`encoded_vertex`, `decoded_vertex` and `encoded_graph` move from a
`for View in (:KetView, :BraView)` loop in `bilinearformnetworkview.jl` to
`AbstractBilinearFormNetworkView` in `abstractbilinearformnetworkview.jl`,
replacing the `vertex_positions`/`ordered_vertices`/`position_graph` methods that
NamedGraphs 0.13 removed. `OperatorView` is now covered as well, as it was by the
methods being replaced. The loop also `@eval`ed against `BraView` above that
type's own definition, so including the file threw `UndefVarError: BraView`.

`QuadraticFormNetwork` gets the same rename; it still defined the three removed
names, so the package did not load. `test_quadraticformnetwork.jl` takes
`incident_edges`, `named_grid` and `named_path_graph` from `NamedGraphs` itself,
since the `GraphsExtensions` and `NamedGraphGenerators` submodules are gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`ITensorNetworkOperator` is the network equivalent of `ITensorBase.ITensorOperator`:
a tensor network together with a positional pairing of its dangling index names,
`outputnames[i]` with `inputnames[i]`. The constructor, reached through
`ITensorBase.operator(tn, out, in)`, throws an `ArgumentError` when the two name
lists differ in length and when a named index is not dangling, since
`dimnamevertices` must return exactly one vertex for an operator leg.

A pair may straddle two vertices, as it does for a swap or a translation, so
`getindex` wraps each vertex tensor as an `ITensorOperator` carrying only the pairs
whose two halves both sit on that vertex; the remaining legs are dangling on the
wrapper, which `NamedTensorOperator` permits for names in neither list. The wrapper
is built even when no pair is local, so `eltype` is `NamedTensorOperator{I, T}` for
every vertex.

`QuadraticFormNetwork` takes one as its operator layer. Its `acted` set is now
`Set{I}(inputnames(operator))` rather than a loop over per-vertex input names, and
`operatortensor` reads the network-level pairing: reading `qf.operator[vertex]`
would skip a crossing pair's output leg, which is dangling on that wrapper, and the
bra layer would not meet it. `operatortensor` therefore returns a plain tensor and
`get_vertex_data` drops its `state` call.

`supportof` gains a method for the new type. Its body moves to
`supportof_dimnames(tn, opnames)` in `abstracttensornetwork.jl` so both methods
share it; a `Union` signature is not possible there because
`ITensorNetworkOperator` is not yet defined at that point in the include order.

`replacedimnames` is not implemented for the new type: `ITensorNetwork` has no
`replacedimnames` method to delegate to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…etwork`

`ketnetwork` and `operatornetwork` return the stored ket network and `ITensorNetworkOperator`.
`branetwork` defaults to a `BraView`, since a bilinear-form network does not store its bra layer.
The belief propagation code for `NormNetwork` now reads its link names through these accessors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ds on `BraView`

`BraView` was the only remaining subtype, so it now subtypes `AbstractITensorNetwork`
directly and carries the graph, encoding, assignment and mutability forwarding itself.
The include order places `bilinearformnetworkview.jl` first, since the forwarding methods
now name `BraView`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pure move: the contents of `bilinearformnetworkview.jl` and
`abstractbilinearformnetworkview.jl` are appended verbatim, and their `using` lines are
merged into the existing imports. `src/bilinearforms/` now holds the interface, `NormNetwork`
and `QuadraticFormNetwork`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in `contract_network`

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`contraction_order(tn; alg)` now splits Gramians before dispatching, matching
`contract_network(alg::Exact, tn)`; previously `contraction_order(nn)` on a
`NormNetwork` threw a `MethodError` calling `size` on a Gramian. Adds tests for
that fix and for `split_gramians`' pass-through on inputs with no Gramian.
Also extends the `braname` docstring to cover its `AbstractGramian` method and
shortens the `operatortensor(g::QuadraticFormGramian)` comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Gramian's indices are the layer indices no other layer at that vertex shares, so the
network-level `linkinds`, `linknames`, `linkaxes`, `siteinds`, `sitenames`, `siteaxes` and
`dimnamevertices` work on bilinear-form networks again. The bra indices are read from
`conj_bratensor`, so no tensor data is conjugated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…operator pairs

`ITensorNetworkOperator` now throws when a pair's output and input sit on different vertices,
so each vertex operator carries its full pairing. `QuadraticFormGramian` stores that operator
in place of the raw tensor and the network-wide name vectors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…map` and the network-level accessors

Graph forwarding, the ket part of `is_vertex_assigned` and `braname` are defined once on
`AbstractBilinearFormNetwork` through `ketnetwork` and a new `branamemap` accessor, and both
constructors build the name map with `select_branames`. `kettensor(bn, v)`, `bratensor(bn, v)`,
`conj_bratensor(bn, v)` and `operatortensor(bn, v)` are removed in favour of calling the
accessor on the Gramian `bn[v]`, and the unused `indmap` is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The output and input name vectors are replaced by one map from each output name to its input
name, so `getindex` looks up a vertex's pairs by name instead of scanning every pair. A repeated
output name now throws an `ArgumentError`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants