Wrong link dimension from random_mps ?

Hi all,
I’m not sure whether this is the expected behavior for the random_mps function. or it is a bug. The point is that when passing to random_mps the parameter linkdims::Int, I’d expect the link dimension to grow exponentially from both ends, until it reaches the value passed for linkdims, but this is only true on the right side, not on the left side. To be more clear, if I have 10 Qubits and I pass linkdims=9 I’d expect to obtain

linkdims(psi) = [2, 4, 8, 9, 9, 9, 8, 4, 2]

but instead I obtain

linkdims(psi) = [9, 9, 9, 9, 9, 9, 8, 4, 2]

This is not really an issue, but it is using more memory than required, and therefore also the following operations will take more time than required. This is the code I used to test:

using LinearAlgebra
using ITensors, ITensorMPS

sites = siteinds("S=1/2",10)
psi = random_mps(sites; linkdims=9)
is_ortho = isortho(psi)
@assert isortho(psi)
@assert orthocenter(psi) == 1

@info "Link dims: $(linkdims(psi))" 

@info "Check that the ITensors are right orthogonal"
for i in reverse(2:length(psi))
	T_i = psi[i]
	T = prime(T_i;tags="l=$(i-1)") * T_i
	@show i Matrix(T, inds(T)...) ≈ Matrix(1.0I, size(T)...)
end

I’m not sure of the underlying algorithm for random_mps offhand (and I know its a bit limited), but to get what you want in the meantime:

  • Call truncate (may need to replace 0 => 1e-16 etc)
     psi = random_mps(sites; linkdims=9)
     @show linkdims(truncate(psi; cutoff=0)
    
    linkdims(truncate(psi; cutoff = 0)) = [2, 4, 8, 9, 9, 9, 8, 4, 2]
    
  • explicitly pass in the linkdims you want
     psi = random_mps(sites; linkdims=[2,4,8,9,9,9,8,4,2]);
    

Thank you for the answer.
I know that there are many work around, the best I found so far is to move the orthocenter from 1 to L/2 where L is the length of the chain (it would work like truncate but it is probably a bit more efficient).

Still I think, if it is possible, to directly construct it with the right dimensions.
I gave a quick look at the implementation, and it starts to build the mps from the right, choosing as left bond size the minimum between linkdims[j-1] and linkdims[j]*dim(sites[j]), in this way the resulting mps will always be left gauged. The point is that one should start to divide, instead of multiplying, after passed the middle of the chain, but this can easily lead to rounding problems. Probably the safest way would be to construct the mps in 2 steps, first from the right to the center, and then from the left to the center, in this way the resulting mps would have L/2 as orthocenter, then the user can move the orthocenter to the first site if he needs to.

Yes, we recently discussed reworking these codes, in part also because the implementation that makes QN-symmetric MPS works very differently right now from the one that does not.

It’s a good suggestion to also think about making it go from both ends to the middle. We are also wanting to think about generalizations to arbitrary tree tensor networks and there it may be more natural to think about starting from the ends (leaves) to some root vertex anyway.