Multi-Site Expectation Value
Posted: 15 Oct 2018, 16:30
I am developing the method that, given a MPS in canonical form, calculates the expectation value of multi-site operators that are tensor product of one-site operators. This is what I implemented so far: it works but does not handle operator strings (like the Jordan-Wigner string that is needed in the presence of fermionic operators) yet.
I am also looking for suggestions on what to do with the "sites" argument. Right now it is not very useful as it only indicates the consecutive sites where the operators are, but it is still necessary to specify all the operators between the initial and final site, and put identities if we don't want anything to happen on that site. One option would be to have the operators [op_1.. op_n] on the sites [site_1... site_n], with the sites being ordered but not consecutive, and have an identity automatically inserted on the unspecified sites. What do you think?
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)