Example #1
0
 def get_r(self, n, r_np1=None):
     """Gets an r[n], even if n < 0 or n > N + 1
     """
     if 0 <= n <= self.N + 1:
         return self.r[n]
     elif n > self.N + 1:
         return self.r[self.N + 1]
     else:
         if r_np1 is None:
             r_m = self.r[0]
             for m in reversed(xrange(n, 0)):
                 r_m = tm.eps_r_noop(r_m, self.A[0], self.A[0])
             return r_m
         else:
             return tm.eps_r_noop(r_np1, self.A[0], self.A[0])
Example #2
0
 def get_r(self, n, r_np1=None):
     """Gets an r[n], even if n < 0 or n > N + 1
     """
     if 0 <= n <= self.N + 1:
         return self.r[n]
     elif n > self.N + 1:
         return self.uni_r.r[(n - 1) % self.uni_r.L]
     else:
         if r_np1 is None:
             r_m = self.r[0]
             for m in (sp.arange(0, n, -1) - 1) % self.uni_l.L:
                 r_m = tm.eps_r_noop(r_m, self.uni_l.A[m], self.uni_l.A[m])
             return r_m
         else:
             m = n % self.uni_l.L
             return tm.eps_r_noop(r_np1, self.uni_l.A[m], self.uni_l.A[m])
Example #3
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)
Example #4
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
Example #5
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        
Example #6
0
 def get_r(self, n, r_np1=None):
     """Gets an r[n], even if n < 0 or n > N + 1
     """
     if 0 <= n <= self.N + 1:
         return self.r[n]
     elif n > self.N + 1:
         return self.uni_r.r[(n - 1) % self.uni_r.L]
     else:
         if r_np1 is None:
             r_m = self.r[0]
             for m in (sp.arange(0, n, -1) - 1) % self.uni_l.L:
                 r_m = tm.eps_r_noop(r_m, self.uni_l.A[m], self.uni_l.A[m])
             return r_m
         else:
             m = n % self.uni_l.L
             return tm.eps_r_noop(r_np1, self.uni_l.A[m], self.uni_l.A[m])
Example #7
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
Example #8
0
 def calc_r(self, n_low=-1, n_high=-1):
     """Updates the r matrices using the current state parameters self.A.
     
     Implements step 5 of the TDVP algorithm or, equivalently, eqn. (41).
     (arXiv:1103.0936v2 [cond-mat.str-el])
     """
     if n_low < 0:
         n_low = 0
     if n_high < 0:
         n_high = self.N - 1
     for n in xrange(n_high, n_low - 1, -1):
         self.r[n] = tm.eps_r_noop(self.r[n + 1], self.A[n + 1], self.A[n + 1])
Example #9
0
 def calc_r(self, n_low=-1, n_high=-1):
     """Updates the r matrices using the current state parameters self.A.
     
     Implements step 5 of the TDVP algorithm or, equivalently, eqn. (41).
     (arXiv:1103.0936v2 [cond-mat.str-el])
     """
     if n_low < 0:
         n_low = 0
     if n_high < 0:
         n_high = self.N - 1
     for n in xrange(n_high, n_low - 1, -1):
         self.r[n] = tm.eps_r_noop(self.r[n + 1], self.A[n + 1], self.A[n + 1])
Example #10
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
Example #11
0
    def restore_RCF(self, use_QR=True, update_l=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        It is possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """   
        if use_QR:
            tm.restore_RCF_r_seq(self.A, self.r, sanity_checks=self.sanity_checks,
                                     sc_data="restore_RCF_r")
        else:
            G_n_i = sp.eye(self.D[self.N], dtype=self.typ) #This is actually just the number 1
            for n in xrange(self.N, 0, -1):
                self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(self.A[n], self.r[n], 
                                                             G_n_i, sc_data=('site', n),
                                                             zero_tol=self.zero_tol,
                                                             sanity_checks=self.sanity_checks)

        if self.sanity_checks:
            if not sp.allclose(self.r[0].A, 1, atol=1E-12, rtol=1E-12):
                log.warning("Sanity Fail in restore_RCF!: r_0 is bad / norm failure")
        
        if diag_l:
            tm.restore_RCF_l_seq(self.A, self.l, sanity_checks=self.sanity_checks,
                                                 sc_data="restore_RCF_l")

            if self.sanity_checks:
                if not sp.allclose(self.l[self.N].A, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: l_N is bad / norm failure")
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)
                
                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning("Sanity Fail in restore_RCF!: r_%u is bad (off by %g)", n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()
Example #12
0
    def restore_RCF(self, use_QR=True, update_l=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        It is possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """   
        if use_QR:
            tm.restore_RCF_r_seq(self.A, self.r, sanity_checks=self.sanity_checks,
                                     sc_data="restore_RCF_r")
        else:
            G_n_i = sp.eye(self.D[self.N], dtype=self.typ) #This is actually just the number 1
            for n in xrange(self.N, 0, -1):
                self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(self.A[n], self.r[n], 
                                                             G_n_i, sc_data=('site', n),
                                                             zero_tol=self.zero_tol,
                                                             sanity_checks=self.sanity_checks)

        if self.sanity_checks:
            if not sp.allclose(self.r[0].A, 1, atol=1E-12, rtol=1E-12):
                log.warning("Sanity Fail in restore_RCF!: r_0 is bad / norm failure")
        
        if diag_l:
            tm.restore_RCF_l_seq(self.A, self.l, sanity_checks=self.sanity_checks,
                                                 sc_data="restore_RCF_l")

            if self.sanity_checks:
                if not sp.allclose(self.l[self.N].A, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: l_N is bad / norm failure")
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)
                
                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning("Sanity Fail in restore_RCF!: r_%u is bad (off by %g)", n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()
Example #13
0
    def calc_B(self, n, set_eta=True):
        """Generates the B[n] tangent vector corresponding to physical evolution of the state.

        In other words, this returns B[n][x*] (equiv. eqn. (47) of
        arXiv:1103.0936v2 [cond-mat.str-el])
        with x* the parameter matrices satisfying the Euler-Lagrange equations
        as closely as possible.
        
        In the case of Bc, use the general Bc generated in calc_B_centre().
        """
        if n == self.N_centre:
            B, eta_c = self.calc_B_centre()
            if set_eta:
                self.eta[self.N_centre] = eta_c
        else:
            l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv = self.calc_l_r_roots(n)
            
            if n > self.N_centre:
                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, right=True)
                
                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)
                    
                if self.sanity_checks:
                    M = tm.eps_r_noop(self.r[n], B, self.A[n])
                    if not sp.allclose(M, 0):
                        print "Sanity Fail in calc_B!: B_%u does not satisfy GFC!" % n
            else:
                Vsh = tm.calc_Vsh_l(self.A[n], l_sqrt, sanity_checks=self.sanity_checks)
                x = self.calc_x(n, Vsh, l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv, right=False)
                
                B = sp.empty_like(self.A[n])
                for s in xrange(self.q[n]):
                    B[s] = mm.mmul(l_sqrt_inv, mm.H(Vsh[s]), x, r_sqrt_inv)
                    
                if self.sanity_checks:
                    M = tm.eps_l_noop(self.l[n - 1], B, self.A[n])
                    if not sp.allclose(M, 0):
                        print "Sanity Fail in calc_B!: B_%u does not satisfy GFC!" % n
            
            if set_eta:
                self.eta[n] = sp.sqrt(mm.adot(x, x))


        return B
Example #14
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)
Example #15
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)
Example #16
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)
Example #17
0
    def matvec(self, x):
        self.calls += 1
        #print self.calls
        
        t = self.tdvp
        n = self.n
        
        Gn = x.reshape((self.D[n], self.D[n]))

        res = self.KLn.dot(Gn) + Gn.dot(t.K[n + 1])
        
        if n < t.N:
            Ap1 = sp.array([Gn.dot(As) for As in t.A[n + 1]])
            AAn = tm.calc_AA(t.A[n], Ap1)
            Cn = tm.calc_C_mat_op_AA(t.ham[n], AAn)
            for s in xrange(t.q[n]):
                sres = tm.eps_r_noop(t.r[n + 1], Cn[s, :], t.A[n + 1])
                res += t.A[n][s].conj().T.dot(t.l[n - 1].dot(sres))
        
        return res.reshape(x.shape) * self.tau
Example #18
0
 def matvec(self, x):
     self.calls += 1
     #print self.calls
     
     t = self.tdvp
     n = self.n
     
     An = x.reshape((self.q[n], self.D[n - 1], self.D[n]))
     
     if n > 1:
         AAnm1 = tm.calc_AA(t.A[n - 1], An)
         Cnm1 = tm.calc_C_mat_op_AA(t.ham[n - 1], AAnm1)
     else:
         AAnm1 = None
         Cnm1 = None
         
     if n < t.N:
         AAn = tm.calc_AA(An, t.A[n + 1])
         Cn = tm.calc_C_mat_op_AA(t.ham[n], AAn)
     else:
         AAn = None
         Cn = None
     
     res = sp.zeros_like(An)
     
     #Assuming RCF        
     if not Cnm1 is None:
         for s in xrange(t.q[n]):
             res[s] += tm.eps_l_noop(t.l[n - 2], t.A[n - 1], Cnm1[:, s])
             res[s] += self.KLnm1.dot(An[s])
         res[s] = self.lm1_i.dot(res[s])
             
     if not Cn is None:
         for s in xrange(t.q[n]):                
             res[s] += tm.eps_r_noop(t.r[n + 1], Cn[s, :], t.A[n + 1])
             res[s] += An[s].dot(t.K[n + 1])
             
     #print "en = ", (sp.inner(An.conj().ravel(), res.ravel())
     #                / sp.inner(An.conj().ravel(), An.ravel()))
     
     return res.reshape(x.shape) * self.tau
Example #19
0
    def expect_1s_cor(self, op1, op2, n1, n2):
        """Computes the correlation of two single site operators acting on two different sites.

        See expect_1S().

        n1 must be smaller than n2.

        Assumes that the state is normalized.

        Parameters
        ----------
        op1 : function
            The first operator, acting on the first site.
        op2 : function
            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).
        """
        A1 = self.get_A(n1)
        A2 = self.get_A(n2)

        if callable(op1):
            op1 = sp.vectorize(op1, otypes=[sp.complex128])
            op1 = sp.fromfunction(op1, (A1.shape[0], A1.shape[0]))

        if callable(op2):
            op2 = sp.vectorize(op2, otypes=[sp.complex128])
            op2 = sp.fromfunction(op2, (A2.shape[0], A2.shape[0]))

        r_n = tm.eps_r_op_1s(self.get_r(n2), A2, A2, op2)

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

        r_n = tm.eps_r_op_1s(r_n, A1, A1, op1)

        return mm.adot(self.get_l(n1 - 1), r_n)
Example #20
0
    def expect_1s_cor(self, op1, op2, n1, n2):
        """Computes the correlation of two single site operators acting on two different sites.

        See expect_1S().

        n1 must be smaller than n2.

        Assumes that the state is normalized.

        Parameters
        ----------
        op1 : function
            The first operator, acting on the first site.
        op2 : function
            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).
        """
        A1 = self.get_A(n1)
        A2 = self.get_A(n2)

        if callable(op1):
            op1 = sp.vectorize(op1, otypes=[sp.complex128])
            op1 = sp.fromfunction(op1, (A1.shape[0], A1.shape[0]))

        if callable(op2):
            op2 = sp.vectorize(op2, otypes=[sp.complex128])
            op2 = sp.fromfunction(op2, (A2.shape[0], A2.shape[0]))

        r_n = tm.eps_r_op_1s(self.get_r(n2), A2, A2, op2)

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

        r_n = tm.eps_r_op_1s(r_n, A1, A1, op1)

        return mm.adot(self.get_l(n1 - 1), r_n)
