예제 #1
0
    def expect_1s_1s(self, op1, op2, n1, n2, return_intermediates=False):
        """Computes the expectation value of two single site operators acting 
        on two different sites.
        
        The result is < op1 op2 >.
        
        See expect_1s().
        
        Requires n1 < n2.
        
        The state must be up-to-date -- see self.update()!
        
        Parameters
        ----------
        op1 : ndarray or callable
            The first operator, acting on the first site.
        op2 : ndarray or callable
            The second operator, acting on the second site.
        n1 : int
            The site number of the first site.
        n2 : int
            The site number of the second site (must be > n1).
        return_intermediates : bool
            Whether to return results for intermediate sites.
            
        Returns
        -------
        expval : complex128 or sequence of complex128
            The expectation value (data type may be complex), or values if
            return_intermediates == True.
        """        
        if callable(op1):
            op1 = sp.vectorize(op1, otypes=[sp.complex128])
            op1 = sp.fromfunction(op1, (self.q[n1], self.q[n1]))
        
        if callable(op2):
            op2 = sp.vectorize(op2, otypes=[sp.complex128])
            op2 = sp.fromfunction(op2, (self.q[n2], self.q[n2])) 
        
        d = n2 - n1
        
        res = sp.zeros((d + 1), dtype=sp.complex128)
        lj = tm.eps_l_op_1s(self.l[n1 - 1], self.A[n1], self.A[n1], op1)
        
        if return_intermediates:
            res[0] = self.expect_1s(op1.dot(op1), n1)

        for j in xrange(1, d + 1):
            if return_intermediates or j == d:
                lj_op = tm.eps_l_op_1s(lj, self.A[n1 + j], self.A[n1 + j], op2)
                res[j] = m.adot(lj_op, self.r[n1 + j])
                
            if j < d:
                lj = tm.eps_l_noop(lj, self.A[n1 + j], self.A[n1 + j])
                
        if return_intermediates:
            return res
        else:
            return res[-1]
예제 #2
0
    def expect_1s_1s(self, op1, op2, n1, n2, return_intermediates=False):
        """Computes the expectation value of two single site operators acting 
        on two different sites.
        
        The result is < op1 op2 >.
        
        See expect_1s().
        
        Requires n1 < n2.
        
        The state must be up-to-date -- see self.update()!
        
        Parameters
        ----------
        op1 : ndarray or callable
            The first operator, acting on the first site.
        op2 : ndarray or callable
            The second operator, acting on the second site.
        n1 : int
            The site number of the first site.
        n2 : int
            The site number of the second site (must be > n1).
        return_intermediates : bool
            Whether to return results for intermediate sites.
            
        Returns
        -------
        expval : complex128 or sequence of complex128
            The expectation value (data type may be complex), or values if
            return_intermediates == True.
        """        
        if callable(op1):
            op1 = sp.vectorize(op1, otypes=[sp.complex128])
            op1 = sp.fromfunction(op1, (self.q[n1], self.q[n1]))
        
        if callable(op2):
            op2 = sp.vectorize(op2, otypes=[sp.complex128])
            op2 = sp.fromfunction(op2, (self.q[n2], self.q[n2])) 
        
        d = n2 - n1
        
        res = sp.zeros((d + 1), dtype=sp.complex128)
        lj = tm.eps_l_op_1s(self.l[n1 - 1], self.A[n1], self.A[n1], op1)
        
        if return_intermediates:
            res[0] = self.expect_1s(op1.dot(op1), n1)

        for j in xrange(1, d + 1):
            if return_intermediates or j == d:
                lj_op = tm.eps_l_op_1s(lj, self.A[n1 + j], self.A[n1 + j], op2)
                res[j] = m.adot(lj_op, self.r[n1 + j])
                
            if j < d:
                lj = tm.eps_l_noop(lj, self.A[n1 + j], self.A[n1 + j])
                
        if return_intermediates:
            return res
        else:
            return res[-1]
