def act_umpo_on_mps(mps, mpo, if_conjugate=False): mps1 = empty_list(mps.__len__()) if if_conjugate: # act on product state (evolve) mps1[0] = copy.deepcopy(mpo[0]) for n in range(1, mps.__len__() - 1): mps1[n] = T_module.cont([mpo[n], mps[n - 1]], [[-1, -3, 1, -4], [-2, 1, -5]]) s = mps1[n].shape mps1[n] = mps1[n].reshape(s[0] * s[1], s[2], s[3] * s[4]) mps1[-1] = T_module.cont([mpo[-1], mps[-2], mps[-1]], [[-1, -3, 2, 3], [-2, 2, 1], [1, 3, -4]]) s = mps1[-1].shape mps1[-1] = mps1[-1].reshape(s[0] * s[1], s[2], s[3]) else: # act on mps (disentangle) mps1[0] = T_module.cont( [mps[0].squeeze(), mps[1], mpo[0].squeeze(), mpo[1]], [[3, 1], [1, 4, -3], [3, 2], [2, 4, -1, -2]]) mps1[0] = mps1[0].reshape(1, mpo[1].shape[2], mpo[1].shape[3] * mps[1].shape[2]) for n in range(2, mps.__len__() - 1): mps1[n - 1] = T_module.cont([mps[n], mpo[n]], [[-2, 1, -5], [-1, 1, -3, -4]]) s = mps1[n - 1].shape mps1[n - 1] = mps1[n - 1].reshape(s[0] * s[1], s[2], s[3] * s[4]) mps1[-2] = T_module.cont([mps[-1].squeeze(), mpo[-1]], [[-2, 1], [-1, 1, -3, -4]]) s = mps1[-2].shape mps1[-2] = mps1[-2].reshape(s[0] * s[1] * s[2], s[3]) mps1[-2], lm, mps1[-1] = np.linalg.svd(mps1[-2], full_matrices=False, compute_uv=True) mps1[-2] = mps1[-2].reshape(s[0] * s[1], s[2], lm.size) mps1[-1] = np.diag(lm).dot(mps1[-1]).reshape(lm.size, s[3], 1) return mps1
def update_effective_ops_kagome(self): # Only use mps[0] assuming left and right parts are symmetrical op_ind = [1, 3, 4, 5] # x, z, u, d for p in [0, 1]: # iterate on two physical bonds for n in range(op_ind.__len__()): tmp = self.update_by_given_effective_ops( self.tensors[1], [self.operators[op_ind[n]]], [p]) self.effective_ops[n + p * 4] = tm.cont( [self.tensors[1].conj(), tmp], [[1, 2, 3, 4, -1], [1, 2, 3, 4, -2]])
def update_by_given_effective_ops(psi, ops, bonds): indexes = bf.empty_list(1 + bonds.__len__()) indexes[0] = list(range(psi.ndim)) x = 1 for n in range(psi.ndim): if n in bonds: indexes[0][n] = x indexes[bonds.index(n) + 1] = [-n - 1, x] x += 1 else: indexes[0][n] = -n - 1 return tm.cont([psi] + ops, indexes)
def permutation_transformation(data, if_inverse=False): ind_con = [list(range(1, data.ndim + 1))] u = list() for n in range(0, data.ndim): order = list(range(0, data.shape[n], 2)) + list( range(1, data.shape[n], 2)) u.append(tm.bond_permutation_transformation(order)) if if_inverse: ind_con.append([n + 1, -n - 1]) else: ind_con.append([-n - 1, n + 1]) return tm.cont([data] + u, ind_con)
def rho_two_body_nlm_simple(self, n_lm): nt1 = self.lm_ten_bond[n_lm, 0, 0] vb1 = self.lm_ten_bond[n_lm, 0, 1] nt2 = self.lm_ten_bond[n_lm, 1, 0] vb2 = self.lm_ten_bond[n_lm, 1, 1] if self._is_debug: if n_lm != self.pos_lm[nt2][vb2]: bf.print_error( 'In rho_two_body_simple, the two virtual bonds must' 'correspond to the same lambda') bonds = list(range(0, self.nVirtual)) bonds.remove(vb1) tmp1 = self.absorb_lm(nt1, False, bonds) tmp2 = self.absorb_lm(nt2, False, 'all') if self.stateType is 'pure': bonds = list(range(1, self.nVirtual + 1)) bonds.remove(vb1 + 1) tmp1 = np.tensordot(tmp1.conj(), tmp1, (bonds, bonds)) bonds = list(range(1, self.nVirtual + 1)) bonds.remove(vb2 + 1) tmp2 = np.tensordot(tmp2.conj(), tmp2, (bonds, bonds)) elif self.stateType is 'mixed': s = tmp1.shape bonds = list(range(1, self.nVirtual + 2)) bonds.remove(vb1 + 2) tmp1 = tmp1.reshape((self.d0, self.d0) + s[1:]) tmp1 = np.tensordot(tmp1.conj(), tmp1, (bonds, bonds)) s = tmp2.shape bonds = list(range(1, self.nVirtual + 2)) bonds.remove(vb2 + 2) tmp2 = tmp2.reshape((self.d0, self.d0) + s[1:]) tmp2 = np.tensordot(tmp2.conj(), tmp2, (bonds, bonds)) rho = tm.cont([tmp1, tmp2], [[-1, 1, -3, 2], [-2, 1, -4, 2]]) rho = rho.reshape(self.d0 * self.d0, self.d0 * self.d0) rho = (rho + rho.conj().T) / 2 rho /= np.trace(rho) return rho
def update_env_tree_dmrg(self, ne, decomp='qr'): # ne: which environment (0, 1, 2, 3) self.calculate_orthogonal_tensor(ne, decomp) s = self.tensors[ne + 1].shape d0 = np.round(np.sqrt(s[0])) tensor = self.tensors[ne + 1].reshape([d0, d0] + s[1:]) tensor = self.evolve_central_tensor(tensor, self.model_related['h2_gate'].T, [0, 1]) # [0, 1, 2, 3, 4, 5] tensor1 = tensor.conj() if ne == 3: tensor1 = self.evolve_central_tensor( tensor1, self.model_related['hbath'][3].T, [1, 5]) # [1, 5, 0, 2, 3, 4] tensor1 = self.evolve_central_tensor( tensor1, self.model_related['hbath'][2].T, [1, 5]) # [1, 4, 5, 0, 2, 3] tensor1 = tensor1.transpose(3, 0, 4, 5, 1, 2) tensor = self.evolve_central_tensor(tensor, self.model_related['hbath'][0], [0, 2], if_permute_back=True) self.env[ne] = tm.cont( [tensor, tensor1, self.model_related['tensor_gate'][0]], [[6, 4, 1, -3, 2, 3], [5, 4, 1, -1, 2, 3], [5, -2, 6]]) elif ne == 2: tensor1 = self.evolve_central_tensor( tensor1, self.model_related['hbath'][3].T, [1, 5]) # [1, 5, 0, 2, 3, 4] tensor1 = self.evolve_central_tensor( tensor1, self.model_related['hbath'][2].T, [1, 5]) # [1, 4, 5, 0, 2, 3] tensor1 = self.evolve_central_tensor( tensor1, self.model_related['hbath'][1].T, [3, 5]) # [0, 3, 1, 4, 5, 2] tensor1 = tensor1.transpose(0, 2, 5, 1, 3, 4) self.env[ne] = tm.cont( [tensor, tensor1, self.model_related['tensor_gate'][0]], [[6, 4, -3, 3, 1, 2], [5, 4, -1, 3, 1, 2], [5, -2, 6]]) elif ne == 1: tensor = self.evolve_central_tensor(tensor, self.model_related['hbath'][0], [0, 2]) # [0, 2, 1, 3, 4, 5] tensor = self.evolve_central_tensor(tensor, self.model_related['hbath'][1], [0, 3]) # [0, 3, 2, 1, 4, 5] tensor = self.evolve_central_tensor(tensor, self.model_related['hbath'][2], [0, 4]) # [0, 4, 3, 2, 1, 5] tensor = tensor.transpose(0, 4, 3, 2, 1, 5) self.env[ne] = tm.cont( [tensor, tensor1, self.model_related['tensor_gate'][1]], [[4, 6, 1, 2, 3, -3], [4, 5, 1, 2, 3, -1], [5, -2, 6]]) elif ne == 0: tensor = self.evolve_central_tensor(tensor, self.model_related['hbath'][0], [0, 2]) # [0, 2, 1, 3, 4, 5] tensor = self.evolve_central_tensor(tensor, self.model_related['hbath'][1], [0, 3]) # [0, 3, 2, 1, 4, 5] tensor = tensor.transpose(0, 3, 2, 1, 4, 5) tensor1 = self.evolve_central_tensor( tensor1, self.model_related['hbath'][3].T, [1, 5], if_permute_back=True) self.env[ne] = tm.cont( [tensor, tensor1, self.model_related['tensor_gate'][1]], [[4, 6, 1, 2, -3, 3], [4, 5, 1, 2, -1, 3], [5, -2, 6]]) self.env[ne] = (self.env[ne] + self.env[ne].transpose(2, 1, 0)) / 2 self.env[ne] /= np.linalg.norm(self.env[ne].reshape(-1, ))
def update_bath_onsite_kagome(self, j1, j2, hx, hz): # baths on the two branches op1 = tm.cont( [self.tensors[1].conj(), self.tensors[1], self.bath_op_onsite], [[4, 5, 1, 3, -1], [4, 5, 2, 3, -2], [1, 2]]) op2 = tm.cont( [self.tensors[1].conj(), self.tensors[1], self.bath_op_onsite], [[4, 5, 2, 1, -1], [4, 5, 2, 3, -2], [1, 3]]) self.bath_op_onsite += op1 + op2 opp = [self.operators[5], self.operators[4], self.operators[3]] # sd, su, sz on the physical site opb = [ self.effective_ops[2], self.effective_ops[3], self.effective_ops[1] ] # su, sd, sz on the 1st bath site for n in range(3): # 1st physical - 1st bath self.bath_op_onsite += j2 * (0.5 + 0.5 * (n == 2)) * tm.cont( [self.tensors[1].conj(), self.tensors[1], opb[n], opp[n]], [[2, 4, 1, 6, -1], [3, 4, 5, 6, -2], [1, 5], [2, 3]]) # 2nd physical - 1st bath self.bath_op_onsite += j2 * (0.5 + 0.5 * (n == 2)) * tm.cont( [self.tensors[1].conj(), self.tensors[1], opb[n], opp[n]], [[3, 2, 5, 1, -1], [3, 4, 5, 6, -2], [1, 6], [2, 4]]) # 1st physical - 2nd bath # self.bath_op_onsite += j2 * (0.5 + 0.5 * (n == 2)) * tm.cont( # [self.tensors[1].conj(), self.tensors[1], opb[n], opp[n]], # [[2, 6, 3, 1, -1], [5, 6, 3, 4, -2], [1, 4], [2, 5]]) opp = [self.operators[5], self.operators[4], self.operators[3]] # sd, su, sz on the physical site opb = [ self.effective_ops[6], self.effective_ops[7], self.effective_ops[5] ] # su, sd, sz on the 2nd bath site for n in range(3): # 1st physical - 2nd bath self.bath_op_onsite += j2 * (0.5 + 0.5 * (n == 2)) * tm.cont( [self.tensors[1].conj(), self.tensors[1], opb[n], opp[n]], [[2, 4, 1, 6, -1], [3, 4, 5, 6, -2], [1, 5], [2, 3]]) # 2nd physical - 2nd bath self.bath_op_onsite += j2 * (0.5 + 0.5 * (n == 2)) * tm.cont( [self.tensors[1].conj(), self.tensors[1], opb[n], opp[n]], [[3, 2, 5, 1, -1], [3, 4, 5, 6, -2], [1, 6], [2, 4]]) # self.bath_op_onsite += j2 * (0.5 + 0.5 * (n == 2)) * tm.cont( # [self.tensors[1].conj(), self.tensors[1], opb[n], opp[n]], # [[5, 2, 1, 4, -1], [5, 6, 3, 4, -2], [1, 3], [2, 6]]) # 2nd physical - 2nd bath op1 = [self.operators[4], self.operators[5], self.operators[3]] # su, sd, sz on the 1st physical site op2 = [self.operators[5], self.operators[4], self.operators[3]] # sd, su, sz on the 2nd physical site for n in range(3): self.bath_op_onsite += j1 * (0.5 + 0.5 * (n == 2)) * tm.cont( [self.tensors[1].conj(), self.tensors[1], op1[n], op2[n]], [[1, 2, 3, 4, -1], [5, 6, 3, 4, -2], [1, 5], [2, 6]]) if abs(hx) > 1e-15: op1 = self.operators[1] # sx self.bath_op_onsite -= hx * tm.cont( [self.tensors[1].conj(), self.tensors[1], op1], [[1, 5, 2, 3, -1], [4, 5, 2, 3, -2], [1, 4]]) self.bath_op_onsite -= hx * tm.cont( [self.tensors[1].conj(), self.tensors[1], op1], [[4, 1, 2, 3, -1], [4, 5, 2, 3, -2], [1, 5]]) if abs(hz) > 1e-15: op1 = self.operators[3] # sz self.bath_op_onsite -= hz * tm.cont( [self.tensors[1].conj(), self.tensors[1], op1], [[1, 5, 2, 3, -1], [4, 5, 2, 3, -2], [1, 4]]) self.bath_op_onsite -= hz * tm.cont( [self.tensors[1].conj(), self.tensors[1], op1], [[4, 1, 2, 3, -1], [4, 5, 2, 3, -2], [1, 5]]) self.bath_op_onsite = (self.bath_op_onsite + self.bath_op_onsite.conj().T) / 2