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 reshape_combine_two_bonds_z2(self, nb): # reshape nb and nb+1 together data = dict() for key in self.data: dim0 = self.data[key].shape[:nb] dim1 = self.data[key].shape[nb + 2:] dim_now = self.data[key].shape[nb] * self.data[key].shape[nb + 1] tmp = self.data[key].reshape(dim0 + (dim_now, ) + dim1) key_num = [int(x) for x in key] key_new = key[:nb] + str( (key_num[nb] + key_num[nb + 1]) % 2) + key[nb + 2:] if key_new not in data: s = list(tmp.shape) s[nb] *= 2 data[key_new] = np.zeros(s) if (key_num[nb] == 0 and key_num[nb + 1] == 0) or \ (key_num[nb] == 0 and key_num[nb + 1] == 1): data[key_new] = tm.operate_tensor_slice( data[key_new], nb, ':' + str(dim_now), tmp) else: data[key_new] = tm.operate_tensor_slice( data[key_new], nb, str(dim_now) + ':', tmp) self.data = data self.ndim -= 1 self.shape[nb] = self.shape[nb] * self.shape[nb + 1] self.shape.pop(nb + 1)
def update_virtual_vecs_train(self, which_t, which_side): if (which_side is 'left') or (which_side is 'both'): tmp = tm.khatri(self.vecsLeft[which_t], self.vecsImages[:, which_t, :].squeeze()) self.vecsLeft[which_t + 1] = np.tensordot( self.mps.mps[which_t], tmp, ([0, 1], [0, 1])) if (which_side is 'right') or (which_side is 'both'): tmp = tm.khatri(self.vecsRight[which_t], self.vecsImages[:, which_t, :].squeeze()) self.vecsRight[which_t - 1] = np.tensordot( self.mps.mps[which_t], tmp, ([2, 1], [0, 1]))
def env_tensor(self, nt, way): s = self.mps.mps[nt].shape env = tm.khatri(tm.khatri( self.vecsLeft[nt], self.vecsImages[:, nt, :].squeeze()).reshape( self.mps.virtual_dim[nt] * self.d, self.numVecSample), self.vecsRight[nt]) if way is 'mera': env = env.dot(np.ones((self.numVecSample, ))) elif way is 'gradient': weight = self.mps.mps[nt].reshape(1, -1).dot(env) env = env.dot(1 / weight) return env.reshape(s)
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 update_tensor_decision_mps_svd_threshold_algo(self, nt, time_r=5, threshold=0.9): self.update_tensor_decision_mps_svd(nt) env = 0 d0 = self.v_ctr_train[0].shape[0] d1 = self.vecsImages[0][:, nt].shape[0] for t in range(0, time_r): for n in self.remaining_samples_train: v1 = tm.absorb_vectors2tensors( self.tensors[nt], (self.v_ctr_train[n], self.vecsImages[n][:, nt]), (0, 1)) norm = np.linalg.norm(v1) fid = self.fun_fidelity(v1 / norm) fid_now = fid[self.classes.index(self.LabelNow[n])] fid = [fid[nn] / fid_now for nn in range(0, self.num_classes)] fid.pop(self.classes.index(self.LabelNow[n])) if max(fid) > threshold: env += np.kron( np.kron(self.v_ctr_train[n], self.vecsImages[n][:, nt]), self.vLabel[self.classes.index(self.LabelNow[n])]) u, self.lm[nt], v = np.linalg.svd( (env / np.linalg.norm(env.reshape(-1, ))).reshape( d0 * d1, self.chi), full_matrices=False) self.tensors[nt] = u.dot(v).reshape([d0, d1, self.chi]) self.lm[nt] /= np.linalg.norm(self.lm[nt])
def update_tensor_decision_mps_gradient_algo(self, nt, time_r=5, threshold=0, step=0.2): self.update_tensor_decision_mps_svd(nt) for t in range(0, time_r): d_tensor = np.zeros(self.tensors[nt].shape) for n in self.remaining_samples_train: v1 = tm.absorb_vectors2tensors( self.tensors[nt], (self.v_ctr_train[n], self.vecsImages[n][:, nt]), (0, 1)) norm = np.linalg.norm(v1) fid = self.fun_fidelity(v1 / norm) fid_now = fid[self.classes.index(self.LabelNow[n])] fid = [fid[nn] / fid_now for nn in range(0, self.num_classes)] fid.pop(self.classes.index(self.LabelNow[n])) if max(fid) > threshold: tmp = np.kron(np.kron(self.v_ctr_train[n], self.vecsImages[n][:, nt]), self.vLabel[self.classes.index(self.LabelNow[n])]) \ / (fid_now * norm) d_tensor += tmp.reshape(self.tensors[nt].shape) d_tensor -= self.tensors[nt] norm = np.linalg.norm(d_tensor.reshape(-1, )) if norm > 1e-10: d_tensor /= norm self.tensors[nt] = self.tensors[nt] + step * d_tensor self.tensors[nt] /= np.linalg.norm(self.tensors[nt].reshape(-1, ))
def __init__(self, dims, state_type='pure', ini='random', operators=None): self.dims = dims self.dim_tot = int(np.prod(self.dims)) self.l = len(self.dims) self.is_vec = True # If self.v is saved as a vector or tensor self.state_type = state_type if type(ini) is np.ndarray: self.v = ini elif ini is 'random': if state_type is 'pure': self.v = np.random.randn(self.dim_tot, ) self.v = tm.normalize_tensor(self.v)[0] else: self.v = np.random.randn(self.dim_tot, self.dim_tot) self.v = self.v + self.v.transpose((1, 0)) else: if state_type is 'pure': self.v = np.ones((self.dim_tot, 1)) / (self.dim_tot**0.5) else: self.v = np.eye(self.dim_tot) if operators is None: op = spin_operators('half') self.operators = [ op['id'], op['sx'], op['sy'], op['sz'], op['su'], op['sd'] ] else: self.operators = operators
def initial_ipeps(self): dim = (self.d, ) + (self.chi, ) * self.nVirtual if self.iniWay is 'random': tensor = tm.symmetrical_rand_peps_tensor(self.d, self.chi, self.nVirtual) if self.stateType is 'mixed': bond = (self.d0, self.d0) + (self.chi, ) * self.nVirtual tensor = tensor.reshape(bond) ind = (1, 0) + tuple(range(2, self.nVirtual + 2)) tensor = (tensor + tensor.transpose(ind)) / 2 bond = (self.d, ) + (self.chi, ) * self.nVirtual tensor = tensor.reshape(bond) for n in range(0, self.nTensor): self.tensors[n] = tensor.copy() elif self.iniWay is 'ones': for n in range(0, self.nTensor): self.tensors[n] = np.ones(dim) elif self.iniWay is 'id': if self.stateType is 'mixed': if self._is_debug: if abs(self.d0**2 - self.d) > 1e-10: bf.print_error('For mixed state, d should be as d0^2. ' 'Check self.d or self.stateType') for n in range(0, self.nTensor): self.tensors[n] = np.eye( self.d0).reshape((self.d, ) + (1, ) * self.nVirtual) else: bf.print_error('Initial way "id" is only for thermal states')
def one_bond_so_transformation(self, nt1, vb1, nt2, vb2): # Super-orthogonal transformation on one virtual bond # vb does NOT count the physical bond if self._is_debug: if self.pos_lm[nt1][vb1] != self.pos_lm[nt2][vb2]: bf.print_error( 'In one_bond_so_transformation, the two virtual bonds must' 'correspond to the same lambda') m1 = self.bond_env_matrix_simple(nt1, vb1) m2 = self.bond_env_matrix_simple(nt2, vb2) flag = False if self._is_debug: _lm = self.lm[self.pos_lm[nt1][vb1]].copy() flag = (self.chi == self.tensors[nt1].shape[vb1 + 1]) u1, u2, self.lm[self.pos_lm[nt1] [vb1]] = tm.transformation_from_env_mats( m1, m2, self.lm[self.pos_lm[nt1][vb1]], self.chi, norm_way=1)[:3] if self._is_debug and flag: _tmp = u1.dot(np.diag(self.lm[self.pos_lm[nt1][vb1]])).dot(u2.T) err = np.linalg.norm(tm.off_diagonal_mat(_tmp).reshape(-1, )) if err > 1e-10: print( 'Warning of the transformations from environment: not diagonal (%g)' % err) _tmp = np.diag(_tmp) _tmp = _tmp / np.linalg.norm(_tmp) err = np.linalg.norm(_tmp - self.lm[self.pos_lm[nt1][vb1]]) if err > 1e-10: print( 'Warning of the transformations from environment: not recover lm (%g)' % err) print(self.lm[self.pos_lm[nt1][vb1]]) self.tensors[nt1] = tm.absorb_matrix2tensor(self.tensors[nt1], u1, vb1 + 1) self.tensors[nt2] = tm.absorb_matrix2tensor(self.tensors[nt2], u2, vb2 + 1) self.tensors[nt1] /= max(abs(self.tensors[nt1].reshape(-1, 1))) self.tensors[nt2] /= max(abs(self.tensors[nt2].reshape(-1, 1))) # self.lm[self.pos_lm[nt1][vb1]] = tm.normalize_tensor(self.lm[self.pos_lm[nt1][vb1]])[0] return m1, m2
def multiple_images2vecs(self, theta_max=np.pi/2): # Put the data of images in self.tmp!!! # The pixels should have been normalized to [0, 1) s = self.tmp.shape self.tmp *= theta_max self.vecsImages = np.zeros((self.d, ) + s) for nd in range(1, self.d+1): self.vecsImages[nd-1, :, :] = (np.sqrt(tm.combination(self.d-1, nd-1)) * ( np.cos(self.tmp)**(self.d-nd)) * (np.sin(self.tmp)**(nd-1)))
def map_to_vectors(self, x, d=None, theta_max=np.pi / 2): if d is None: d = self.d x *= theta_max y = np.zeros((self.d, ) + x.shape) for nd in range(1, self.d + 1): y[nd - 1, :, :] = (np.sqrt(tm.combination(d - 1, nd - 1)) * (np.cos(x)**(d - nd)) * (np.sin(x)**(nd - 1))) return y
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 images2vecs(self, theta_max=np.pi / 2): # The pixels should have been normalized to [0, 1) s = self.images.shape self.numVecSample = s[1] self.images *= theta_max self.vecsImages = np.zeros((self.d, ) + s) for nd in range(1, self.d + 1): self.vecsImages[nd - 1, :, :] = ( np.sqrt(tm.combination(self.d - 1, nd - 1)) * (np.cos(self.images)**(self.d - nd)) * (np.sin(self.images)**(nd - 1)))
def update_tensor_gradient(self, nt, step): # for n in self.mps.mps: # print(n) # input() self.mps.correct_orthogonal_center(nt) env = self.env_tensor((nt, 'all', 'gradient')) env = tm.normalize_tensor(env)[0] # env /= np.linalg.norm(env.reshape(-1, )) self.mps.mps[nt] = self.mps.mps[nt] * (1 - step) + step * env.reshape( self.mps.mps[nt].shape) self.mps.mps[nt] /= np.linalg.norm(self.mps.mps[nt].reshape(-1, ))
def fidelity_mps_image(self, mps_ref, ni): # Calculate the fidelity between an MPS and one image fid = 0 length = mps_ref.__len__() v0 = np.ones((1, )) image = self.vecsImages[ni] for n in range(0, self.length): v0 = tm.absorb_vectors2tensors(mps_ref[n], (v0, image[:, n]), (0, 1)) norm = np.linalg.norm(v0) v0 /= norm fid -= np.log(norm) / length return fid
def compute_fidelities(self, mps): fid = np.zeros((self.numVecSample, 1)) vecs = np.ones((1, self.numVecSample)) for nt in range(self.length): s = mps[nt].shape vecs = np.tensordot(mps[nt], tm.khatri(vecs, self.vecsImages[:, nt, :]), ([0, 1], [0, 1])) norm = np.linalg.norm(vecs, axis=0) vecs /= norm.repeat(s[2]).reshape(self.numVecSample, s[2]).T fid -= np.log(norm.reshape(self.numVecSample, 1)) return fid / self.length
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 update_virtual_vecs_train(self, which_t, which_side): if (which_side is 'left') or (which_side is 'both'): tmp = tm.khatri(self.vecsLeft[which_t], self.vecsImages[:, which_t, :]) self.vecsLeft[which_t + 1] = np.tensordot(self.mps.mps[which_t], tmp, ([0, 1], [0, 1])) norm = np.linalg.norm(self.vecsLeft[which_t + 1], axis=0) self.norms[which_t, :] = norm self.vecsLeft[which_t + 1] /= norm.repeat( self.mps.virtual_dim[which_t + 1]).reshape( self.numVecSample, self.mps.virtual_dim[which_t + 1]).T if (which_side is 'right') or (which_side is 'both'): tmp = tm.khatri(self.vecsRight[which_t], self.vecsImages[:, which_t, :]) self.vecsRight[which_t - 1] = np.tensordot(self.mps.mps[which_t], tmp, ([2, 1], [0, 1])) norm = np.linalg.norm(self.vecsRight[which_t - 1], axis=0) self.norms[which_t, :] = norm self.vecsRight[which_t - 1] /= norm.repeat( self.mps.virtual_dim[which_t]).reshape( self.numVecSample, self.mps.virtual_dim[which_t]).T
def absorb_lm(self, nt, if_sqrt, which_vb): # which_vb does NOT count physical bond tensor = self.tensors[nt].copy() if if_sqrt: if which_vb is 'all': tensor = tm.absorb_matrices2tensor(tensor, [ np.diag(np.sqrt(self.lm[self.pos_lm[nt][n]])) for n in range(0, self.nVirtual) ], [n + 1 for n in range(0, self.nVirtual)]) elif type(which_vb) is int: tensor = tm.absorb_matrix2tensor( tensor, np.diag(np.sqrt(self.lm[self.pos_lm[nt][which_vb]])), which_vb + 1) else: tensor = tm.absorb_matrices2tensor(tensor, [ np.diag(np.sqrt(self.lm[self.pos_lm[nt][n]])) for n in which_vb ], [n + 1 for n in which_vb]) else: if which_vb is 'all': tensor = tm.absorb_matrices2tensor(tensor, [ np.diag(self.lm[self.pos_lm[nt][n]]) for n in range(0, self.nVirtual) ], [n + 1 for n in range(0, self.nVirtual)]) elif type(which_vb) is int: tensor = tm.absorb_matrix2tensor( tensor, np.diag(self.lm[self.pos_lm[nt][which_vb]]), which_vb + 1) else: tensor = tm.absorb_matrices2tensor( tensor, [np.diag(self.lm[self.pos_lm[nt][n]]) for n in which_vb], [n + 1 for n in which_vb]) return tensor
def bond_env_matrix_simple(self, nt, vb, is_symme=True, is_normalize=True): # the nb-th bond matrix of the nt-th tensor (including the phys bond) bonds = list(range(0, self.nVirtual)) bonds.remove(vb) tmp = self.absorb_lm(nt, False, bonds) bonds = list(range(0, self.nVirtual + 1)) bonds.remove(vb + 1) tmp = np.tensordot(tmp, tmp, (bonds, bonds)) if is_symme: tmp = (tmp + tmp.conj().T) / 2 if is_normalize: tmp = tm.normalize_tensor(tmp)[0] return tmp
def compute_bond_vectors(self, nb=0): # Contract the samples to the MPS but left the nb-th physical bond empty # The bond vectors are normalized vecsL = np.ones((1, self.numVecSample)) for nt in range(0, nb): s = self.mps.mps[nt].shape tmp = tm.khatri(vecsL, self.vecsImages[:, nt, :].squeeze()) vecsL = np.tensordot(self.mps.mps[nt], tmp, ([0, 1], [0, 1])) norm = np.linalg.norm(vecsL, axis=0) vecsL /= norm.repeat(s[2]).reshape(self.numVecSample, s[2]).T vecsR = np.ones((1, self.numVecSample)) for nt in range(self.length - 1, nb, -1): s = self.mps.mps[nt].shape tmp = tm.khatri(vecsR, self.vecsImages[:, nt, :].squeeze()) vecsR = np.tensordot(self.mps.mps[nt], tmp, ([2, 1], [0, 1])) norm = np.linalg.norm(vecsR, axis=0) vecsR /= norm.repeat(s[2]).reshape(self.numVecSample, s[2]).T s = self.mps.mps[nb].shape tmp = np.tensordot(self.mps.mps[nb], tm.khatri(vecsL, vecsR), ([0, 2], [0, 1])) norm = np.linalg.norm(tmp, axis=0) tmp /= norm.repeat(s[2]).reshape(self.numVecSample, s[2]).T return tmp
def observation_kagome(self, j1, j2, hx, hz): # compatible to one-site iDMRG and one-site deep iDMRG z = np.linalg.norm(self.tensors[0].reshape(-1, )) tmp = self.tensors[0].reshape((self.d, ) * 3 + (self.chi, ) * 3) / z mag = dict() mag['x'] = np.zeros((3, )) mag['z'] = np.zeros((3, )) for n in range(3): ind = list(range(6)) ind.pop(n) rho = np.tensordot(tmp.conj(), tmp, [ind, ind]) mag['x'][n] = np.trace(rho.dot(self.operators[1])) mag['z'][n] = np.trace(rho.dot(self.operators[3])) energy = np.zeros(self.rho.__len__(), ) j_coup = [j1, j1, j2] for n in range(self.rho.__len__()): h = j_coup[n] * ( np.kron(self.operators[4], self.operators[5]) / 2 + np.kron(self.operators[5], self.operators[4]) / 2 + np.kron(self.operators[3], self.operators[3])) energy[n] = np.trace(self.rho[n].dot(h)) energy_site = np.sum(energy) - hx * ( mag['x'][0] / 2 + mag['x'][1] + mag['x'][2] / 2) - hz * ( mag['z'][0] / 2 + mag['z'][1] + mag['z'][2] / 2) energy_site /= 2 lm = list() lm.append( np.linalg.svd(self.tensors[0].transpose(0, 3, 1, 2, 4, 5).reshape( self.d * self.chi, self.d * self.d * self.chi * self.chi), compute_uv=False)) lm.append( np.linalg.svd(self.tensors[0].transpose(1, 4, 0, 2, 3, 5).reshape( self.d * self.chi, self.d * self.d * self.chi * self.chi), compute_uv=False)) lm.append( np.linalg.svd(self.tensors[0].transpose(2, 5, 0, 1, 3, 4).reshape( self.d * self.chi, self.d * self.d * self.chi * self.chi), compute_uv=False)) ent = [tm.entanglement_entropy(x) for x in lm] return energy, mag, energy_site, ent
def analyse_dataset(self): # Total number of samples self.dataInfo['NumTotalTrain'] = self.labels.__len__() # Order the samples and labels order = np.argsort(self.labels) self.images = bf.sort_vecs(self.images, order, which=1) self.labels = np.array(sorted(self.labels)) # Total number of classes self.dataInfo['NumClass'] = int(self.labels[-1] + 1) # Detailed information self.dataInfo['nStart'] = np.zeros((self.dataInfo['NumClass'], ), dtype=int) self.dataInfo['nClassNum'] = np.zeros((self.dataInfo['NumClass'],), dtype=int) self.dataInfo['nStart'][0] = 0 for n in range(1, self.dataInfo['NumClass']): x = tm.arg_find_array(self.labels[self.dataInfo['nStart'][n-1] + 1:] == n, 1, 'first') self.dataInfo['nClassNum'][n-1] = x + 1 self.dataInfo['nStart'][n] = x + self.dataInfo['nStart'][n-1] + 1 self.dataInfo['nClassNum'][-1] = \ self.dataInfo['NumTotalTrain'] - self.dataInfo['nStart'][-1]
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
import os import sys import numpy as np import library.Parameters as pm import library.HamiltonianModule as hm import library.TensorBasicModule as tm import library.BasicFunctions as bf import scipy.linalg as la import pickle import math import os.path as opath import time import torch import library.TNmachineLearning as TNML from library.MPSClass import MpsOpenBoundaryClass from algorithms.DeepMPSfinite import act_umpo_on_mps num = 4 mps = tm.mps_ghz_state(num) a = MpsOpenBoundaryClass(num, 2, 2) mpd = tm.mpd_of_ghz(num) mps = act_umpo_on_mps(mps, mpd) a.input_mps(mps, if_deepcopy=False) a.correct_orthogonal_center(a.length - 1) a.check_mps_norm1() f0 = a.fidelity_log_by_spins_up() print(f0)
def update_v_ctr_test(self, nt): for n in self.remaining_samples_test: self.v_ctr_test[n] = tm.absorb_vectors2tensors( self.tensors[nt], (self.v_ctr_test[n], self.vecsTest[:, nt, n]), (0, 1)) self.v_ctr_test[n] /= np.linalg.norm(self.v_ctr_test[n])
def update_v_ctr_train(self, nt): for n in self.remaining_samples_train: self.v_ctr_train[n] = tm.absorb_vectors2tensors( self.tensors[nt], (self.v_ctr_train[n], self.vecsImages[n][:, nt]), (0, 1)) self.v_ctr_train[n] /= np.linalg.norm(self.v_ctr_train[n])
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
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, ))