예제 #3
0
 def calc_BHB_prereq(self, tdvp, tdvp2):
     """Calculates prerequisites for the application of the effective Hamiltonian in terms of tangent vectors.
     
     This is called (indirectly) by the self.excite.. functions.
     
     Parameters
     ----------
     tdvp2: EvoMPS_TDVP_Uniform
         Second state (may be the same, or another ground state).
         
     Returns
     -------
     A lot of stuff.
     """
     l = tdvp.l[0]
     r_ = tdvp2.r[0]
     r__sqrt = tdvp2.r_sqrt[0]
     r__sqrt_i = tdvp2.r_sqrt_i[0]
     A = tdvp.A[0]
     A_ = tdvp2.A[0]
         
     #Note: V has ~ D**2 * q**2 elements. We avoid making any copies of it except this one.
     #      This one is only needed because low-level routines force V_[s] to be contiguous.
     #      TODO: Store V instead of Vsh in tdvp_uniform too...
     V_ = sp.transpose(tdvp2.Vsh[0], axes=(0, 2, 1)).conj().copy(order='C')
             
     if self.ham_sites == 2:
         #eyeham = m.eyemat(self.q, dtype=sp.complex128)
         eyeham = sp.eye(self.q, dtype=sp.complex128)
         #diham = m.simple_diag_matrix(sp.repeat([-tdvp.h_expect.real], self.q))
         diham = -tdvp.h_expect.real * sp.eye(self.q, dtype=sp.complex128)
         _ham_tp = self.ham_tp + [[diham, eyeham]]  #subtract norm dof
         
         Ao1 = get_Aop(A, _ham_tp, 2, conj=False)
         
         AhlAo1 = [tm.eps_l_op_1s(l, A, A, o1.conj().T) for o1, o2 in _ham_tp]
         
         A_o2c = get_Aop(A_, _ham_tp, 1, conj=True)
         
         Ao1c = get_Aop(A, _ham_tp, 0, conj=True)
         
         A_Vr_ho2 = [tm.eps_r_op_1s(r__sqrt, A_, V_, o2) for o1, o2 in _ham_tp]
         
         A_A_o12c = get_A_ops(A_, A_, _ham_tp, conj=True)
         
         A_o1 = get_Aop(A_, _ham_tp, 2, conj=False)
         tmp = sp.empty((A_.shape[1], V_.shape[1]), dtype=A.dtype, order='C')
         tmp2 = sp.empty((A_.shape[1], A_o2c[0].shape[1]), dtype=A.dtype, order='C')
         rhs10 = 0
         for al in xrange(len(A_o1)):
             tmp2 = tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2)
             tmp3 = m.mmul(tmp2, r__sqrt_i)
             rhs10 += tm.eps_r_noop_inplace(tmp3, A_o1[al], V_, tmp)
             
         return V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp
         
     elif self.ham_sites == 3:
         return
