Exemple #1
0
    def restore_CF_dbg(self):
        for n in xrange(self.N + 2):
            print (n, self.l[n].trace().real, self.r[n].trace().real,
                   mm.adot(self.l[n], self.r[n]).real)

        norm_r = mm.adot(self.uni_r.l[-1], self.r[self.N])
        norm_l = mm.adot(self.l[0], self.uni_l.r[-1])
        print "norm of uni_r: ", norm_r
        print "norm of uni_l: ", norm_l

        #r_m1 = self.eps_r(0, self.r[0])
        #print mm.adot(self.l[0], r_m1).real

        norm = mm.adot(self.l[0], self.r[0]).real
        
        try:
            h = sp.empty((self.N + 1), dtype=self.typ)
            for n in xrange(self.N + 1):
                h[n] = self.expect_2s(self.h_nn[n], n)
            h *= 1/norm
    
            #self.uni_l.A = self.A[0] #FIXME: Not sure how to handle this yet...
            self.uni_l.l[-1] = self.l[0]
            self.uni_l.calc_AA()
            h_left = self.uni_l.expect_2s(self.uni_l.ham.copy()) / norm_l
    
            #self.uni_r.A = self.A[self.N + 1]
            self.uni_r.r[-1] = self.r[self.N]
            self.uni_r.calc_AA()
            h_right = self.uni_r.expect_2s(self.uni_r.ham.copy()) / norm_r
    
            return h, h_left, h_right
        except AttributeError:
            return sp.array([0]), 0, 0
    def restore_CF_dbg(self):
        for n in xrange(self.N + 2):
            print (n, self.l[n].trace().real, self.r[n].trace().real,
                   mm.adot(self.l[n], self.r[n]).real)

        norm_r = mm.adot(self.uni_r.l, self.r[self.N])
        norm_l = mm.adot(self.l[0], self.uni_l.r)
        print "norm of uni_r: ", norm_r
        print "norm of uni_l: ", norm_l

        #r_m1 = self.eps_r(0, self.r[0])
        #print mm.adot(self.l[0], r_m1).real

        norm = mm.adot(self.l[0], self.r[0]).real

        h = sp.empty((self.N + 1), dtype=self.typ)
        for n in xrange(self.N + 1):
            h[n] = self.expect_2s(self.h_nn[n], n)
        h *= 1/norm

        self.uni_l.A = self.A[0]
        self.uni_l.l = self.l[0]
        self.uni_l.calc_AA()
        h_left = self.uni_l.expect_2s(self.uni_l.ham.copy()) / norm_l

        self.uni_r.A = self.A[self.N + 1]
        self.uni_r.r = self.r[self.N]
        self.uni_r.calc_AA()
        h_right = self.uni_l.expect_2s(self.uni_r.ham.copy()) / norm_r

        return h, h_left, h_right
Exemple #3
0
    def restore_CF_dbg(self):
        for n in xrange(self.N + 2):
            print(n, self.l[n].trace().real, self.r[n].trace().real,
                  mm.adot(self.l[n], self.r[n]).real)

        norm_r = mm.adot(self.uni_r.l[-1], self.r[self.N])
        norm_l = mm.adot(self.l[0], self.uni_l.r[-1])
        print "norm of uni_r: ", norm_r
        print "norm of uni_l: ", norm_l

        #r_m1 = self.eps_r(0, self.r[0])
        #print mm.adot(self.l[0], r_m1).real

        norm = mm.adot(self.l[0], self.r[0]).real

        try:
            h = sp.empty((self.N + 1), dtype=self.typ)
            for n in xrange(self.N + 1):
                h[n] = self.expect_2s(self.h_nn[n], n)
            h *= 1 / norm

            #self.uni_l.A = self.A[0] #FIXME: Not sure how to handle this yet...
            self.uni_l.l[-1] = self.l[0]
            self.uni_l.calc_AA()
            h_left = self.uni_l.expect_2s(self.uni_l.ham.copy()) / norm_l

            #self.uni_r.A = self.A[self.N + 1]
            self.uni_r.r[-1] = self.r[self.N]
            self.uni_r.calc_AA()
            h_right = self.uni_r.expect_2s(self.uni_r.ham.copy()) / norm_r

            return h, h_left, h_right
        except AttributeError:
            return sp.array([0]), 0, 0
Exemple #4
0
 def calc_B1(self):
     """Calculate the optimal B1 given right gauge-fixing on B2..N and
     no gauge-fixing on B1.
     
     We use the non-norm-preserving K's, since the norm-preservation
     is not needed elsewhere. It is cleaner to subtract the relevant
     norm-changing terms from the K's here than to generate all K's
     with norm-preservation.
     """
     B1 = sp.empty_like(self.A[1])
     
     try:
         r1_i = self.r[1].inv()
     except AttributeError:
         r1_i = mm.invmh(self.r[1])
         
     try:
         l0_i = self.l[0].inv()
     except AttributeError:
         l0_i = mm.invmh(self.l[0])
     
     A0 = self.A[0]
     A1 = self.A[1]
     A2 = self.A[2]
     r1 = self.r[1]
     r2 = self.r[2]
     l0 = self.l[0]
     
     KLh = mm.H(self.u_gnd_l.K_left - l0 * mm.adot(self.u_gnd_l.K_left, self.r[0]))
     K2 = self.K[2] - r1 * mm.adot(self.l[1], self.K[2])
     
     C1 = self.C[1] - self.h_expect[1] * self.AA1
     C0 = self.C[0] - self.h_expect[0] * self.AA0
     
     for s in xrange(self.q[1]):
         try:
             B1[s] = A1[s].dot(r1_i.dot_left(K2))
         except AttributeError:
             B1[s] = A1[s].dot(K2.dot(r1_i))
         
         for t in xrange(self.q[2]):
             try:
                 B1[s] += C1[s, t].dot(r2.dot(r1_i.dot_left(mm.H(A2[t]))))
             except AttributeError:
                 B1[s] += C1[s, t].dot(r2.dot(mm.H(A2[t]).dot(r1_i)))                    
             
         B1sbit = KLh.dot(A1[s])
                         
         for t in xrange(self.q[0]):
             B1sbit += mm.H(A0[t]).dot(l0.dot(C0[t,s]))
             
         B1[s] += l0_i.dot(B1sbit)
        
     rb = sp.zeros_like(self.r[0])
     for s in xrange(self.q[1]):
         rb += B1[s].dot(r1.dot(mm.H(B1[s])))
     eta = sp.sqrt(mm.adot(l0, rb))
             
     return B1, eta
