MPS after imaginary time evolution.

Hi!

I am trying to get a finite temperature state using imaginary time evolution. One thing to note that my Hamiltonian is next nearest neighbour. I have followed the example in ITensor.jl/purification closely for the test. But after imaginary time evolution,the MPS I get have all the link indices with tag “Link,n=1” irrespective of their actual site. The id though is correct. Here is a small snippet to reproduce the issue.

using ITensors

function ITensors.op(::OpName"expτXXZ", ::SiteType"S=1/2", s1::Index, s2::Index; τ,J,Δ)
  
    h =
        J * op("Sx", s1) * op("Sx", s2) +
        J * op("Sy", s1) * op("Sy", s2) +
        (J*Δ)*op("Sz", s1) * op("Sz", s2)
      return exp(τ * h)
  end

function inf_temp_mps(sites)

    num_sites=length(sites)
    if(num_sites %2 !=0)
        throw(DomainError(num_sites,"Expects even number of sites for ancilla-physical singlets."))
    else
        
        ψ=MPS(sites)
        for j=1:2:num_sites-1

            
            s1=sites[j]
            s2=sites[j+1]
            
            if(j==1)
                

                rightlink=commonind(ψ[j+1],ψ[j+2])
                A=ITensor(ComplexF64 ,s1,s2,rightlink )

                A[s1=>1,s2=>2,rightlink=>1]= 1/sqrt(2)
                A[s1=>2,s2=>1,rightlink=>1]= -1/sqrt(2)

                U,S,V=svd(A,(s1),cutoff=1e-15)
                ψ[j]= replacetags(U,"u", "l=$(j)")
                ψ[j+1]= replacetags(S*V,"u", "l=$(j)")

            elseif(j==num_sites-1)
                
                leftlink =commonind(ψ[j-1],ψ[j])
                A=ITensor(ComplexF64 ,s1,s2,leftlink )

                A[s1=>1,s2=>2,leftlink =>1]= 1/sqrt(2)
                A[s1=>2,s2=>1,leftlink =>1]= -1/sqrt(2)

                U,S,V=svd(A,(s1,leftlink ),cutoff=1e-15)
                ψ[j]= replacetags(U,"u", "l=$(j)")
                ψ[j+1]= replacetags(S*V,"u", "l=$(j)")
            else
                

                rightlink=commonind(ψ[j+1],ψ[j+2])
                leftlink =commonind(ψ[j-1],ψ[j])
            
                A=ITensor(ComplexF64 ,s1,s2,rightlink,leftlink )

                A[s1=>1,s2=>2,rightlink=>1,leftlink =>1]= 1/sqrt(2)
                A[s1=>2,s2=>1,rightlink=>1,leftlink =>1]= -1/sqrt(2)

                U,S,V=svd(A,(s1,leftlink ),cutoff=1e-15)
                ψ[j]= replacetags(U,"u", "l=$(j)")
                ψ[j+1]= replacetags(S*V,"u", "l=$(j)")
            end
        end

        return ψ

    end
end

# Configure system
δτ=0.1# trotter step
# Model parameters
J=0.5
Δ=0.1 
#Inverse temp
beta_max=2.0
N=6
s=siteinds("S=1/2",N)
ψ=inf_temp_mps(s)

os = OpSum()
for j in 1:2:(N - 2)
    
    os += J,"Sx",j,"Sx",j+2
    os += J,"Sy",j,"Sy",j+2
    os += J*Δ,"Sz",j,"Sz",j+2
    
end
#Physical hamiltonian
H_physical = MPO(os, s)

# Create gates for imaginary time evolution (Apply only on physical sites)

  # Make gates (1,3),(3,5),(5,7),...
  gates_imag_timeevo = ops([("expτXXZ", (n, n + 2), (τ=-δτ / 2,J,Δ)) for n in 1:2:(N - 2)], s)
  # Include gates in reverse order to complete Trotter formula
  append!(gates_imag_timeevo, reverse(gates_imag_timeevo))

for β in 0:δτ:beta_max
  
  energy=inner(ψ',H_physical,ψ)
  push!(energy_psi,energy)

  @printf("β = %.2f energy = %.8f\n", β, energy)
  ψ= apply(gates_imag_timeevo, ψ; cutoff=1e-15)
  normalize!(ψ)
end
# Check the link index tags in the output ψ
println(ψ)

The output is given below.You may notice the MPS printed with multiple linkindices having tag for “Link,n=1”

β = 0.00 energy = 0.00000000
β = 0.10 energy = -0.01260422
β = 0.20 energy = -0.02526980
β = 0.30 energy = -0.03796322
β = 0.40 energy = -0.05065010
β = 0.50 energy = -0.06329558
β = 0.60 energy = -0.07586472
β = 0.70 energy = -0.08832296
β = 0.80 energy = -0.10063654
β = 0.90 energy = -0.11277288
β = 1.00 energy = -0.12470100
β = 1.10 energy = -0.13639189
β = 1.20 energy = -0.14781876
β = 1.30 energy = -0.15895735
β = 1.40 energy = -0.16978611
β = 1.50 energy = -0.18028634
β = 1.60 energy = -0.19044226
β = 1.70 energy = -0.20024107
β = 1.80 energy = -0.20967287
β = 1.90 energy = -0.21873063
β = 2.00 energy = -0.22741003
MPS
[1] ((dim=2|id=198|"S=1/2,Site,n=1"), (dim=2|id=105|"Link,n=1"))
[2] ((dim=2|id=105|"Link,n=1"), (dim=2|id=450|"S=1/2,Site,n=2"), (dim=4|id=667|"Link,n=1"))
[3] ((dim=4|id=667|"Link,n=1"), (dim=2|id=834|"S=1/2,Site,n=3"), (dim=8|id=923|"Link,n=1"))
[4] ((dim=2|id=656|"S=1/2,Site,n=4"), (dim=4|id=522|"Link,n=1"), (dim=8|id=923|"Link,n=1"))
[5] ((dim=2|id=790|"S=1/2,Site,n=5"), (dim=2|id=302|"Link,l=5"), (dim=4|id=522|"Link,n=1"))
[6] ((dim=2|id=395|"S=1/2,Site,n=6"), (dim=2|id=302|"Link,l=5"))

They are associated with proper sites as it seems from the link ids.

To be precise, my even sites are ancilla & odd sites are physical qubits.
I guess using apply for non-consecutive sites have some restrictions in C++. I checked the apply function definition in Julia version & the docstring suggests this has been taken care of using movesite. I am not sure what is going wrong here. Though as the link ids are correct,I guess the results should not get affected in subsequent calculations.

I would really appreciate any suggestion.