Code: Select all

```
def expectation_value_multi_site(self, ops, sites, opstr=None, str_on_first=True):
r"""Expectation value ``<psi|op_1 op_2 ... op_n |psi>/<psi|psi>`` of
tensor products of single site operators.
Given the MPS in canonical form, it calculates the expectation value of
a tensor product of single-site operators.
For example the contraction of three one-site operators on sites `i`
`i+1` `i+2` would look like::
| .--S--B[i]---B[i+1]--B[i+2]--.
| | | | | |
| | op1 op2 op3 |
| | | | | |
| | | | | |
| .--S--B*[i]--B*[i+1]-B*[i+2]-.
Parameters
----------
ops : List of { :class:`~tenpy.linalg.np_conserved.Array` | str }
sList of one-site operators. This method calculates the
expectation value of the n-sites operator given by their tensor
product.
sites : List of int
List of site indices.
``ops[x]`` acts on site ``sites[x]``.
Is sorted before use, i.e. the order is ignored.
opstr : None | (list of) { :class:`~tenpy.linalg.np_conserved.Array` | str }
Ignored by default (``None``).
"""
ops = npc.to_iterable_arrays(ops)
sites = np.sort(sites)
initial_site = sites[0]
m = len(sites)
op = self.get_op(ops, 0)
theta = self.get_theta(initial_site, 1)
C = npc.tensordot(op, theta, axes=['p*', 'p0'])
C = npc.tensordot(theta.conj(), C, axes = [['p0*', 'vL*'],['p', 'vL']])
for i in range(m-1):
B = self.get_B(initial_site+i+1, form ='B')
C = npc.tensordot(C, B, axes=['vR', 'vL'])
op = self.get_op(ops, i+1)
C = npc.tensordot(op, C, axes=['p*','p'])
if i == m-2:
C_exp = npc.inner(B.conj(), C, axes=[['vL*','p*','vR*'],['vR*','p','vR']])
break
else:
C = npc.tensordot(B.conj(), C, axes=[['vL*','p*'],['vR*','p']])
return np.real_if_close(C_exp)
```