Exemple #5
0
    def calc_K(self):
        """Generates the right K matrices used to calculate the B's

        K[n] is recursively defined. It depends on C[m] and A[m] for all m >= n.

        It directly depends on A[n], A[n + 1], r[n], r[n + 1], C[n] and K[n + 1].

        This is equivalent to K on p. 14 of arXiv:1103.0936v2 [cond-mat.str-el], except
        that it is for the non-norm-preserving case.

        K[1] is, assuming a normalized state, the expectation value H of Ĥ.
        
        Return the excess energy.
        """
        n_low = 0
        n_high = self.N + 1
            
        H = mm.H
        
        self.h_expect = sp.zeros((self.N + 1), dtype=self.typ)
        
        self.u_gnd_r.calc_AA()
        self.u_gnd_r.calc_C()
        self.u_gnd_r.calc_K()
        self.K[self.N + 1][:] = self.u_gnd_r.K

        for n in reversed(xrange(n_low, n_high)):
            self.K[n].fill(0)
            
            K = self.K[n]
            Kp1 = self.K[n + 1]
            C = self.C[n]
            rp1 = self.r[n + 1]
            A = self.A[n]
            Ap1 = self.A[n + 1]
            
            Hr = sp.zeros_like(K)

            for s in xrange(self.q[n]):
                Ash = H(A[s])
                for t in xrange(self.q[n+1]):
                    Hr += C[s, t].dot(rp1.dot(H(Ap1[t]).dot(Ash)))

                K += A[s].dot(Kp1.dot(Ash))
                
            self.h_expect[n] = mm.adot(self.get_l(n), Hr)
                
            K += Hr
            
        self.u_gnd_l.calc_AA()
        self.u_gnd_l.calc_C()
        K_left, h_left_uni = self.u_gnd_l.calc_K_l()

        h = (mm.adot(K_left, self.r[0]) + mm.adot(self.l[0], self.K[0]) 
             - (self.N + 1) * self.u_gnd_r.h)
             
        return h
Exemple #6
0
 def density_2s(self, d):
     """Returns a reduced density matrix for a pair of (seperated) sites.
     
     The site number basis is used: rho[s * q + u, t * q + v]
     with 0 <= s, t < q and 0 <= u, v < q.
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     d : int
         The distance between the first and the second sites considered (d = n2 - n1).
         
     Returns
     -------
     rho : ndarray
         Reduced density matrix in the number basis.
     """
     rho = sp.empty((self.q * self.q, self.q * self.q), dtype=sp.complex128)
     
     for s2 in xrange(self.q):
         for t2 in xrange(self.q):
             r_n2 = m.mmul(self.A[t2], self.r, m.H(self.A[s2]))
             
             r_n = r_n2
             for n in xrange(d - 1):
                 r_n = tm.eps_r_noop(r_n, self.A, self.A)
                 
             for s1 in xrange(self.q):
                 for t1 in xrange(self.q):
                     r_n1 = m.mmul(self.A[t1], r_n, m.H(self.A[s1]))
                     tmp = m.adot(self.l, r_n1)
                     rho[s1 * self.q + s2, t1 * self.q + t2] = tmp
     return rho        
Exemple #7
0
 def expect_2s(self, op):
     """Computes the expectation value of a nearest-neighbour two-site operator.
     
     The operator should be a q x q x q x q array 
     such that op[s, t, u, v] = <st|op|uv> or a function of the form 
     op(s, t, u, v) = <st|op|uv>.
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     op : ndarray or callable
         The operator array or function.
         
     Returns
     -------
     expval : floating point number
         The expectation value (data type may be complex)
     """
     if callable(op):
         op = np.vectorize(op, otypes=[np.complex128])
         op = np.fromfunction(op, (self.q, self.q, self.q, self.q))        
     
     C = tm.calc_C_mat_op_AA(op, self.AA)
     res = tm.eps_r_op_2s_C12_AA34(self.r, C, self.AA)
     
     return m.adot(self.l, res)
Exemple #8
0
    def calc_K(self):
        """Generates the right K matrices used to calculate the B's
        
        K[n] contains 'column-vectors' such that <l[n]|K[n]> = trace(l[n].dot(K[n])).
        K_l[n] contains 'bra-vectors' such that <K_l[n]|r[n]> = trace(K_l[n].dot(r[n])).
        """
   
        self.h_expect = sp.zeros((self.N + 1), dtype=self.typ)
        
        self.uni_r.calc_AA()
        self.uni_r.calc_C()
        self.uni_r.calc_K()
        self.K[self.N + 1][:] = self.uni_r.K[0]

        self.uni_l.calc_AA()
        self.uni_l.calc_C()
        K_left, h_left_uni = self.uni_l.calc_K_l()
        
        self.K_l[0][:] = K_left[-1]

        for n in xrange(self.N, self.N_centre - 1, -1):
            self.K[n], he = tm.calc_K(self.K[n + 1], self.C[n], self.get_l(n - 1),
                                      self.r[n + 1], self.A[n], self.get_AA(n))
                
            self.h_expect[n] = he

        for n in xrange(1, self.N_centre + 1):
            self.K_l[n], he = tm.calc_K_l(self.K_l[n - 1], self.C[n - 1], self.get_l(n - 2),
                                          self.r[n], self.A[n], self.get_AA(n - 1))
                
            self.h_expect[n - 1] = he

        self.dH_expect = (mm.adot_noconj(self.K_l[self.N_centre], self.r[self.N_centre]) 
                          + mm.adot(self.l[self.N_centre - 1], self.K[self.N_centre]) 
                          - (self.N + 1) * self.uni_r.h_expect)
Exemple #9
0
    def expect_2s(self, op, n):
        """Computes the expectation value of a nearest-neighbour two-site operator.

        The operator should be a q[n] x q[n + 1] x q[n] x q[n + 1] array
        such that op[s, t, u, v] = <st|op|uv> or a function of the form
        op(s, t, u, v) = <st|op|uv>.

        Parameters
        ----------
        o : ndarray or callable
            The operator array or function.
        n : int
            The leftmost site number (operator acts on n, n + 1).
        """
        A = self.get_A(n)
        Ap1 = self.get_A(n + 1)
        AA = tm.calc_AA(A, Ap1)

        if callable(op):
            op = sp.vectorize(op, otypes=[sp.complex128])
            op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0]))

        C = tm.calc_C_mat_op_AA(op, AA)
        res = tm.eps_r_op_2s_C12_AA34(self.get_r(n + 1), C, AA)
        return mm.adot(self.get_l(n - 1), res)