예제 #4
0
def _excite_correlation_1s_1s(AL, AR, B, lL, rR, op1, op2, d, g):
    pseudo = AL is AR
    
    BBL = pinv_1mE(tm.eps_l_noop(lL, B, B), [AR], [AR], lL, rR, p=0, 
                   left=True, pseudo=True)
                   
    B1L = pinv_1mE(tm.eps_l_noop(lL, B, AL), [AR], [AL], lL, rR, p=0, 
                   left=True, pseudo=pseudo)
                   
    B2L = pinv_1mE(tm.eps_l_noop(lL, AL, B), [AL], [AR], lL, rR, p=0, 
                   left=True, pseudo=pseudo)
    
    B1B2L = pinv_1mE(tm.eps_l_noop(B1L, AR, B), [AR], [AR], lL, rR, p=0, 
                     left=True, pseudo=True)
                     
    B2B1L = pinv_1mE(tm.eps_l_noop(B2L, B, AR), [AR], [AR], lL, rR, p=0, 
                     left=True, pseudo=True)
    
    BBR = pinv_1mE(tm.eps_r_noop(rR, B, B), [AL], [AL], lL, rR, p=0, 
                   left=False, pseudo=True)
                   
    print "gauge fixing:", la.norm(tm.eps_r_noop(rR, B, AR))
                   
    res = [0.] * (d + 1)
    
    #B's on the left terms (0, 1, 2, 5)
    res[0] += m.adot(tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1.dot(op2) - g[0] * sp.eye(len(op1))), rR)
    res[0] += m.adot(tm.eps_l_op_1s(B1L, AR, B, op1.dot(op2)), rR)
    res[0] += m.adot(tm.eps_l_op_1s(B2L, B, AR, op1.dot(op2)), rR)
    res[0] += m.adot(tm.eps_l_op_1s(lL, B, B, op1.dot(op2) - g[0] * sp.eye(len(op1))), rR)
    
    l1 = tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1)
    l1 += tm.eps_l_op_1s(B1L, AR, B, op1)
    l1 += tm.eps_l_op_1s(B2L, B, AR, op1)
    l1 += tm.eps_l_op_1s(lL, B, B, op1)
    for n in xrange(1, d + 1):
        res[n] += m.adot(l1, tm.eps_r_op_1s(rR, AR, AR, op2))
        res[n] -= 2 * g[n]
        if n == d:
            break
        l1 = tm.eps_l_noop(l1, AR, AR)
        
    print 1, res
    
    #Terms 3, 4, 6, 7, a
    ls = [None] * (d + 1)
    ls[0] = tm.eps_l_op_1s(B1L, AR, AL, op1) + tm.eps_l_op_1s(lL, B, AL, op1)
    for k in xrange(1, d + 1):
        ls[k] = tm.eps_l_noop(ls[k - 1], AR, AL)
        
    rs = [None] * (d + 1)
    rs[d - 1] = tm.eps_r_op_1s(rR, AR, AR, op2)
    for k in xrange(d - 1, 0, -1):
        rs[k - 1] = tm.eps_r_noop(rs[k], AR, AR)
        
    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], AR, B))
        
        res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, AR, B, op2))
        
    print 2, res
        
    #Terms 3, 4, 6, 7, b
    ls = [None] * (d + 1)
    ls[0] = tm.eps_l_op_1s(B2L, AL, AR, op1) + tm.eps_l_op_1s(lL, AL, B, op1)
    for k in xrange(1, d + 1):
        ls[k] = tm.eps_l_noop(ls[k - 1], AL, AR)
        
    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, AR))
        
        res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, B, AR, op2))
        
    print 3, res
    
    #Term 8
    ls = [None] * (d + 1)
    ls[0] = tm.eps_l_op_1s(lL, AL, AL, op1)
    for k in xrange(1, d + 1):
        ls[k] = tm.eps_l_noop(ls[k - 1], AL, AL)
        
    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, B))
            res[n] -= g[n]
            
    print 4, res
            
    #Terms 9 and 10
    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            lj = tm.eps_l_noop(ls[k - 1], AL, B)
            for j in xrange(k + 1, n):
                res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], B, AR))
                lj = tm.eps_l_noop(lj, AL, AR)
            res[n] += m.adot(lj, tm.eps_r_op_1s(rR, B, AR, op2))

            lj = tm.eps_l_noop(ls[k - 1], B, AL)
            for j in xrange(k + 1, n):
                res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], AR, B))
                lj = tm.eps_l_noop(lj, AL, AR)
            res[n] += m.adot(lj, tm.eps_r_op_1s(rR, AR, B, op2))
            
    print 5, res
    
    #Term 11
    res[0] += m.adot(tm.eps_l_op_1s(lL, AL, AL, op1.dot(op2) - g[0] * sp.eye(len(op1))), BBR)
    for n in xrange(1, d + 1):
        res[n] += m.adot(tm.eps_l_op_1s(ls[n - 1], AL, AL, op2), BBR)
        res[n] -= g[n]
    
    return res
