Here is one way I can think of. Move the sites until they are next to each other and then contract left to right:
orig_sites = collect(1:N)
new_sites = collect(1:N)
# set up the new site ordering
for i=1:2:N÷2
new_sites[i+1],new_sites[i+N÷2] = new_sites[i+N÷2],new_sites[i+1]
end
psi2 = movesites(psi,orig_sites,new_sites)
# contract with the NN pairs
O = 1
for i=1:2:N-1
O*= psi[i]*psi[i+1]
O*= dag(delta(s[new_sites[i]],s[new_sites[i+1]]))
end
total = O[]
@show total
An alternative method would be to create MPS which represent “Bell pair” states connecting pairs of sites, then contract them with your MPS to carry out the contractions one by one that you have indicated. If you go this route, I would recommend writing the MPS contractions by hand rather than using one of our pre-written algorithms such as inner.
The idea is that if your ‘physical indices’ have dimension d, then each of these Bell pair MPS would have maximum bond dimension d also, so the contraction would be efficient no matter how far apart the pair of sites you’re contracting are. The only possible catch is that after the contraction, it can increase the bond dimension of the sites in between. But the pattern you are doing where your contractions remove one site from the edge of the system each time should mitigate this issue.
Thank you very much for the earnest replies from ryanlevy and miles!
Inspired by the ideas provided by the two of you, I thought that I could use a two-site manual contraction and gradually contract towards the nearest neighbors, and then I could get the result I expected.
function cross_overlap(psi, N, sites)
res = 1.0
for j in 1:div(N, 2)
res *= psi[j] * psi[j+div(N, 2)] * delta(sites[j], sites[j+div(N, 2)])
end
return Array(res)[1]
end
res = cross_overlap(psi, N, sites)
I think this is a relatively good implementation method. Once again, thank you very much for the replies from ryanlevy and miles. I think my question has been solved!