예제 #1
0
 def get_obs_ops(self):
     obs_ops = dict()
     s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
     obs_ops["sz"] = s2.SZ()
     obs_ops["sp"] = s2.SP()
     obs_ops["sm"] = s2.SM()
     return obs_ops
예제 #2
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(4, dtype=self.dtype, device=self.device)
        id2 = id2.view(2, 2, 2, 2).contiguous()
        rot_op = s2.BP_rot()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        SS = SS.contiguous()

        SS_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, SS, rot_op)

        h2x2_SS = torch.einsum('ijab,klcd->ijklabcd', SS, id2)
        h2x2_nn= h2x2_SS + h2x2_SS.permute(2,3,0,1,6,7,4,5) + h2x2_SS.permute(0,2,1,3,4,6,5,7)\
            + h2x2_SS.permute(2,0,3,1,6,4,7,5)
        h2x2_nnn = h2x2_SS.permute(0, 3, 2, 1, 4, 7, 6, 5) + h2x2_SS.permute(
            2, 0, 1, 3, 6, 4, 5, 7)

        h2x2_nn = h2x2_nn.contiguous()
        h2x2_nnn = h2x2_nnn.contiguous()

        # sublattice rotation for single-site bipartite (BP) ansatz
        h2x2_nn_rot= torch.einsum('irtlaxyd,jr,kt,xb,yc->ijklabcd',\
            h2x2_nn,rot_op,rot_op,rot_op,rot_op)
        h2x2_nnn_rot= torch.einsum('irtlaxyd,jr,kt,xb,yc->ijklabcd',\
            h2x2_nnn,rot_op,rot_op,rot_op,rot_op)

        h2x2_nn_rot = h2x2_nn_rot.contiguous()
        h2x2_nnn_rot = h2x2_nnn_rot.contiguous()

        return SS, SS_rot, h2x2_nn, h2x2_nnn, h2x2_nn_rot, h2x2_nnn_rot
예제 #3
0
def build_gate(tau=1.0, H=j1j2.J1J2_C4V_BIPARTITE(j1=args.j1, j2=args.j2)):
    """Part of j1j2.py code.
    H is a class with j1=1.0 and j2=0 by default.
    Simple pi/2 rotation of the gate gives the Hamiltonian on another bond."""
    s2 = su2.SU2(H.phys_dim, dtype=H.dtype, device=H.device)
    expr_kron = 'ij,ab->iajb'

    # Spin-spin operator
    #   s1|   |s2
    #     |   |
    #   [  S.S  ]
    #     |   |
    #  s1'|   |s2'

    SS = torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
        + torch.einsum(expr_kron,s2.SM(),s2.SP()))
    SS = SS.view(4, 4).contiguous()

    # Diagonalization of SS and creation of Hamiltonian Ha
    eig_va, eig_vec = np.linalg.eigh(SS)
    eig_va = np.exp(-tau / 2 * args.j1 * eig_va)
    U = torch.tensor(eig_vec)
    D = torch.diag(torch.tensor(eig_va))
    # Ha = U D U^{\dagger}
    Ga = torch.einsum('ij,jk,lk->il', U, D, U)
    Ga = Ga.view(2, 2, 2, 2).contiguous()
    return Ga
예제 #4
0
    def get_h(self):
        pd = self.phys_dim
        irrep = su2.SU2(pd, dtype=self.dtype, device=self.device)
        # identity operator on two spin-S spins
        idp = torch.eye(pd**2, dtype=self.dtype, device=self.device)
        idp = idp.view(pd, pd, pd, pd).contiguous()
        SS = irrep.SS()
        SS = SS.view(pd**2, pd**2)
        h2 = self.j1 * SS + self.k1 * SS @ SS
        # Reshape back into rank-4 tensor for later use with reduced density matrices
        h2 = h2.view(pd, pd, pd, pd).contiguous()

        h2x2_h2 = torch.einsum('ijab,klcd->ijklabcd', h2, idp)
        # Create operators acting on four spins-S on plaquette. These are useful
        # for computing energy by different rearragnement of Hamiltonian terms
        #
        # NN-terms along horizontal bonds of plaquette
        hp_h = h2x2_h2 + h2x2_h2.permute(2, 3, 0, 1, 6, 7, 4, 5)
        # NN-terms along vertical bonds of plaquette
        hp_v = h2x2_h2.permute(0, 2, 1, 3, 4, 6, 5, 7) + h2x2_h2.permute(
            2, 0, 3, 1, 6, 4, 7, 5)
        # All NN-terms within plaquette
        hp = hp_h + hp_v

        return h2, hp_h, hp_v, hp
