Tensor product together MPS

Hello,

I would like to prepare a n-qubit state

|0\rangle \otimes |r\rangle

where |r\rangle is an n-1 qubit randomMPS (with some maxdim=chi), which is tensored with the zero state on the first qubit. I was unable to find a reference in the documentation for how to tensor/kronecker product together 2 MPS.

Please can you advise the best way to do this, thanks in advance.

A good way to do this in ITensor would be to make a new MPS with n qubits and then assign the MPS tensors of \ket{r} to the sites j=2,3,4,...,n of this MPS and then set the first MPS tensor to the \ket{0} state. I’d do it in the following way:

  1. make the set of qubit indices s = siteinds("Qubit",n)
  2. make \ket{r} by calling r = randomMPS(s[2:n]; linkdims=chi)
  3. make an MPS psi = MPS(s,"0") of qubits all in the \ket{0} state
  4. finally, write a for loop that just assigns the tensors of the MPS \ket{r} to the appropriate tensors of psi

Great, thanks Miles

Hi @miles, I have a follow-up question.

I would like to use this method to make multiple of these random states, and then take inner products between combinations of them. However, I am getting an error saying that the indices of the MPS do not match. I have followed your advice in another question and tried to manually make the indices match, however this has not solved the issue.
Please could you suggest a way around this, thanks.

(I would also like these states to be from QN conserving MPS from different symmetry sectors, however I get the same error when using dense MPS)

See below for an example:

N = 10

s = siteinds("Qubit", N; conserve_qns=true)

state = [n<=1 ? "Dn" : "Up" for n=1:N-1]

r = randomMPS(s[2:N], state; linkdims=12)
psi_temp = MPS(s,"0")
for i in 2:N
   psi_temp[i]=r[i-1] 
end

psi1 = psi_temp

state = [n<=2 ? "Dn" : "Up" for n=1:N-1]

r = randomMPS(s[2:N], state; linkdims=2)
psi_temp = MPS(s,"0")
for i in 2:N
   psi_temp[i]=r[i-1] 
end

psi2 = psi_temp

s1 = siteinds(psi1)
s2 = siteinds(psi2)

for j=1:length(psi1)
  replaceind!(psi1[j],s1[j],s2[j])
end

os = OpSum()
os += "Sz",1

@show inner(psi1', MPO(os, s), psi2)

Hi, so regarding the error about the indices not matching, have you tried printing out the two MPS after you run the code that makes them or alters their indices to see if the code you wrote did what you want? I.e. do the indices actually not match? If they don’t, there may be a bug in the code you wrote, and would suggest printing out the tensors as they are being processed to ensure the logic of your code is correct.

Yes when I check the indices they do match for the sites but are different for the links (I was under the impression the link indices do not need to match?), yet when I do ‘inner’ between them, which should be exactly zero, I still get an error about site indices not matching.

For instance:

N = 3

s = siteinds("Qubit", N; conserve_qns=true)

state = [n<=2 ? "Dn" : "Up" for n=1:N-1]

r = randomMPS(s[2:N], state; linkdims=2)
psi_temp = MPS(s,"0")

for i in 2:N
   psi_temp[i]=r[i-1] 
end

psi1 = psi_temp

state = [n<=1 ? "Dn" : "Up" for n=1:N-1]

r = randomMPS(s[2:N], state; linkdims=1)
psi_temp = MPS(s,"0")
for i in 2:N
   psi_temp[i]=r[i-1] 
end

psi2 = psi_temp

s1 = siteinds(psi1)
s2 = siteinds(psi2)

for j=1:length(psi1)
  replaceind!(psi1[j],s1[j],s2[j])
end

@show siteinds(psi1)
@show siteinds(psi2)
println()
@show linkinds(psi1)
@show linkinds(psi2)
println()
@show inner(psi1', psi2)

Gives the error:

siteinds(psi1) = Index{Vector{Pair{QN, Int64}}}[(dim=2|id=763|"Qubit,Site,n=1") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1, (dim=2|id=146|"Qubit,Site,n=2") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1, (dim=2|id=350|"Qubit,Site,n=3") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1]
siteinds(psi2) = Index{Vector{Pair{QN, Int64}}}[(dim=2|id=763|"Qubit,Site,n=1") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1, (dim=2|id=146|"Qubit,Site,n=2") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1, (dim=2|id=350|"Qubit,Site,n=3") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1]

linkinds(psi1) = Union{Nothing, Index{Vector{Pair{QN, Int64}}}}[nothing, (dim=2|id=954|"Link,l=1") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1]
linkinds(psi2) = Union{Nothing, Index{Vector{Pair{QN, Int64}}}}[nothing, (dim=1|id=527|"Link,l=1") <In>
 1: QN("Parity",1,2) => 1]

Calling `dot(ϕ::MPS/MPO, ψ::MPS/MPO)` with multiple site indices per MPS/MPO tensor but the site indices don't match. Even with `make_inds_match = true`, the case of multiple site indices per MPS/MPO is not handled automatically. The sites with unmatched site indices are:

    inds(ϕ[1]) = ((dim=2|id=763|"Qubit,Site,n=1")' <In>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1, (dim=1|id=652|"Link,l=1")' <Out>
 1: QN("Parity",0,2) => 1)

    inds(ψ[1]) = ((dim=2|id=763|"Qubit,Site,n=1") <Out>
 1: QN("Parity",0,2) => 1
 2: QN("Parity",1,2) => 1, (dim=1|id=343|"Link,l=1") <In>
 1: QN("Parity",0,2) => 1)

Make sure the site indices of your MPO/MPS match. You may need to prime one of the MPS, such as `dot(ϕ', ψ)`.

Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:35
  [2] deprecate_make_inds_match!(::typeof(ITensors._log_or_not_dot), M1dag::MPS, M2::MPS, loginner::Bool; make_inds_match::Bool)
    @ ITensors ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1040
  [3] _log_or_not_dot(M1::MPS, M2::MPS, loginner::Bool; make_inds_match::Bool)
    @ ITensors ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1068
  [4] _log_or_not_dot
    @ ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1059 [inlined]
  [5] #dot#664
    @ ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1115 [inlined]
  [6] dot
    @ ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1114 [inlined]
  [7] #inner#666
    @ ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1157 [inlined]
  [8] inner(M1::MPS, M2::MPS)
    @ ITensors ~/.julia/packages/ITensors/5CAqA/src/mps/abstractmps.jl:1157
  [9] top-level scope
    @ show.jl:1047
 [10] eval
    @ ./boot.jl:368 [inlined]
 [11] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
    @ Base ./loading.jl:1428