ITensor/ITensors.jl

[ITensors] [BUG] unexpected `uniqueinds` result

Closed this issue · 5 comments

Description of bug

Let A and B be collections of type Index and if A has duplicated elements, uniqueinds(A,B) returns the element in B duplicated in A, which is not in the set difference A - B.

I am not sure whether this is a bug or not.
If this behavior is intentional, adding documentation explaining how it differs from Base.setdiff would be beneficial.
The current documentation for uniqueinds states that it is similar to Base.setdiff , so this difference might confuse users.
For example, setdiff([1,1],1) returns Int64[].

Minimal code demonstrating the bug or unexpected behavior

i = index(2)
uniqueinds([i,i],i)

Expected output or behavior

Index{Int64}[]

Actual output or behavior

julia> i = Index(2)
(dim=2|id=955)

julia> uniqueinds([i,i],i)
1-element Vector{Index{Int64}}:
 (dim=2|id=955)

Version information

  • Output from versioninfo():
julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 8 × Apple M2
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 1 default, 0 interactive, 1 GC (on 4 virtual cores)
  • Output from using Pkg; Pkg.status("ITensors"):
julia> using Pkg; Pkg.status("ITensors")
Status `~/.julia/environments/v1.10/Project.toml`
  [9136182c] ITensors v0.3.67

I agree it should have the behavior you describe, however currently I would just consider that to be undefined behavior since ITensor indices are expected to have unique indices to begin with.

Thank you for responding.
I do not think this is too serious because it has not been a problem before.
I note the situation occurs when A has both unprimed and primed identical indices (like A=ITensor(i, i')) and the function noprime is combined as in uniqueinds(noprime(A), i).

I see, in that kind of situation making the ITensor noprime(A) is considered undefined behavior. We throw an error for that if you enable debug checks:

julia> using ITensors

julia> ITensors.enable_debug_checks()

julia> i = Index(2)
(dim=2|id=123)

julia> a = ITensor(i, i')
ITensor ord=2 (dim=2|id=123) (dim=2|id=123)'
NDTensors.EmptyStorage{NDTensors.EmptyNumber, NDTensors.Dense{NDTensors.EmptyNumber, Vector{NDTensors.EmptyNumber}}}

julia> noprime(a)
ERROR: Trying to create ITensors with collection of indices ((dim=2|id=123), (dim=2|id=123)). Indices must be unique.
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] macro expansion
   @ ~/.julia/packages/ITensors/c1wvC/src/itensor.jl:91 [inlined]
 [3] macro expansion
   @ ~/.julia/packages/ITensors/c1wvC/src/global_variables.jl:198 [inlined]
 [4] ITensor
   @ ~/.julia/packages/ITensors/c1wvC/src/itensor.jl:88 [inlined]
 [5] itensor(args::NDTensors.EmptyTensor{NDTensors.EmptyNumber, 2, Tuple{…}, NDTensors.EmptyStorage{…}})
   @ ITensors ~/.julia/packages/ITensors/c1wvC/src/itensor.jl:135
 [6] noprime(::ITensor; kwargs::@Kwargs{})
   @ ITensors ~/.julia/packages/ITensors/c1wvC/src/itensor.jl:1554
 [7] top-level scope
   @ REPL[11]:1
Some type information was truncated. Use `show(err)` to see complete types.

For performance reasons we don't check it all the time.

I'll close this since most cases should be caught by ITensors.enable_debug_checks(), though we might consider adding debug checks in index set operations like uniqueinds for cases when ITensors aren't involved, since the checks are only put into the ITensor constructor.

The need for index-only debug checks could be infrequent, but having them prepared would enhance robustness.
Thank you for your time on this issue.