Exemple #10
0
 def expect_2s(self, op, n, AA=None):
     """Computes the expectation value of a nearest-neighbour two-site operator.
     
     The operator should be a q[n] x q[n + 1] x q[n] x q[n + 1] array 
     such that op[s, t, u, v] = <st|op|uv> or a function of the form 
     op(s, t, u, v) = <st|op|uv>.
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     op : ndarray or callable
         The operator array or function.
     n : int
         The leftmost site number (operator acts on n, n + 1).
         
     Returns
     -------
     expval : floating point number
         The expectation value (data type may be complex)
     """
     A = self.A[n]
     Ap1 = self.A[n + 1]
     if AA is None:
         AA = tm.calc_AA(A, Ap1)
     
     if callable(op):
         op = sp.vectorize(op, otypes=[sp.complex128])
         op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0]))
         
     C = tm.calc_C_mat_op_AA(op, AA)
     res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], C, AA)
     return m.adot(self.l[n - 1], res)
Exemple #11
0
def _excite_expect_2s_tp_sep(AL, AR, B, lL, rR, op, d, n1, n2):
    ls = [None] * (d + 1)
    ls[0] = lL
    rs = [None] * (d + 1)
    rs[-1] = rR

    As1 = [None] + [AL] * (n1 - 1) + [B] + [AR] * (d - n1 + 1)
    As2 = [None] + [AL] * (n2 - 1) + [B] + [AR] * (d - n2 + 1)

    for n in xrange(1, d):
        ls[n] = tm.eps_l_noop(ls[n - 1], As1[n], As2[n])

    for n in xrange(d, 0, -1):
        rs[n - 1] = tm.eps_r_noop(rs[n], As1[n], As2[n])

    Cs1 = [None] * (d + 1)
    for n in xrange(1, d):
        Cs1[n] = tm.calc_C_tp(op, As1[n], As1[n + 1])

    res = [
        m.adot(ls[n - 1],
               tm.eps_r_op_2s_C12_tp(rs[n + 1], Cs1[n], As2[n], As2[n + 1]))
        for n in xrange(1, d)
    ]

    return sp.array(res)
Exemple #12
0
 def expect_1s(self, op):
     """Computes the expectation value of a single-site operator.
     
     The operator should be a self.q x self.q matrix or generating function 
     such that op[s, t] or op(s, t) equals <s|op|t>.
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     op : ndarray or callable
         The operator.
         
     Returns
     -------
     expval : floating point number
         The expectation value (data type may be complex)
     """        
     if callable(op):
         op = np.vectorize(op, otypes=[np.complex128])
         op = np.fromfunction(op, (self.q, self.q))
         
     Or = tm.eps_r_op_1s(self.r, self.A, self.A, op)
     
     return m.adot(self.l, Or)
Exemple #13
0
    def expect_3s(self, op, n):
        """Computes the expectation value of a nearest-neighbour three-site operator.

        The operator should be a q[n] x q[n + 1] x q[n + 2] x q[n] x
        q[n + 1] x q[n + 2] array such that op[s, t, u, v, w, x] =
        <stu|op|vwx> or a function of the form op(s, t, u, v, w, x) =
        <stu|op|vwx>.

        The state must be up-to-date -- see self.update()!

        Parameters
        ----------
        op : ndarray or callable
            The operator array or function.
        n : int
            The leftmost site number (operator acts on n, n + 1, n + 2).

        Returns
        -------
        expval : floating point number
            The expectation value (data type may be complex)
        """
        A = self.A[n]
        Ap1 = self.A[n + 1]
        Ap2 = self.A[n + 2]
        AAA = tm.calc_AAA(A, Ap1, Ap2)

        if callable(op):
            op = sp.vectorize(op, otypes=[sp.complex128])
            op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], Ap2.shape[0],
                                      A.shape[0], Ap1.shape[0], Ap2.shape[0]))

        C = tm.calc_C_3s_mat_op_AAA(op, AAA)
        res = tm.eps_r_op_3s_C123_AAA456(self.r[n + 2], C, AAA)
        return m.adot(self.l[n - 1], res)
Exemple #14
0
def calc_BB_Y_2s_ham_3s(A_m1, A_p2, C, C_m1, Vlh, Vrh_p1, l_m2, r_p2, l_s_m1,
                        l_si_m1, r_s_p1, r_si_p1):
    Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj()

    Vrri_p1 = sp.zeros_like(Vr_p1)
    try:
        for s in xrange(Vrri_p1.shape[0]):
            Vrri_p1[s] = r_si_p1.dot_left(Vr_p1[s])
    except AttributeError:
        for s in xrange(Vrri_p1.shape[0]):
            Vrri_p1[s] = Vr_p1[s].dot(r_si_p1)

    Vl = sp.transpose(Vlh, axes=(0, 2, 1)).conj()
    liVl = sp.zeros_like(Vl)
    for s in xrange(liVl.shape[0]):
        liVl[s] = l_si_m1.dot(Vl[s])

    Y = sp.zeros((Vlh.shape[1], Vrh_p1.shape[2]), dtype=Vrh_p1.dtype)
    if not A_p2 is None:
        for s in xrange(C.shape[0]):
            Y += Vlh[s].dot(
                l_s_m1.dot(eps_r_op_2s_C12(r_p2, C[s], Vrri_p1, A_p2)))
    if not A_m1 is None:
        for u in xrange(C_m1.shape[2]):
            Y += eps_l_op_2s_A1_A2_C34(l_m2, A_m1, liVl,
                                       C_m1[:, :,
                                            u]).dot(r_s_p1.dot(Vrh_p1[u]))

    etaBB_sq = mm.adot(Y, Y)

    return Y, etaBB_sq
Exemple #15
0
    def density_2s(self, n1, n2):
        """Returns a reduced density matrix for a pair of sites.
        
        Currently only supports sites in the nonuniform window.

        Parameters
        ----------
        n1 : int
            The site number of the first site.
        n2 : int
            The site number of the second site (must be > n1).
        """
        rho = sp.empty((self.q[n1] * self.q[n2], self.q[n1] * self.q[n2]),
                       dtype=sp.complex128)
        r_n2 = sp.empty_like(self.r[n2 - 1])
        r_n1 = sp.empty_like(self.r[n1 - 1])
        ln1m1 = self.get_l(n1 - 1)

        for s2 in xrange(self.q[n2]):
            for t2 in xrange(self.q[n2]):
                r_n2 = mm.mmul(self.A[n2][t2], self.r[n2],
                               mm.H(self.A[n2][s2]))

                r_n = r_n2
                for n in reversed(xrange(n1 + 1, n2)):
                    r_n = tm.eps_r_noop(r_n, self.A[n], self.A[n])

                for s1 in xrange(self.q[n1]):
                    for t1 in xrange(self.q[n1]):
                        r_n1 = mm.mmul(self.A[n1][t1], r_n,
                                       mm.H(self.A[n1][s1]))
                        tmp = mm.adot(ln1m1, r_n1)
                        rho[s1 * self.q[n1] + s2, t1 * self.q[n1] + t2] = tmp
        return rho
