Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Returns:
List: measurements :math:`\\langle` `ops[n]`:math:`\\rangle` for n in `sites`
Raises:
ValueError if `len(ops) != len(sites)`
"""
if not len(ops) == len(sites):
raise ValueError('measure_1site_ops: len(ops) has to be len(sites)!')
right_envs = self.right_envs(sites)
left_envs = self.left_envs(sites)
res = []
for n, site in enumerate(sites):
O = Node(ops[n], backend=self.backend)
R = right_envs[site]
L = left_envs[site]
A = Node(self.nodes[site], backend=self.backend)
conj_A = conj(A)
O[1] ^ A[1]
O[0] ^ conj_A[1]
R[0] ^ A[2]
R[1] ^ conj_A[2]
L[0] ^ A[0]
L[1] ^ conj_A[0]
result = L @ A @ O @ conj_A @ R
res.append(result.tensor)
return res
# compute all neccessary right reduced
# density matrices in one go. This is
# more efficient than calling right_envs
# for each site individually
if right_sites:
right_sites_mod = list({n % N for n in right_sites})
rs = self.right_envs([site1] + right_sites_mod)
c = []
if left_sites:
left_sites_mod = list({n % N for n in left_sites})
ls = self.left_envs(left_sites_mod + [site1])
A = Node(self.nodes[site1], backend=self.backend)
O1 = Node(op1, backend=self.backend)
conj_A = conj(A)
R = rs[site1]
R[0] ^ A[2]
R[1] ^ conj_A[2]
A[1] ^ O1[1]
conj_A[1] ^ O1[0]
R = ((R @ A) @ O1) @ conj_A
n1 = np.min(left_sites)
# -- A--------
# | |
# compute op1(site1) |
# | |
# -- A*-------
# and evolve it to the left by contracting tensors at site2 < site1
# if site2 is in `sites2`, calculate the observable
#
# ---A--........-- A--------
# (including center_position) are all identities
right_sites = sites[sites >= self.center_position]
right_envs = {}
for site in right_sites:
right_envs[site] = Node(
self.backend.eye(N=self.nodes[site].shape[2], dtype=self.dtype),
backend=self.backend)
# right reduced density matrices at sites < center_position
# have to be calculated from a network contraction
if n1 < self.center_position:
nodes = {}
conj_nodes = {}
for site in reversed(range(n1 + 1, self.center_position + 1)):
nodes[site] = Node(self.nodes[site], backend=self.backend)
conj_nodes[site] = conj(self.nodes[site])
nodes[self.center_position][2] ^ conj_nodes[self.center_position][2]
nodes[self.center_position][1] ^ conj_nodes[self.center_position][1]
for site in reversed(range(n1 + 1, self.center_position)):
nodes[site][2] ^ nodes[site + 1][0]
conj_nodes[site][2] ^ conj_nodes[site + 1][0]
nodes[site][1] ^ conj_nodes[site][1]
edges = {site: node[0] for site, node in nodes.items()}
conj_edges = {site: node[0] for site, node in conj_nodes.items()}
right_env = contract_between(nodes[self.center_position],
conj_nodes[self.center_position])
if self.center_position - 1 in sites:
right_env.reorder_edges(
Args:
which: * if `'l'` or `'left'`: check left orthogonality
* if `'r`' or `'right'`: check right orthogonality
site: The site of the tensor.
Returns:
scalar `Tensor`: The L2 norm of the deviation from identity.
Raises:
ValueError: If which is different from 'l','left', 'r' or 'right'.
"""
if which not in ('l', 'left', 'r', 'right'):
raise ValueError(
"Wrong value `which`={}. "
"`which` as to be 'l','left', 'r' or 'right.".format(which))
n1 = self.get_node(site) #we need to absorb the connector_matrix
n2 = conj(n1)
if which in ('l', 'left'):
n1[0] ^ n2[0]
n1[1] ^ n2[1]
elif which in ('r', 'right'):
n1[2] ^ n2[2]
n1[1] ^ n2[1]
result = n1 @ n2
return self.backend.norm(
abs(result.tensor - self.backend.eye(
N=result.shape[0], M=result.shape[1], dtype=self.dtype)))
Compute the action of the MPS transfer-operator at site `site`.
Args:
site: a site of the MPS
direction:
* if `1, 'l'` or `'left'`: compute the left-action
of the MPS transfer-operator at `site` on the input `matrix`.
* if `-1, 'r'` or `'right'`: compute the right-action
of the MPS transfer-operator at `site` on the input `matrix`
matrix: A rank-2 tensor or matrix.
Returns:
`Node`: The result of applying the MPS transfer-operator to `matrix`
"""
mat = Node(matrix, backend=self.backend)
node = self.get_node(site)
conj_node = conj(node)
node[1] ^ conj_node[1]
if direction in (1, 'l', 'left'):
mat[0] ^ node[0]
mat[1] ^ conj_node[0]
edge_order = [node[2], conj_node[2]]
elif direction in (-1, 'r', 'right'):
mat[0] ^ node[2]
mat[1] ^ conj_node[2]
edge_order = [node[0], conj_node[0]]
result = mat @ node @ conj_node
return result.reorder_edges(edge_order)
# (including center_position) are all identities
left_sites = sites[sites <= self.center_position]
left_envs = {}
for site in left_sites:
left_envs[site] = Node(
self.backend.eye(N=self.nodes[site].shape[0], dtype=self.dtype),
backend=self.backend)
# left reduced density matrices at sites > center_position
# have to be calculated from a network contraction
if n2 > self.center_position:
nodes = {}
conj_nodes = {}
for site in range(self.center_position, n2):
nodes[site] = Node(self.nodes[site], backend=self.backend)
conj_nodes[site] = conj(self.nodes[site])
nodes[self.center_position][0] ^ conj_nodes[self.center_position][0]
nodes[self.center_position][1] ^ conj_nodes[self.center_position][1]
for site in range(self.center_position + 1, n2):
nodes[site][0] ^ nodes[site - 1][2]
conj_nodes[site][0] ^ conj_nodes[site - 1][2]
nodes[site][1] ^ conj_nodes[site][1]
edges = {site: node[2] for site, node in nodes.items()}
conj_edges = {site: node[2] for site, node in conj_nodes.items()}
left_env = contract_between(nodes[self.center_position],
conj_nodes[self.center_position])
left_env.reorder_edges(
[edges[self.center_position], conj_edges[self.center_position]])