Example #21
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 = 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()
Example #22
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)
Example #23
0
    def density_2s(self, n1, n2):
        """Returns a reduced density matrix for a pair of (seperated) sites.
        
        The site number basis is used: rho[s * q[n1] + u, t * q[n1] + v]
        with 0 <= s, t < q[n1] and 0 <= u, v < q[n2].
        
        The state must be up-to-date -- see self.update()!
        
        Parameters
        ----------
        n1 : int
            The site number of the first site.
        n2 : int
            The site number of the second site (must be > n1).
            
        Returns
        -------
        rho : ndarray
            Reduced density matrix in the number basis.
        """
        rho = sp.empty((self.q[n1] * self.q[n2], self.q[n1] * self.q[n2]),
                       dtype=sp.complex128)

        for s2 in xrange(self.q[n2]):
            for t2 in xrange(self.q[n2]):
                r_n2 = m.mmul(self.A[n2][t2], self.r[n2], m.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 = m.mmul(self.A[n1][t1], r_n, m.H(self.A[n1][s1]))
                        tmp = m.adot(self.l[n1 - 1], r_n1)
                        rho[s1 * self.q[n1] + s2, t1 * self.q[n1] + t2] = tmp
        return rho
Example #24
0
 def _calc_lr_brute(self):
     E = np.zeros((self.D**2, self.D**2), dtype=self.typ, order='C')
     
     for s in xrange(self.q):
         E += sp.kron(self.A[s], self.A[s].conj())
         
     ev, eVL, eVR = la.eig(E, left=True, right=True)
     
     i = np.argmax(ev)
     
     self.A *= 1 / sp.sqrt(ev[i])        
     
     self.l = eVL[:,i].reshape((self.D, self.D))
     self.r = eVR[:,i].reshape((self.D, self.D))
     
     norm = m.adot(self.l, self.r)
     self.l *= 1 / sp.sqrt(norm)
     self.r *= 1 / sp.sqrt(norm)        
     
     log.warning("Sledgehammer:")
     log.warning("Left ok?: %s", np.allclose(
         tm.eps_l_noop(self.l, self.A, self.A), self.l))
     log.warning("Right ok?: %s", np.allclose(
         tm.eps_r_noop(self.r, self.A, self.A), self.r))
Example #25
0
 def density_2s(self, n1, n2):
     """Returns a reduced density matrix for a pair of (seperated) sites.
     
     The site number basis is used: rho[s * q[n1] + u, t * q[n1] + v]
     with 0 <= s, t < q[n1] and 0 <= u, v < q[n2].
     
     The state must be up-to-date -- see self.update()!
     
     Parameters
     ----------
     n1 : int
         The site number of the first site.
     n2 : int
         The site number of the second site (must be > n1).
         
     Returns
     -------
     rho : ndarray
         Reduced density matrix in the number basis.
     """
     rho = sp.empty((self.q[n1] * self.q[n2], self.q[n1] * self.q[n2]), dtype=sp.complex128)
     
     for s2 in xrange(self.q[n2]):
         for t2 in xrange(self.q[n2]):
             r_n2 = m.mmul(self.A[n2][t2], self.r[n2], m.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 = m.mmul(self.A[n1][t1], r_n, m.H(self.A[n1][s1]))
                     tmp = m.adot(self.l[n1 - 1], r_n1)
                     rho[s1 * self.q[n1] + s2, t1 * self.q[n1] + t2] = tmp
     return rho
Example #26
0
    def overlap(self, other, sanity_checks=False):
        if not self.N == other.N:
            print "States must have same number of non-uniform sites!"
            return

        if not sp.all(self.D == other.D):
            print "States must have same bond-dimensions!"
            return

        if not sp.all(self.q == other.q):
            print "States must have same Hilbert-space dimensions!"
            return

        dL, phiL, gLl = self.uni_l.fidelity_per_site(other.uni_l,
                                                     full_output=True,
                                                     left=True)

        dR, phiR, gRr = self.uni_r.fidelity_per_site(other.uni_r,
                                                     full_output=True,
                                                     left=False)

        gLl = gLl.reshape(self.uni_l.D, self.uni_l.D)
        gRr = gRr.reshape(self.uni_r.D, self.uni_r.D)

        gr = mm.H(la.inv(gRr).dot(sp.asarray(self.uni_r.r[-1])))
        gri = mm.H(la.inv(sp.asarray(self.uni_r.r[-1])).dot(gRr))

        #        if sanity_checks: #FIXME: Not gonna work for L > 1....
        #            AR = other.uni_r.A.copy()
        #            for s in xrange(AR.shape[0]):
        #                AR[s] = gr.dot(AR[s]).dot(gri)
        #
        #            print la.norm(AR - self.uni_r.A)

        r = gr.dot(sp.asarray(other.uni_r.r)).dot(mm.H(gr))
        fac = la.norm(sp.asarray(self.uni_r.r)) / la.norm(r)
        gr *= sp.sqrt(fac)
        gri /= sp.sqrt(fac)

        if sanity_checks:
            r *= fac
            print la.norm(r - self.uni_r.r[-1])

#            AN = other.A[self.N].copy()
#            for s in xrange(AN.shape[0]):
#                AN[s] = AN[s].dot(gri)
#            r = tm.eps_r_noop(self.uni_r.r, AN, AN)
#            print la.norm(r - other.r[self.N - 1])

        gl = la.inv(sp.asarray(self.uni_l.l[-1])).dot(gLl)
        gli = la.inv(gLl).dot(sp.asarray(self.uni_l.l[-1]))

        l = mm.H(gli).dot(sp.asarray(other.uni_l.l[-1])).dot(gli)
        fac = la.norm(sp.asarray(self.uni_l.l[-1])) / la.norm(l)

        gli *= sp.sqrt(fac)
        gl /= sp.sqrt(fac)

        if sanity_checks:
            l *= fac
            print la.norm(l - self.uni_l.l[-1])

            l = mm.H(gli).dot(sp.asarray(other.uni_l.l[-1])).dot(gli)
            print la.norm(l - self.uni_l.l[-1])

        #print (dL, dR, phiL, phiR)

        if not abs(dL - 1) < 1E-12:
            print "Left bulk states do not match!"
            return 0

        if not abs(dR - 1) < 1E-12:
            print "Right bulk states do not match!"
            return 0

        AN = other.A[self.N].copy()
        for s in xrange(AN.shape[0]):
            AN[s] = AN[s].dot(gri)

        A1 = other.A[1].copy()
        for s in xrange(A1.shape[0]):
            A1[s] = gl.dot(A1[s])

        r = tm.eps_r_noop(self.uni_r.r[-1], self.A[self.N], AN)
        for n in xrange(self.N - 1, 1, -1):
            r = tm.eps_r_noop(r, self.A[n], other.A[n])
        r = tm.eps_r_noop(r, self.A[1], A1)

        return mm.adot(self.uni_l.l[-1], r)
Example #27
0
    def _calc_lr_ARPACK(self, x, tmp, calc_l=False, A1=None, A2=None, rescale=True,
                        tol=1E-14, ncv=None, k=1):
        if A1 is None:
            A1 = self.A
        if A2 is None:
            A2 = self.A
            
        if self.D == 1:
            x.fill(1)
            if calc_l:
                ev = tm.eps_l_noop(x, A1, A2)[0, 0]
            else:
                ev = tm.eps_r_noop(x, A1, A2)[0, 0]
            
            if rescale and not abs(ev - 1) < tol:
                A1 *= 1 / sp.sqrt(ev)
            
            return x, True, 1
                        
        try:
            norm = la.get_blas_funcs("nrm2", [x])
        except (ValueError, AttributeError):
            norm = np.linalg.norm
    
        n = x.size #we will scale x so that stuff doesn't get too small
        
        #start = time.clock()
        opE = EOp(A1, A2, calc_l)
        x *= n / norm(x.ravel())
        try:
            ev, eV = las.eigs(opE, which='LM', k=k, v0=x.ravel(), tol=tol, ncv=ncv)
            conv = True
        except las.ArpackNoConvergence:
            log.warning("Reset! (l? %s)", calc_l)
            ev, eV = las.eigs(opE, which='LM', k=k, tol=tol, ncv=ncv)
            conv = True
            
        #print ev2
        #print ev2 * ev2.conj()
        ind = ev.argmax()
        ev = np.real_if_close(ev[ind])
        ev = np.asscalar(ev)
        eV = eV[:, ind]
        
        #remove any additional phase factor
        eVmean = eV.mean()
        eV *= sp.sqrt(sp.conj(eVmean) / eVmean)
        
        if eV.mean() < 0:
            eV *= -1

        eV = eV.reshape(self.D, self.D)
        
        eV *= n / norm(eV.ravel())
        
        x[:] = eV
        
        #print "splinalg: %g" % (time.clock() - start)   
        
        #print "Herm? %g" % norm((eV - m.H(eV)).ravel())
        #print "Norm of diff: %g" % norm((eV - x).ravel())
        #print "Norms: (%g, %g)" % (norm(eV.ravel()), norm(x.ravel()))
                    
        if rescale and not abs(ev - 1) < tol:
            A1 *= 1 / sp.sqrt(ev)
            if self.sanity_checks:
                if not A1 is A2:
                    log.warning("Sanity check failed: Re-scaling with A1 <> A2!")
                if calc_l:
                    tm.eps_l_noop_inplace(x, A1, A2, tmp)
                else:
                    tm.eps_r_noop_inplace(x, A1, A2, tmp)
                ev = tmp.mean() / x.mean()
                if not abs(ev - 1) < tol:
                    log.warning("Sanity check failed: Largest ev after re-scale = %s", ev)
        
        return x, conv, opE.calls
Example #28
0
    def restore_RCF(self, ret_g=False, zero_tol=None):
        """Restores right canonical form.
        
        In this form, self.r = sp.eye(self.D) and self.l is diagonal, with
        the squared Schmidt coefficients corresponding to the half-chain
        decomposition as eigenvalues.
        
        Parameters
        ----------
        ret_g : bool
            Whether to return the gauge-transformation matrices used.
            
        Returns
        -------
        g, g_i : ndarray
            Gauge transformation matrix g and its inverse g_i.
        """
        if zero_tol is None:
            zero_tol = self.zero_tol
        
        #First get G such that r = eye
        G, G_i, rank = tm.herm_fac_with_inv(self.r, lower=True, zero_tol=zero_tol,
                                            return_rank=True)

        self.l = m.mmul(m.H(G), self.l, G)
        
        #Now bring l into diagonal form, trace = 1 (guaranteed by r = eye..?)
        ev, EV = la.eigh(self.l)

        G = G.dot(EV)
        G_i = m.H(EV).dot(G_i)
        
        for s in xrange(self.q):
            self.A[s] = m.mmul(G_i, self.A[s], G)
            
        #ev contains the squares of the Schmidt coefficients,
        self.S_hc = - np.sum(ev * sp.log2(ev))
        
        self.l = m.simple_diag_matrix(ev, dtype=self.typ)
        
        r_old = self.r
        
        if rank == self.D:
            self.r = m.eyemat(self.D, self.typ)
        else:
            self.r = sp.zeros((self.D), dtype=self.typ)
            self.r[-rank:] = 1
            self.r = m.simple_diag_matrix(self.r, dtype=self.typ)

        if self.sanity_checks:            
            r_ = m.mmul(G_i, r_old, m.H(G_i)) 
            
            if not np.allclose(self.r, r_, 
                               rtol=self.itr_rtol*self.check_fac,
                               atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: RestoreRCF, bad r (bad GT).")
            
            l = tm.eps_l_noop(self.l, self.A, self.A)
            r = tm.eps_r_noop(self.r, self.A, self.A)
            
            if not np.allclose(r, self.r,
                               rtol=self.itr_rtol*self.check_fac, 
                               atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: Restore_RCF, r not eigenvector! %s", la.norm(r - self.r))

            if not np.allclose(l, self.l,
                               rtol=self.itr_rtol*self.check_fac, 
                               atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: Restore_RCF, l not eigenvector! %s", la.norm(l - self.l))
        
        if ret_g:
            return G, G_i
        else:
            return
Example #29
0
    def calc_BHB(self,
                 x,
                 p,
                 tdvp,
                 tdvp2,
                 prereq,
                 M_prev=None,
                 y_pi_prev=None,
                 pinv_solver=None):
        if pinv_solver is None:
            pinv_solver = las.gmres

        if self.ham_sites == 3:
            V_, Vr_, Vri_, Vri_A_, C_, C_Vri_AA_, C_AAA_r_Ah_Vrih, \
                    C_AhAhlAA, C_AA_r_Ah_Vrih_, C_AAA_Vrh_, C_Vri_A_r_Ah_, \
                    C_AhlAA, C_AhlAA_conj, C_AA_Vrh, rhs10 = prereq
        else:
            C_, C_conj, V_, Vr_, Vri_, C_Vri_A_conj, C_AhlA, C_A_Vrh_, rhs10 = prereq

        A = tdvp.A[0]
        A_ = tdvp2.A[0]
        AA = tdvp.AA[0]

        l = tdvp.l[0]
        r_ = tdvp2.r[0]

        l_sqrt = tdvp.l_sqrt[0]
        l_sqrt_i = tdvp.l_sqrt_i[0]

        r__sqrt = tdvp2.r_sqrt[0]
        r__sqrt_i = tdvp2.r_sqrt_i[0]

        K__r = tdvp2.K[0]
        K_l = tdvp.K_left[0]

        pseudo = tdvp2 is tdvp

        B = tdvp2.get_B_from_x(x, tdvp2.Vsh[0], l_sqrt_i, r__sqrt_i)

        #Skip zeros due to rank-deficiency
        if la.norm(B) == 0:
            return sp.zeros_like(x), M_prev, y_pi_prev

        if self.sanity_checks:
            tst = tm.eps_r_noop(r_, B, A_)
            if not la.norm(tst) > self.sanity_tol:
                log.warning("Sanity check failed: Gauge-fixing violation! " +
                            str(la.norm(tst)))

        if self.sanity_checks:
            B2 = np.zeros_like(B)
            for s in xrange(self.q):
                B2[s] = l_sqrt_i.dot(x.dot(Vri_[s]))
            if la.norm(B - B2) / la.norm(B) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad Vri!")

        BA_ = tm.calc_AA(B, A_)
        AB = tm.calc_AA(A, B)
        if self.ham_sites == 3:
            BAA_ = tm.calc_AAA_AA(BA_, A_)
            ABA_ = tm.calc_AAA_AA(AB, A_)
            AAB = tm.calc_AAA_AA(AA, B)

        y = tm.eps_l_noop(l, B, A)

        #        if pseudo:
        #            y = y - m.adot(r_, y) * l #should just = y due to gauge-fixing
        M = pinv_1mE(y, [A_], [A],
                     l,
                     r_,
                     p=-p,
                     left=True,
                     pseudo=pseudo,
                     out=M_prev,
                     tol=self.pinv_tol,
                     solver=pinv_solver,
                     use_CUDA=self.pinv_CUDA,
                     CUDA_use_batch=self.pinv_CUDA_batch,
                     sanity_checks=self.sanity_checks,
                     sc_data='M')

        #print m.adot(r, M)
        if self.sanity_checks:
            y2 = M - sp.exp(+1.j * p) * tm.eps_l_noop(M, A_, A)
            norm = la.norm(y.ravel())
            if norm == 0:
                norm = 1
            tst = la.norm(y - y2) / norm
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad M. Off by: %g", tst)


#        if pseudo:
#            M = M - l * m.adot(r_, M)
        Mh = M.conj().T.copy(order='C')

        if self.ham_sites == 3:
            tmp = BAA_ + sp.exp(+1.j * p) * ABA_ + sp.exp(+2.j * p) * AAB
            res = l_sqrt.dot(tm.eps_r_op_3s_C123_AAA456(
                r_, tmp, C_Vri_AA_))  #1 1D, #3, #3c
        else:
            tmp = BA_ + sp.exp(+1.j * p) * AB
            res = l_sqrt.dot(tm.eps_r_op_2s_AA12_C34(r_, tmp,
                                                     C_Vri_A_conj))  #1, #3 OK

        res += sp.exp(-1.j * p) * l_sqrt_i.dot(Mh.dot(rhs10))  #10

        exp = sp.exp
        subres = sp.zeros_like(res)
        eye = m.eyemat(C_.shape[2], dtype=tdvp.typ)
        eye2 = m.eyemat(A.shape[2], dtype=tdvp.typ)
        if self.ham_sites == 3:
            subres += exp(-2.j * p) * tm.eps_l_noop(Mh, A,
                                                    C_AAA_r_Ah_Vrih)  #12
            subres += exp(-3.j * p) * tm.eps_l_op_2s_AA12_C34(
                Mh, AA, C_AAA_Vrh_)  #12b
            for s in xrange(self.q):
                #subres += exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_AAA_r_Ah_Vrih[s])) #12
                subres += tm.eps_r_noop(B[s], C_AhAhlAA[s, :], Vr_)  #2b
                subres += exp(-1.j * p) * tm.eps_l_noop(
                    l.dot(B[s]), A, C_AA_r_Ah_Vrih_[s, :])  #4
                subres += A[s].conj().T.dot(
                    l.dot(
                        tm.eps_r_op_2s_AA12_C34(eye2, AB, C_Vri_A_r_Ah_[
                            s, :, :])))  #2 -ive of that it should be....
                subres += exp(-1.j * p) * tm.eps_l_op_2s_AA12_C34(
                    eye2, C_AhlAA_conj[s, :, :], BA_).dot(Vr_[s].conj().T)  #4b
                subres += exp(-2.j * p) * tm.eps_l_op_2s_AA12_C34(
                    l.dot(B[s]), AA, C_AA_Vrh[s, :, :])  #4c
                subres += exp(+1.j * p) * tm.eps_r_op_2s_AA12_C34(
                    r_.dot_left(B[s]), C_AhlAA[s, :, :], Vri_A_)  #3b
                #for t in xrange(self.q):
                #subres += (C_AhAhlAA[t, s].dot(B[s]).dot(Vr_[t].conj().T)) #2b
                #subres += (exp(-1.j * p) * A[s].conj().T.dot(l.dot(B[t])).dot(C_AA_r_Ah_Vrih_[s, t])) #4
                #subres += (exp(-3.j * p) * AA[t, s].conj().T.dot(Mh).dot(C_AAA_Vrh_[t, s])) #12b

                #for u in xrange(self.q):
                #subres += A[s].conj().T.dot(l.dot(AB[t, u]).dot(C_A_r_Ah_Vrih[s, t, u])) #2 -ive of that it should be....
                #subres += (exp(+1.j * p) * C_AhlAA[t, s, s].dot(B[u]).dot(r_.dot(A_[u].conj().T)).dot(Vri_[t].conj().T)) #3b
                #subres += (exp(-1.j * p) * C_AhAhlA[s, t, u].dot(BA_[t, u]).dot(Vr_[s].conj().T)) #4b
                #subres += (exp(-2.j * p) * AA[t, s].conj().T.dot(l.dot(B[u])).dot(C_AA_Vrh[t, s, u])) #4c
        else:
            for s in xrange(self.q):
                #subres += C_AhlA[s, t].dot(B[s]).dot(Vr_[t].conj().T) #2 OK
                subres += tm.eps_r_noop(B[s], C_AhlA[s, :], Vr_)  #2
                #+ exp(-1.j * p) * A[t].conj().T.dot(l.dot(B[s])).dot(C_A_Vrh_[t, s]) #4 OK with 3
                subres += exp(-1.j * p) * tm.eps_l_noop(
                    l.dot(B[s]), A, C_A_Vrh_[s, :])  #4
                #+ exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_[s, t])).dot(Vr_[t].conj().T)) #12
                subres += exp(-2.j * p) * A[s].conj().T.dot(Mh).dot(
                    tm.eps_r_noop(eye, C_[s, :], Vr_))  #12

        res += l_sqrt_i.dot(subres)

        res += l_sqrt.dot(tm.eps_r_noop(K__r, B, Vri_))  #5

        res += l_sqrt_i.dot(K_l.dot(tm.eps_r_noop(r__sqrt, B, V_)))  #6

        res += sp.exp(-1.j * p) * l_sqrt_i.dot(
            Mh.dot(tm.eps_r_noop(K__r, A_, Vri_)))  #8

        y1 = sp.exp(+1.j * p) * tm.eps_r_noop(K__r, B, A_)  #7

        if self.ham_sites == 3:
            tmp = sp.exp(+1.j * p) * BAA_ + sp.exp(+2.j * p) * ABA_ + sp.exp(
                +3.j * p) * AAB  #9, #11, #11b
            y = y1 + tm.eps_r_op_3s_C123_AAA456(r_, tmp, C_)
        elif self.ham_sites == 2:
            tmp = sp.exp(+1.j * p) * BA_ + sp.exp(+2.j * p) * AB  #9, #11
            y = y1 + tm.eps_r_op_2s_AA12_C34(r_, tmp, C_conj)

        if pseudo:
            y = y - m.adot(l, y) * r_
        y_pi = pinv_1mE(y, [A], [A_],
                        l,
                        r_,
                        p=p,
                        left=False,
                        pseudo=pseudo,
                        out=y_pi_prev,
                        tol=self.pinv_tol,
                        solver=pinv_solver,
                        use_CUDA=self.pinv_CUDA,
                        CUDA_use_batch=self.pinv_CUDA_batch,
                        sanity_checks=self.sanity_checks,
                        sc_data='y_pi')
        #print m.adot(l, y_pi)
        if self.sanity_checks:
            z = y_pi - sp.exp(+1.j * p) * tm.eps_r_noop(y_pi, A, A_)
            tst = la.norm((y - z).ravel()) / la.norm(y.ravel())
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad x_pi. Off by: %g",
                            tst)

        res += l_sqrt.dot(tm.eps_r_noop(y_pi, A, Vri_))

        if self.sanity_checks:
            expval = m.adot(x, res) / m.adot(x, x)
            #print "expval = " + str(expval)
            if expval < -self.sanity_tol:
                log.warning(
                    "Sanity Fail in calc_BHB! H is not pos. semi-definite (%s)",
                    expval)
            if abs(expval.imag) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! H is not Hermitian (%s)",
                            expval)

        return res, M, y_pi
Example #30
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
Example #31
0
    def restore_SCF(self, ret_g=False, zero_tol=None):
        """Restores symmetric canonical form.
        
        In this canonical form, self.l == self.r and are diagonal matrices
        with the Schmidt coefficients corresponding to the half-chain
        decomposition form the diagonal entries.
        
        Parameters
        ----------
        ret_g : bool
            Whether to return the gauge-transformation matrices used.
            
        Returns
        -------
        g, g_i : ndarray
            Gauge transformation matrix g and its inverse g_i.
        """
        if zero_tol is None:
            zero_tol = self.zero_tol
        
        X, Xi = tm.herm_fac_with_inv(self.r, lower=True, zero_tol=zero_tol)
        
        Y, Yi = tm.herm_fac_with_inv(self.l, lower=False, zero_tol=zero_tol)          
            
        U, sv, Vh = la.svd(Y.dot(X))
        
        #s contains the Schmidt coefficients,
        lam = sv**2
        self.S_hc = - np.sum(lam * sp.log2(lam))
        
        S = m.simple_diag_matrix(sv, dtype=self.typ)
        Srt = S.sqrt()
        
        g = m.mmul(Srt, Vh, Xi)
        
        g_i = m.mmul(Yi, U, Srt)
        
        for s in xrange(self.q):
            self.A[s] = m.mmul(g, self.A[s], g_i)
                
        if self.sanity_checks:
            Sfull = np.asarray(S)
            
            if not np.allclose(g.dot(g_i), np.eye(self.D)):
                log.warning("Sanity check failed! Restore_SCF, bad GT!")
            
            l = m.mmul(m.H(g_i), self.l, g_i)
            r = m.mmul(g, self.r, m.H(g))
            
            if not np.allclose(Sfull, l):
                log.warning("Sanity check failed: Restorce_SCF, left failed!")
                
            if not np.allclose(Sfull, r):
                log.warning("Sanity check failed: Restorce_SCF, right failed!")
                
            l = tm.eps_l_noop(Sfull, self.A, self.A)
            r = tm.eps_r_noop(Sfull, self.A, self.A)
            
            if not np.allclose(Sfull, l, rtol=self.itr_rtol*self.check_fac, 
                               atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: Restorce_SCF, left bad!")
                
            if not np.allclose(Sfull, r, rtol=self.itr_rtol*self.check_fac, 
                               atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: Restorce_SCF, right bad!")

        self.l = S
        self.r = S
        
        if ret_g:
            return g, g_i
        else:
            return
Example #32
0
    def restore_RCF(self, update_l=True, normalize=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        This performs two 'almost' gauge transformations, where the 'almost'
        means we allow the norm to vary (if "normalize" = True).
        
        The last step (A[1]) is done diffently to the others since G[0],
        the gauge-transf. matrix, is just a number, which can be found more
        efficiently and accurately without using matrix methods.
        
        The last step (A[1]) is important because, if we have successfully made 
        r[1] = 1 in the previous steps, it fully determines the normalization 
        of the state via r[0] ( = l[N]).
        
        Optionally (normalize=False), the function will not attempt to make
        A[1] satisfy the orthonorm. condition, and will take G[0] = 1 = G[N],
        thus performing a pure gauge-transformation, but not ensuring complete
        canonical form.
        
        It is also possible to begin the process from a site n other than N,
        in case the sites > n are known to be in the desired form already.
        
        It is also possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        normalize : bool
            Whether to also attempt to normalize the state.
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """   
        start = self.N
        
        G_n_i = sp.eye(self.D[start], dtype=self.typ) #This is actually just the number 1
        for n in xrange(start, 1, -1):
            self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(self.A[n], self.r[n], 
                                                         G_n_i, sc_data=('site', n),
                                                         zero_tol=self.zero_tol,
                                                         sanity_checks=self.sanity_checks)
        
        #Now do A[1]...
        #Apply the remaining G[1]^-1 from the previous step.
        for s in xrange(self.q[1]):                
            self.A[1][s] = m.mmul(self.A[1][s], G_n_i)
                    
        #Now finish off
        tm.eps_r_noop_inplace(self.r[1], self.A[1], self.A[1], out=self.r[0])
        
        if normalize:
            G0 = 1. / sp.sqrt(self.r[0].squeeze().real)
            self.A[1] *= G0
            self.r[0][:] = 1
            
            if self.sanity_checks:
                r0 = tm.eps_r_noop(self.r[1], self.A[1], self.A[1])
                if not sp.allclose(r0, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: r_0 is bad / norm failure")

        if diag_l:
            G_nm1 = sp.eye(self.D[0], dtype=self.typ)
            for n in xrange(1, self.N):
                self.l[n], G_nm1, G_nm1_i = tm.restore_RCF_l(self.A[n],
                                                             self.l[n - 1],
                                                             G_nm1,
                                                             self.sanity_checks)

            #Apply remaining G_Nm1 to A[N]
            n = self.N
            for s in xrange(self.q[n]):
                self.A[n][s] = m.mmul(G_nm1, self.A[n][s])

            #Deal with final, scalar l[N]
            tm.eps_l_noop_inplace(self.l[n - 1], self.A[n], self.A[n], out=self.l[n])

            if self.sanity_checks:
                if not sp.allclose(self.l[self.N].real, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: l_N is bad / norm failure")
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)
                
                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning("Sanity Fail in restore_RCF!: r_%u is bad (off by %g)", n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()
Example #33
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
Example #34
0
    def calc_BHB(self, x, p, tdvp, tdvp2, prereq,
                    M_prev=None, y_pi_prev=None, pinv_solver=None):
        if pinv_solver is None:
            pinv_solver = las.gmres
            
        if self.ham_sites == 3:
            return
        else:
            V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp = prereq
        
        A = tdvp.A[0]
        A_ = tdvp2.A[0]
        
        l = tdvp.l[0]
        r_ = tdvp2.r[0]
        
        l_sqrt = tdvp.l_sqrt[0]
        l_sqrt_i = tdvp.l_sqrt_i[0]
        
        r__sqrt = tdvp2.r_sqrt[0]
        r__sqrt_i = tdvp2.r_sqrt_i[0]
        
        K__r = tdvp2.K[0]
        K_l = tdvp.K_left[0]
        
        pseudo = tdvp2 is tdvp
        
        B = tdvp2.get_B_from_x(x, tdvp2.Vsh[0], l_sqrt_i, r__sqrt_i)
        
        #Skip zeros due to rank-deficiency
        if la.norm(B) == 0:
            return sp.zeros_like(x), M_prev, y_pi_prev
        
        if self.sanity_checks:
            tst = tm.eps_r_noop(r_, B, A_)
            if not la.norm(tst) > self.sanity_tol:
                log.warning("Sanity check failed: Gauge-fixing violation! " 
                            + str(la.norm(tst)))

        if self.sanity_checks:
            B2 = np.zeros_like(B)
            for s in xrange(self.q):
                B2[s] = l_sqrt_i.dot(x.dot(m.mmul(V_[s], r__sqrt_i)))
            if la.norm(B - B2) / la.norm(B) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad Vri!")

        y = tm.eps_l_noop(l, B, A)
        
#        if pseudo:
#            y = y - m.adot(r_, y) * l #should just = y due to gauge-fixing
        M = pinv_1mE(y, [A_], [A], l, r_, p=-p, left=True, pseudo=pseudo, 
                     out=M_prev, tol=self.pinv_tol, solver=pinv_solver,
                     use_CUDA=self.pinv_CUDA, CUDA_use_batch=self.pinv_CUDA_batch,
                     sanity_checks=self.sanity_checks, sc_data='M')
        
        #print m.adot(r, M)
        if self.sanity_checks:
            y2 = M - sp.exp(+1.j * p) * tm.eps_l_noop(M, A_, A)
            norm = la.norm(y.ravel())
            if norm == 0:
                norm = 1
            tst = la.norm(y - y2) / norm
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad M. Off by: %g", tst)
#        if pseudo:
#            M = M - l * m.adot(r_, M)
        Mh = M.conj().T.copy(order='C')
        
        res_ls = 0
        res_lsi = 0
        
        exp = sp.exp
        
        if self.ham_sites == 3:
            pass
        else:
            Bo1 = get_Aop(B, _ham_tp, 2, conj=False)
            tmp = sp.empty((B.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')
            tmp3 = sp.empty_like(tmp2, order='C')
            for al in xrange(len(Bo1)):
                tmp3 = m.dot_inplace(tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2), r__sqrt_i, tmp3)
                res_ls += tm.eps_r_noop_inplace(tmp3, Bo1[al], V_, tmp) #1
                
                tmp3 = m.dot_inplace(tm.eps_r_noop_inplace(r_, B, A_o2c[al], tmp2), r__sqrt_i, tmp3)
                tmp = tm.eps_r_noop_inplace(tmp3, Ao1[al], V_, tmp) #3
                tmp *= exp(+1.j * p)
                res_ls += tmp
            del(tmp)
            del(tmp2)
            del(tmp3)
                        
        res_lsi += sp.exp(-1.j * p) * Mh.dot(rhs10) #10
        
        if self.ham_sites == 3:
            pass
        else:
            Bo2 = get_Aop(B, _ham_tp, 3, conj=False)
            for al in xrange(len(AhlAo1)):
                res_lsi += AhlAo1[al].dot(tm.eps_r_noop(r__sqrt, Bo2[al], V_)) #2
                res_lsi += exp(-1.j * p) * tm.eps_l_noop(l, Ao1c[al], B).dot(A_Vr_ho2[al]) #4
                res_lsi += exp(-2.j * p) * tm.eps_l_noop(Mh, Ao1c[al], A_).dot(A_Vr_ho2[al]) #12
                    
        K__rri = m.mmul(K__r, r__sqrt_i)
        res_ls += tm.eps_r_noop(K__rri, B, V_) #5
        
        res_lsi += K_l.dot(tm.eps_r_noop(r__sqrt, B, V_)) #6
        
        res_lsi += sp.exp(-1.j * p) * Mh.dot(tm.eps_r_noop(K__rri, A_, V_)) #8

        y1 = sp.exp(+1.j * p) * tm.eps_r_noop(K__r, B, A_) #7
        
        if self.ham_sites == 3:
            pass
        elif self.ham_sites == 2:
            tmp = 0
            for al in xrange(len(A_A_o12c)):
                tmp += sp.exp(+1.j * p) * tm.eps_r_noop(tm.eps_r_noop(r_, A_, A_A_o12c[al][1]), B, A_A_o12c[al][0]) #9
                tmp += sp.exp(+2.j * p) * tm.eps_r_noop(tm.eps_r_noop(r_, B, A_A_o12c[al][1]), A, A_A_o12c[al][0]) #11
            y = y1 + tmp #7, 9, 11
            del(tmp)
        
        if pseudo:
            y = y - m.adot(l, y) * r_
        y_pi = pinv_1mE(y, [A], [A_], l, r_, p=p, left=False, 
                        pseudo=pseudo, out=y_pi_prev, tol=self.pinv_tol, 
                        solver=pinv_solver, use_CUDA=self.pinv_CUDA,
                        CUDA_use_batch=self.pinv_CUDA_batch,
                        sanity_checks=self.sanity_checks, sc_data='y_pi')
        #print m.adot(l, y_pi)
        if self.sanity_checks:
            z = y_pi - sp.exp(+1.j * p) * tm.eps_r_noop(y_pi, A, A_)
            tst = la.norm((y - z).ravel()) / la.norm(y.ravel())
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad x_pi. Off by: %g", tst)
        
        res_ls += tm.eps_r_noop(m.mmul(y_pi, r__sqrt_i), A, V_)
        
        res = l_sqrt.dot(res_ls)
        res += l_sqrt_i.dot(res_lsi)
        
        if self.sanity_checks:
            expval = m.adot(x, res) / m.adot(x, x)
            #print "expval = " + str(expval)
            if expval < -self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! H is not pos. semi-definite (%s)", expval)
            if abs(expval.imag) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! H is not Hermitian (%s)", expval)
        
        return res, M, y_pi  
Example #35
0
    def calc_BHB(self, x, p, tdvp, tdvp2, prereq,
                    M_prev=None, y_pi_prev=None, pinv_solver=None):
        if pinv_solver is None:
            pinv_solver = las.gmres
            
        if self.ham_sites == 3:
            V_, Vr_, Vri_, Vri_A_, C_, C_Vri_AA_, C_AAA_r_Ah_Vrih, \
                    C_AhAhlAA, C_AA_r_Ah_Vrih_, C_AAA_Vrh_, C_Vri_A_r_Ah_, \
                    C_AhlAA, C_AhlAA_conj, C_AA_Vrh, rhs10 = prereq
        else:
            C_, C_conj, V_, Vr_, Vri_, C_Vri_A_conj, C_AhlA, C_A_Vrh_, rhs10 = prereq
        
        A = tdvp.A[0]
        A_ = tdvp2.A[0]
        AA = tdvp.AA[0]
        
        l = tdvp.l[0]
        r_ = tdvp2.r[0]
        
        l_sqrt = tdvp.l_sqrt[0]
        l_sqrt_i = tdvp.l_sqrt_i[0]
        
        r__sqrt = tdvp2.r_sqrt[0]
        r__sqrt_i = tdvp2.r_sqrt_i[0]
        
        K__r = tdvp2.K[0]
        K_l = tdvp.K_left[0]
        
        pseudo = tdvp2 is tdvp
        
        B = tdvp2.get_B_from_x(x, tdvp2.Vsh[0], l_sqrt_i, r__sqrt_i)
        
        #Skip zeros due to rank-deficiency
        if la.norm(B) == 0:
            return sp.zeros_like(x), M_prev, y_pi_prev
        
        if self.sanity_checks:
            tst = tm.eps_r_noop(r_, B, A_)
            if not la.norm(tst) > self.sanity_tol:
                log.warning("Sanity check failed: Gauge-fixing violation! " 
                            + str(la.norm(tst)))

        if self.sanity_checks:
            B2 = np.zeros_like(B)
            for s in xrange(self.q):
                B2[s] = l_sqrt_i.dot(x.dot(Vri_[s]))
            if la.norm(B - B2) / la.norm(B) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad Vri!")
        
        BA_ = tm.calc_AA(B, A_)
        AB = tm.calc_AA(A, B)
        if self.ham_sites == 3:
            BAA_ = tm.calc_AAA_AA(BA_, A_)
            ABA_ = tm.calc_AAA_AA(AB, A_)
            AAB = tm.calc_AAA_AA(AA, B)

        y = tm.eps_l_noop(l, B, A)
        
#        if pseudo:
#            y = y - m.adot(r_, y) * l #should just = y due to gauge-fixing
        M = pinv_1mE(y, [A_], [A], l, r_, p=-p, left=True, pseudo=pseudo, 
                     out=M_prev, tol=self.pinv_tol, solver=pinv_solver,
                     use_CUDA=self.pinv_CUDA, CUDA_use_batch=self.pinv_CUDA_batch,
                     sanity_checks=self.sanity_checks, sc_data='M')
        
        #print m.adot(r, M)
        if self.sanity_checks:
            y2 = M - sp.exp(+1.j * p) * tm.eps_l_noop(M, A_, A)
            norm = la.norm(y.ravel())
            if norm == 0:
                norm = 1
            tst = la.norm(y - y2) / norm
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad M. Off by: %g", tst)
#        if pseudo:
#            M = M - l * m.adot(r_, M)
        Mh = M.conj().T.copy(order='C')
        
        if self.ham_sites == 3:
            tmp = BAA_ + sp.exp(+1.j * p) * ABA_ + sp.exp(+2.j * p) * AAB
            res = l_sqrt.dot(tm.eps_r_op_3s_C123_AAA456(r_, tmp, C_Vri_AA_)) #1 1D, #3, #3c
        else:
            tmp = BA_ + sp.exp(+1.j * p) * AB
            res = l_sqrt.dot(tm.eps_r_op_2s_AA12_C34(r_, tmp, C_Vri_A_conj)) #1, #3 OK
                    
        res += sp.exp(-1.j * p) * l_sqrt_i.dot(Mh.dot(rhs10)) #10
        
        exp = sp.exp
        subres = sp.zeros_like(res)
        eye = m.eyemat(C_.shape[2], dtype=tdvp.typ)
        eye2 = m.eyemat(A.shape[2], dtype=tdvp.typ)
        if self.ham_sites == 3:
            subres += exp(-2.j * p) * tm.eps_l_noop(Mh, A, C_AAA_r_Ah_Vrih) #12
            subres += exp(-3.j * p) * tm.eps_l_op_2s_AA12_C34(Mh, AA, C_AAA_Vrh_) #12b
            for s in xrange(self.q):
                #subres += exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_AAA_r_Ah_Vrih[s])) #12
                subres += tm.eps_r_noop(B[s], C_AhAhlAA[s, :], Vr_) #2b
                subres += exp(-1.j * p) * tm.eps_l_noop(l.dot(B[s]), A, C_AA_r_Ah_Vrih_[s, :]) #4
                subres += A[s].conj().T.dot(l.dot(tm.eps_r_op_2s_AA12_C34(eye2, AB, C_Vri_A_r_Ah_[s, :, :]))) #2 -ive of that it should be....
                subres += exp(-1.j * p) * tm.eps_l_op_2s_AA12_C34(eye2, C_AhlAA_conj[s, :, :], BA_).dot(Vr_[s].conj().T) #4b
                subres += exp(-2.j * p) * tm.eps_l_op_2s_AA12_C34(l.dot(B[s]), AA, C_AA_Vrh[s, :, :]) #4c
                subres += exp(+1.j * p) * tm.eps_r_op_2s_AA12_C34(r_.dot_left(B[s]), C_AhlAA[s, :, :], Vri_A_) #3b
                #for t in xrange(self.q):
                    #subres += (C_AhAhlAA[t, s].dot(B[s]).dot(Vr_[t].conj().T)) #2b
                    #subres += (exp(-1.j * p) * A[s].conj().T.dot(l.dot(B[t])).dot(C_AA_r_Ah_Vrih_[s, t])) #4
                    #subres += (exp(-3.j * p) * AA[t, s].conj().T.dot(Mh).dot(C_AAA_Vrh_[t, s])) #12b
                    
                    #for u in xrange(self.q):
                        #subres += A[s].conj().T.dot(l.dot(AB[t, u]).dot(C_A_r_Ah_Vrih[s, t, u])) #2 -ive of that it should be....
                        #subres += (exp(+1.j * p) * C_AhlAA[t, s, s].dot(B[u]).dot(r_.dot(A_[u].conj().T)).dot(Vri_[t].conj().T)) #3b
                        #subres += (exp(-1.j * p) * C_AhAhlA[s, t, u].dot(BA_[t, u]).dot(Vr_[s].conj().T)) #4b
                        #subres += (exp(-2.j * p) * AA[t, s].conj().T.dot(l.dot(B[u])).dot(C_AA_Vrh[t, s, u])) #4c
        else:
            for s in xrange(self.q):
                #subres += C_AhlA[s, t].dot(B[s]).dot(Vr_[t].conj().T) #2 OK
                subres += tm.eps_r_noop(B[s], C_AhlA[s, :], Vr_) #2
                #+ exp(-1.j * p) * A[t].conj().T.dot(l.dot(B[s])).dot(C_A_Vrh_[t, s]) #4 OK with 3
                subres += exp(-1.j * p) * tm.eps_l_noop(l.dot(B[s]), A, C_A_Vrh_[s, :]) #4
                #+ exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_[s, t])).dot(Vr_[t].conj().T)) #12
                subres += exp(-2.j * p) * A[s].conj().T.dot(Mh).dot(tm.eps_r_noop(eye, C_[s, :], Vr_)) #12
                    
        res += l_sqrt_i.dot(subres)
        
        res += l_sqrt.dot(tm.eps_r_noop(K__r, B, Vri_)) #5
        
        res += l_sqrt_i.dot(K_l.dot(tm.eps_r_noop(r__sqrt, B, V_))) #6
        
        res += sp.exp(-1.j * p) * l_sqrt_i.dot(Mh.dot(tm.eps_r_noop(K__r, A_, Vri_))) #8
        
        y1 = sp.exp(+1.j * p) * tm.eps_r_noop(K__r, B, A_) #7
        
        if self.ham_sites == 3:
            tmp = sp.exp(+1.j * p) * BAA_ + sp.exp(+2.j * p) * ABA_ + sp.exp(+3.j * p) * AAB #9, #11, #11b
            y = y1 + tm.eps_r_op_3s_C123_AAA456(r_, tmp, C_)
        elif self.ham_sites == 2:
            tmp = sp.exp(+1.j * p) * BA_ + sp.exp(+2.j * p) * AB #9, #11
            y = y1 + tm.eps_r_op_2s_AA12_C34(r_, tmp, C_conj)
        
        if pseudo:
            y = y - m.adot(l, y) * r_
        y_pi = pinv_1mE(y, [A], [A_], l, r_, p=p, left=False, 
                        pseudo=pseudo, out=y_pi_prev, tol=self.pinv_tol, 
                        solver=pinv_solver, use_CUDA=self.pinv_CUDA,
                        CUDA_use_batch=self.pinv_CUDA_batch,
                        sanity_checks=self.sanity_checks, sc_data='y_pi')
        #print m.adot(l, y_pi)
        if self.sanity_checks:
            z = y_pi - sp.exp(+1.j * p) * tm.eps_r_noop(y_pi, A, A_)
            tst = la.norm((y - z).ravel()) / la.norm(y.ravel())
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad x_pi. Off by: %g", tst)
        
        res += l_sqrt.dot(tm.eps_r_noop(y_pi, A, Vri_))
        
        if self.sanity_checks:
            expval = m.adot(x, res) / m.adot(x, x)
            #print "expval = " + str(expval)
            if expval < -self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! H is not pos. semi-definite (%s)", expval)
            if abs(expval.imag) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! H is not Hermitian (%s)", expval)
        
        return res, M, y_pi   
Example #36
0
    def restore_CF(self, dbg=False):
        if dbg:
            self.calc_l()
            self.calc_r()
            self.simple_renorm()
            print "BEFORE..."
            h_before, h_left_before, h_right_before = self.restore_CF_dbg()

            print (h_left_before, h_before, h_right_before)

        self.uni_l.A = self.uni_l.A #.copy()
        #self.uni_l.l = self.uni_l.l.copy()
        #r_old = self.uni_l.r.copy()
        self.uni_l.calc_lr() #Ensures largest ev of E=1
        if dbg:
            print "uni_l calc_lr iterations: ", (self.uni_l.itr_l, self.uni_l.itr_r)
        #uniform calc_lr() scales for RCF, but we have LCF,
        #so we have to correct the scaling here
        fac = self.uni_l.D / self.uni_l.l.trace().real
        if dbg:
            print "Scale l[0]: %g" % fac
        self.uni_l.l *= fac
        self.uni_l.r *= 1/fac

#        if self.sanity_checks:
#            if not sp.allclose(self.uni_l.l, self.l[0], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: True l[0] and l[L] mismatch!", la.norm(self.l[0] - self.uni_l.l)
#
#            if not sp.allclose(self.uni_l.r, r_old, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: Bad r[L]!", la.norm(r_old - self.uni_l.r)
#
#            if not sp.allclose(self.uni_l.A, self.A[0], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: A[0] was scaled!", la.norm(self.A[0] - self.uni_l.A)

        #self.uni_l.l = self.l[0]
        #self.uni_l.r = r_old
        #self.uni_l.A = self.A[0]
        self.l[0] = self.uni_l.l
        self.A[0] = self.uni_l.A

        self.uni_r.A = self.uni_r.A #.copy()
        self.uni_r.r = self.uni_r.r #.copy()
        #l_old = self.uni_r.l.copy()
        self.uni_r.calc_lr() #Ensures largest ev of E=1
        if dbg:
            print "uni_r calc_lr iterations: ", (self.uni_r.itr_l, self.uni_r.itr_r)
#        if self.sanity_checks:
#            if not sp.allclose(self.uni_r.A, self.A[self.N + 1], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: A[R] was scaled! ", la.norm(self.A[self.N + 1] - self.uni_r.A)
#
#            if not sp.allclose(l_old, self.uni_r.l, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: Bad l[R]! ", la.norm(l_old - self.uni_r.l)
#
#            if not sp.allclose(self.r[self.N], self.uni_r.r, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: r[N] and r[R] mismatch!", la.norm(self.r[self.N] - self.uni_r.r)

        self.r[self.N] = self.uni_r.r
        self.A[self.N + 1] = self.uni_r.A

        self._restore_CF_ONR()

        nc = self.N_centre
        self.r[nc - 1] = tm.eps_r_noop(self.r[nc], self.A[nc], self.A[nc])
        self.simple_renorm(update_lr=False)

        if dbg:
            self.calc_l()
            self.calc_r()
            print "AFTER ONR..."
            h_mid, h_left_mid, h_right_mid = self.restore_CF_dbg()

            print (h_left_mid, h_mid, h_right_mid)

        self._restore_CF_diag()

        #l[0] is identity, r_L = ?
        self.uni_l.A = self.A[0]
        self.uni_l.l = self.l[0]
        self.uni_l.l_before_CF = self.uni_l.l
        self.uni_l.r_before_CF = self.uni_l.r

        #r[N] is identity, l_R = ?
        self.uni_r.A = self.A[self.N + 1]
        self.uni_r.r = self.r[self.N]
        self.uni_r.l_before_CF = self.uni_r.l
        self.uni_r.r_before_CF = self.uni_r.r

        #Set l[N + 1] as well...
        self.l[self.N + 1][:] = tm.eps_l_noop(self.l[self.N],
                                              self.A[self.N + 1],
                                              self.A[self.N + 1])

        if self.sanity_checks:
            l_n = self.l[0]
            for n in xrange(0, self.N + 1):
                l_n = tm.eps_l_noop(l_n, self.A[n], self.A[n])
                if not sp.allclose(l_n, self.l[n], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_CF!: l_%u is bad" % n

            r_nm1 = self.r[self.N + 1]
            for n in reversed(xrange(1, self.N + 2)):
                r_nm1 = tm.eps_r_noop(r_nm1, self.A[n], self.A[n])
                if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_CF!: r_%u is bad" % (n - 1)
        if dbg:
            print "AFTER..."
            h_after, h_left_after, h_right_after = self.restore_CF_dbg()

            print (h_left_after, h_after, h_right_after)

            print h_after - h_before

            print (h_after.sum() - h_before.sum() + h_left_after - h_left_before
                   + h_right_after - h_right_before)
Example #37
0
    def calc_B_centre(self):
        """Calculate the optimal B_centre given right gauge-fixing on n_centre+1..N and
        left gauge-fixing on 1..n_centre-1.
        
        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.
        """
        Bc = sp.empty_like(self.A[self.N_centre])

        Nc = self.N_centre

        try:
            rc_i = self.r[Nc].inv()
        except AttributeError:
            rc_i = mm.invmh(self.r[Nc])

        try:
            lcm1_i = self.l[Nc - 1].inv()
        except AttributeError:
            lcm1_i = mm.invmh(self.l[Nc - 1])

        Acm1 = self.A[Nc - 1]
        Ac = self.A[Nc]
        Acp1 = self.A[Nc + 1]
        rc = self.r[Nc]
        rcp1 = self.r[Nc + 1]
        lcm1 = self.l[Nc - 1]
        lcm2 = self.l[Nc - 2]

        #Note: this is a 'bra-vector'
        K_l_cm1 = self.K_l[Nc - 1] - lcm1 * mm.adot_noconj(
            self.K_l[Nc - 1], self.r[Nc - 1])

        Kcp1 = self.K[Nc + 1] - rc * mm.adot(self.l[Nc], self.K[Nc + 1])

        Cc = self.C[Nc] - self.h_expect[Nc] * self.AAc
        Ccm1 = self.C[Nc - 1] - self.h_expect[Nc - 1] * self.AAcm1

        for s in xrange(self.q[1]):
            try:  #3
                Bc[s] = Ac[s].dot(rc_i.dot_left(Kcp1))
            except AttributeError:
                Bc[s] = Ac[s].dot(Kcp1.dot(rc_i))

            for t in xrange(self.q[2]):  #1
                try:
                    Bc[s] += Cc[s,
                                t].dot(rcp1.dot(rc_i.dot_left(mm.H(Acp1[t]))))
                except AttributeError:
                    Bc[s] += Cc[s, t].dot(rcp1.dot(mm.H(Acp1[t]).dot(rc_i)))

            Bcsbit = K_l_cm1.dot(Ac[s])  #4

            for t in xrange(self.q[0]):  #2
                Bcsbit += mm.H(Acm1[t]).dot(lcm2.dot(Ccm1[t, s]))

            Bc[s] += lcm1_i.dot(Bcsbit)

        rb = tm.eps_r_noop(rc, Bc, Bc)
        eta = sp.sqrt(mm.adot(lcm1, rb))

        return Bc, eta
Example #38
0
    def calc_B_centre(self):
        """Calculate the optimal B_centre given right gauge-fixing on n_centre+1..N and
        left gauge-fixing on 1..n_centre-1.
        
        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.
        """
        Bc = sp.empty_like(self.A[self.N_centre])
        
        Nc = self.N_centre

        try:
            rc_i = self.r[Nc].inv()
        except AttributeError:
            rc_i = mm.invmh(self.r[Nc])
            
        try:
            lcm1_i = self.l[Nc - 1].inv()
        except AttributeError:
            lcm1_i = mm.invmh(self.l[Nc - 1])
        
        Acm1 = self.A[Nc - 1]
        Ac = self.A[Nc]
        Acp1 = self.A[Nc + 1]
        rc = self.r[Nc]
        rcp1 = self.r[Nc + 1]
        lcm1 = self.l[Nc - 1]
        lcm2 = self.l[Nc - 2]
        
        #Note: this is a 'bra-vector'
        K_l_cm1 = self.K_l[Nc - 1] - lcm1 * mm.adot_noconj(self.K_l[Nc - 1], self.r[Nc - 1])
        
        Kcp1 = self.K[Nc + 1] - rc * mm.adot(self.l[Nc], self.K[Nc + 1])
        
        Cc = self.C[Nc] - self.h_expect[Nc] * self.AAc
        Ccm1 = self.C[Nc - 1] - self.h_expect[Nc - 1] * self.AAcm1
        
        for s in xrange(self.q[1]):
            try: #3
                Bc[s] = Ac[s].dot(rc_i.dot_left(Kcp1))
            except AttributeError:
                Bc[s] = Ac[s].dot(Kcp1.dot(rc_i))
            
            for t in xrange(self.q[2]): #1
                try:
                    Bc[s] += Cc[s, t].dot(rcp1.dot(rc_i.dot_left(mm.H(Acp1[t]))))
                except AttributeError:
                    Bc[s] += Cc[s, t].dot(rcp1.dot(mm.H(Acp1[t]).dot(rc_i)))                    
                
            Bcsbit = K_l_cm1.dot(Ac[s]) #4
                            
            for t in xrange(self.q[0]): #2
                Bcsbit += mm.H(Acm1[t]).dot(lcm2.dot(Ccm1[t,s]))
                
            Bc[s] += lcm1_i.dot(Bcsbit)
           
        rb = tm.eps_r_noop(rc, Bc, Bc)
        eta = sp.sqrt(mm.adot(lcm1, rb))
                
        return Bc, eta
Example #39
0
    def calc_B(self, n, set_eta=True):
        """Generates the B[n] tangent vector corresponding to physical evolution of the state.

        In other words, this returns B[n][x*] (equiv. eqn. (47) of
        arXiv:1103.0936v2 [cond-mat.str-el])
        with x* the parameter matrices satisfying the Euler-Lagrange equations
        as closely as possible.
        
        In the case of Bc, use the general Bc generated in calc_B_centre().
        """
        if n == self.N_centre:
            B, eta_c = self.calc_B_centre()
            if set_eta:
                self.eta[self.N_centre] = eta_c
        else:
            l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv = self.calc_l_r_roots(n)

            if n > self.N_centre:
                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,
                                right=True)

                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)

                if self.sanity_checks:
                    M = tm.eps_r_noop(self.r[n], B, self.A[n])
                    if not sp.allclose(M, 0):
                        print "Sanity Fail in calc_B!: B_%u does not satisfy GFC!" % n
            else:
                Vsh = tm.calc_Vsh_l(self.A[n],
                                    l_sqrt,
                                    sanity_checks=self.sanity_checks)
                x = self.calc_x(n,
                                Vsh,
                                l_sqrt,
                                r_sqrt,
                                l_sqrt_inv,
                                r_sqrt_inv,
                                right=False)

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

                if self.sanity_checks:
                    M = tm.eps_l_noop(self.l[n - 1], B, self.A[n])
                    if not sp.allclose(M, 0):
                        print "Sanity Fail in calc_B!: B_%u does not satisfy GFC!" % n

            if set_eta:
                self.eta[n] = sp.sqrt(mm.adot(x, x))

        return B
Example #40
0
    def restore_CF(self, dbg=False):
        if dbg:
            self.calc_l()
            self.calc_r()
            self.simple_renorm()
            print "BEFORE..."
            h_before, h_left_before, h_right_before = self.restore_CF_dbg()

            print (h_left_before, h_before, h_right_before)

        self.uni_l.calc_lr() #Ensures largest ev of E=1
        if dbg:
            print "uni_l calc_lr iterations: ", (self.uni_l.itr_l, self.uni_l.itr_r)

#        if self.sanity_checks:
#            if not sp.allclose(self.uni_l.l, self.l[0], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: True l[0] and l[L] mismatch!", la.norm(self.l[0] - self.uni_l.l)
#
#            if not sp.allclose(self.uni_l.r, r_old, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: Bad r[L]!", la.norm(r_old - self.uni_l.r)
#
#            if not sp.allclose(self.uni_l.A, self.A[0], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: A[0] was scaled!", la.norm(self.A[0] - self.uni_l.A)

        self.l[0] = self.uni_l.l[-1]
        self.A[0] = None

        self.uni_r.calc_lr() #Ensures largest ev of E=1
        if dbg:
            print "uni_r calc_lr iterations: ", (self.uni_r.itr_l, self.uni_r.itr_r)
#        if self.sanity_checks:
#            if not sp.allclose(self.uni_r.A, self.A[self.N + 1], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: A[R] was scaled! ", la.norm(self.A[self.N + 1] - self.uni_r.A)
#
#            if not sp.allclose(l_old, self.uni_r.l, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: Bad l[R]! ", la.norm(l_old - self.uni_r.l)
#
#            if not sp.allclose(self.r[self.N], self.uni_r.r, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: r[N] and r[R] mismatch!", la.norm(self.r[self.N] - self.uni_r.r)

        self.r[self.N] = self.uni_r.r[-1]
        self.A[self.N + 1] = None

        self._restore_CF_ONR()

        nc = self.N_centre
        self.r[nc - 1] = tm.eps_r_noop(self.r[nc], self.A[nc], self.A[nc])
        self.simple_renorm(update_lr=False)

        if dbg:
            self.calc_l()
            self.calc_r()
            print "AFTER ONR..."
            h_mid, h_left_mid, h_right_mid = self.restore_CF_dbg()

            print (h_left_mid, h_mid, h_right_mid)

        self._restore_CF_diag(dbg=dbg)

        #l[0] is identity, r_L = ?
        self.uni_l.l_before_CF = self.uni_l.l[-1]
        self.uni_l.r_before_CF = self.uni_l.r[-1]

        #r[N] is identity, l_R = ?
        self.uni_r.l_before_CF = self.uni_r.l[-1]
        self.uni_r.r_before_CF = self.uni_r.r[-1]

        #Set l[N + 1] as well...
        self.l[self.N + 1][:] = tm.eps_l_noop(self.l[self.N],
                                              self.uni_r.A[0],
                                              self.uni_r.A[0])

        if self.sanity_checks:
            l_n = self.l[0]
            for n in xrange(1, self.N + 1):
                l_n = tm.eps_l_noop(l_n, self.A[n], self.A[n])
                if not sp.allclose(l_n, self.l[n], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_CF!: l_%u is bad" % n

            r_nm1 = self.r[self.N]
            for n in reversed(xrange(1, self.N)):
                r_nm1 = tm.eps_r_noop(r_nm1, self.A[n], self.A[n])
                if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_CF!: r_%u is bad" % (n - 1)
        if dbg:
            print "AFTER..."
            h_after, h_left_after, h_right_after = self.restore_CF_dbg()

            print (h_left_after, h_after, h_right_after)

            print h_after - h_before

            print (h_after.sum() - h_before.sum() + h_left_after - h_left_before
                   + h_right_after - h_right_before)
Example #41
0
    def restore_CF(self, dbg=False):
        if dbg:
            self.calc_l()
            self.calc_r()
            self.simple_renorm()
            print "BEFORE..."
            h_before, h_left_before, h_right_before = self.restore_CF_dbg()

            print(h_left_before, h_before, h_right_before)

        self.uni_l.calc_lr()  #Ensures largest ev of E=1
        if dbg:
            print "uni_l calc_lr iterations: ", (self.uni_l.itr_l,
                                                 self.uni_l.itr_r)

#        if self.sanity_checks:
#            if not sp.allclose(self.uni_l.l, self.l[0], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: True l[0] and l[L] mismatch!", la.norm(self.l[0] - self.uni_l.l)
#
#            if not sp.allclose(self.uni_l.r, r_old, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: Bad r[L]!", la.norm(r_old - self.uni_l.r)
#
#            if not sp.allclose(self.uni_l.A, self.A[0], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: A[0] was scaled!", la.norm(self.A[0] - self.uni_l.A)

        self.l[0] = self.uni_l.l[-1]
        self.A[0] = None

        self.uni_r.calc_lr()  #Ensures largest ev of E=1
        if dbg:
            print "uni_r calc_lr iterations: ", (self.uni_r.itr_l,
                                                 self.uni_r.itr_r)
#        if self.sanity_checks:
#            if not sp.allclose(self.uni_r.A, self.A[self.N + 1], atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: A[R] was scaled! ", la.norm(self.A[self.N + 1] - self.uni_r.A)
#
#            if not sp.allclose(l_old, self.uni_r.l, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: Bad l[R]! ", la.norm(l_old - self.uni_r.l)
#
#            if not sp.allclose(self.r[self.N], self.uni_r.r, atol=1E-12, rtol=1E-12):
#                print "Sanity Fail in restore_CF!: r[N] and r[R] mismatch!", la.norm(self.r[self.N] - self.uni_r.r)

        self.r[self.N] = self.uni_r.r[-1]
        self.A[self.N + 1] = None

        self._restore_CF_ONR()

        nc = self.N_centre
        self.r[nc - 1] = tm.eps_r_noop(self.r[nc], self.A[nc], self.A[nc])
        self.simple_renorm(update_lr=False)

        if dbg:
            self.calc_l()
            self.calc_r()
            print "AFTER ONR..."
            h_mid, h_left_mid, h_right_mid = self.restore_CF_dbg()

            print(h_left_mid, h_mid, h_right_mid)

        self._restore_CF_diag(dbg=dbg)

        #l[0] is identity, r_L = ?
        self.uni_l.l_before_CF = self.uni_l.l[-1]
        self.uni_l.r_before_CF = self.uni_l.r[-1]

        #r[N] is identity, l_R = ?
        self.uni_r.l_before_CF = self.uni_r.l[-1]
        self.uni_r.r_before_CF = self.uni_r.r[-1]

        #Set l[N + 1] as well...
        self.l[self.N + 1][:] = tm.eps_l_noop(self.l[self.N], self.uni_r.A[0],
                                              self.uni_r.A[0])

        if self.sanity_checks:
            l_n = self.l[0]
            for n in xrange(1, self.N + 1):
                l_n = tm.eps_l_noop(l_n, self.A[n], self.A[n])
                if not sp.allclose(l_n, self.l[n], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_CF!: l_%u is bad" % n

            r_nm1 = self.r[self.N]
            for n in reversed(xrange(1, self.N)):
                r_nm1 = tm.eps_r_noop(r_nm1, self.A[n], self.A[n])
                if not sp.allclose(
                        r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_CF!: r_%u is bad" % (n - 1)
        if dbg:
            print "AFTER..."
            h_after, h_left_after, h_right_after = self.restore_CF_dbg()

            print(h_left_after, h_after, h_right_after)

            print h_after - h_before

            print(h_after.sum() - h_before.sum() + h_left_after -
                  h_left_before + h_right_after - h_right_before)
Example #42
0
    def calc_BHB(self,
                 x,
                 p,
                 tdvp,
                 tdvp2,
                 prereq,
                 M_prev=None,
                 y_pi_prev=None,
                 pinv_solver=None):
        if pinv_solver is None:
            pinv_solver = las.gmres

        if self.ham_sites == 3:
            return
        else:
            V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp = prereq

        A = tdvp.A[0]
        A_ = tdvp2.A[0]

        l = tdvp.l[0]
        r_ = tdvp2.r[0]

        l_sqrt = tdvp.l_sqrt[0]
        l_sqrt_i = tdvp.l_sqrt_i[0]

        r__sqrt = tdvp2.r_sqrt[0]
        r__sqrt_i = tdvp2.r_sqrt_i[0]

        K__r = tdvp2.K[0]
        K_l = tdvp.K_left[0]

        pseudo = tdvp2 is tdvp

        B = tdvp2.get_B_from_x(x, tdvp2.Vsh[0], l_sqrt_i, r__sqrt_i)

        #Skip zeros due to rank-deficiency
        if la.norm(B) == 0:
            return sp.zeros_like(x), M_prev, y_pi_prev

        if self.sanity_checks:
            tst = tm.eps_r_noop(r_, B, A_)
            if not la.norm(tst) > self.sanity_tol:
                log.warning("Sanity check failed: Gauge-fixing violation! " +
                            str(la.norm(tst)))

        if self.sanity_checks:
            B2 = np.zeros_like(B)
            for s in xrange(self.q):
                B2[s] = l_sqrt_i.dot(x.dot(m.mmul(V_[s], r__sqrt_i)))
            if la.norm(B - B2) / la.norm(B) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad Vri!")

        y = tm.eps_l_noop(l, B, A)

        #        if pseudo:
        #            y = y - m.adot(r_, y) * l #should just = y due to gauge-fixing
        M = pinv_1mE(y, [A_], [A],
                     l,
                     r_,
                     p=-p,
                     left=True,
                     pseudo=pseudo,
                     out=M_prev,
                     tol=self.pinv_tol,
                     solver=pinv_solver,
                     use_CUDA=self.pinv_CUDA,
                     CUDA_use_batch=self.pinv_CUDA_batch,
                     sanity_checks=self.sanity_checks,
                     sc_data='M')

        #print m.adot(r, M)
        if self.sanity_checks:
            y2 = M - sp.exp(+1.j * p) * tm.eps_l_noop(M, A_, A)
            norm = la.norm(y.ravel())
            if norm == 0:
                norm = 1
            tst = la.norm(y - y2) / norm
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad M. Off by: %g", tst)


#        if pseudo:
#            M = M - l * m.adot(r_, M)
        Mh = M.conj().T.copy(order='C')

        res_ls = 0
        res_lsi = 0

        exp = sp.exp

        if self.ham_sites == 3:
            pass
        else:
            Bo1 = get_Aop(B, _ham_tp, 2, conj=False)
            tmp = sp.empty((B.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')
            tmp3 = sp.empty_like(tmp2, order='C')
            for al in xrange(len(Bo1)):
                tmp3 = m.dot_inplace(
                    tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2), r__sqrt_i,
                    tmp3)
                res_ls += tm.eps_r_noop_inplace(tmp3, Bo1[al], V_, tmp)  #1

                tmp3 = m.dot_inplace(
                    tm.eps_r_noop_inplace(r_, B, A_o2c[al], tmp2), r__sqrt_i,
                    tmp3)
                tmp = tm.eps_r_noop_inplace(tmp3, Ao1[al], V_, tmp)  #3
                tmp *= exp(+1.j * p)
                res_ls += tmp
            del (tmp)
            del (tmp2)
            del (tmp3)

        res_lsi += sp.exp(-1.j * p) * Mh.dot(rhs10)  #10

        if self.ham_sites == 3:
            pass
        else:
            Bo2 = get_Aop(B, _ham_tp, 3, conj=False)
            for al in xrange(len(AhlAo1)):
                res_lsi += AhlAo1[al].dot(tm.eps_r_noop(r__sqrt, Bo2[al],
                                                        V_))  #2
                res_lsi += exp(-1.j * p) * tm.eps_l_noop(l, Ao1c[al], B).dot(
                    A_Vr_ho2[al])  #4
                res_lsi += exp(-2.j * p) * tm.eps_l_noop(Mh, Ao1c[al], A_).dot(
                    A_Vr_ho2[al])  #12

        K__rri = m.mmul(K__r, r__sqrt_i)
        res_ls += tm.eps_r_noop(K__rri, B, V_)  #5

        res_lsi += K_l.dot(tm.eps_r_noop(r__sqrt, B, V_))  #6

        res_lsi += sp.exp(-1.j * p) * Mh.dot(tm.eps_r_noop(K__rri, A_, V_))  #8

        y1 = sp.exp(+1.j * p) * tm.eps_r_noop(K__r, B, A_)  #7

        if self.ham_sites == 3:
            pass
        elif self.ham_sites == 2:
            tmp = 0
            for al in xrange(len(A_A_o12c)):
                tmp += sp.exp(+1.j * p) * tm.eps_r_noop(
                    tm.eps_r_noop(r_, A_, A_A_o12c[al][1]), B,
                    A_A_o12c[al][0])  #9
                tmp += sp.exp(+2.j * p) * tm.eps_r_noop(
                    tm.eps_r_noop(r_, B, A_A_o12c[al][1]), A,
                    A_A_o12c[al][0])  #11
            y = y1 + tmp  #7, 9, 11
            del (tmp)

        if pseudo:
            y = y - m.adot(l, y) * r_
        y_pi = pinv_1mE(y, [A], [A_],
                        l,
                        r_,
                        p=p,
                        left=False,
                        pseudo=pseudo,
                        out=y_pi_prev,
                        tol=self.pinv_tol,
                        solver=pinv_solver,
                        use_CUDA=self.pinv_CUDA,
                        CUDA_use_batch=self.pinv_CUDA_batch,
                        sanity_checks=self.sanity_checks,
                        sc_data='y_pi')
        #print m.adot(l, y_pi)
        if self.sanity_checks:
            z = y_pi - sp.exp(+1.j * p) * tm.eps_r_noop(y_pi, A, A_)
            tst = la.norm((y - z).ravel()) / la.norm(y.ravel())
            if tst > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! Bad x_pi. Off by: %g",
                            tst)

        res_ls += tm.eps_r_noop(m.mmul(y_pi, r__sqrt_i), A, V_)

        res = l_sqrt.dot(res_ls)
        res += l_sqrt_i.dot(res_lsi)

        if self.sanity_checks:
            expval = m.adot(x, res) / m.adot(x, x)
            #print "expval = " + str(expval)
            if expval < -self.sanity_tol:
                log.warning(
                    "Sanity Fail in calc_BHB! H is not pos. semi-definite (%s)",
                    expval)
            if abs(expval.imag) > self.sanity_tol:
                log.warning("Sanity Fail in calc_BHB! H is not Hermitian (%s)",
                            expval)

        return res, M, y_pi
Example #43
0
    def calc_lr(self):
        """Determines the dominant left and right eigenvectors of the transfer 
        operator E.
        
        Uses an iterative method (e.g. Arnoldi iteration) to determine the
        largest eigenvalue and the correspoinding left and right eigenvectors,
        which are stored as self.l and self.r respectively.
        
        The parameter tensor self.A is rescaled so that the largest eigenvalue
        is equal to 1 (thus normalizing the state).
        
        The largest eigenvalue is assumed to be non-degenerate.
        
        """
        tmp = np.empty_like(self.tmp)
        
        #Make sure...
        self.l_before_CF = np.asarray(self.l_before_CF)
        self.r_before_CF = np.asarray(self.r_before_CF)
        
        if self.ev_use_arpack:
            self.l, self.conv_l, self.itr_l = self._calc_lr_ARPACK(self.l_before_CF, tmp,
                                                   calc_l=True,
                                                   tol=self.itr_rtol,
                                                   k=self.ev_arpack_nev,
                                                   ncv=self.ev_arpack_ncv)
        else:
            self.l, self.conv_l, self.itr_l = self._calc_lr(self.l_before_CF, 
                                                    tmp, 
                                                    calc_l=True,
                                                    max_itr=self.pow_itr_max,
                                                    rtol=self.itr_rtol, 
                                                    atol=self.itr_atol)
                                        
        self.l_before_CF = self.l.copy()

        if self.ev_use_arpack:
            self.r, self.conv_r, self.itr_r = self._calc_lr_ARPACK(self.r_before_CF, tmp, 
                                                   calc_l=False,
                                                   tol=self.itr_rtol,
                                                   k=self.ev_arpack_nev,
                                                   ncv=self.ev_arpack_ncv)
        else:
            self.r, self.conv_r, self.itr_r = self._calc_lr(self.r_before_CF, 
                                                    tmp, 
                                                    calc_l=False,
                                                    max_itr=self.pow_itr_max,
                                                    rtol=self.itr_rtol, 
                                                    atol=self.itr_atol)
        self.r_before_CF = self.r.copy()
            
        #normalize eigenvectors:

        if self.symm_gauge:
            norm = m.adot(self.l, self.r).real
            itr = 0 
            while not np.allclose(norm, 1, atol=1E-13, rtol=0) and itr < 10:
                self.l *= 1. / ma.sqrt(norm)
                self.r *= 1. / ma.sqrt(norm)
                
                norm = m.adot(self.l, self.r).real
                
                itr += 1
                
            if itr == 10:
                log.warning("Warning: Max. iterations reached during normalization!")
        else:
            fac = self.D / np.trace(self.r).real
            self.l *= 1 / fac
            self.r *= fac

            norm = m.adot(self.l, self.r).real
            itr = 0 
            while not np.allclose(norm, 1, atol=1E-13, rtol=0) and itr < 10:
                self.l *= 1. / norm
                norm = m.adot(self.l, self.r).real
                itr += 1
                
            if itr == 10:
                log.warning("Warning: Max. iterations reached during normalization!")

        if self.sanity_checks:
            if not np.allclose(tm.eps_l_noop(self.l, self.A, self.A), self.l,
            rtol=self.itr_rtol*self.check_fac, 
            atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: Left eigenvector bad! Off by: %s",
                            la.norm(tm.eps_l_noop(self.l, self.A, self.A) - self.l))
                       
            if not np.allclose(tm.eps_r_noop(self.r, self.A, self.A), self.r,
            rtol=self.itr_rtol*self.check_fac,
            atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: Right eigenvector bad! Off by: %s",
                            la.norm(tm.eps_r_noop(self.r, self.A, self.A) - self.r))
            
            if not np.allclose(self.l, m.H(self.l),
            rtol=self.itr_rtol*self.check_fac, 
            atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: l is not hermitian!")

            if not np.allclose(self.r, m.H(self.r),
            rtol=self.itr_rtol*self.check_fac, 
            atol=self.itr_atol*self.check_fac):
                log.warning("Sanity check failed: r is not hermitian!")
            
            if not np.all(la.eigvalsh(self.l) > 0):
                log.warning("Sanity check failed: l is not pos. def.!")
                
            if not np.all(la.eigvalsh(self.r) > 0):
                log.warning("Sanity check failed: r is not pos. def.!")
            
            norm = m.adot(self.l, self.r)
            if not np.allclose(norm, 1.0, atol=1E-13, rtol=0):
                log.warning("Sanity check failed: Bad norm = %s", norm)
Example #44
0
    def overlap(self, other, sanity_checks=False):
        if not self.N == other.N:
            print "States must have same number of non-uniform sites!"
            return

        if not sp.all(self.D == other.D):
            print "States must have same bond-dimensions!"
            return

        if not sp.all(self.q == other.q):
            print "States must have same Hilbert-space dimensions!"
            return

        dL, phiL, gLl = self.uni_l.fidelity_per_site(other.uni_l, full_output=True, left=True)

        dR, phiR, gRr = self.uni_r.fidelity_per_site(other.uni_r, full_output=True, left=False)

        gLl = gLl.reshape(self.uni_l.D, self.uni_l.D)
        gRr = gRr.reshape(self.uni_r.D, self.uni_r.D)

        gr = mm.H(la.inv(gRr).dot(sp.asarray(self.uni_r.r[-1])))
        gri = mm.H(la.inv(sp.asarray(self.uni_r.r[-1])).dot(gRr))

#        if sanity_checks: #FIXME: Not gonna work for L > 1....
#            AR = other.uni_r.A.copy()
#            for s in xrange(AR.shape[0]):
#                AR[s] = gr.dot(AR[s]).dot(gri)
#
#            print la.norm(AR - self.uni_r.A)

        r = gr.dot(sp.asarray(other.uni_r.r)).dot(mm.H(gr))
        fac = la.norm(sp.asarray(self.uni_r.r)) / la.norm(r)
        gr *= sp.sqrt(fac)
        gri /= sp.sqrt(fac)

        if sanity_checks:
            r *= fac
            print la.norm(r - self.uni_r.r[-1])

#            AN = other.A[self.N].copy()
#            for s in xrange(AN.shape[0]):
#                AN[s] = AN[s].dot(gri)
#            r = tm.eps_r_noop(self.uni_r.r, AN, AN)
#            print la.norm(r - other.r[self.N - 1])

        gl = la.inv(sp.asarray(self.uni_l.l[-1])).dot(gLl)
        gli = la.inv(gLl).dot(sp.asarray(self.uni_l.l[-1]))

        l = mm.H(gli).dot(sp.asarray(other.uni_l.l[-1])).dot(gli)
        fac = la.norm(sp.asarray(self.uni_l.l[-1])) / la.norm(l)

        gli *= sp.sqrt(fac)
        gl /= sp.sqrt(fac)

        if sanity_checks:
            l *= fac
            print la.norm(l - self.uni_l.l[-1])

            l = mm.H(gli).dot(sp.asarray(other.uni_l.l[-1])).dot(gli)
            print la.norm(l - self.uni_l.l[-1])

        #print (dL, dR, phiL, phiR)

        if not abs(dL - 1) < 1E-12:
            print "Left bulk states do not match!"
            return 0

        if not abs(dR - 1) < 1E-12:
            print "Right bulk states do not match!"
            return 0

        AN = other.A[self.N].copy()
        for s in xrange(AN.shape[0]):
            AN[s] = AN[s].dot(gri)

        A1 = other.A[1].copy()
        for s in xrange(A1.shape[0]):
            A1[s] = gl.dot(A1[s])

        r = tm.eps_r_noop(self.uni_r.r[-1], self.A[self.N], AN)
        for n in xrange(self.N - 1, 1, -1):
            r = tm.eps_r_noop(r, self.A[n], other.A[n])
        r = tm.eps_r_noop(r, self.A[1], A1)

        return mm.adot(self.uni_l.l[-1], r)
Example #45
0
    def restore_RCF(self, update_l=True, normalize=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        This performs two 'almost' gauge transformations, where the 'almost'
        means we allow the norm to vary (if "normalize" = True).
        
        The last step (A[1]) is done diffently to the others since G[0],
        the gauge-transf. matrix, is just a number, which can be found more
        efficiently and accurately without using matrix methods.
        
        The last step (A[1]) is important because, if we have successfully made 
        r[1] = 1 in the previous steps, it fully determines the normalization 
        of the state via r[0] ( = l[N]).
        
        Optionally (normalize=False), the function will not attempt to make
        A[1] satisfy the orthonorm. condition, and will take G[0] = 1 = G[N],
        thus performing a pure gauge-transformation, but not ensuring complete
        canonical form.
        
        It is also possible to begin the process from a site n other than N,
        in case the sites > n are known to be in the desired form already.
        
        It is also possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        normalize : bool
            Whether to also attempt to normalize the state.
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """
        start = self.N

        G_n_i = sp.eye(self.D[start],
                       dtype=self.typ)  #This is actually just the number 1
        for n in xrange(start, 1, -1):
            self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(
                self.A[n],
                self.r[n],
                G_n_i,
                sc_data=('site', n),
                zero_tol=self.zero_tol,
                sanity_checks=self.sanity_checks)

        #Now do A[1]...
        #Apply the remaining G[1]^-1 from the previous step.
        for s in xrange(self.q[1]):
            self.A[1][s] = m.mmul(self.A[1][s], G_n_i)

        #Now finish off
        tm.eps_r_noop_inplace(self.r[1], self.A[1], self.A[1], out=self.r[0])

        if normalize:
            G0 = 1. / sp.sqrt(self.r[0].squeeze().real)
            self.A[1] *= G0
            self.r[0][:] = 1

            if self.sanity_checks:
                r0 = tm.eps_r_noop(self.r[1], self.A[1], self.A[1])
                if not sp.allclose(r0, 1, atol=1E-12, rtol=1E-12):
                    log.warning(
                        "Sanity Fail in restore_RCF!: r_0 is bad / norm failure"
                    )

        if diag_l:
            G_nm1 = sp.eye(self.D[0], dtype=self.typ)
            for n in xrange(1, self.N):
                self.l[n], G_nm1, G_nm1_i = tm.restore_RCF_l(
                    self.A[n], self.l[n - 1], G_nm1, self.sanity_checks)

            #Apply remaining G_Nm1 to A[N]
            n = self.N
            for s in xrange(self.q[n]):
                self.A[n][s] = m.mmul(G_nm1, self.A[n][s])

            #Deal with final, scalar l[N]
            tm.eps_l_noop_inplace(self.l[n - 1],
                                  self.A[n],
                                  self.A[n],
                                  out=self.l[n])

            if self.sanity_checks:
                if not sp.allclose(
                        self.l[self.N].real, 1, atol=1E-12, rtol=1E-12):
                    log.warning(
                        "Sanity Fail in restore_RCF!: l_N is bad / norm failure"
                    )
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)

                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(
                            r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning(
                            "Sanity Fail in restore_RCF!: r_%u is bad (off by %g)",
                            n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()