예제 #5
0
 def get_h(self):
     s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
     expr_kron = 'ij,ab->iajb'
     SS = torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
         + torch.einsum(expr_kron,s2.SM(),s2.SP()))
     rot_op = s2.BP_rot()
     SS_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, SS, rot_op)
     return SS, SS_rot
예제 #6
0
    def get_h(self):
        # from "bra" tuple of indices return corresponing bra-ket pair of indices
        # 0 -> 0;1; 1,0 -> 1,0;3,2; ...
        def bk(*bras):
            kets = [b + len(bras) for b in bras]
            return tuple(list(bras) + kets)

        s2 = su2.SU2(2, dtype=self.dtype, device=self.device)
        id2 = torch.eye(4, dtype=self.dtype, device=self.device)
        id2 = id2.view(2, 2, 2, 2).contiguous()
        id3 = torch.eye(8, dtype=self.dtype, device=self.device)
        id3 = id3.view(2, 2, 2, 2, 2, 2).contiguous()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        SSp = SS - 0.25 * id2
        SSid2 = torch.einsum('ijab,klcd->ijklabcd', SS, id2)
        SSpSSp = torch.einsum('ijab,klcd->ijklabcd', SSp, SSp)
        SSpSSp = SSpSSp + SSpSSp.permute(bk(0, 2, 1, 3))

        # on-site term
        h1= self.j1*(SSid2 +SSid2.permute(bk(2,3,0,1)) +SSid2.permute(bk(0,2,1,3))\
            +SSid2.permute(bk(2,0,3,1))) - self.q*SSpSSp
        h1 = h1.view(self.phys_dim, self.phys_dim)

        # nearest-neighbour term:
        #
        # S.S terms:
        # (s0 s1 s2 s3)_i(s0 s1 s2 s3)_j;(s0's1's2's3')_i(s0's1's2's3')_j
        #     ^           ^                  ^            ^
        # s0--s1~~s0--s1
        # |   |   |   |
        # s2--s3  s2--s3
        # i       j
        #
        SiSj = torch.einsum('ijab,efgmno,qrsxyz->eifgjqrsmanobxyz', SS, id3,
                            id3)
        #
        # SSpSSp terms:
        # s0--s1  s0--s1 + s0--s1==s0--s1
        # |   ||  ||   |   |   |   |    |
        # s2--s3  s2--s3   s2--s3==s2--s3
        # i       j        i       j
        SSpiSSpj = torch.einsum('ijklabcd,efmn,ghxy->eifjkglhmanbcxdy', SSpSSp,
                                id2, id2)
        h2 = self.j1 * (SiSj + SiSj.permute(bk(0, 3, 2, 1, 6, 5, 4,
                                               7))) - self.q_inter * (SSpiSSpj)
        h2+= self.j1*(SiSj.permute(bk(0,2,1,3,4,5,6,7)) + SiSj.permute(bk(0,3,2,1,5,4,6,7)))\
            -self.q_inter*(SSpiSSpj.permute(bk(0,2,1,3,4,6,5,7)))
        h2 = h2.contiguous().view(self.phys_dim * self.phys_dim,
                                  self.phys_dim * self.phys_dim)
        h2_U, h2_S, h2_V = torch.svd(h2)
        h2_S = h2_S[h2_S > 1.0e-14]
        h2_U = h2_U[:, :len(h2_S)]
        h2_V = h2_V[:, :len(h2_S)]
        h2 = h2.view(self.phys_dim, self.phys_dim, self.phys_dim,
                     self.phys_dim)
        return h1, h2, (h2_U, h2_S, h2_V), SS
