StackOverflowError when contracting with specified cutoff

I’ve been coming across a strange problem in ITensors v0.3.17.

s = [Index(2) for i in 1:3]
a = randomITensor(s[1], s[2])
b = randomITensor(s[2], s[3])

Contracting these two tensors without specifying the cutoff keyword works fine:

julia> contract([a, b])
ITensor ord=2 (dim=2|id=803) (dim=2|id=272)
NDTensors.Dense{Float64, Vector{Float64}}

But specifying the cutoff seems to make it infinitely recurse:

julia> contract([a, b]; cutoff=1e-13)
ERROR: StackOverflowError:
Stacktrace:
     [1] contract(::ITensor, ::Vararg{ITensor}; kwargs::Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}})
       @ ITensors ~/.julia/packages/ITensors/MUEOu/src/itensor.jl:2060
     [2] (::ITensors.var"#233#235"{Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}}})(A::ITensor, B::ITensor)
       @ ITensors ~/.julia/packages/ITensors/MUEOu/src/itensor.jl:2050
     [3] (::Base.BottomRF{ITensors.var"#233#235"{Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}}}})(acc::ITensor, x::ITensor)
       @ Base ./reduce.jl:81
     [4] afoldl(::Base.BottomRF{ITensors.var"#233#235"{Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}}}}, ::Base._InitialValue, ::ITensor, ::ITensor)
       @ Base ./operators.jl:613
     [5] _foldl_impl(op::Base.BottomRF{ITensors.var"#233#235"{Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}}}}, init::Base._InitialValue, itr::Tuple{ITensor, ITensor})
       @ Base ./tuple.jl:277
     [6] foldl_impl(op::Base.BottomRF{ITensors.var"#233#235"{Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}}}}, nt::Base._InitialValue, itr::Tuple{ITensor, ITensor})
       @ Base ./reduce.jl:48
     [7] mapfoldl_impl(f::typeof(identity), op::ITensors.var"#233#235"{Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}}}, nt::Base._InitialValue, itr::Tuple{ITensor, ITensor})
       @ Base ./reduce.jl:44
     [8] mapfoldl(f::Function, op::Function, itr::Tuple{ITensor, ITensor}; init::Base._InitialValue)
       @ Base ./reduce.jl:162
     [9] mapfoldl
       @ ./reduce.jl:162 [inlined]
    [10] #foldl#245
       @ ./reduce.jl:180 [inlined]
    [11] foldl(op::Function, itr::Tuple{ITensor, ITensor})
       @ Base ./reduce.jl:180
    [12] contract(As::Tuple{ITensor, ITensor}; sequence::String, kwargs::Base.Pairs{Symbol, Float64, Tuple{Symbol}, NamedTuple{(:cutoff,), Tuple{Float64}}})
       @ ITensors ~/.julia/packages/ITensors/MUEOu/src/itensor.jl:2050
--- the last 12 lines are repeated 4703 more times ---

Looking at line 2050 in ITensors.jl,

    return foldl((A, B) -> contract(A, B; kwargs...), As)

it isn’t immediately obvious to me how this could cause the infinite recursion. Am I using contract incorrectly somehow?

I’m not sure why adding that keyword argument causes an infinite recursion, but cutoff isn’t supported for contracting ITensors anyway since approximate contraction of ITensors is not currently support through contract.

1 Like