예제 #5
0
def _excite_correlation_1s_1s(AL, AR, B, lL, rR, op1, op2, d, g):
    pseudo = AL is AR

    BBL = pinv_1mE(tm.eps_l_noop(lL, B, B), [AR], [AR],
                   lL,
                   rR,
                   p=0,
                   left=True,
                   pseudo=True)

    B1L = pinv_1mE(tm.eps_l_noop(lL, B, AL), [AR], [AL],
                   lL,
                   rR,
                   p=0,
                   left=True,
                   pseudo=pseudo)

    B2L = pinv_1mE(tm.eps_l_noop(lL, AL, B), [AL], [AR],
                   lL,
                   rR,
                   p=0,
                   left=True,
                   pseudo=pseudo)

    B1B2L = pinv_1mE(tm.eps_l_noop(B1L, AR, B), [AR], [AR],
                     lL,
                     rR,
                     p=0,
                     left=True,
                     pseudo=True)

    B2B1L = pinv_1mE(tm.eps_l_noop(B2L, B, AR), [AR], [AR],
                     lL,
                     rR,
                     p=0,
                     left=True,
                     pseudo=True)

    BBR = pinv_1mE(tm.eps_r_noop(rR, B, B), [AL], [AL],
                   lL,
                   rR,
                   p=0,
                   left=False,
                   pseudo=True)

    print "gauge fixing:", la.norm(tm.eps_r_noop(rR, B, AR))

    res = [0.] * (d + 1)

    #B's on the left terms (0, 1, 2, 5)
    res[0] += m.adot(
        tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR,
                       op1.dot(op2) - g[0] * sp.eye(len(op1))), rR)
    res[0] += m.adot(tm.eps_l_op_1s(B1L, AR, B, op1.dot(op2)), rR)
    res[0] += m.adot(tm.eps_l_op_1s(B2L, B, AR, op1.dot(op2)), rR)
    res[0] += m.adot(
        tm.eps_l_op_1s(lL, B, B,
                       op1.dot(op2) - g[0] * sp.eye(len(op1))), rR)

    l1 = tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1)
    l1 += tm.eps_l_op_1s(B1L, AR, B, op1)
    l1 += tm.eps_l_op_1s(B2L, B, AR, op1)
    l1 += tm.eps_l_op_1s(lL, B, B, op1)
    for n in xrange(1, d + 1):
        res[n] += m.adot(l1, tm.eps_r_op_1s(rR, AR, AR, op2))
        res[n] -= 2 * g[n]
        if n == d:
            break
        l1 = tm.eps_l_noop(l1, AR, AR)

    print 1, res

    #Terms 3, 4, 6, 7, a
    ls = [None] * (d + 1)
    ls[0] = tm.eps_l_op_1s(B1L, AR, AL, op1) + tm.eps_l_op_1s(lL, B, AL, op1)
    for k in xrange(1, d + 1):
        ls[k] = tm.eps_l_noop(ls[k - 1], AR, AL)

    rs = [None] * (d + 1)
    rs[d - 1] = tm.eps_r_op_1s(rR, AR, AR, op2)
    for k in xrange(d - 1, 0, -1):
        rs[k - 1] = tm.eps_r_noop(rs[k], AR, AR)

    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], AR, B))

        res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, AR, B, op2))

    print 2, res

    #Terms 3, 4, 6, 7, b
    ls = [None] * (d + 1)
    ls[0] = tm.eps_l_op_1s(B2L, AL, AR, op1) + tm.eps_l_op_1s(lL, AL, B, op1)
    for k in xrange(1, d + 1):
        ls[k] = tm.eps_l_noop(ls[k - 1], AL, AR)

    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, AR))

        res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, B, AR, op2))

    print 3, res

    #Term 8
    ls = [None] * (d + 1)
    ls[0] = tm.eps_l_op_1s(lL, AL, AL, op1)
    for k in xrange(1, d + 1):
        ls[k] = tm.eps_l_noop(ls[k - 1], AL, AL)

    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, B))
            res[n] -= g[n]

    print 4, res

    #Terms 9 and 10
    for n in xrange(2, d + 1):
        for k in xrange(2, n):
            lj = tm.eps_l_noop(ls[k - 1], AL, B)
            for j in xrange(k + 1, n):
                res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], B, AR))
                lj = tm.eps_l_noop(lj, AL, AR)
            res[n] += m.adot(lj, tm.eps_r_op_1s(rR, B, AR, op2))

            lj = tm.eps_l_noop(ls[k - 1], B, AL)
            for j in xrange(k + 1, n):
                res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], AR, B))
                lj = tm.eps_l_noop(lj, AL, AR)
            res[n] += m.adot(lj, tm.eps_r_op_1s(rR, AR, B, op2))

    print 5, res

    #Term 11
    res[0] += m.adot(
        tm.eps_l_op_1s(lL, AL, AL,
                       op1.dot(op2) - g[0] * sp.eye(len(op1))), BBR)
    for n in xrange(1, d + 1):
        res[n] += m.adot(tm.eps_l_op_1s(ls[n - 1], AL, AL, op2), BBR)
        res[n] -= g[n]

    return res