Exemple #16
0
 def expect_2s(self, op, n, AA=None):
     """Computes the expectation value of a nearest-neighbour two-site operator.
     
     The operator should be a q[n] x q[n + 1] x q[n] x q[n + 1] array 
     such that op[s, t, u, v] = <st|op|uv> or a function of the form 
     op(s, t, u, v) = <st|op|uv>.
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     op : ndarray or callable
         The operator array or function.
     n : int
         The leftmost site number (operator acts on n, n + 1).
         
     Returns
     -------
     expval : floating point number
         The expectation value (data type may be complex)
     """
     A = self.A[n]
     Ap1 = self.A[n + 1]
     if AA is None:
         AA = tm.calc_AA(A, Ap1)
     
     if callable(op):
         op = sp.vectorize(op, otypes=[sp.complex128])
         op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0]))
         
     C = tm.calc_C_mat_op_AA(op, AA)
     res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], C, AA)
     return m.adot(self.l[n - 1], res)
Exemple #17
0
def calc_BB_Y_2s_ham_3s(A_m1, A_p2, C, C_m1, Vlh, Vrh_p1, l_m2, r_p2, l_s_m1, l_si_m1, r_s_p1, r_si_p1):
    Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj()
    
    Vrri_p1 = sp.zeros_like(Vr_p1)
    try:
        for s in xrange(Vrri_p1.shape[0]):
            Vrri_p1[s] = r_si_p1.dot_left(Vr_p1[s])
    except AttributeError:
        for s in xrange(Vrri_p1.shape[0]):
            Vrri_p1[s] = Vr_p1[s].dot(r_si_p1)
    
    Vl = sp.transpose(Vlh, axes=(0, 2, 1)).conj()        
    liVl = sp.zeros_like(Vl)            
    for s in xrange(liVl.shape[0]):
        liVl[s] = l_si_m1.dot(Vl[s])

    Y = sp.zeros((Vlh.shape[1], Vrh_p1.shape[2]), dtype=Vrh_p1.dtype)
    if not A_p2 is None:
        for s in xrange(C.shape[0]):
            Y += Vlh[s].dot(l_s_m1.dot(eps_r_op_2s_C12(r_p2, C[s], Vrri_p1, A_p2)))
    if not A_m1 is None:
        for u in xrange(C_m1.shape[2]):
            Y += eps_l_op_2s_A1_A2_C34(l_m2, A_m1, liVl, C_m1[:, :, u]).dot(r_s_p1.dot(Vrh_p1[u]))

    etaBB_sq = mm.adot(Y, Y)
    
    return Y, etaBB_sq
Exemple #18
0
    def expect_3s(self, op, n):
        """Computes the expectation value of a nearest-neighbour three-site operator.

        The operator should be a q[n] x q[n + 1] x q[n + 2] x q[n] x
        q[n + 1] x q[n + 2] array such that op[s, t, u, v, w, x] =
        <stu|op|vwx> or a function of the form op(s, t, u, v, w, x) =
        <stu|op|vwx>.

        The state must be up-to-date -- see self.update()!

        Parameters
        ----------
        op : ndarray or callable
            The operator array or function.
        n : int
            The leftmost site number (operator acts on n, n + 1, n + 2).

        Returns
        -------
        expval : floating point number
            The expectation value (data type may be complex)
        """
        A = self.A[n]
        Ap1 = self.A[n + 1]
        Ap2 = self.A[n + 2]
        AAA = tm.calc_AAA(A, Ap1, Ap2)

        if callable(op):
            op = sp.vectorize(op, otypes=[sp.complex128])
            op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], Ap2.shape[0],
                                      A.shape[0], Ap1.shape[0], Ap2.shape[0]))

        C = tm.calc_C_3s_mat_op_AAA(op, AAA)
        res = tm.eps_r_op_3s_C123_AAA456(self.r[n + 2], C, AAA)
        return m.adot(self.l[n - 1], res)
Exemple #19
0
    def density_1s(self, n):
        """Returns a reduced density matrix for a single site.
        
        The site number basis is used: rho[s, t] 
        with 0 <= s, t < q[n].
        
        The state must be up-to-date -- see self.update()!
        
        Parameters
        ----------
        n1 : int
            The site number.
            
        Returns
        -------
        rho : ndarray
            Reduced density matrix in the number basis.
        """
        rho = sp.empty((self.q[n], self.q[n]), dtype=sp.complex128)

        r_n = self.r[n]
        r_nm1 = sp.empty_like(self.r[n - 1])
        for s in xrange(self.q[n]):
            for t in xrange(self.q[n]):
                r_nm1 = m.mmul(self.A[n][t], r_n, m.H(self.A[n][s]))
                rho[s, t] = m.adot(self.l[n - 1], r_nm1)
        return rho
Exemple #20
0
    def expect_2s(self, op, n):
        """Computes the expectation value of a nearest-neighbour two-site operator.

        The operator should be a q[n] x q[n + 1] x q[n] x q[n + 1] array
        such that op[s, t, u, v] = <st|op|uv> or a function of the form
        op(s, t, u, v) = <st|op|uv>.

        Parameters
        ----------
        o : ndarray or callable
            The operator array or function.
        n : int
            The leftmost site number (operator acts on n, n + 1).
        """
        A = self.get_A(n)
        Ap1 = self.get_A(n + 1)
        AA = tm.calc_AA(A, Ap1)

        if callable(op):
            op = sp.vectorize(op, otypes=[sp.complex128])
            op = sp.fromfunction(
                op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0]))

        C = tm.calc_C_mat_op_AA(op, AA)
        res = tm.eps_r_op_2s_C12_AA34(self.get_r(n + 1), C, AA)
        return mm.adot(self.get_l(n - 1), res)
Exemple #21
0
    def expect_1s(self, op, n):
        """Computes the expectation value of a single-site operator.
        
        The operator should be a q[n] x q[n] matrix or generating function 
        such that op[s, t] or op(s, t) equals <s|op|t>.
        
        The state must be up-to-date -- see self.update()!
        
        Parameters
        ----------
        op : ndarray or callable
            The operator.
        n : int
            The site number (1 <= n <= N).
            
        Returns
        -------
        expval : floating point number
            The expectation value (data type may be complex)
        """
        if callable(op):
            op = sp.vectorize(op, otypes=[sp.complex128])
            op = sp.fromfunction(op, (self.q[n], self.q[n]))

        res = tm.eps_r_op_1s(self.r[n], self.A[n], self.A[n], op)
        return m.adot(self.l[n - 1], res)
