# Trying to understand "product" function in projmps.jl and how to generalize to n-site DMRG (Julia)

+1 vote
asked
edited

I am working on generalizing DMRG, for which only the 2-site version is currently supported, to a generalized n-site DMRG. I opened a pull request for it here (https://github.com/ITensor/ITensors.jl/pull/434), and it passes all of the provided tests. But I later realized that it still throws an error if one tries to call DMRG with an MPS vector as an input (i.e. if one is trying to compute excited states, as opposed to just the ground state). After examining the error messages and scouring the repository for a while, I am now fairly certain that the issue is that I have yet to adapt the following function, which appears in ITensors.jl/src/mps/projmps.jl:

function product(P::ProjMPS,
v::ITensor)::ITensor
if nsite(P) != 2
error("Only two-site ProjMPS currently supported")
end

Lpm = dag(prime(P.M[P.lpos+1],"Link"))
!isnothing(lproj(P)) && (Lpm *= lproj(P))

Rpm = dag(prime(P.M[P.rpos-1],"Link"))
!isnothing(rproj(P)) && (Rpm *= rproj(P))

pm = Lpm*Rpm

pv = scalar(pm*v)

Mv = pv*dag(pm)

return noprime(Mv)
end


I understand that this function multiplies a ProjMPS object and an ITensor object, and that there is a similar function "product(P::ProjMPS, v::ITensor)::ITensor" in ITensors.jl/src/mps/projmpo_mps.jl that calls this first one repeatedly. I also understand that this ultimately works in service of adding a penalizing term w|psi><psi| to the Hamiltonian for some weight w and MPS |psi>. However, I am generally finding this method itself very hard to parse. Would it be possible to get a simple explanation of what this method is really doing, as well as an explanation of what would need to be changed to adapt this to n-site DMRG (and how hard you expect this to be)?

## 1 Answer

+1 vote
answered by (50.5k points)

Hi Sujay,
To answer your question I thought it would be easier to show you some diagrams, which I uploaded to this link:

https://itensor.org/miles/ProjMPS.pdf

Can you please let me know if those notes answer your question and give a clear enough idea of what the code there is doing?

The purpose of this ProjMPS overall is to make a Hamiltonian term that is equal to |M><M| for some state M (represented as an MPS) then include this Hamiltonian term in an efficient way within a DMRG calculation that's optimizing an MPS psi.

I think the code there already partially works for n-site DMRG, because you can see that makeL! and makeR! (which are called by position!) query a parameter P.nsite which right now is always set to 2 but could be adjusted. Then the code in product would need to be extended to multiply on the center "n" tensors of M in the lower part of the diagram in the notes, rather than just the two center tensors right now. These two tensors right now are getting included by the lines:

Lpm = dag(prime(P.M[P.lpos+1],"Link"))


and

Rpm = dag(prime(P.M[P.rpos-1],"Link"))


Best,
Miles

commented by (1k points)
Hi Miles, thank you so much! I was ultimately able to figure out how to adapt this function to n-site DMRG some time last week, but I forgot to update this question with that information. But your answer was still very helpful. By the way, since this lets us handle excited states now, I updated the n-site DMRG code for ITensors.jl in this pull request (https://github.com/ITensor/ITensors.jl/pull/434).