You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tensor4all.TensorNetworks.elementwise_product(a, b; threshold, maxdim) (which forwards to partial_contract with the default method=:zipup) honors the threshold / maxdim kwargs at the bond-dimension cap, but does not shrink bonds whose canonical rank is below the cap. Calling truncate(...; threshold, maxdim) on the result of an unconstrained elementwise_product(a, b) produces a strictly smaller, canonical-rank tensor train at the same accuracy. Users currently need a manual second pass to obtain a fully compressed answer.
Steps to reproduce
This is the 04_operations_on_qtts tutorial scenario: f(x) = x², g(x) = sin(10x) on [0, 1), R = 7, tolerance = 1e-12, maxbonddim = 32.
Accuracy is at machine precision in both cases — the issue is not numerical correctness, it is that tt_h_raw keeps a leading bond at 4 even though the canonical rank under the requested tolerance is 2. The in-product truncation step appears not to be reaching that canonical rank.
The same pattern shows up more strongly on flatter input spectra. With two random linkdim=32 TensorTrains over 12 sites of physical dim 2 (bonds saturated, no rapidly decaying singular values), the in-product call returns leading linkdims [4, 16, 32, 32, …] whereas a follow-up truncate reaches [2, 4, 8, 16, 32, …]. Accuracy degrades visibly on that flatter spectrum too — the relative error vs the exact product is several times larger than the follow-up truncate path — but the QTT-style smooth-function case in the tutorial is dominated by the compression symptom, not the accuracy one.
method=:fit with nfullsweeps > 0 reaches the same canonical linkdims as the follow-up truncate path, which suggests the suboptimal step is local to the :zipup truncation in the underlying TreeTN kernel.
Expected behavior
elementwise_product(a, b; threshold, maxdim) should produce a result with linkdims matching:
so that no separate truncate pass is required to reach canonical rank.
Tensor4all.jl version
main (verified at commit 834d0be).
Julia version
1.11
OS
macOS 15
Proposed approach (for spec discussion)
The truncation kwargs are correctly plumbed through Julia (elementwise_product → partial_contract → FFI t4a_treetn_partial_contract); the suboptimal compression appears to come from the TreeTN :zipup truncation kernel in tensor4all-rs. A canonical-rank result requires an SVD truncation against an orthogonalized environment on both sides, which a single-direction zip-up sweep does not provide.
Possible directions:
Fix the :zipup truncation in tensor4all-rs so the result matches the linkdims of a stand-alone truncate(...) pass. Most aligned with the user expectation, almost certainly a tensor4all-rs change.
Change the default of partial_contract / elementwise_product (e.g. :zipup followed by an automatic final canonicalize+truncate sweep, or :fit with at least one full sweep). Pure Tensor4all.jl change.
Document the limitation and recommend method=:fit, nfullsweeps≥1 (or a follow-up truncate) when truncation is requested. Lowest effort, leaves the suboptimality in place.
Option 1 is the proper fix and likely needs a tensor4all-rs companion issue (see CONTRIBUTING.md "Cross-Repository Changes"). Options 2 or 3 can be done purely in Tensor4all.jl as a stop-gap.
Acceptance criteria
On the tutorial reproducer above, elementwise_product(tt_f, tt_g; threshold, maxdim) returns linkdims equal to those of truncate(elementwise_product(tt_f, tt_g); threshold, maxdim).
Same for partial_contract(a, b, spec; threshold, maxdim) with the default method.
A regression test under test/tensornetworks/partial_contract.jl asserts that the truncating path reaches canonical-rank linkdims (not just the bond-dim cap).
If the fix lands in tensor4all-rs, deps/build.jl is repinned and the new pin is recorded.
The docstring for elementwise_product / partial_contract either no longer needs the workaround, or — if :zipup is intentionally single-sweep — documents the compression caveat and points to :fit or a follow-up truncate.
This issue was drafted by Claude (Anthropic, model claude-opus-4-7[1m]) in collaboration with @sdirnboeck and filed via gh on her authenticated session. Reproducer was generated and run locally by the assistant against main at commit 834d0be.
Description
Tensor4all.TensorNetworks.elementwise_product(a, b; threshold, maxdim)(which forwards topartial_contractwith the defaultmethod=:zipup) honors thethreshold/maxdimkwargs at the bond-dimension cap, but does not shrink bonds whose canonical rank is below the cap. Callingtruncate(...; threshold, maxdim)on the result of an unconstrainedelementwise_product(a, b)produces a strictly smaller, canonical-rank tensor train at the same accuracy. Users currently need a manual second pass to obtain a fully compressed answer.Steps to reproduce
This is the
04_operations_on_qttstutorial scenario:f(x) = x²,g(x) = sin(10x)on[0, 1),R = 7,tolerance = 1e-12,maxbonddim = 32.Actual behavior
In the example above:
elementwise_product(tt_f, tt_g; threshold, maxdim)[4, 6, 6, 6, 4, 2]truncate(...; threshold, maxdim)[2, 4, 6, 6, 4, 2]Accuracy is at machine precision in both cases — the issue is not numerical correctness, it is that
tt_h_rawkeeps a leading bond at 4 even though the canonical rank under the requested tolerance is 2. The in-product truncation step appears not to be reaching that canonical rank.The same pattern shows up more strongly on flatter input spectra. With two random
linkdim=32TensorTrains over 12 sites of physical dim 2 (bonds saturated, no rapidly decaying singular values), the in-product call returns leading linkdims[4, 16, 32, 32, …]whereas a follow-uptruncatereaches[2, 4, 8, 16, 32, …]. Accuracy degrades visibly on that flatter spectrum too — the relative error vs the exact product is several times larger than the follow-uptruncatepath — but the QTT-style smooth-function case in the tutorial is dominated by the compression symptom, not the accuracy one.method=:fitwithnfullsweeps > 0reaches the same canonical linkdims as the follow-uptruncatepath, which suggests the suboptimal step is local to the:zipuptruncation in the underlying TreeTN kernel.Expected behavior
elementwise_product(a, b; threshold, maxdim)should produce a result with linkdims matching:so that no separate truncate pass is required to reach canonical rank.
Tensor4all.jl version
main(verified at commit834d0be).Julia version
1.11
OS
macOS 15
Proposed approach (for spec discussion)
The truncation kwargs are correctly plumbed through Julia (
elementwise_product→partial_contract→ FFIt4a_treetn_partial_contract); the suboptimal compression appears to come from the TreeTN:zipuptruncation kernel in tensor4all-rs. A canonical-rank result requires an SVD truncation against an orthogonalized environment on both sides, which a single-direction zip-up sweep does not provide.Possible directions:
:zipuptruncation in tensor4all-rs so the result matches the linkdims of a stand-alonetruncate(...)pass. Most aligned with the user expectation, almost certainly a tensor4all-rs change.partial_contract/elementwise_product(e.g.:zipupfollowed by an automatic final canonicalize+truncate sweep, or:fitwith at least one full sweep). Pure Tensor4all.jl change.method=:fit, nfullsweeps≥1(or a follow-uptruncate) when truncation is requested. Lowest effort, leaves the suboptimality in place.Option 1 is the proper fix and likely needs a tensor4all-rs companion issue (see CONTRIBUTING.md "Cross-Repository Changes"). Options 2 or 3 can be done purely in Tensor4all.jl as a stop-gap.
Acceptance criteria
elementwise_product(tt_f, tt_g; threshold, maxdim)returns linkdims equal to those oftruncate(elementwise_product(tt_f, tt_g); threshold, maxdim).partial_contract(a, b, spec; threshold, maxdim)with the default method.test/tensornetworks/partial_contract.jlasserts that the truncating path reaches canonical-rank linkdims (not just the bond-dim cap).deps/build.jlis repinned and the new pin is recorded.elementwise_product/partial_contracteither no longer needs the workaround, or — if:zipupis intentionally single-sweep — documents the compression caveat and points to:fitor a follow-uptruncate.This issue was drafted by Claude (Anthropic, model
claude-opus-4-7[1m]) in collaboration with @sdirnboeck and filed viaghon her authenticated session. Reproducer was generated and run locally by the assistant againstmainat commit834d0be.