Exemple #22
0
 def density_1s(self, n):
     """Returns a reduced density matrix for a single site.
     
     The site number basis is used: rho[s, t] 
     with 0 <= s, t < q[n].
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     n1 : int
         The site number.
         
     Returns
     -------
     rho : ndarray
         Reduced density matrix in the number basis.
     """
     rho = sp.empty((self.q[n], self.q[n]), dtype=sp.complex128)
                 
     r_n = self.r[n]
     r_nm1 = sp.empty_like(self.r[n - 1])
     for s in xrange(self.q[n]):
         for t in xrange(self.q[n]):
             r_nm1 = m.mmul(self.A[n][t], r_n, m.H(self.A[n][s]))                
             rho[s, t] = m.adot(self.l[n - 1], r_nm1)
     return rho
Exemple #23
0
    def calc_B_1s_diss(self, op, n):
        """Applies a single-site operator to a single site and returns
        the parameter tensor for that site after the change with the
        change in the norm of the state projected out.
        
        Parameters
        ----------
        op : ndarray or callable
            The single-site operator. See self.expect_1s().
        n: int
            The site to apply the operator to.
        """
        if callable(op):
            op = sp.vectorize(op, otypes=[sp.complex128])
            op = sp.fromfunction(op, (self.q[n], self.q[n]))

        newAn = sp.zeros_like(self.A[n])

        for s in xrange(self.q[n]):
            for t in xrange(self.q[n]):
                newAn[s] += self.A[n][t] * op[s, t]

        r_nm1 = TDVP.tm.eps_r_noop(self.r[n], newAn, newAn)
        ev = mm.adot(self.l[n - 1], r_nm1)

        newAn -= ev * self.A[n]  #norm-fixing

        return newAn
Exemple #24
0
    def expect_3s(self, op, n, AAA=None):
        """Computes the expectation value of a nearest-neighbour three-site operator.

        The operator should be a q[n] x q[n + 1] x q[n + 2] x q[n] x
        q[n + 1] x q[n + 2] array such that op[s, t, u, v, w, x] =
        <stu|op|vwx> or a function of the form op(s, t, u, v, w, x) =
        <stu|op|vwx>.

        The state must be up-to-date -- see self.update()!

        Parameters
        ----------
        op : ndarray or callable
            The operator array or function.
        n : int
            The leftmost site number (operator acts on n, n + 1, n + 2).

        Returns
        -------
        expval : floating point number
            The expectation value (data type may be complex)
        """
        if AAA is None:
            if not self.AAA[n] is None:
                AAA = self.AAA[n]
            else:
                AAA = tm.calc_AAA_AA(self.AA[n], self.A[n + 2])
                
        if op is self.ham[n] and self.ham_sites == 3:
            res = tm.eps_r_op_3s_C123_AAA456(self.r[n + 2], self.C[n], AAA)
            return m.adot(self.l[n - 1], res)
        else:
            return super(EvoMPS_MPS_Generic).expect_3s(op, n, AAA=AAA)
Exemple #25
0
 def expect_1s(self, op, n):
     """Computes the expectation value of a single-site operator.
     
     The operator should be a q[n] x q[n] matrix or generating function 
     such that op[s, t] or op(s, t) equals <s|op|t>.
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     op : ndarray or callable
         The operator.
     n : int
         The site number (1 <= n <= N).
         
     Returns
     -------
     expval : floating point number
         The expectation value (data type may be complex)
     """        
     if callable(op):
         op = sp.vectorize(op, otypes=[sp.complex128])
         op = sp.fromfunction(op, (self.q[n], self.q[n]))
         
     res = tm.eps_r_op_1s(self.r[n], self.A[n], self.A[n], op)
     return  m.adot(self.l[n - 1], res)
Exemple #26
0
    def density_2s(self, n1, n2):
        """Returns a reduced density matrix for a pair of sites.
        
        Currently only supports sites in the nonuniform window.

        Parameters
        ----------
        n1 : int
            The site number of the first site.
        n2 : int
            The site number of the second site (must be > n1).
        """
        rho = sp.empty((self.q[n1] * self.q[n2], self.q[n1] * self.q[n2]), dtype=sp.complex128)
        r_n2 = sp.empty_like(self.r[n2 - 1])
        r_n1 = sp.empty_like(self.r[n1 - 1])
        ln1m1 = self.get_l(n1 - 1)

        for s2 in xrange(self.q[n2]):
            for t2 in xrange(self.q[n2]):
                r_n2 = mm.mmul(self.A[n2][t2], self.r[n2], mm.H(self.A[n2][s2]))

                r_n = r_n2
                for n in reversed(xrange(n1 + 1, n2)):
                    r_n = tm.eps_r_noop(r_n, self.A[n], self.A[n])

                for s1 in xrange(self.q[n1]):
                    for t1 in xrange(self.q[n1]):
                        r_n1 = mm.mmul(self.A[n1][t1], r_n, mm.H(self.A[n1][s1]))
                        tmp = mm.adot(ln1m1, r_n1)
                        rho[s1 * self.q[n1] + s2, t1 * self.q[n1] + t2] = tmp
        return rho
Exemple #27
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]
Exemple #28
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]
Exemple #29
0
 def matvec(self, v):
     x = v.reshape((self.D, self.D))
     
     if self.left:
         xE = self.tdvp._eps_l_noop_dense_A(x, self.out)
         QEQ = xE - m.H(self.l) * m.adot(self.r, x)
     else:
         Ex = self.tdvp._eps_r_noop_dense_A(x, self.out)
         QEQ = Ex - self.r * m.adot(self.l, x)        
     
     
     if not self.p == 0:
         QEQ *= np.exp(1.j * self.p)
     
     res = x - QEQ
     
     return res.ravel()
Exemple #30
0
def calc_BB_Y_2s(C, Vlh, Vrh_p1, l_s_m1, r_s_p1):
    Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj()

    Y = sp.zeros((Vlh.shape[1], Vrh_p1.shape[2]), dtype=C.dtype)
    for s in xrange(Vlh.shape[0]):
        Y += Vlh[s].dot(l_s_m1.dot(eps_r_noop(r_s_p1, C[s], Vr_p1)))

    etaBB_sq = mm.adot(Y, Y)

    return Y, etaBB_sq
