def OptT(Mpo, HL, HR, T): # 所有T Ns = len(T) Eng0 = np.zeros(Ns) Eng1 = np.zeros(Ns) for r in range(100): #print (r) for i in range(Ns - 1): T[i], Eng1[i] = OptTSite(Mpo, HL[i], HR[i], T[i], Method=1) # print i,Eng1[i] T[i], U = Sub.Mps_QR0P(T[i]) HL[i + 1] = Sub.NCon( [HL[i], np.conj(T[i]), Mpo, T[i]], [[1, 3, 5], [1, 2, -1], [3, 4, -2, 2], [5, 4, -3]]) T[i + 1] = np.tensordot(U, T[i + 1], (1, 0)) for i in range(Ns - 1, 0, -1): T[i], Eng1[i] = OptTSite(Mpo, HL[i], HR[i], T[i], Method=1) # print i,Eng1[i] U, T[i] = Sub.Mps_LQ0P(T[i]) HR[i - 1] = Sub.NCon( [HR[i], T[i], Mpo, np.conj(T[i])], [[1, 3, 5], [-1, 2, 1], [-2, 2, 3, 4], [-3, 4, 5]]) T[i - 1] = np.tensordot(T[i - 1], U, (2, 0)) #print (Eng1) if abs(Eng1[1] - Eng0[1]) < 1.0e-7: # Eng1[1]是第一个非边界点 break Eng0 = copy.copy(Eng1) # Eng0 = Eng1会导致0随1一起改变 print(Eng1 / float(Ns)) return T, Eng1[0] / float(Ns)
def OptTSite(Mpo, HL, HR, T, Method=0): # 一个T DT = np.shape(T) Dl = np.prod(DT) if Method == 0: A = Sub.NCon([HL, Mpo, HR], [[-1, 1, -4], [1, -5, 2, -2], [-6, 2, -3]]) A = Sub.Group(A, [[0, 1, 2], [3, 4, 5]]) Eig, V = LAs.eigsh(A, k=1, which='SA') # 本征值从小到大排列,对应能量,为负数 T = np.reshape(V, DT) if Method == 1: def UpdateV(V): V = np.reshape(V, DT) V = Sub.NCon([HL, V, Mpo, HR], [[-1, 3, 1], [1, 2, 4], [3, 2, 5, -2], [4, 5, -3]]) V = np.reshape(V, [Dl]) return V V0 = np.reshape(T, [Dl]) MV = LAs.LinearOperator((Dl, Dl), matvec=UpdateV) Eig, V = LAs.eigsh(MV, k=1, which='SA', v0=V0) # 等价于直接求MV*v,而不知道MV具体多少 # print Eig T = np.reshape(V, DT) Eig = np.real(Eig) return T, Eig
def Operator_Identity(Mpo, T): Ns = len(T) Dmpo = np.shape(Mpo)[0] Dp = np.shape(Mpo)[1] opL = [None] * Ns opR = [None] * Ns opL[0] = np.zeros((1, Dmpo, 1)) opL[0][0, 0, 0] = 1.0 opR[-1] = np.zeros((1, Dmpo, 1)) opR[-1][0, -1, 0] = 1.0 I_mpo = GetMpo_Identity(Dp) for i in range(Ns - 1, 0, -1): opR[i - 1] = Sub.NCon( [opR[i], T[i], I_mpo, np.conj(T[i])], [[1, 3, 5], [-1, 2, 1], [-2, 2, 3, 4], [-3, 4, 5]]) for i in range(0, Ns - 1): opL[i + 1] = Sub.NCon([opL[i], np.conj(T[i]), I_mpo, T[i]], [[1, 3, 5], [1, 2, -1], [3, 4, -2, 2], [5, 4, -3]]) return opL, opR
def OptT_TwoSite(Mpo, HL, HR, T1, T2, Method=1): Dl = T1.shape[0] Dm = T1.shape[2] Dr = T2.shape[2] Dp = Mpo.shape[1] T = Sub.NCon([T1, T2], [[-1, -2, 1], [1, -3, -4]]) DT = np.shape(T) DT_V = np.prod(DT) if Method == 1: def UpdateV(V): V = np.reshape(V, DT) V = Sub.NCon([HL, V, Mpo, Mpo, HR], [[-1, 3, 1], [1, 2, 6, 5], [3, 2, 4, -2], [4, 6, 7, -3], [5, 7, -4]]) V = np.reshape(V, [DT_V]) return V V0 = np.reshape(T, [DT_V]) MV = LAs.LinearOperator((DT_V, DT_V), matvec=UpdateV) Eig, V = LAs.eigsh(MV, k=1, which='SA', v0=V0) T_mix = np.reshape(V, [Dl * Dp, Dp * Dr]) T1, s, T2, Dm = Sub.SplitSvd_Lapack(T_mix, Dm, 0) T1 = T1.reshape(Dl, Dp, -1) T2 = T2.reshape(-1, Dp, Dr) return T1, T2, s, Eig
def UpdateV(V): V = np.reshape(V, DT) V = Sub.NCon([HL, V, Mpo, Mpo, HR], [[-1, 3, 1], [1, 2, 6, 5], [3, 2, 4, -2], [4, 6, 7, -3], [5, 7, -4]]) V = np.reshape(V, [DT_V]) return V
def Get_Value(op, T, Dp): Ns = len(T) Mpo = GetMpo_OneSite(op, Dp) opL, opR = Operator_Identity(Mpo, T) value = [None] * Ns for site in range(Ns): value[site] = Sub.NCon( [opL[site], Mpo, opR[site], T[site], np.conj(T[site])], [[5, 3, 1], [3, 2, 7, 4], [8, 7, 6], [1, 2, 8], [5, 4, 6]]) return value
def InitH(Mpo, T): Ns = len(T) Dmpo = np.shape(Mpo)[0] HL = [None] * Ns HR = [None] * Ns HL[0] = np.zeros((1, Dmpo, 1)) HL[0][0, 0, 0] = 1.0 HR[-1] = np.zeros((1, Dmpo, 1)) HR[-1][0, -1, 0] = 1.0 for i in range(Ns - 1, 0, -1): HR[i - 1] = Sub.NCon([HR[i], T[i], Mpo, np.conj(T[i])], [[1, 3, 5], [-1, 2, 1], [-2, 2, 3, 4], [-3, 4, 5]]) for i in range(0, Ns - 1): HL[i + 1] = Sub.NCon([HL[i], np.conj(T[i]), Mpo, T[i]], [[1, 3, 5], [1, 2, -1], [3, 4, -2, 2], [5, 4, -3]]) return HL, HR
def InitMps(Ns, Dp, Ds): T = [None] * Ns # Refer to page 17 on 20191021 slides # Bond dimension of T varies along the chain for i in range(Ns): Dl = min(Dp**i, Dp**(Ns - i), Ds) Dr = min(Dp**(i + 1), Dp**(Ns - 1 - i), Ds) T[i] = np.random.rand(Dl, Dp, Dr) U = np.eye(np.shape(T[-1])[-1]) for i in range(Ns - 1, 0, -1): U, T[i] = Sub.Mps_LQP(T[i], U) return T
def OptT(Mpo, HL, HR, T): Ns = len(T) Eng0 = np.zeros(Ns) Eng1 = np.zeros(Ns) File_Entopy = open('Entropy.txt', 'w') for r in range(100): Entropy = [None] * Ns for i in range(Ns - 1): T[i], T[i + 1], s, Eng1[i] = OptT_TwoSite(Mpo, HL[i], HR[i + 1], T[i], T[i + 1]) T[i], U = Sub.Mps_QR0P(T[i]) HL[i + 1] = Sub.NCon( [HL[i], np.conj(T[i]), Mpo, T[i]], [[1, 3, 5], [1, 2, -1], [3, 4, -2, 2], [5, 4, -3]]) T[i + 1] = Sub.NCon([U, np.diag(s), T[i + 1]], [[-1, 1], [1, 2], [2, -2, -3]]) Entropy[i] = Get_Entropy(s) File_Entopy.write(str(Entropy)[1:-1] + '\n') Entropy = [None] * Ns for i in range(Ns - 1, 0, -1): T[i - 1], T[i], s, Eng1[i] = OptT_TwoSite(Mpo, HL[i - 1], HR[i], T[i - 1], T[i]) U, T[i] = Sub.Mps_LQ0P(T[i]) HR[i - 1] = Sub.NCon( [HR[i], T[i], Mpo, np.conj(T[i])], [[1, 3, 5], [-1, 2, 1], [-2, 2, 3, 4], [-3, 4, 5]]) T[i - 1] = Sub.NCon([U, np.diag(s), T[i - 1]], [[2, -3], [1, 2], [-1, -2, 1]]) Entropy[i] = Get_Entropy(s) File_Entopy.write(str(Entropy)[1:-1] + '\n') if abs(Eng1[1] - Eng0[1]) < 1.0e-7: break Eng0 = copy.copy(Eng1) File_Entopy.close() print(Eng1 / float(Ns)) return T, Eng1[0] / float(Ns)
def UpdateV(V): V = np.reshape(V, DT) V = Sub.NCon([HL, V, Mpo, HR], [[-1, 3, 1], [1, 2, 4], [3, 2, 5, -2], [4, 5, -3]]) V = np.reshape(V, [Dl]) return V