A correct way to define a ITensor is the following
using ITensors
i = Index(2)
j = Index(2)
A = random_itensor(i, j)
Now what if I do the following
A = random_itensor(i,i)
It does not raise any warning or error.
But more than this, it gives incorrect results when setting values at specific positions. See the following example
i=Index(2)
j=Index(2)
A=random_itensor(i,i)
B=random_itensor(i,j)
@show A
@show B
println("After setting value at 1,2 for both A and B")
A[i=>1,i=>2]=999
B[i=>1,j=>2]=999
@show A
@show B
And here is the output:
A = ITensor ord=2
Dim 1: (dim=2|id=168)
Dim 2: (dim=2|id=168)
NDTensors.Dense{Float64, Vector{Float64}}
2×2
-0.8951148439378779 0.36977219901378616
-0.4788833082871866 0.34125666612909394
B = ITensor ord=2
Dim 1: (dim=2|id=168)
Dim 2: (dim=2|id=84)
NDTensors.Dense{Float64, Vector{Float64}}
2×2
-1.5456158351721794 -0.26621937104864807
-0.217078897761148 0.29058283067273155
After setting value at 1,2 for both A and B
A = ITensor ord=2
Dim 1: (dim=2|id=168)
Dim 2: (dim=2|id=168)
NDTensors.Dense{Float64, Vector{Float64}}
2×2
999.0 0.36977219901378616
-0.4788833082871866 0.34125666612909394
B = ITensor ord=2
Dim 1: (dim=2|id=168)
Dim 2: (dim=2|id=84)
NDTensors.Dense{Float64, Vector{Float64}}
2×2
-1.5456158351721794 999.0
-0.217078897761148 0.29058283067273155
You can see A[i=>1,i=>2]=999 replace the value incorrectly at A[1,1] position.
I know nobody should use the Index in such a way to define an ITensor, but the ITensor should properly handle this situation.
Duplicate indices are only checked when debug checks are enabled:
julia> using ITensors
julia> ITensors.enable_debug_checks()
julia> i = Index(2)
(dim=2|id=970)
julia> ITensor(i, i)
ERROR: Trying to create ITensors with collection of indices ((dim=2|id=970), (dim=2|id=970)). Indices must be unique.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] macro expansion
@ ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:94 [inlined]
[3] macro expansion
@ ~/.julia/packages/ITensors/KvHvB/src/global_variables.jl:180 [inlined]
[4] ITensor
@ ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:91 [inlined]
[5] ITensor(as::NDTensors.AllowAlias, st::NDTensors.EmptyStorage{NDTensors.EmptyNumber, NDTensors.Dense{…}}, is::Tuple{Index{…}, Index{…}})
@ ITensors ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:122
[6] itensor(::NDTensors.EmptyStorage{NDTensors.EmptyNumber, NDTensors.Dense{NDTensors.EmptyNumber, Vector{NDTensors.EmptyNumber}}}, ::Vararg{Any}; kwargs::@Kwargs{})
@ ITensors ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:138
[7] itensor
@ ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:138 [inlined]
[8] ITensor
@ ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:181 [inlined]
[9] ITensor(::Type{NDTensors.EmptyNumber}, ::Index{Int64}, ::Vararg{Index{Int64}})
@ ITensors ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:184
[10] ITensor(::Index{Int64}, ::Vararg{Index{Int64}})
@ ITensors ~/.julia/packages/ITensors/KvHvB/src/itensor.jl:186
[11] top-level scope
@ REPL[4]:1
Some type information was truncated. Use `show(err)` to see complete types.
We do that for efficiency, otherwise we would be checking for duplicate indices a lot. It is good practice to enable debug checks when developing ITensor code, and once it is working disable them for efficiency.