# Contracting MPS with different lengths

Dear community,

The problem I have in hand is: I have three MPS, |\psi1>, |\psi2>, |\psi3>, with length 2*N, N, N, respectively. I want to contract the first N index of |\psi1> with |\psi2>, and the second N index with |\psi3>.

I had a solution for the small system, which requires me to change the data type from MPS to ITensor, since I cannot multiply MPS using innerC with different size. Here is my code:

// Change the data type, so that we can perform contraction
ITensor mpsToTensor(MPS & psi0){

ITensor psi = psi0.A(1);
int N = length(psi0);

for (int j=2; j <=N; ++j){
psi *= psi0.A(j);
}

return psi;

}


This works for small system. But when I tried N=20, it throws error terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc.
Do you have a smarter way to perform this task that won't cause this error? I am thinking about making a big MPS by combining |\psi2> and |\psi3>, but haven't found a way to do this.

Many thanks,
Yuhan

selected by

Converting an MPS to an ITensor will require an exponential amount of memory in the number of sites, so it is best to avoid that.

I would recommend combining the two MPS @@\psi2@@ and @@\psi3@@ into a single MPS (say @@\phi@@) and then taking the inner product of @@\phi@@ with @@\psi1@@.

commented by (150 points)
Thanks Matt! Could you also explain a little bit how to combine two MPS into a single MPS?
commented by (14.1k points)
You should be able to initialize a new MPS @@\phi@@ of length @@2N@@ and fill the elements in a loop with the tensors of the MPSs @@\psi2@@ and @@\psi3@@. For example something like this:

auto phi = MPS(2N);
for(int j=1; j <=2N; ++j)
{
if(j <= N) phi.set(j, psi2(j));
else phi.set(j, psi3(j - N));
}
commented by (150 points)
Thank you very much! It is really helpful. I am also a bit curious why this conversion takes exponential amount of memory in sites. From my naive understanding, in the case where I have bond dimension being 64 and spin 1/2 on the site, each MPS stores 64*64*2 complex numbers. In the case where it causes error, the sites N = 20.  I guess 64*64*2*20 shouldn't be a large number for a machine? I assume the required memory scales linearly with N and don't quite understand the exponential scaling.
commented by (14.1k points)
When you contract the MPS tensors with each other, you sum over the internal dimensions (the bond dimensions) and the site dimension remain. So for N = 20 and spin-1/2 particles, the full many-body wavefunction has a dimension 2^20.