Exemple #31
0
def calc_K_tp(Kp1, lm1, rp1, A, Ap1, C_tp):
    K = eps_r_noop(Kp1, A, A)
    
    Hr = eps_r_op_2s_C12_tp(rp1, C_tp, A, Ap1)

    op_expect = mm.adot(lm1, Hr)
        
    K += Hr
    
    return K, op_expect
Exemple #32
0
def calc_K_3s(Kp1, C, lm1, rp2, A, AAp1Ap2):
    K = eps_r_noop(Kp1, A, A)

    Hr = eps_r_op_3s_C123_AAA456(rp2, C, AAp1Ap2)

    op_expect = mm.adot(lm1, Hr)

    K += Hr

    return K, op_expect
    def matvec(self, v):
        x = v.reshape((self.D, self.D))

        if self.left:  #Multiplying from the left, but x is a col. vector, so use mat_dagger
            Ehx = tm.eps_l_noop_inplace(x, self.A1, self.A2, self.out)
            if self.pseudo:
                QEQhx = Ehx - self.l * m.adot(self.r, x)
                res = x - sp.exp(-1.j * self.p) * QEQhx
            else:
                res = x - sp.exp(-1.j * self.p) * Ehx
        else:
            Ex = tm.eps_r_noop_inplace(x, self.A1, self.A2, self.out)
            if self.pseudo:
                QEQx = Ex - self.r * m.adot(self.l, x)
                res = x - sp.exp(1.j * self.p) * QEQx
            else:
                res = x - sp.exp(1.j * self.p) * Ex

        return res.ravel()
Exemple #34
0
def calc_K(Kp1, C, lm1, rp1, A, AAp1):
    K = eps_r_noop(Kp1, A, A)

    Hr = eps_r_op_2s_C12_AA34(rp1, C, AAp1)

    op_expect = mm.adot(lm1, Hr)

    K += Hr

    return K, op_expect
Exemple #35
0
def calc_K_tp(Kp1, lm1, rp1, A, Ap1, C_tp):
    K = eps_r_noop(Kp1, A, A)

    Hr = eps_r_op_2s_C12_tp(rp1, C_tp, A, Ap1)

    op_expect = mm.adot(lm1, Hr)

    K += Hr

    return K, op_expect
Exemple #36
0
    def matvec(self, v):
        x = v.reshape((self.D, self.D))

        res = self.tmp
        out = self.out
        res[:] = x

        if self.left:  # Multiplying from the left, but x is a col. vector, so use mat_dagger
            for k in xrange(len(self.A1)):
                out = tm.eps_l_noop_inplace(res, self.A1[k], self.A2[k], out)
                tmp = res
                res = out
                out = tmp

            if self.pseudo:
                out[:] = self.lL
                out *= m.adot(self.rL, x)
                res -= out
                res *= -sp.exp(-1.0j * self.p)
                res += x
            else:
                res *= -sp.exp(-1.0j * self.p)
                res += x
        else:
            for k in xrange(len(self.A1) - 1, -1, -1):
                out = tm.eps_r_noop_inplace(res, self.A1[k], self.A2[k], out)
                tmp = res
                res = out
                out = tmp

            if self.pseudo:
                out[:] = self.rL
                out *= m.adot(self.lL, x)
                res -= out
                res *= -sp.exp(1.0j * self.p)
                res += x
            else:
                res *= -sp.exp(1.0j * self.p)
                res += x

        return (
            res.copy().ravel()
        )  # apparently we can't reuse the memory we return (seems to blow up lgmres), so we make a copy
Exemple #37
0
def calc_BB_Y_2s(C, Vlh, Vrh_p1, l_s_m1, r_s_p1):
    Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj()

    Y = sp.zeros((Vlh.shape[1], Vrh_p1.shape[2]), dtype=C.dtype)
    for s in xrange(Vlh.shape[0]):
        Y += Vlh[s].dot(l_s_m1.dot(eps_r_noop(r_s_p1, C[s], Vr_p1)))

    etaBB_sq = mm.adot(Y, Y)
    
    return Y, etaBB_sq
Exemple #38
0
def calc_K(Kp1, C, lm1, rp1, A, AAp1):    
    K = eps_r_noop(Kp1, A, A)
    
    Hr = eps_r_op_2s_C12_AA34(rp1, C, AAp1)

    op_expect = mm.adot(lm1, Hr)
        
    K += Hr
    
    return K, op_expect
Exemple #39
0
def calc_K_3s(Kp1, C, lm1, rp2, A, AAp1Ap2):    
    K = eps_r_noop(Kp1, A, A)
    
    Hr = eps_r_op_3s_C123_AAA456(rp2, C, AAp1Ap2)
        
    op_expect = mm.adot(lm1, Hr)
        
    K += Hr
    
    return K, op_expect
Exemple #40
0
 def matvec(self, v):
     x = v.reshape((self.D, self.D))
     
     if self.left: #Multiplying from the left, but x is a col. vector, so use mat_dagger
         Ehx = tm.eps_l_noop_inplace(x, self.A1, self.A2, self.out)
         if self.pseudo:
             QEQhx = Ehx - self.l * m.adot(self.r, x)
             res = x - sp.exp(-1.j * self.p) * QEQhx
         else:
             res = x - sp.exp(-1.j * self.p) * Ehx
     else:
         Ex = tm.eps_r_noop_inplace(x, self.A1, self.A2, self.out)
         if self.pseudo:
             QEQx = Ex - self.r * m.adot(self.l, x)
             res = x - sp.exp(1.j * self.p) * QEQx
         else:
             res = x - sp.exp(1.j * self.p) * Ex
     
     return res.ravel()
Exemple #41
0
 def calc_K(self):
     Hr = np.zeros_like(self.A[0])
     
     for s in xrange(self.q):
         for t in xrange(self.q):
             Hr += m.mmul(self.C[s, t], self.r, m.H(self.AA[s, t]))
     
     self.h = m.adot(self.l, Hr)
     
     QHr = Hr - self.r * self.h
     
     self.calc_PPinv(QHr, out=self.K)
     
     if self.sanity_checks:
         Ex = self.eps_r(self.K)
         QEQ = Ex - self.r * m.adot(self.l, self.K)
         res = self.K - QEQ
         if not np.allclose(res, QHr):
             print "Sanity check failed: Bad K!"
             print "Off by: " + str(la.norm(res - QHr))