예제 #7
0
    def get_obs_ops(self):
        obs_ops = dict()
        irrep = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        obs_ops["sz"] = irrep.SZ()
        obs_ops["sp"] = irrep.SP()
        obs_ops["sm"] = irrep.SM()
        obs_ops["SS"] = irrep.SS()

        return obs_ops
예제 #8
0
파일: akltS2.py 프로젝트: tateobori/AD-peps
 def get_h(self):
     pd = self.phys_dim
     s5 = su2.SU2(pd, dtype=self.dtype, device=self.device)
     expr_kron = 'ij,ab->iajb'
     SS = torch.einsum(expr_kron,s5.SZ(),s5.SZ()) + 0.5*(torch.einsum(expr_kron,s5.SP(),s5.SM()) \
         + torch.einsum(expr_kron,s5.SM(),s5.SP()))
     SS = SS.view(pd*pd,pd*pd)
     h = (1./14)*(SS + (7./10.)*SS@SS + (7./45.)*SS@SS@SS + (1./90.)*SS@SS@SS@SS)
     h = h.view(pd,pd,pd,pd)
     SS = SS.view(pd,pd,pd,pd)
     return h, SS
예제 #9
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id3 = torch.eye(8**3)
        id3 = id3.view(8, 8, 8, 8, 8, 8).contiguous()

        # h_up : on site hamiltonian in d=8
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP())) -0.25*self.Hz*(torch.einsum(expr_kron,s2.SZ(),s2.I()) \
            + torch.einsum(expr_kron,s2.I(),s2.SZ()) )
        SS = SS.contiguous()
        expr_kron = 'ijab,kc->ijkabc'
        SSS = torch.einsum(expr_kron, SS, s2.I())
        SSS = SSS + SSS.permute(2, 0, 1, 5, 3, 4) + SSS.permute(
            1, 2, 0, 4, 5, 3)  # -A-B- + -B-C- + -C-A-
        h_down = SSS.view(8, 8).contiguous()
        h2x2_down = torch.einsum('ia,jklbcd->ijklabcd', h_down, id3)

        h2x2_down= h2x2_down + h2x2_down.permute(3,0,1,2,7,4,5,6) + h2x2_down.permute(2,3,0,1,6,7,4,5)\
            + h2x2_down.permute(1,2,3,0,5,6,7,4)## -A1- + -A2- + -A3- + -A4-

        h2x2_down = h2x2_down.contiguous()

        # h_down : made of 3 kinds of bonds
        # h_x:   corresponds to h_bc terms on up triangle
        # h_y:   corresponds to h_ca terms on up triangle
        # h_nnn: correspomds to h_ba terms on up triangle
        id4 = torch.eye(16)
        id4 = id4.view(2, 2, 2, 2, 2, 2, 2, 2).contiguous()
        h_bc = torch.einsum('ijab,klmncdef->kilmnjcadefb', SS, id4)
        h_ca = torch.einsum('ijab,klmncdef->klijmncdabef', SS, id4)
        h_ba = torch.einsum('ijab,klmncdef->kiljmncadbef', SS, id4)

        h_x = h_bc.contiguous().view(8, 8, 8, 8)
        h_y = h_ca.contiguous().view(8, 8, 8, 8)
        h_nnn = h_ba.contiguous().view(8, 8, 8, 8)

        id2 = torch.eye(8**2, dtype=self.dtype, device=self.device)
        id2 = id2.view(8, 8, 8, 8).contiguous()

        h2x2_x = torch.einsum('ijab,klcd->ijklabcd', h_x, id2)
        #h2x2_x= h2x2_x + h2x2_x.permute(2,3,0,1,6,7,4,5)

        h2x2_y = torch.einsum('ijab,klcd->ikjlacbd', h_y, id2)
        #h2x2_y= h2x2_y + h2x2_y.permute(1,0,3,2,5,4,7,6)

        h2x2_nn = h2x2_x.contiguous() + h2x2_y.contiguous()

        h2x2_nnn = torch.einsum('ijab,klcd->ikljacdb', h_nnn, id2)
        h2x2_nnn = h2x2_nnn.contiguous()

        Ham = (h2x2_down / 4.0 + h2x2_nn + h2x2_nnn) / 3.0
        #Ham = h2x2_nnn
        return Ham
