# partial MPS-MPO contraction

**URL:** <https://itensor.discourse.group/t/partial-mps-mpo-contraction/69>\
**Category:** ITensor Julia Questions\
**Tags:** mps, mpo\
**Created:** [April 22, 2022, 9:24am UTC](https://itensor.discourse.group/t/partial-mps-mpo-contraction/69 "2022-04-22T09:24:44Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![chreggi](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/chreggi/32/25_2.png) [@chreggi](https://itensor.discourse.group/u/chreggi)\
**Post date:** [April 22, 2022, 9:24am UTC](https://itensor.discourse.group/t/partial-mps-mpo-contraction/69/1 "2022-04-22T09:24:44Z")

</div>

Is it possible to do a “partial overlap” of an MPS with an MPO?

I try to do the following: for an MPO on sites 1:N and an MPS on sites 1:n (with n\<N) I’d like to get the MPO on sites n+1:N corresponding to \langle MPS | MPO| MPS\rangle. If the MPO is a density matrix it would correspond to a local projective measurement of |MPS\rangle \langle MPS| (I think 😅).

Thanks a lot for any answer!

---

<div class="post-metadata">

**Author:** ![miles](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/miles/32/6_2.png) [@miles](https://itensor.discourse.group/u/miles)\
**Post date:** [April 22, 2022, 1:04pm UTC](https://itensor.discourse.group/t/partial-mps-mpo-contraction/69/2 "2022-04-22T13:04:08Z")

</div>

Interesting question: yes, that’s definitely something you can do with ITensor. Here are some diagrams showing how to do it and some sample code that implements this approach:

 ![IMG_4460E4728EC0-1](https://global.discourse-cdn.com/free1/uploads/itensor/original/1X/dab3bf85e8a1cc2d69cfe184668efdac1866299a.jpeg)

```auto
using ITensors

let
  N = 8
  Nh = N÷2
  s = siteinds("S=1/2",N)

  psi = randomMPS(s[1:Nh])
  M = randomMPO(s)

  # Project the left half of M with psi
  L = ITensor(1.)
  for n=1:Nh
    L *= psi[n]
    L *= M[n]
    L *= prime(dag(psi[n]))
  end

  # Make a new MPO with the remaining tensors of M
  MP = MPO(M[Nh+1:N])

  # Multiply the tensor representing the projection
  # with psi into MP
  MP[1] *= L

  @show MP

  return
end

```

Of course you’ll want to replace the random MPS and MPO with your MPS and MPO. To write `N÷2` you can type `N\div` then hit Tab then `2`. Or you can use `div(N,2)`.

The numbers in the figure, showing how the tensor L is made, refer to the order in which the MPS and MPO tensors can be contracted in an efficient way.

---

<div class="post-metadata">

**Author:** ![chreggi](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/chreggi/32/25_2.png) [@chreggi](https://itensor.discourse.group/u/chreggi)\
**Post date:** [April 25, 2022, 4:09pm UTC](https://itensor.discourse.group/t/partial-mps-mpo-contraction/69/3 "2022-04-25T16:09:00Z")

</div>

Thanks a lot, that’s exactly what I’ve been looking for!  
A followup question: for complex valued `psi` I need to do `L *= prime(dag(psi[n]))`?

---

<div class="post-metadata">

**Author:** ![miles](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/miles/32/6_2.png) [@miles](https://itensor.discourse.group/u/miles)\
**Post date:** [April 26, 2022, 1:44pm UTC](https://itensor.discourse.group/t/partial-mps-mpo-contraction/69/4 "2022-04-26T13:44:31Z")

</div>

Great! It’s a good point about including a call to `dag` for the primed MPS tensors. That is definitely necessary if the MPS is complex-valued or if the tensors conserve quantum numbers. So I just edited the code above to include a call to `dag` there. It never hurts to be correct about that so that the same code can handle all cases!