Exemple #42
0
def calc_BB_Y_2s_tp(C_tp, Vlh, Vrh_p1, l_s_m1, r_s_p1):
    Vl = sp.transpose(Vlh, axes=(0, 2, 1)).conj().copy()
    Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj().copy()

    Y = 0
    for al in xrange(len(C_tp)):
        Y += eps_l_noop(l_s_m1, Vl, C_tp[al][0]).dot(eps_r_noop(r_s_p1, C_tp[al][1], Vr_p1))

    etaBB_sq = mm.adot(Y, Y)
    
    return Y, etaBB_sq
Exemple #43
0
    def matvec(self, v):
        x = v.reshape((self.D, self.D))
        
        res = self.tmp
        out = self.out
        res[:] = x
        
        if self.left: #Multiplying from the left, but x is a col. vector, so use mat_dagger
            for k in xrange(len(self.A1)):
                out = tm.eps_l_noop_inplace(res, self.A1[k], self.A2[k], out)
                tmp = res
                res = out
                out = tmp
                
            if self.pseudo:
                out[:] = self.lL
                out *= m.adot(self.rL, x)
                res -= out
                res *= -sp.exp(-1.j * self.p)
                res += x
            else:
                res *= -sp.exp(-1.j * self.p)
                res += x
        else:
            for k in xrange(len(self.A1) - 1, -1, -1):
                out = tm.eps_r_noop_inplace(res, self.A1[k], self.A2[k], out)
                tmp = res
                res = out
                out = tmp
                
            if self.pseudo:
                out[:] = self.rL 
                out *= m.adot(self.lL, x)
                res -= out
                res *= -sp.exp(1.j * self.p)
                res += x
            else:
                res *= -sp.exp(1.j * self.p)
                res += x

        return res.copy().ravel() #apparently we can't reuse the memory we return (seems to blow up lgmres), so we make a copy
Exemple #44
0
    def simple_renorm(self, update_lr=True):
        """Renormalizes the state in by multiplying one of the parameter
        tensors by a factor.
        """
        norm = mm.adot(self.l[self.N_centre - 1], self.r[self.N_centre - 1])

        if abs(1 - norm) > 1E-15:
            self.A[self.N_centre] *= 1 / sp.sqrt(norm)

        if update_lr:
            self.calc_l(n_low=self.N_centre)
            self.calc_r(n_high=self.N_centre)
Exemple #45
0
    def simple_renorm(self, update_lr=True):
        """Renormalizes the state in by multiplying one of the parameter
        tensors by a factor.
        """
        norm = mm.adot(self.l[self.N_centre - 1], self.r[self.N_centre - 1])

        if abs(1 - norm) > 1E-15:
            self.A[self.N_centre] *= 1 / sp.sqrt(norm)

        if update_lr:
            self.calc_l(n_low=self.N_centre)
            self.calc_r(n_high=self.N_centre)
Exemple #46
0
def calc_BB_Y_2s_tp(C_tp, Vlh, Vrh_p1, l_s_m1, r_s_p1):
    Vl = sp.transpose(Vlh, axes=(0, 2, 1)).conj().copy()
    Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj().copy()

    Y = 0
    for al in xrange(len(C_tp)):
        Y += eps_l_noop(l_s_m1, Vl,
                        C_tp[al][0]).dot(eps_r_noop(r_s_p1, C_tp[al][1],
                                                    Vr_p1))

    etaBB_sq = mm.adot(Y, Y)

    return Y, etaBB_sq
Exemple #47
0
 def calc_K_l(self):
     lH = np.zeros_like(self.A[0])
     
     for s in xrange(self.q):
         for t in xrange(self.q):
             lH += m.mmul(m.H(self.AA[s, t]), self.l, self.C[s, t])
     
     h = m.adot(lH, self.r)
     
     lHQ = lH - self.l * h
     
     self.K_left = self.calc_PPinv(lHQ, left=True, out=self.K_left)
     
     if self.sanity_checks:
         xE = self.eps_l(self.K_left)
         QEQ = xE - self.l * m.adot(self.K_left, self.r)
         res = self.K_left - QEQ
         if not np.allclose(res, lHQ):
             print "Sanity check failed: Bad K_left!"
             print "Off by: " + str(la.norm(res - lHQ))
     
     
     return self.K_left, h
 def matvec(self, v):
     x = v.reshape((self.D, self.D))
     
     if self.left: #Multiplying from the left, but x is a col. vector, so use mat_dagger
         Ehx = x
         for k in xrange(len(self.A1)):
             Ehx = tm.eps_l_noop(Ehx, self.A1[k], self.A2[k])
         if self.pseudo:
             QEQhx = Ehx - self.lL * m.adot(self.rL, x)
             res = x - sp.exp(-1.j * self.p) * QEQhx
         else:
             res = x - sp.exp(-1.j * self.p) * Ehx
     else:
         Ex = x
         for k in xrange(len(self.A1) - 1, -1, -1):
             Ex = tm.eps_r_noop(Ex, self.A1[k], self.A2[k])
         if self.pseudo:
             QEQx = Ex - self.rL * m.adot(self.lL, x)
             res = x - sp.exp(1.j * self.p) * QEQx
         else:
             res = x - sp.exp(1.j * self.p) * Ex
     
     return res.ravel()
Exemple #49
0
 def f(tau, *args):
     if tau < 0:
         if use_tangvec_overlap:
             res = tau**2 + self.eta_sq.sum().real
         else:
             res = tau**2 + h_expect_0.real
         log.debug((tau, res, "punishing negative tau!"))
         taus.append(tau)
         ress.append(res)
         hs.append(h_expect_0.real)
         return res
     try:
         i = taus.index(tau)
         log.debug((tau, ress[i], "from stored"))
         return ress[i]
     except ValueError:
         for n in xrange(1, self.N + 1):
             if not Bs[n] is None:
                 self.A[n] = As0[n] - tau * Bs[n]
             
         if use_tangvec_overlap:
             self.update(restore_CF=False)
             Bsg = self.calc_B(set_eta=False)
             res = 0
             for n in xrange(1, self.N + 1):
                 if not Bs[n] is None:
                     res += abs(m.adot(self.l[n - 1], tm.eps_r_noop(self.r[n], Bsg[n], Bs[n])))
             h_exp = self.H_expect.real
         else:
             self.calc_l()
             self.calc_r()
             self.simple_renorm()
             self.calc_C()
             
             h_exp = 0
             if self.ham_sites == 2:
                 for n in xrange(1, self.N):
                     h_exp += self.expect_2s(self.ham[n], n).real
             else:
                 for n in xrange(1, self.N - 1):
                     h_exp += self.expect_3s(self.ham[n], n).real
             res = h_exp
         
         log.debug((tau, res, h_exp, h_exp - h_expect_0.real))
         
         taus.append(tau)
         ress.append(res)
         hs.append(h_exp)
         
         return res