예제 #10
0
파일: ising.py 프로젝트: tateobori/AD-peps
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(4, dtype=self.dtype, device=self.device)
        id2 = id2.view(2, 2, 2, 2).contiguous()
        SzSz = 4 * torch.einsum('ij,ab->iajb', s2.SZ(), s2.SZ())
        SzSzIdId = torch.einsum('ijab,klcd->ijklabcd', SzSz, id2)
        SzSzSzSz = torch.einsum('ijab,klcd->ijklabcd', SzSz, SzSz)
        Sx = s2.SP() + s2.SM()
        SxIdIdId = torch.einsum('ia,jb,kc,ld->ijklabcd', Sx, s2.I(), s2.I(),
                                s2.I())

        hp = -SzSzIdId - SzSzIdId.permute(
            0, 2, 1, 3, 4, 6, 5, 7) - self.q * SzSzSzSz - self.hx * SxIdIdId

        return SzSz, SzSzSzSz, Sx, hp
예제 #11
0
파일: akltS2.py 프로젝트: tateobori/AD-peps
 def get_h(self):
     pd = self.phys_dim
     s5 = su2.SU2(pd, dtype=self.dtype, device=self.device)
     expr_kron = 'ij,ab->iajb'
     SS = torch.einsum(expr_kron,s5.SZ(),s5.SZ()) + 0.5*(torch.einsum(expr_kron,s5.SP(),s5.SM()) \
         + torch.einsum(expr_kron,s5.SM(),s5.SP()))
     rot_op = s5.BP_rot()
     SS_rot = torch.einsum('jl,ilak,kb->ijab',rot_op,SS,rot_op)
     SS = SS.view(pd*pd,pd*pd)
     h = (1./14)*(SS + (7./10.)*SS@SS + (7./45.)*SS@SS@SS + (1./90.)*SS@SS@SS@SS)
     h = h.view(pd,pd,pd,pd)
     # apply a rotation on physical index of every "odd" site
     # A A => A B
     # A A => B A
     h_rot = torch.einsum('jl,ilak,kb->ijab',rot_op,h,rot_op)
     SS = SS.view(pd,pd,pd,pd)
     return h_rot, SS, SS_rot
예제 #12
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(4, dtype=self.dtype, device=self.device)
        id2 = id2.view(2, 2, 2, 2).contiguous()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        SSp = SS - 0.25 * id2
        SSpSSp = torch.einsum('ijab,klcd->ijklabcd', SSp, SSp)
        SSpSSp = SSpSSp + SSpSSp.permute(0, 2, 1, 3, 4, 6, 5, 7)

        h2x2_SS = torch.einsum('ijab,klcd->ijklabcd', SS, id2)
        hp_h_q = self.j1 * (h2x2_SS + h2x2_SS.permute(2, 3, 0, 1, 6, 7, 4,
                                                      5)) - self.q * SSpSSp
        hp_v_q= self.j1*(h2x2_SS.permute(0,2,1,3,4,6,5,7) + h2x2_SS.permute(2,0,3,1,6,4,7,5)) \
            - self.q*SSpSSp
        return SS, SSpSSp, hp_h_q, hp_v_q
예제 #13
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(self.phys_dim**2, dtype=self.dtype, device=self.device)
        id2 = id2.view(tuple([self.phys_dim] * 4)).contiguous()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        rot_op = s2.BP_rot()
        SS_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, SS, rot_op)

        h2x2_SS_rot = torch.einsum('ijab,klcd->ijklabcd', SS_rot,
                                   id2)  # nearest neighbours
        h2x2_SS = torch.einsum('ijab,klcd->ikljacdb', SS,
                               id2)  # next-nearest neighbours
        hp= self.j1*(h2x2_SS_rot + h2x2_SS_rot.permute(0,2,1,3,4,6,5,7))\
            + self.j2*(h2x2_SS + h2x2_SS.permute(1,0,3,2,5,4,7,6))
        hp = hp.contiguous()
        return SS, SS_rot, hp
