# Applying local MPOs in Julia

+1 vote
edited

Hi,

I am trying to apply a local MPO at a single site on a MPS. This seems to be easy enough in Julia but I am not sure if the answer I get is sensible.

using ITensors
N = 6
bond_dim=24
sites = siteinds("S=1/2",N)
psi = randomMPS(sites, bond_dim);
psi1 = randomMPS(sites, bond_dim);

j=3  #Choose where to apply the 1-local MPO
#First way (Don't know why this doesn't work)
s = siteind(psi,j)
newpsi= 2*op(s,"Sx") * psi[j]
noprime!(newpsi)
psi[j]= newpsi
println("Firstvalue is ", inner(psi1, psi))
#Second way (This works)
sample = AutoMPO()
sample += 2,"Sx", j;
Operator= MPO(sample,sites);
secondvalue=inner(psi1,Operator,psi)


However the two give different outputs:

Firstvalue is -0.04429389151813912
0.27968037863018275


I am sure I am missing something trivial here but can you point me to why the first method doesn't work?

+1 vote

It looks like both approaches work fine. However, in the first approach, you are modifying psi, and you are using the modified version of psi in the second approach. To avoid this, you need to make a copy of the state before modifying it, for example:

using ITensors
N = 6
bond_dim=24
sites = siteinds("S=1/2",N)
psi0 = randomMPS(sites, bond_dim);
psi1 = randomMPS(sites, bond_dim);

j = 3
psi = copy(psi0)
s = siteind(psi,j)
newpsi= 2*op(s,"Sx") * psi[j]
noprime!(newpsi)
psi[j]= newpsi
println("First value is ", inner(psi1, psi))

sample = AutoMPO()
sample += 2,"Sx", j;
Operator= MPO(sample,sites);
println("Second value is ", inner(psi1, Operator, psi0))


which outputs for me:

First value is -0.14996338790894725
Second value is -0.14996338790894728


In the original post, in the second approach you are effectively applying the operator 2 Sz twice to the original MPS psi.

As I'm sure you know, it is best to use the first approach since it doesn't scale with the number of sites, whereas the second approach uses an MPO that scales with the number of sites.

-Matt

commented by (13.6k points)
Also, I wanted to point out the apply function for applying gates to an MPS:

using ITensors
N = 6
bond_dim=24
sites = siteinds("S=1/2",N)
psi = randomMPS(sites, bond_dim)
j = 3
apply(2 * op("Sx", sites, j), psi)

This automatically finds the correct site to apply the gate to and does the correct unpriming of the indices.

You can see the docs with some examples here: https://itensor.github.io/ITensors.jl/stable/MPSandMPO.html#Gate-evolution-1 and some other examples here: https://github.com/ITensor/ITensors.jl/tree/master/examples/gate_evolution
commented by (760 points)
Thanks! That clears things up.
commented by (760 points)
This is neat!