Skip to content

TensorNetworks.add fuses same-id prime-pair MPO site legs into Link legs #82

@shinaoka

Description

@shinaoka

Summary

TensorNetworks.add can corrupt site metadata for MPO-like TensorTrains whose two site legs at each tensor are ITensor-style prime pairs: same Index.id, same tags, different plev.

Instead of preserving two site legs per tensor, the backend add result exposes a single generic Link site leg per tensor. This makes downstream ITensorCompat.MPO(result) invalid and can hide the root cause behind later topology or norm failures.

This was found while porting BubbleTeaCI Task 9 away from direct ITensors/Quantics/T4A* dependencies.

Minimal reproducer

using Tensor4all
const TN = Tensor4all.TensorNetworks

function make_mpo_like_indices()
    inputs = [Index(3; tags=["Site$n"], plev=0) for n in 1:3]
    outputs = prime.(inputs)  # same id/tags, plev=1
    links = [Index(9; tags=["Link", "l=1"]), Index(3; tags=["Link", "l=2"])]
    return inputs, outputs, links
end

function make_mpo_like_tt(; scale=1.0, inputs=nothing, outputs=nothing, links=nothing)
    if inputs === nothing
        inputs, outputs, links = make_mpo_like_indices()
    end
    return TN.TensorTrain([
        Tensor(scale .* reshape(collect(1.0:81.0), 3, 3, 9),
               [inputs[1], outputs[1], links[1]]),
        Tensor(scale .* reshape(collect(1.0:243.0), 9, 3, 3, 3),
               [links[1], inputs[2], outputs[2], links[2]]),
        Tensor(scale .* reshape(collect(1.0:27.0), 3, 3, 3),
               [links[2], inputs[3], outputs[3]]),
    ])
end

inputs, outputs, links = make_mpo_like_indices()
tt1 = make_mpo_like_tt(; scale=1.0, inputs, outputs, links)
tt2 = make_mpo_like_tt(; scale=-0.5, inputs, outputs, links)
result = TN.add(tt1, tt2)

println(TN.siteinds(tt1))
println(TN.siteinds(result))
println(length.(TN.siteinds(result)))

Observed behavior

The result site groups become one generic Link leg per tensor:

Vector{Index}[[Index(6|Link; plev=0)], [Index(6|Link; plev=0)], [Index(6|Link; plev=0)]]
[1, 1, 1]

For the BubbleTeaCI reproducer, valid chain MPOs from permute_legs_TCI and permute_legs! both had site lengths [2, 2, 2], but TN.add(a.tt, (-b).tt; ...) returned site lengths [1, 1, 1].

Expected behavior

TensorNetworks.add should preserve the caller-visible site grouping:

TN.siteinds(result) == TN.siteinds(tt1)
length.(TN.siteinds(result)) == [2, 2, 2]

The two physical site legs in each MPO tensor should remain distinct even when they share Index.id and differ only by prime level.

Notes

A Julia-level SimpleTT direct-sum workaround can preserve the site groups, but that is only a workaround. The owning bug appears to be in the TreeTN backend add path or in the Tensor4all Julia/FFI index conversion around same-id, different-prime site legs.

Until the backend preserves these site pairs correctly, callers should avoid silently accepting the corrupted result.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions