예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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
예제 #13
0
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
예제 #16
0
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
예제 #17
0
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
예제 #18
0
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
예제 #19
0
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
예제 #20
0
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