Exemple #50
0
 def expect_string_1s(self, op, n, d):
     """Calculates the expectation values of finite strings
     with lengths 1 to d, starting at position n.
     """
     if callable(op):
         op = sp.vectorize(op, otypes=[sp.complex128])
         op = sp.fromfunction(op, (self.q, self.q))
     
     res = sp.zeros((d), dtype=self.A[1].dtype)
     x = self.l[n - 1]
     for j in xrange(n, n + d + 1):
         Aop = sp.tensordot(op, self.A[j], axes=([1],[0]))
         x = tm.eps_l_noop(x, self.A[j], Aop)
         res[j - n - 1] = m.adot(x, self.r[j])
     
     return res
Exemple #51
0
    def expect_1s_1s(self, op1, op2, d):
        """Computes the expectation value of two single site operators acting 
        on two different sites.
        
        The result is < op1_n op2_n+d > with the operators acting on sites
        n and n + d.
        
        See expect_1s().
        
        Requires d > 0.
        
        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.
        d : int
            The distance (number of sites) between the two sites acted on non-trivially.
            
        Returns
        -------
        expval : floating point number
            The expectation value (data type may be complex)
        """        
        
        assert d > 0, 'd must be greater than 1'
        
        if callable(op1):
            op1 = sp.vectorize(op1, otypes=[sp.complex128])
            op1 = sp.fromfunction(op1, (self.q, self.q))
        
        if callable(op2):
            op2 = sp.vectorize(op2, otypes=[sp.complex128])
            op2 = sp.fromfunction(op2, (self.q, self.q)) 
        
        r_n = tm.eps_r_op_1s(self.r, self.A, self.A, op2)

        for n in xrange(d - 1):
            r_n = tm.eps_r_noop(r_n, self.A, self.A)

        r_n = tm.eps_r_op_1s(r_n, self.A, self.A, op1)
         
        return m.adot(self.l, r_n)
    def calc_K(self):
        """Generates the right K matrices used to calculate the B's
        
        K[n] contains 'column-vectors' such that <l[n]|K[n]> = trace(l[n].dot(K[n])).
        K_l[n] contains 'bra-vectors' such that <K_l[n]|r[n]> = trace(K_l[n].dot(r[n])).
        """

        self.h_expect = sp.zeros((self.N + 1), dtype=self.typ)

        self.uni_r.calc_AA()
        self.uni_r.calc_C()
        self.uni_r.calc_K()
        self.K[self.N + 1][:] = self.uni_r.K

        self.uni_l.calc_AA()
        self.uni_l.calc_C()
        K_left, h_left_uni = self.uni_l.calc_K_l()
        self.K_l[0][:] = K_left

        for n in xrange(self.N, self.N_centre - 1, -1):
            self.K[n], he = tm.calc_K(self.K[n + 1],
                                      self.C[n],
                                      self.get_l(n - 1),
                                      self.r[n + 1],
                                      self.A[n],
                                      self.A[n + 1],
                                      sanity_checks=self.sanity_checks)

            self.h_expect[n] = he

        for n in xrange(1, self.N_centre + 1):
            self.K_l[n], he = tm.calc_K_l(self.K_l[n - 1],
                                          self.C[n - 1],
                                          self.get_l(n - 2),
                                          self.r[n],
                                          self.A[n],
                                          self.A[n - 1],
                                          sanity_checks=self.sanity_checks)

            self.h_expect[n - 1] = he

        self.dH_expect = (
            mm.adot_noconj(self.K_l[self.N_centre], self.r[self.N_centre]) +
            mm.adot(self.l[self.N_centre - 1], self.K[self.N_centre]) -
            (self.N + 1) * self.uni_r.h_expect)
Exemple #53
0
 def density_1s(self):
     """Returns a reduced density matrix for a single site.
     
     The site number basis is used: rho[s, t] 
     with 0 <= s, t < q.
     
     The state must be up-to-date -- see self.update()!
         
     Returns
     -------
     rho : ndarray
         Reduced density matrix in the number basis.
     """
     rho = np.empty((self.q, self.q), dtype=self.typ)
     for s in xrange(self.q):
         for t in xrange(self.q):                
             rho[s, t] = m.adot(self.l, m.mmul(self.A[t], self.r, m.H(self.A[s])))
     return rho
Exemple #54
0
    def expect_1s_1s(self, op1, op2, n1, n2):
        """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).
            
        Returns
        -------
        expval : floating point number
            The expectation value (data type may be complex)
        """
        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]))

        r_n = tm.eps_r_op_1s(self.r[n2], self.A[n2], self.A[n2], op2)

        for n in reversed(xrange(n1 + 1, n2)):
            r_n = tm.eps_r_noop(r_n, self.A[n], self.A[n])

        r_n = tm.eps_r_op_1s(r_n, self.A[n1], self.A[n1], op1)

        return m.adot(self.l[n1 - 1], r_n)
Exemple #55
0
    def calc_K_common(self, Kp1, C, lm1, rp1, A, Ap1):
        Dm1 = A.shape[1]
        q = A.shape[0]
        qp1 = Ap1.shape[0]

        K = sp.zeros((Dm1, Dm1), dtype=A.dtype)

        Hr = sp.zeros_like(K)

        for s in xrange(q):
            Ash = A[s].conj().T
            for t in xrange(qp1):
                test = Ap1[t]
                Hr += C[t, s].dot(rp1.dot(mm.H(test).dot(Ash)))
            K += A[s].dot(Kp1.dot(Ash))

        op_expect = mm.adot(lm1, Hr)

        K += Hr
        return K, op_expect
Exemple #56
0
    def _calc_B_r_diss(self, op, K, C, n, set_eta=True):
        if self.q[n] * self.D[n] - self.D[n - 1] > 0:
            l_sqrt, l_sqrt_inv, r_sqrt, r_sqrt_inv = tm.calc_l_r_roots(
                self.l[n - 1],
                self.r[n],
                sanity_checks=self.sanity_checks,
                sc_data=("site", n))
            Vsh = tm.calc_Vsh(self.A[n],
                              r_sqrt,
                              sanity_checks=self.sanity_checks)
            x = self.calc_x(n, Vsh, l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv)
            if set_eta:
                self.eta[n] = sp.sqrt(mm.adot(x, x))

            B = sp.empty_like(self.A[n])
            for s in xrange(self.q[n]):
                B[s] = mm.mmul(l_sqrt_inv, x, mm.H(Vsh[s]), r_sqrt_inv)
            return B
        else:
            return None