Hi,

I want to calculate the expectation value \(\langle \psi| S_i^z S_{i+1}^z |\phi \rangle\).

Because the two MPS are different, I create a tenpy.networks.mps.MPSEnvironment. What is the best way to compute the above correlation function? For tenpy.networks.mps.MPS there is tenpy.networks.mps.MPS.term_correlation_function_left() which I can use to define a left and right operator, but it seems that MPSEnvironment does not have this functionality. In that case, should I loop over \(i\), apply the local operators and then calculate the overlap via tenpy.networks.mps.MPSEnvironment.full_contraction()?

Thank you

## term_correlation_function_left for MPSEnvironment

### Re: term_correlation_function_left for MPSEnvironment

Really, the proper functions is to adjust the *correlation_function methods of the MPS to the MPSEnvironment, see the new Issue #173.

If you really just need the nearest-neighbor correlations, the expectation_value actually supports this:

I assume you're working with finite MPS here? For Finite MPS, applying local operator is fine, even though it's definitely not efficient...

For infinite MPS, using the strategy with `apply_local_op` and a subsequent `overlap` is "wrong" because it would apply the operator in each MPS unit cell, i.e. calculate something like \( \langle \psi | \left(\prod_{n \in \mathbb{Z}} S^z_{i+n*L}\right) S^z_{i+1}|\phi \rangle \) (or similar, depending on how you set it up exactly).

Edit: correctly normalize MPSEnvironment expectation values

If you really just need the nearest-neighbor correlations, the expectation_value actually supports this:

Code: Select all

```
import tenpy
s = tenpy.networks.site.SpinHalfSite()
psi = tenpy.networks.mps.MPS.from_singlets(s, 10, [(i,i+1) for i in range(0, 10, 2)])
print(psi.correlation_function('Sp', 'Sm'))
SpSm = tenpy.networks.site.kron(s.Sp, s.Sm, group=False)
print(psi.expectation_value(SpSm))
assert np.allclose(psi.expectation_value(SpSm), np.diag(psi.correlation_function('Sp', 'Sm'), k=1))
print(tenpy.networks.mps.MPSEnvironment(psi, psi).expectation_value(SpSm)/psi.norm/psi.norm)
```

For infinite MPS, using the strategy with `apply_local_op` and a subsequent `overlap` is "wrong" because it would apply the operator in each MPS unit cell, i.e. calculate something like \( \langle \psi | \left(\prod_{n \in \mathbb{Z}} S^z_{i+n*L}\right) S^z_{i+1}|\phi \rangle \) (or similar, depending on how you set it up exactly).

Edit: correctly normalize MPSEnvironment expectation values

### Re: term_correlation_function_left for MPSEnvironment

Dear Johannes,

yes, I am using finite MPS.

Thank you very much for opening up the issue on github.

In my case it's actually not i+1, but actually i+2, because I am working on a ladder.

I am actually not sure whether I understand why the example that you kindly provided works. So is it because you set group=False in 'kron' that 'Sm' is evaluated on the neighboring site?

Thanks!

Edit: Oh and shouldn't one also divide by some norm in the case of using an MPSEnvironment for an expectation value?

yes, I am using finite MPS.

Thank you very much for opening up the issue on github.

In my case it's actually not i+1, but actually i+2, because I am working on a ladder.

I am actually not sure whether I understand why the example that you kindly provided works. So is it because you set group=False in 'kron' that 'Sm' is evaluated on the neighboring site?

Thanks!

Edit: Oh and shouldn't one also divide by some norm in the case of using an MPSEnvironment for an expectation value?

### Re: term_correlation_function_left for MPSEnvironment

You can also do
The tenpy.networks.site.kron function with n input onsite operators generates an operator acting on n consecutive sites at once, with n input and n output legs, e.g for n=3,

The
While this is a good trick for (next) nearest neighbors, this becomes expenonentially expensive with the number of sites n involved, so don't concatenate too many of them...

Oh, and yes, you should in general divide by the norm, even though it's guaranteed to be 1 in this example. Edit above.

Code: Select all

```
SpIdSm = tenpy.networks.site.kron(s.Sp, s.Id, S.Sm, group=False)
```

`p0*, p1*, p2*, p0, p1, p2`

.The

`expectation_value`

functions can handle such generic n-site operators. You can even add them before if you want, e.g.
Code: Select all

```
SmIdSp = tenpy.networks.site.kron(s.Sm, s.Id, S.Sp, group=False)
sigma_x_NNN = SmIdSp + SpIdSm
psi.expectation_value(sigma_x_NNN)
```

Oh, and yes, you should in general divide by the norm, even though it's guaranteed to be 1 in this example. Edit above.