def random_open_mps(l, phys_dim, chi, is_eco=False): # Create a random MPS with open boundary condition # l: length; d: physical dimension; chi: virtual dimension mps = list(range(0, l)) dims = empty_list(l + 1, 1) if is_eco: for n in range(0, l): if type(phys_dim) is int: chi0 = min([phys_dim ** n, chi, phys_dim ** (l - n)]) chi1 = min([phys_dim ** (n + 1), chi, phys_dim ** (l - n - 1)]) d = phys_dim else: chi0 = min([np.prod(phys_dim[:n]), chi, np.prod(phys_dim[n:])]) chi1 = min([np.prod(phys_dim[:n+1]), chi, np.prod(phys_dim[:n+1])]) d = phys_dim[n] dims[n + 1] = chi1 mps[n] = np.random.randn(chi0, d, chi1) else: if type(phys_dim) is int: mps[0] = np.random.randn(1, phys_dim, chi) mps[l-1] = np.random.randn(chi, phys_dim, 1) for n in range(1, l-1): mps[n] = np.random.randn(chi, phys_dim, chi) dims[n] = chi dims[l-1] = chi else: mps[0] = np.random.randn(1, phys_dim[0], chi) mps[l - 1] = np.random.randn(chi, phys_dim[l-1], 1) for n in range(1, l - 1): mps[n] = np.random.randn(chi, phys_dim[n], chi) dims[n] = chi dims[l - 1] = chi return mps, dims
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 mps_ghz_state(num): d = 2 mps = empty_list(num) mps[0] = np.eye(d) / np.sqrt(2) mps[0] = mps[0].reshape(1, d, d) for n in range(1, num-1): mps[n] = delta_tensor(d, 3) mps[num-1] = np.eye(d).reshape(d, d, 1) return mps
def artificial_open_mps(l, d, chi,): """ Generate an open MPS randomly :param l: length of MPS :param d: dimension on the physical bonds :param chi: dimension of inner bonds :param is_eco: use economic dimensions :return: MPS """ # Create a random MPS with open boundary condition # l: length; d: physical dimension; chi: virtual dimension temp_mps_up_0 = np.zeros((1, d, chi)) temp_mps_up_end = np.zeros((chi, d, 1)) temp_mps_up = np.zeros((chi,d,chi)) temp_mps_down_0 = np.zeros((1, d, chi)) temp_mps_down_end = np.zeros((chi, d, 1)) temp_mps_down = np.zeros((chi,d,chi)) R = 0.0001 if d==2: temp_mps_up_0[0, :, 0] = np.array([1,0]) temp_mps_up_end[0, :, 0] = np.array([1,0]) temp_mps_up[0, :, 0] = np.array([1,0]) temp_mps_down_0[0, :, 0] = np.array([0, 1]) temp_mps_down_end[0, :, 0] = np.array([0, 1]) temp_mps_down[0, :, 0] = np.array([0, 1]) elif d==3: temp_mps_up_0[0, :, 0] = np.array([1, 0, 0]) temp_mps_up_end[0, :, 0] = np.array([1, 0, 0]) temp_mps_up[0, :, 0] = np.array([1, 0, 0]) temp_mps_down_0[0, :, 0] = np.array([0, 0, 1]) temp_mps_down_end[0, :, 0] = np.array([0, 0, 1]) temp_mps_down[0, :, 0] = np.array([0, 0, 1]) mps = list(range(0, l)) dims = empty_list(l + 1, 1) mps[0] = temp_mps_up_0 + R*np.random.randn(1, d, chi) if np.mod(l,2)==0: mps[l-1] = temp_mps_down_end + R*np.random.randn(chi, d, 1) else: mps[l-1] = temp_mps_up_end + R*np.random.randn(chi, d, 1) for n in range(1, l - 1): if np.mod(n, 2) == 0: mps[n] = temp_mps_up+ R * np.random.randn(chi, d, chi) elif np.mod(n, 2)==1: mps[n] = temp_mps_down + R *np.random.randn(chi, d, chi) dims[n] = chi dims[l - 1] = chi return mps, dims
def random_open_mps(l, d, chi, is_eco=False): """ Generate an open MPS randomly :param l: length of MPS :param d: dimension on the physical bonds :param chi: dimension of inner bonds :param is_eco: use economic dimensions :return: MPS Example: >>>M = random_open_mps(3, 2, 3) >>>print(M[0]) [[[-2.5679364 -1.12846181 0.12026503] [ 1.23217514 0.58611443 0.66304506]]] >>>print(M[1]) [[[ 0.02140644 -0.2359836 1.41704847] [ 0.42441594 0.11000762 -0.23754322]] [[ 0.42759564 0.32495413 -0.81798019] [-0.54115541 0.63275244 -0.31163543]] [[-1.11706565 0.36694417 -1.67561183] [-0.37247627 0.85373283 0.99919477]]] >>>print(M[2]) [[[-1.01253065] [-0.82606855]] [[ 0.524324 ] [ 0.52489905]] [[ 0.68181659] [-0.62746486]]] """ # Create a random MPS with open boundary condition # l: length; d: physical dimension; chi: virtual dimension mps = list(range(0, l)) dims = empty_list(l + 1, 1) if is_eco: for n in range(0, l): chi0 = min([d ** n, chi, d ** (l - n)]) chi1 = min([d ** (n + 1), chi, d ** (l - n - 1)]) dims[n + 1] = chi1 mps[n] = np.random.randn(chi0, d, chi1) else: mps[0] = np.random.randn(1, d, chi) mps[l-1] = np.random.randn(chi, d, 1) for n in range(1, l-1): mps[n] = np.random.randn(chi, d, chi) dims[n] = chi dims[l-1] = chi return mps, dims
def ones_open_mps(l, d, chi, is_eco=False): """ Generate an open MPS with all elements are 1 :param l: length of MPS :param d: dimension on the physical bonds :param chi: dimension of inner bonds :return: MPS Example: >>>M = ones_open_mps(3, 2, 3) >>>print(M[0]) [[[1. 1. 1.] [1. 1. 1.]]] >>>print(M[1]) [[[1. 1. 1.] [1. 1. 1.]] [[1. 1. 1.] [1. 1. 1.]] [[1. 1. 1.] [1. 1. 1.]]] >>>print(M[2]) [[[1.] [1.]] [[1.] [1.]] [[1.] [1.]]] """ mps = list(range(0, l)) dims = empty_list(l + 1, 1) if is_eco: for n in range(0, l): chi0 = min([d ** n, chi, d ** (l - n)]) chi1 = min([d ** (n + 1), chi, d ** (l - n - 1)]) dims[n + 1] = chi1 mps[n] = np.random.randn(chi0, d, chi1) else: mps[0] = np.random.randn(1, d, chi) mps[l - 1] = np.random.randn(chi, d, 1) for n in range(1, l - 1): mps[n] = np.random.randn(chi, d, chi) dims[n] = chi dims[l-1] = chi return mps, dims
def tensor_zn(shape, way): dim = len(shape) print(dim) ind = empty_list(dim, 0) shape = np.array(shape).reshape(-1, ) tensor = np.zeros(shape) while ind[-1] != shape[-1]: if sum(ind) % 2 == 0: if way is 'randn': tensor[tuple(ind)] = np.random.randn() elif way is 'one': tensor[tuple(ind)] = 1 ind[0] += 1 for n in range(0, dim - 1): if ind[n] == shape[n]: ind[n] = 0 ind[n + 1] += 1 return tensor
def mpd_of_ghz(num): d = 2 mpd = empty_list(num) mpd[0] = np.eye(d) mat = np.zeros((4, 4)) mat[:, 0] = np.array([1, 0, 0, 0]) mat[:, 1] = np.array([0, 0, 0, 1]) mat[:, 2] = np.array([0, 1, 0, 0]) mat[:, 3] = np.array([0, 0, 1, 0]) mat = mat.reshape([d, d, d, d]) for n in range(1, num-1): mpd[n] = copy.deepcopy(mat) mpd[num-1] = np.zeros((4, 4)) mpd[num-1][:, 0] = np.array([1, 0, 0, 1]) / np.sqrt(2) mpd[num-1][:, 1] = np.array([1, 0, 0, -1]) / np.sqrt(2) mpd[num-1][:, 2] = np.array([0, 1, 0, 0]) mpd[num-1][:, 3] = np.array([0, 0, 1, 0]) mpd[num - 1] = mpd[num-1].reshape([d, d, d, d]) return mpd
def deep_mps_qubit(mps, para=None, para_dmrg=None): if para is None: para = parameters_dmps() fid0 = mps.fidelity_log_by_spins_up() fid = np.ones((para['num_layers'], )) lm_mid = empty_list(para['num_layers']) ent = empty_list(para['num_layers']) mpo = empty_list(para['num_layers']) for n in range(para['num_layers']): # mps_chi2 = Mob(length=para_dmrg['l'], d=para_dmrg['d'], chi=para_dmrg['chi'], way='qr', ini_way='r', # operators=para_dmrg['op'], is_parallel=para_dmrg['isParallel'], # is_save_op=para_dmrg['is_save_op'], eig_way=para_dmrg['eigWay'], # is_env_parallel_lmr=para_dmrg['isParallelEnvLMR']) # mps_chi2.mps = copy.deepcopy(mps.mps) mps_chi2 = copy.deepcopy(mps) mps_chi2.truncate_virtual_bonds(chi1=2, center=mps_chi2.length - 1, way='full') if para['theta'] is None: theta = np.arange(0, 1, 1 / para['num_theta']) mps_tmp = copy.deepcopy(mps_chi2) mps_new = copy.deepcopy(mps_chi2) for nn in range(theta.size): mpo_tmp = mps_chi2.to_unitary_mpo_qubits( theta[nn], if_trun=False) # calculate unitary MPO mps_data = act_umpo_on_mps( mps.mps, mpo_tmp) # disentangle MPS to |0...0> by uMPO mps_tmp.input_mps(mps_data, if_deepcopy=if_deepcopy ) # calculate fidelity with b|0...0> # Normalize MPS (actually not necessary since umpo is unitary) mps_tmp.orthogonalize_mps(0, mps_tmp.length - 1, normalize=True, is_trun=False) fid1 = mps_tmp.fidelity_log_by_spins_up() if fid1 < fid[n]: mps_new = copy.deepcopy(mps_tmp) mpo[n] = copy.deepcopy(mpo_tmp) fid[n] = fid1 else: mpo[n] = mps_chi2.to_unitary_mpo_qubits( para['theta'], if_trun=False) # calculate unitary MPO mps_data = act_umpo_on_mps( mps.mps, mpo[n]) # disentangle MPS to |0...0> by uMPO mps_new = copy.deepcopy(mps) mps_new.input_mps(mps_data, if_deepcopy=if_deepcopy) fid[n] = mps_new.fidelity_log_by_spins_up() # print('The log-fidelity with |0...0> = ' + str(fid[n])) # Truncate the MPS mps_new.orthogonalize_mps(mps_new.length - 1, 0, normalize=True, is_trun=False) mps_new.center = 0 mps_new.orthogonalize_mps(0, mps_new.length - 1, normalize=True, is_trun=True, chi=para['chi_overlap']) mps_new.center = mps_new.length - 1 mps_new.calculate_entanglement_entropy() lm_mid[n] = mps_new.lm[round(mps_new.length / 2)] ent[n] = mps_new.ent.reshape(-1, 1) # print('The entanglement entropy of the new MPS = ') # print(ent[n].reshape(1, -1)) mps = mps_new fid1 = np.zeros((fid.size + 1, )) fid1[0] = fid0 fid1[1:] = fid return fid1, ent, lm_mid, mpo, mps