예제 #14
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(4, dtype=self.dtype, device=self.device)
        id2 = id2.view(2, 2, 2, 2).contiguous()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        SS = SS.contiguous()

        h2x2_SS = torch.einsum('ijab,klcd->ijklabcd', SS, id2)
        h2x2_nn= h2x2_SS + h2x2_SS.permute(2,3,0,1,6,7,4,5) + h2x2_SS.permute(0,2,1,3,4,6,5,7)\
            + h2x2_SS.permute(2,0,3,1,6,4,7,5)## --A--B-- + --C--D-- + --A--C-- + --B--D--
        h2x2_nnn = h2x2_SS.permute(0, 3, 2, 1, 4, 7, 6, 5)  #+

        h2x2_nn = h2x2_nn.contiguous()
        h2x2_nnn = h2x2_nnn.contiguous()

        return SS, h2x2_nn, h2x2_nnn
예제 #15
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(self.phys_dim**2, dtype=self.dtype, device=self.device)
        id2 = id2.view(tuple([self.phys_dim] * 4)).contiguous()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        rot_op = s2.BP_rot()
        SS_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, SS, rot_op)

        h2x2_SS = torch.einsum('ijab,klcd->ijklabcd', SS,
                               id2)  # nearest neighbours
        # 0 1     0 1   0 x   x x   x 1
        # 2 3 ... x x + 2 x + 2 3 + x 3
        hp= 0.5*self.j1*(h2x2_SS + h2x2_SS.permute(0,2,1,3,4,6,5,7)\
           + h2x2_SS.permute(2,3,0,1,6,7,4,5) + h2x2_SS.permute(3,1,2,0,7,5,6,4)) \
           + self.j2*(h2x2_SS.permute(0,3,2,1,4,7,6,5) + h2x2_SS.permute(2,1,0,3,6,5,4,7))
        hp = torch.einsum('xj,yk,ixylauvd,ub,vc->ijklabcd', rot_op, rot_op, hp,
                          rot_op, rot_op)
        hp = hp.contiguous()
        return SS, SS_rot, hp
예제 #16
0
    def get_h(self):
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(4, dtype=self.dtype, device=self.device)
        id2 = id2.view(2, 2, 2, 2).contiguous()
        expr_kron = 'ij,ab->iajb'
        SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        SSp = SS - 0.25 * id2
        SSpSSp = torch.einsum('ijab,klcd->ijklabcd', SSp, SSp)
        SSpSSp = SSpSSp + SSpSSp.permute(0, 2, 1, 3, 4, 6, 5, 7)

        h2x2_SS = torch.einsum('ijab,klcd->ijklabcd', SS, id2)

        #
        #      i===j   i---j         i===j   i---j
        # j1*( |   | + ||  | ) - q*( |   | + || || )
        #      k---l   k---l         k===l   k---l
        #
        hp = self.j1 * (h2x2_SS + h2x2_SS.permute(0, 2, 1, 3, 4, 6, 5,
                                                  7)) - self.q * SSpSSp
        return SS, SSpSSp, hp
