def compute_energy_mpo(Hp, S): E = 0.0 E2 = 0.0 N = len(Hp) Ns = S.shape[0] for i in range(Ns): # contracting the entire TN for each sample S[i,:] eT = Hp[0][S[i, 0], :] for j in range(1, N - 1): eT = ncon((eT, Hp[j][:, S[i, j], :]), ([1], [1, -1])) j = N - 1 eT = ncon((eT, Hp[j][:, S[i, j]]), ([1], [1])) #print i, eT E = E + eT E2 = E2 + eT**2 Fest = E / float(i + 1) F2est = E2 / float(i + 1) Error = np.sqrt(np.abs(F2est - Fest**2) / float(i + 1)) #print i,np.real(Fest),Error #disp([i,i/Ns, real(Fest), real(Error)]) #fflush(stdout); E2 = E2 / float(Ns) E = np.abs(E / float(Ns)) Error = np.sqrt(np.abs(E2 - E**2) / float(Ns)) return np.real(E), Error
def mps_to_density(mps): site = len(mps) #for i in range(site): # print(mps[i]) #assert False, 'stop' psi = ncon((mps[0], mps[1]), ([-1, 1], [1, -2, -3])) psi = np.reshape(psi, [4, -1]) for i in range(site - 3): psi = ncon((psi, mps[i + 2]), ([-1, 1], [1, -2, -3])) psi = np.reshape(psi, [2**(i + 3), -1]) pho = ncon((psi, psi.conj()), ([-1, -3], [-2, -4])) pho = ncon((pho, mps[site - 1], mps[site - 1].conj()), ([-1, -3, 1, 2], [-2, 1], [-4, 2])) pho = np.reshape(pho, (2**site, 2**site)) #site = len(mps) #pho = ncon((mps[0],mps[0]),([-1,-3],[-2,-4])) #for i in range(1, site-1): # print(i) # print(mps[i].shape) # pho = ncon((pho,mps[i],mps[i]),([-1,-2,1,2],[1,-3,-5],[2,-4,-6])) # pho = ncon((pho),([1,2,1,2,-1,-2])) # print(pho.shape) #pho = ncon((pho,mps[site-1],mps[site-1]),([-1,-2,1,2],[-3,1],[-4,2])) #pho = ncon((pho),([1,2,1,2])) return pho
def mps_cFidelity(MPS, povm_M, Nqubit, S, logP): Fidelity = 0.0 F2 = 0.0 Ns = S.shape[0] L1 = 0.0 L1_2 = 0.0 for i in range(Ns): P = ncon((MPS[0].conj(), MPS[0], povm_M[S[i, 0], :, :]), ([1, -1], [2, -2], [1, 2])) # contracting the entire TN for each sample S[i,:] for j in range(1, Nqubit - 1): P = ncon((P, MPS[j].conj(), MPS[j], povm_M[S[i, j], :, :]), ([1, 2], [1, 3, -1], [2, 4, -2], [3, 4])) P = ncon((P, MPS[Nqubit - 1].conj(), MPS[Nqubit - 1], povm_M[S[i, Nqubit - 1], :, :]), ([1, 2], [3, 1], [4, 2], [3, 4])) ratio = P / np.exp(logP[i]) ee = np.sqrt(ratio) Fidelity = Fidelity + ee F2 = F2 + ee**2 L1 = L1 + np.abs(1 - ratio) L1_2 = L1_2 + np.abs(1 - ratio)**2 F2 = F2 / float(Ns) Fidelity = np.abs(Fidelity / float(Ns)) Error = np.sqrt(np.abs(F2 - Fidelity**2) / float(Ns)) L1_2 = L1_2 / float(Ns) L1 = np.abs(L1 / float(Ns)) L1_err = np.sqrt(np.abs(L1_2 - L1**2) / float(Ns)) return np.real(Fidelity), np.real(Error), np.real(L1), np.real(L1_err)
def trg_loss(Ainit, Binit, chi, log2L, hl, hr): # print('trg_loss is executed') chiD = Ainit.shape[0] chiH = hl.shape[2] RGstep = 2 * log2L - 2; # remain 4 tensors # %%%%% Construct <psi| psi> & <psi|H| psi> gA = double_ten(Ainit) gB = double_ten(Binit) gOA = double_imp_left(Ainit, hl) gOB = double_imp_right(Binit, hr) TA = gA.clone(); TB = gB.clone(); Nsq = 1; checkConv_norm = [] checkConv_expect = [] # %%%%% do TRG iteration for iter in range(RGstep): print('RGstep = ',iter+1, ) Tnorm = torch.sqrt(torch.norm(TA) * torch.norm(TB)); Nsq = Nsq * torch.exp(torch.log(Tnorm) / (2 ** (iter))); TA = TA/Tnorm; TB = TB/Tnorm; U1, V1 = construct_uv(TA, chi) TB = TB.permute(3,0,1,2) U2, V2 = construct_uv(TB, chi) #%%%%% Now we are going to consider the expectation value! %%%%% gOA, gOB, gA, gB = map(lambda x: x/Tnorm,(gOA, gOB, gA, gB) ) # decompose gOA and gOB if iter == 0: # incoporate hl,hr U11, V11 = construct_uv_imp_left(gOA, chiH, chi) gOB = gOB.permute(3,0,1,2) U12, V12 = construct_uv_imp_right(gOB, chiH, chi) else: U11, V11 = construct_uv(gOA, chi) gOB = gOB.permute(3, 0, 1, 2) U12 ,V12 = construct_uv(gOB, chi) gB = gB.permute(3, 0, 1, 2) U21, V21 = construct_uv(gB, chi) U22, V22 = construct_uv(gA, chi) # construct new gOA,gOB,gB,gA TA = constract_four_ten(V1, U2, V2, U1) TB = constract_four_ten(V1, U2, V2, U1) gOB = constract_four_ten(V11, U12, V2, U1) gA = constract_four_ten(V22, U2, V12, U1) gOA = constract_four_ten(V1, U21, V2, U11) gB = constract_four_ten(V1, U2, V21, U22) checkConv_expect.append(torch.norm(gOA).item()) checkConv_norm.append(Tnorm.item()) # contract the remaining 4 tensor TATA = ncon([TA,TA],[[1,-1,2,-3],[2,-2,1,-4]]); Rest = ncon([TATA,TATA],[[1,2,3,4],[3,4,1,2]]); Nsq = Nsq * torch.exp(torch.log(Rest) / 2 ** (2 * log2L)); T11T12 = ncon([gOA,gOB],[[1,-1,2,-3], [2,-2,1,-4]]); T21T22 = ncon([gB,gA],[[1,-1,2,-3], [2,-2,1,-4]]); ThamRest = ncon([T11T12,T21T22],[[1,2,3,4],[3,4,1,2]]); ExpectEner = 2 * ThamRest / Rest; # we only evaluate 2 interaction for each sites print('ExpectEner.item() = ', ExpectEner.item()) return ExpectEner
def corner_big(c1t1_a, t4w_a, c4t3_a): dim1 = c1t1_a.shape[0] * t4w_a.shape[1] dim2 = t4w_a.shape[2] c_a1_big = ncon([c1t1_a, t4w_a], [[-1, 1], [1, -2, -3]]).reshape([dim1, dim2]) dim1 = t4w_a.shape[0] dim2 = t4w_a.shape[1] * c4t3_a.shape[1] c_a4_big = ncon([c4t3_a, t4w_a], [[1, -3], [-1, -2, 1]]).reshape([dim1, dim2]) return c_a1_big, c_a4_big
def ctmrg(ten_a, ten_b, hloc, dim_cut, ctm_step): double_ten_a = double_ten(ten_a) double_ten_b = double_ten(ten_b) w_a, cns_a, tms_b = weight_cns_tms(double_ten_a) w_b, cns_b, tms_a = weight_cns_tms(double_ten_b) weight_imp = create_weight_imp(ten_a, ten_b, hloc) energy = 0 energy_mem = -1 for i in range(ctm_step): print('ctm step = ', i + 1) # print('energy = ', energy.item(), 'ctm step = ', i) # print('dE = ', abs(energy - energy_mem).item()) for _ in range(4): c1t1_a, t4w_a, c4t3_a = extend_tensors(cns_a[0], tms_a[0], tms_a[3], w_a, cns_a[3], tms_a[2]) c1t1_b, t4w_b, c4t3_b = extend_tensors(cns_b[0], tms_b[0], tms_b[3], w_b, cns_b[3], tms_b[2]) c_a1_big, c_a4_big = corner_big(c1t1_a, t4w_a, c4t3_a) c_b1_big, c_b4_big = corner_big(c1t1_b, t4w_b, c4t3_b) u_ab, d_ab = create_projectors_orus(c_a1_big, c_b4_big, dim_cut) u_ba, d_ba = create_projectors_orus(c_b1_big, c_a4_big, dim_cut) cns_b[0], tms_b[3], cns_b[3] = coarse_grain( c1t1_a, t4w_a, c4t3_a, u_ba, d_ba, u_ab, d_ab) cns_a[0], tms_a[3], cns_a[3] = coarse_grain( c1t1_b, t4w_b, c4t3_b, u_ab, d_ab, u_ba, d_ba) cns_a, tms_a, cns_b, tms_b = map(list_rotation, (cns_a, tms_a, cns_b, tms_b)) w_a, w_b = map(weight_rotate, (w_a, w_b)) cns_a = list(map(normalize, cns_a)) cns_b = list(map(normalize, cns_b)) tms_a = list(map(normalize, tms_a)) tms_b = list(map(normalize, tms_b)) w_ab = ncon([w_a, w_b], [[-1, -2, 1, -6], [1, -3, -4, -5]]) norm = ncon([ cns_a[0], tms_a[0], cns_a[1], tms_a[3], tms_a[1], w_ab, tms_b[3], tms_b[2], cns_b[3], tms_b[2], cns_b[2] ], [[1, 3], [2, 4, 1], [5, 2], [3, 6, 8], [10, 7, 5], [ 4, 7, 12, 14, 11, 6 ], [8, 11, 13], [15, 12, 10], [13, 16], [16, 14, 17], [17, 15]]) expect = ncon([ cns_a[0], tms_a[0], cns_a[1], tms_a[3], tms_a[1], weight_imp, tms_b[3], tms_b[2], cns_b[3], tms_b[2], cns_b[2] ], [[1, 3], [2, 4, 1], [5, 2], [3, 6, 8], [10, 7, 5], [ 4, 7, 12, 14, 11, 6 ], [8, 11, 13], [15, 12, 10], [13, 16], [16, 14, 17], [17, 15]]) energy_mem = energy energy = expect / norm * 2 print('energy = ', energy.item()) return energy
def target_state_ham(povm, circuit, tau, step, boundary, mode='imag'): """ :return: povm_t and pho_t after imaginary/real time evolution """ Nqubit = circuit.nb_qbits povm.construct_psi() povm.construct_Nframes() povm.construct_ham(boundary) # prepare state #psi, E = povm.ham_eigh() #pho = np.outer(psi, np.conjugate(psi)) #prob = ncon((pho,povm.Mn),([1,2],[-1,2,1])).real # construct density matrix psi_t = povm.psi.copy() psi_t = psi_t / np.linalg.norm(psi_t) pho_t = np.outer(psi_t, np.conjugate(psi_t)) prob_t = ncon((pho_t, povm.Mn), ([1, 2], [-1, 2, 1])).real pho_t0 = pho_t.copy() prob_t0 = prob_t.copy() # imaginary time if mode == 'imag': for i in range(step): pho_t = pho_t - tau * (povm.ham @ pho_t + pho_t @ povm.ham) #prob_t_raw = ncon((pho_t,povm.Mn),([1,2],[-1,2,1])).real.astype(np.float32) pho_t = pho_t / np.trace(pho_t) prob_t = ncon((pho_t, povm.Mn), ([1, 2], [-1, 2, 1])).real.astype(np.float32) elif mode == 'real': for i in range(step): pho_t = pho_t - 1j * tau * (povm.ham @ pho_t - pho_t @ povm.ham) #prob_t_raw = ncon((pho_t,povm.Mn),([1,2],[-1,2,1])).real.astype(np.float32) pho_t = pho_t / np.trace(pho_t) prob_t = ncon((pho_t, povm.Mn), ([1, 2], [-1, 2, 1])).real.astype(np.float32) #print('Fid', np.linalg.norm(pho_t - pho_t0)) #print('E', np.trace(pho_t @ povm.ham)) else: assert False, 'mode does not exist' # test #cFid2 = np.dot(np.sqrt(prob_t0), np.sqrt(prob_t)) ##cFid2 = np.linalg.norm(prob-prob_povm,ord=2) ##cFid2 = np.dot(prob, np.log(prob_povm)) ##Fid2 = ncon((pho,pho_povm),([1,2],[2,1])) ## true for 2 qubit #Fid2 = np.square(np.trace(sp.linalg.sqrtm(pho_t0 @ pho_t @pho_t0))) ## true for pure state pho #print('Fidelity', cFid2, Fid2) return prob_t, pho_t
def mps_to_vector(mps): """ mps should have site more than 2 :return: vector form of the mps """ site = len(mps) psi = ncon((mps[0], mps[1]), ([-1, 1], [1, -2, -3])) psi = np.reshape(psi, [4, -1]) for i in range(site - 3): psi = ncon((psi, mps[i + 2]), ([-1, 1], [1, -2, -3])) psi = np.reshape(psi, [2**(i + 3), -1]) psi = ncon((psi, mps[site - 1]), ([-1, 1], [-2, 1])) psi = np.reshape(psi, [2**site]) return psi
def extend_tensors(c1, t1, t4, w, c4, t3): ## c1t1 chi0, chi1, chi2 = (t1.shape[0], c1.shape[1], t1.shape[1]) c1t1 = ncon([c1, t1], [[1, -2], [-1, -3, 1]]) c1t1 = c1t1.reshape([chi0, chi1 * chi2]) ## t4w chi0, chi1, chi2, chi3, chi4 = (t4.shape[0], w.shape[0], w.shape[0], t4.shape[2], w.shape[0]) t4w = ncon([t4, w], [[-1, 1, -4], [-2, -3, -5, 1]]) t4w = t4w.reshape([chi0 * chi1, chi2, chi3 * chi4]) ## c4t3 chi0, chi1, chi2 = (c4.shape[0], t3.shape[1], t3.shape[2]) c4t3 = ncon([c4, t3], [[-1, 1], [1, -2, -3]]) c4t3 = c4t3.reshape([chi0 * chi1, chi2]) return c1t1, t4w, c4t3
def create_weight_imp(ten_a, ten_b, two_sites_op): weight_imp = ncon([ten_a, ten_b, two_sites_op, ten_a, ten_b], [[-1, -3, 5, -11, 1], [5, -5, -7, -9, 2], [1, 2, 3, 4], [-2, -4, 6, -12, 3], [6, -6, -8, -10, 4]]) dim = ten_a.shape[0]**2 weight_imp = weight_imp.reshape([dim] * 6) return weight_imp
def Fidelity_test(Nqubit, target_vocab_size, povm, prob, pho, model, device=torch.device("cpu")): """ test the fidelity between given prob and pho, and the model predicted prob and pho :return: cFid2 is classical fidelity and Fid2 is quantum fidelity """ prob_povm = np.exp(vectorize(Nqubit, target_vocab_size, model, device)) pho_povm = ncon((prob_povm, povm.Ntn), ([1], [1, -1, -2])) #Et = np.trace(pho_povm @ povm.ham) #print('exact E:', E, 'current E:', Et.real) cFid = np.dot(np.sqrt(prob), np.sqrt(prob_povm)) L1 = np.linalg.norm(prob - prob_povm, ord=1) KL = np.dot(prob, np.log(prob_povm)) #Fid2 = ncon((pho,pho_povm),([1,2],[2,1])) ## true for 2 qubit Fid = np.abs(np.trace(sp.linalg.sqrtm( pho @ pho_povm @ pho)))**2 ## true for pure state pho #print('cFid_ED: ', cFid2, Fid2) #a = np.array(list(it.product(range(4),repeat = Nqubit))) #a = torch.tensor(a) #l = torch.sum(torch.exp(model.logP(a))) #print("prob", l) return cFid, L1, KL, Fid
def create_projectors_corboz(c1, c2, c3, c4, dim_cut): upper_half = ncon([c1, c2], [[1, -2], [-1, 1]]) lower_half = ncon([c4, c3], [[-2, 1], [1, -1]]) _, r_up = torch_qr(upper_half) _, r_down = torch_qr(lower_half) rr = r_up @ r_down.T.contiguous() u, s, v = torch_svd(rr) vT = v.T dim_new = min(s.shape[0], dim_cut) s = s[:dim_new] s_inv2 = torch.diag(1 / s**0.5) u_tmp = u[:, :dim_new] @ s_inv2 v_tmp = s_inv2 @ vT[:dim_new, :] p_up = r_down.T @ v_tmp.T p_down = r_up.T @ u_tmp return p_up, p_down
def corner_extend_corboz(c1, t1, t4, w): c1_label = [2, 1] t1_label = [-1, 3, 2] t4_label = [1, 4, -3] w_label = [3, -2, -4, 4] c1_new = ncon([c1, t1, t4, w], [c1_label, t1_label, t4_label, w_label]) dim1 = c1_new.shape[0] * c1_new.shape[1] dim2 = c1_new.shape[2] * c1_new.shape[3] c1_new = c1_new.reshape([dim1, dim2]) return c1_new
def lnz_trg(betaval, chiM, RGstep): # Jtemp = torch.zeros((2, 2, 2), dtype=dtype, device=device) # Jtemp[0, 0, 0] = 1 # Jtemp[1, 1, 1] = 1 p_beta = torch.exp(betaval) m_beta = torch.exp(-betaval) # print(p_beta) Etemp = [p_beta, m_beta, m_beta, p_beta] Etemp = torch.stack(Etemp).view(2, 2) # Ainit = ncon([Jtemp, Jtemp, Jtemp, Jtemp, Etemp, Etemp, Etemp, Etemp], # [[-1, 8, 1], [-2, 2, 3], [-3, 4, 5], [-4, 6, 7], [1, 2], [3, 4], [5, 6], [7, 8]]) w, v = torch_eigh(Etemp) # print(w) Q_sqrt = v @ torch.diag(torch.sqrt(w)) @ torch.inverse(v) delta = torch.zeros([2, 2, 2, 2], dtype=dtype, device=device) delta[0, 0, 0, 0] = delta[1, 1, 1, 1] = 1 # print(torch.norm(Q_sqrt@Q_sqrt-Etemp)) T = ncon([Q_sqrt, Q_sqrt, Q_sqrt, Q_sqrt, delta], [[-1, 1], [-2, 2], [-3, 3], [-4, 4], [1, 2, 3, 4]]) Atemp = T # test_a = Atemp.norm() # test, = torch.autograd.grad(test_a, betaval, create_graph=True) # print('fine') lnz = 0.0 for k in range(RGstep): print('sizeA = ', Atemp.shape, ', RGstep = ', k + 1) Amax = Atemp.abs().max() Atemp = Atemp / Amax lnz += 2**(-k) * torch.log(Amax) # # decompose A site U1, V1 = construct_uv(Atemp, chiM) # decompose B site Atemp = Atemp.permute(3, 0, 1, 2) U2, V2 = construct_uv(Atemp, chiM) Atemp = ncon([V1, U2, V2, U1], [[1, 4, -1], [2, 1, -2], [4, 3, -4], [3, 2, -3]]) lnz += torch.log(ncon([Atemp], [[1, 2, 1, 2]])) / 2**(RGstep) return lnz
def double_ten(Ainit): chiD = Ainit.shape[0] gA = ncon([Ainit, (Ainit)], [[-1, -3, -5, -7, 1], [-2, -4, -6, -8, 1]]); gA = gA.reshape(chiD ** 2, chiD ** 2, chiD ** 2, chiD ** 2); return gA
def coarse_grain(c1t1, t4w, c4t3, u_up, u_down): c1 = c1t1 @ u_up t4 = ncon([u_down, t4w, u_up], [[1, -1], [1, -2, 2], [2, -3]]) c4 = u_down.T.contiguous() @ c4t3 return c1, t4, c4
def free_energy_ctmrg(lattice, beta, chiM, CTMRGstep, thres=1e-7): p_beta = torch.exp(beta) m_beta = torch.exp(-beta) # print(p_beta) Q = [p_beta, m_beta, m_beta, p_beta] Q = torch.stack(Q).view(2, 2) w, v = torch_eigh(Q) # print(w) Q_sqrt = v @ torch.diag(torch.sqrt(w)) @ torch.inverse(v) if lattice == 'square': delta = torch.zeros([2, 2, 2, 2], dtype=dtype, device=device) delta[0, 0, 0, 0] = delta[1, 1, 1, 1] = 1 # print(torch.norm(Q_sqrt @ Q_sqrt - Q)) weight = ncon([Q_sqrt, Q_sqrt, Q_sqrt, Q_sqrt, delta], [[-1, 1], [-2, 2], [-3, 3], [-4, 4], [1, 2, 3, 4]]) s_mag = torch.zeros([2, 2, 2, 2], dtype=dtype, device=device) s_mag[0, 0, 0, 0] = 1 s_mag[1, 1, 1, 1] = -1 weight_mag = ncon([Q_sqrt, Q_sqrt, Q_sqrt, Q_sqrt, s_mag], [[-1, 1], [-2, 2], [-3, 3], [-4, 4], [1, 2, 3, 4]]) elif lattice == 'honeycomb': delta = torch.zeros([2, 2, 2], dtype=dtype, device=device) delta[0, 0, 0] = delta[1, 1, 1] = 1 ten_a = ncon([Q_sqrt, Q_sqrt, Q_sqrt, delta], [[-1, 1], [-2, 2], [-3, 3], [1, 2, 3]]) weight = ncon([ten_a, ten_a], [[1, -3, -4], [1, -1, -2]]) s_mag = torch.zeros([2, 2, 2], dtype=dtype, device=device) s_mag[0, 0, 0] = 1 s_mag[1, 1, 1] = -1 a_mag = ncon([Q_sqrt, Q_sqrt, Q_sqrt, s_mag], [[-1, 1], [-2, 2], [-3, 3], [1, 2, 3]]) weight_mag = ncon([a_mag, a_mag], [[1, -3, -4], [1, -1, -2]]) cns = [torch.rand([2, 2], dtype=dtype, device=device)] * 4 tms = [torch.rand([2, 2, 2], dtype=dtype, device=device)] * 4 lnz_val = 0 lnz_mem_val = -1 steps = 0 while abs(lnz_val - lnz_mem_val) > thres and steps < CTMRGstep: # while steps < CTMRGstep: # print('c1.shape = ', tuple(c1.shape), ', CTMRGstep = ', steps + 1) for i in range(4): # four direction ######################## Extend tensors c1t1, t4w, c4t3 = extend_tensors(cns[0], tms[0], tms[3], weight, cns[3], tms[2]) # print(c1t1.shape) ######################## Create projector # Orus scheme u_up, u_down = create_projectors_orus(c1t1, c4t3, chiM) ## Corboz scheme # corner_extended = [] # for _ in range(4): # corner_extended.append(corner_extend_corboz(c1, t1, t4, weight)) # c1, c2, c3, c4 = tuple_rotation(c1, c2, c3, c4) # t1, t2, t3, t4 = tuple_rotation(t1, t2, t3, t4) # weight = weight_rotate(weight) # u_up, u_down = create_projectors_corboz(*corner_extended, chiM) ###################### Coarse grain tensors cns[0], tms[3], cns[3] = coarse_grain(c1t1, t4w, c4t3, u_up, u_down) ###################### Rotate tensors cns, tms = map(list_rotation, (cns, tms)) weight = weight_rotate(weight) cns = list(map(normalize, cns)) tms = list(map(normalize, tms)) c1, c2, c3, c4 = cns t1, t2, t3, t4 = tms # print(t4.shape) expect1 = ncon([c1, t1, c2, t4, weight, t2, c4, t3, c3], [[1, 3], [2, 4, 1], [5, 2], [3, 6, 8], [4, 7, 9, 6], [10, 7, 5], [8, 11], [11, 9, 12], [12, 10]]) expect2 = ncon([c1, c2, c3, c4], [[1, 2], [3, 1], [4, 3], [2, 4]]) expect3 = ncon([c1, t1, c2, c3, t3, c4], [[1, 3], [2, 4, 1], [5, 2], [7, 5], [6, 4, 7], [3, 6]]) expect4 = ncon([c1, c2, t4, t2, c4, c3], [[1, 2], [3, 1], [2, 4, 5], [6, 4, 3], [5, 7], [7, 6]]) expect_mag = ncon([c1, t1, c2, t4, weight_mag, t2, c4, t3, c3], [[1, 3], [2, 4, 1], [5, 2], [3, 6, 8], [4, 7, 9, 6], [10, 7, 5], [8, 11], [11, 9, 12], [12, 10]]) lnz = torch.log(expect1 * expect2 / (expect3 * expect4)) steps += 1 lnz_mem_val = lnz_val lnz_val = lnz mag = expect_mag / expect1 # print('lnz = ', lnz.item()) # print('(lnz-lnz_old) = ', abs(lnz_val - lnz_mem_val).item()/lnz_val.item()) if steps < CTMRG_step: print('converge!') if lattice == 'honeycomb': lnz = lnz / 2 mag = mag / 2 print('CTMRGstep = ', steps + 1) return lnz, mag
def target_state_gate(povm, circuit, step, mode="Graph"): """ :return: povm_t and pho_t after applying gate """ Nqubit = circuit.nb_qbits povm.construct_psi() povm.construct_Nframes() # GHZ state psi = np.zeros(2**Nqubit) psi[0] = 1. psi[-1] = 1. psi = psi / np.sqrt(2) pho = np.outer(psi, np.conjugate(psi)) prob = ncon((pho, povm.Mn), ([1, 2], [-1, 2, 1])).real # construct density matrix psi_t = povm.psi.copy() psi_t = psi_t / np.linalg.norm(psi_t) pho_t = np.outer(psi_t, np.conjugate(psi_t)) prob_t = ncon((pho_t, povm.Mn), ([1, 2], [-1, 2, 1])).real pho_t0 = pho_t.copy() prob_t0 = prob_t.copy() if mode == "Graph": SITE = [] GATE = [] P_GATE = [] for i in range(step): SITE.append([i, i + 1]) GATE.append(povm.cz) P_GATE.append(povm.P_gate(povm.cz)) elif mode == "GHZ": SITE = [[0]] GATE = [povm.H] P_GATE = [povm.P_gate(povm.H)] for i in range(step - 1): SITE.append([i, i + 1]) GATE.append(povm.cnot) P_GATE.append(povm.P_gate(povm.cnot)) else: assert False, "mode does not exist" for i in range(len(SITE)): sites = SITE[i] gate = P_GATE[i] gtype = int(gate.ndim / 2) kron_gate = povm.kron_gate(GATE[i], sites[0], Nqubit) psi_t = psi_t @ kron_gate psi_t = psi_t / np.linalg.norm(psi_t) pho_t = np.outer(psi_t, np.conjugate(psi_t)) prob_t = ncon((pho_t, povm.Mn), ([1, 2], [-1, 2, 1])).real # test cFid2 = np.dot(np.sqrt(prob), np.sqrt(prob_t)) ##cFid2 = np.linalg.norm(prob-prob_povm,ord=2) ##cFid2 = np.dot(prob, np.log(prob_povm)) ##Fid2 = ncon((pho,pho_povm),([1,2],[2,1])) ## true for 2 qubit #Fid2 = np.square(np.trace(sp.linalg.sqrtm(pho_t0 @ pho_t @pho_t0))) ## true for pure state pho #print('Fidelity', cFid2, Fid2) print('Fidelity', cFid2) return prob_t, pho_t
def coarse_grain(c1t1_a, t4w_a, c4t3_a, u_ba, d_ba, u_ab, d_ab): c1_b = c1t1_a @ u_ba t4_b = ncon([d_ba, t4w_a, u_ab], [[1, -1], [1, -2, 2], [2, -3]]) c4_b = d_ab.T.contiguous() @ c4t3_a return c1_b, t4_b, c4_b
def double_ten(ten_a): double_ten = ncon([ten_a, ten_a], [[-1, -3, -5, -7, 1], [-2, -4, -6, -8, 1]]) return double_ten
def double_imp_left(Ainit, hl): chiD = Ainit.shape[0] chiH = hl.shape[2] gOA = ncon([Ainit, hl, (Ainit)], [[-1, -3, -5, -8, 1], [1, 2, -7], [-2, -4, -6, -9, 2]]); gOA = torch.reshape(gOA, [chiD ** 2, chiD ** 2, chiD ** 2 * chiH, chiD ** 2]); return gOA
def constract_four_ten(V1,U2,V2,U1): return ncon([V1, U2, V2, U1], [[1, 4, -1], [2, 1, -2], [4, 3, -4], [3, 2, -3]]);
def double_imp_right(Binit, hr): chiD = Binit.shape[0] chiH = hr.shape[2] gOB = ncon([Binit,hr,(Binit)], [[-1,-4,-6,-8,1], [1,2,-3], [-2,-5,-7,-9,2]]); gOB = torch.reshape(gOB, [chiD ** 2 * chiH, chiD ** 2, chiD ** 2, chiD ** 2]); return gOB