예제 #6
0
    def calc_BHB_prereq(self, tdvp, tdvp2):
        """Calculates prerequisites for the application of the effective Hamiltonian in terms of tangent vectors.
        
        This is called (indirectly) by the self.excite.. functions.
        
        Parameters
        ----------
        tdvp2: EvoMPS_TDVP_Uniform
            Second state (may be the same, or another ground state).
            
        Returns
        -------
        A lot of stuff.
        """
        l = tdvp.l[0]
        r_ = tdvp2.r[0]
        r__sqrt = tdvp2.r_sqrt[0]
        r__sqrt_i = tdvp2.r_sqrt_i[0]
        A = tdvp.A[0]
        A_ = tdvp2.A[0]

        #Note: V has ~ D**2 * q**2 elements. We avoid making any copies of it except this one.
        #      This one is only needed because low-level routines force V_[s] to be contiguous.
        #      TODO: Store V instead of Vsh in tdvp_uniform too...
        V_ = sp.transpose(tdvp2.Vsh[0], axes=(0, 2, 1)).conj().copy(order='C')

        if self.ham_sites == 2:
            #eyeham = m.eyemat(self.q, dtype=sp.complex128)
            eyeham = sp.eye(self.q, dtype=sp.complex128)
            #diham = m.simple_diag_matrix(sp.repeat([-tdvp.h_expect.real], self.q))
            diham = -tdvp.h_expect.real * sp.eye(self.q, dtype=sp.complex128)
            _ham_tp = self.ham_tp + [[diham, eyeham]]  #subtract norm dof

            Ao1 = get_Aop(A, _ham_tp, 2, conj=False)

            AhlAo1 = [
                tm.eps_l_op_1s(l, A, A,
                               o1.conj().T) for o1, o2 in _ham_tp
            ]

            A_o2c = get_Aop(A_, _ham_tp, 1, conj=True)

            Ao1c = get_Aop(A, _ham_tp, 0, conj=True)

            A_Vr_ho2 = [
                tm.eps_r_op_1s(r__sqrt, A_, V_, o2) for o1, o2 in _ham_tp
            ]

            A_A_o12c = get_A_ops(A_, A_, _ham_tp, conj=True)

            A_o1 = get_Aop(A_, _ham_tp, 2, conj=False)
            tmp = sp.empty((A_.shape[1], V_.shape[1]),
                           dtype=A.dtype,
                           order='C')
            tmp2 = sp.empty((A_.shape[1], A_o2c[0].shape[1]),
                            dtype=A.dtype,
                            order='C')
            rhs10 = 0
            for al in xrange(len(A_o1)):
                tmp2 = tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2)
                tmp3 = m.mmul(tmp2, r__sqrt_i)
                rhs10 += tm.eps_r_noop_inplace(tmp3, A_o1[al], V_, tmp)

            return V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp

        elif self.ham_sites == 3:
            return