예제 #17
0
    def energy_2x2_1site_BP(self, state, env):
        r"""
        :param state: wavefunction
        :param env: CTM environment
        :type state: IPEPS
        :type env: ENV
        :return: energy per site
        :rtype: float

        We assume 1x1 iPEPS which tiles the lattice with a bipartite pattern composed 
        of two tensors A, and B=RA, where R rotates approriately the physical Hilbert space 
        of tensor A on every "odd" site::

            1x1 C4v => rotation P => BIPARTITE

            A A A A                  A B A B
            A A A A                  B A B A
            A A A A                  A B A B
            A A A A                  B A B A

        A single reduced density matrix :py:func:`ctm.rdm.rdm2x2` of a 2x2 plaquette
        is used to evaluate the energy.
        """
        if not (hasattr(self, 'h2x2_nn_rot') or hasattr(self, 'h2x2_nn_nrot')):
            s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
            rot_op = s2.BP_rot()
            self.h2x2_nn_rot= torch.einsum('irtlaxyd,jr,kt,xb,yc->ijklabcd',\
                self.h2x2_nn,rot_op,rot_op,rot_op,rot_op)
            self.h2x2_nnn_rot= torch.einsum('irtlaxyd,jr,kt,xb,yc->ijklabcd',\
                self.h2x2_nnn,rot_op,rot_op,rot_op,rot_op)

        tmp_rdm = rdm.rdm2x2((0, 0), state, env)
        energy_nn = torch.einsum('ijklabcd,ijklabcd', tmp_rdm,
                                 self.h2x2_nn_rot)
        energy_nnn = torch.einsum('ijklabcd,ijklabcd', tmp_rdm,
                                  self.h2x2_nnn_rot)
        energy_per_site = 2.0 * (self.j1 * energy_nn / 4.0 +
                                 self.j2 * energy_nnn / 2.0)

        return energy_per_site
예제 #18
0
    def get_obs_ops(self):
        obs_ops = dict()
        expr_kron1 = 'ij,ab->iajb'
        expr_kron2 = 'ijab,kc->ijkabc'
        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        obs_ops["sz_A"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.SZ(), s2.I()),
            s2.I()).view(8, 8).contiguous()
        obs_ops["sp_A"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.SP(), s2.I()),
            s2.I()).view(8, 8).contiguous()
        obs_ops["sm_A"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.SM(), s2.I()),
            s2.I()).view(8, 8).contiguous()

        obs_ops["sz_B"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.I(), s2.SZ()),
            s2.I()).view(8, 8).contiguous()
        obs_ops["sp_B"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.I(), s2.SP()),
            s2.I()).view(8, 8).contiguous()
        obs_ops["sm_B"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.I(), s2.SM()),
            s2.I()).view(8, 8).contiguous()

        obs_ops["sz_C"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.I(), s2.I()),
            s2.SZ()).view(8, 8).contiguous()
        obs_ops["sp_C"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.I(), s2.I()),
            s2.SP()).view(8, 8).contiguous()
        obs_ops["sm_C"] = torch.einsum(
            expr_kron2, torch.einsum(expr_kron1, s2.I(), s2.I()),
            s2.SM()).view(8, 8).contiguous()

        return obs_ops
예제 #19
0
 def get_h(self):
     s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
     expr_kron = 'ij,ab->iajb'
     SS = einsum(expr_kron,s2.SZ(),s2.SZ()) + 0.5*(einsum(expr_kron,s2.SP(),s2.SM()) \
         + einsum(expr_kron,s2.SM(),s2.SP()))
     return SS
예제 #20
0
    def __init__(self, j1=1.0, j2=0, j3=0, hz_stag= 0.0, delta_zz=1.0, \
        global_args=cfg.global_args):
        r"""
        :param j1: nearest-neighbour interaction
        :param j2: next nearest-neighbour interaction
        :param hz_stag: staggered magnetic field
        :param delta_zz: easy-axis (nearest-neighbour) anisotropy
        :param global_args: global configuration
        :type j1: float
        :type j2: float
        :type hz_stag: float
        :type detla_zz: float
        :type global_args: GLOBALARGS

        Build Spin-1/2 :math:`J_1-J_2` Hamiltonian

        .. math:: 

            H = J_1\sum_{<i,j>} \mathbf{S}_i.\mathbf{S}_j + J_2\sum_{<<i,j>>} \mathbf{S}_i.\mathbf{S}_j
            = \sum_{p} h_p

        on the square lattice. Where the first sum runs over the pairs of sites `i,j` 
        which are nearest-neighbours (denoted as `<.,.>`), and the second sum runs over 
        pairs of sites `i,j` which are next nearest-neighbours (denoted as `<<.,.>>`)::

            y\x
               _:__:__:__:_
            ..._|__|__|__|_...
            ..._|__|__|__|_...
            ..._|__|__|__|_...
            ..._|__|__|__|_...
            ..._|__|__|__|_...
                :  :  :  :

        where

        * :math:`h_p = J_1(S^x_{r}.S^x_{r+\vec{x}} 
          + S^y_{r}.S^y_{r+\vec{x}} + \delta_{zz} S^z_{r}.S^z_{r+\vec{x}} + (x<->y))
          + J_2(\mathbf{S}_{r}.\mathbf{S}_{r+\vec{x}+\vec{y}} + \mathbf{S}_{r+\vec{x}}.\mathbf{S}_{r+\vec{y}})
          + h_stag (S^z_{r} - S^z_{r+\vec{x}} - S^z_{r+\vec{y}} + S^z_{r+\vec{x}+\vec{y}})` 
          with indices of spins ordered as follows :math:`s_r s_{r+\vec{x}} s_{r+\vec{y}} s_{r+\vec{x}+\vec{y}};
          s'_r s'_{r+\vec{x}} s'_{r+\vec{y}} s'_{r+\vec{x}+\vec{y}}`

        """
        self.dtype = global_args.torch_dtype
        self.device = global_args.device
        self.phys_dim = 2
        self.j1 = j1
        self.j2 = j2
        self.j3 = j3
        self.hz_stag = hz_stag
        self.delta_zz = delta_zz

        self.obs_ops = self.get_obs_ops()

        s2 = su2.SU2(self.phys_dim, dtype=self.dtype, device=self.device)
        id2 = torch.eye(self.phys_dim**2, dtype=self.dtype, device=self.device)
        id2 = id2.view(tuple([self.phys_dim] * 4)).contiguous()
        expr_kron = 'ij,ab->iajb'

        self.SS_delta_zz= self.delta_zz*torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + \
            0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        self.SS= torch.einsum(expr_kron,s2.SZ(),s2.SZ()) + \
            0.5*(torch.einsum(expr_kron,s2.SP(),s2.SM()) \
            + torch.einsum(expr_kron,s2.SM(),s2.SP()))
        hz_2x1_nn = torch.einsum(expr_kron, s2.SZ(), s2.I()) + torch.einsum(
            expr_kron, s2.I(), -s2.SZ())

        rot_op = s2.BP_rot()
        SS_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, self.SS, rot_op)
        SS_delta_zz_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op,
                                       self.SS_delta_zz, rot_op)
        hz_2x1_rot = torch.einsum('ki,kjcb,ca->ijab', rot_op, hz_2x1_nn,
                                  rot_op)
        self.SS_rot = SS_rot.contiguous()
        self.SS_delta_zz_rot = SS_delta_zz_rot.contiguous()
        self.hz_2x1_rot = hz_2x1_rot.contiguous()

        h2x2_SS_delta_zz = torch.einsum('ijab,klcd->ijklabcd',
                                        self.SS_delta_zz,
                                        id2)  # nearest neighbours
        h2x2_SS = torch.einsum('ijab,klcd->ijklabcd', self.SS,
                               id2)  # next-nearest neighbours
        # 0 1     0 1   0 x   x x   x 1
        # 2 3 ... x x + 2 x + 2 3 + x 3
        hp= 0.5*self.j1*(h2x2_SS_delta_zz + h2x2_SS_delta_zz.permute(0,2,1,3,4,6,5,7)\
           + h2x2_SS_delta_zz.permute(2,3,0,1,6,7,4,5) + h2x2_SS_delta_zz.permute(3,1,2,0,7,5,6,4)) \
           + self.j2*(h2x2_SS.permute(0,3,2,1,4,7,6,5) + h2x2_SS.permute(2,1,0,3,6,5,4,7))\
           - 0.25*self.hz_stag*torch.einsum('ia,jb,kc,ld->ijklabcd',s2.SZ(),-s2.SZ(),-s2.SZ(),s2.SZ())
        hp = torch.einsum('xj,yk,ixylauvd,ub,vc->ijklabcd', rot_op, rot_op, hp,
                          rot_op, rot_op)
        self.hp = hp.contiguous()