예제 #1
0
    def _calc_lr(self, x, tmp, calc_l=False, A1=None, A2=None, rescale=True,
                 max_itr=1000, rtol=1E-14, atol=1E-14):
        """Power iteration to obtain eigenvector corresponding to largest
           eigenvalue.
           
           x is modified in place.
        """        
        if A1 is None:
            A1 = self.A
        if A2 is None:
            A2 = self.A
                        
        try:
            norm = la.get_blas_funcs("nrm2", [x])
        except (ValueError, AttributeError):
            norm = np.linalg.norm
            
#        try:
#            allclose = ac.allclose_mat
#        except:
#            allclose = np.allclose
#            print "Falling back to numpy allclose()!"
        
        n = x.size #we will scale x so that stuff doesn't get too small

        x *= n / norm(x.ravel())
        tmp[:] = x
        for i in xrange(max_itr):
            x[:] = tmp
            if calc_l:
                tm.eps_l_noop_inplace(x, A1, A2, tmp)
            else:
                tm.eps_r_noop_inplace(x, A1, A2, tmp)
            ev_mag = norm(tmp.ravel()) / n
            ev = (tmp.mean() / x.mean()).real
            tmp *= (1 / ev_mag)
            if norm((tmp - x).ravel()) < atol + rtol * n:
#            if allclose(tmp, x, rtol, atol):                
                #print (i, ev, ev_mag, norm((tmp - x).ravel())/n, atol, rtol)
                x[:] = tmp
                break            
#        else:
#            print (i, ev, ev_mag, norm((tmp - x).ravel())/norm(x.ravel()), atol, rtol)
                    
        if rescale and not abs(ev - 1) < atol:
            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) < atol:
                    log.warning("Sanity check failed: Largest ev after re-scale = %s", ev)
        
        return x, i < max_itr - 1, i
예제 #2
0
 def calc_BHB_prereq(self, tdvp, tdvp2):
     """Calculates prerequisites for the application of the effective Hamiltonian in terms of tangent vectors.
     
     This is called (indirectly) by the self.excite.. functions.
     
     Parameters
     ----------
     tdvp2: EvoMPS_TDVP_Uniform
         Second state (may be the same, or another ground state).
         
     Returns
     -------
     A lot of stuff.
     """
     l = tdvp.l[0]
     r_ = tdvp2.r[0]
     r__sqrt = tdvp2.r_sqrt[0]
     r__sqrt_i = tdvp2.r_sqrt_i[0]
     A = tdvp.A[0]
     A_ = tdvp2.A[0]
         
     #Note: V has ~ D**2 * q**2 elements. We avoid making any copies of it except this one.
     #      This one is only needed because low-level routines force V_[s] to be contiguous.
     #      TODO: Store V instead of Vsh in tdvp_uniform too...
     V_ = sp.transpose(tdvp2.Vsh[0], axes=(0, 2, 1)).conj().copy(order='C')
             
     if self.ham_sites == 2:
         #eyeham = m.eyemat(self.q, dtype=sp.complex128)
         eyeham = sp.eye(self.q, dtype=sp.complex128)
         #diham = m.simple_diag_matrix(sp.repeat([-tdvp.h_expect.real], self.q))
         diham = -tdvp.h_expect.real * sp.eye(self.q, dtype=sp.complex128)
         _ham_tp = self.ham_tp + [[diham, eyeham]]  #subtract norm dof
         
         Ao1 = get_Aop(A, _ham_tp, 2, conj=False)
         
         AhlAo1 = [tm.eps_l_op_1s(l, A, A, o1.conj().T) for o1, o2 in _ham_tp]
         
         A_o2c = get_Aop(A_, _ham_tp, 1, conj=True)
         
         Ao1c = get_Aop(A, _ham_tp, 0, conj=True)
         
         A_Vr_ho2 = [tm.eps_r_op_1s(r__sqrt, A_, V_, o2) for o1, o2 in _ham_tp]
         
         A_A_o12c = get_A_ops(A_, A_, _ham_tp, conj=True)
         
         A_o1 = get_Aop(A_, _ham_tp, 2, conj=False)
         tmp = sp.empty((A_.shape[1], V_.shape[1]), dtype=A.dtype, order='C')
         tmp2 = sp.empty((A_.shape[1], A_o2c[0].shape[1]), dtype=A.dtype, order='C')
         rhs10 = 0
         for al in xrange(len(A_o1)):
             tmp2 = tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2)
             tmp3 = m.mmul(tmp2, r__sqrt_i)
             rhs10 += tm.eps_r_noop_inplace(tmp3, A_o1[al], V_, tmp)
             
         return V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp
         
     elif self.ham_sites == 3:
         return
예제 #3
0
    def restore_LCF(self):
        Gm1 = sp.eye(self.D[0], dtype=self.typ) #This is actually just the number 1
        for n in xrange(1, self.N):
            self.l[n], G, Gi = tm.restore_LCF_l(self.A[n], self.l[n - 1], Gm1,
                                                zero_tol=self.zero_tol,
                                                sanity_checks=self.sanity_checks)
            Gm1 = G
        
        #Now do A[N]...
        #Apply the remaining G[N - 1] from the previous step.
        for s in xrange(self.q[self.N]):                
            self.A[self.N][s] = Gm1.dot(self.A[self.N][s])
                    
        #Now finish off
        tm.eps_l_noop_inplace(self.l[self.N - 1], self.A[self.N], self.A[self.N], out=self.l[self.N])
        
        #normalize
        GNi = 1. / sp.sqrt(self.l[self.N].squeeze().real)
        self.A[self.N] *= GNi
        self.l[self.N][:] = 1
        
        if self.sanity_checks:
            lN = tm.eps_l_noop(self.l[self.N - 1], self.A[self.N], self.A[self.N])
            if not sp.allclose(lN, 1, atol=1E-12, rtol=1E-12):
                log.warning("Sanity Fail in restore_LCF!: l_N is bad / norm failure")

        #diag r
        Gi = sp.eye(self.D[self.N], dtype=self.typ)
        for n in xrange(self.N, 1, -1):
            self.r[n - 1], Gm1, Gm1_i = tm.restore_LCF_r(self.A[n], self.r[n],
                                                         Gi, self.sanity_checks)
            Gi = Gm1_i

        #Apply remaining G1i to A[1]
        for s in xrange(self.q[1]):
            self.A[1][s] = self.A[1][s].dot(Gi)

        #Deal with final, scalar r[0]
        tm.eps_r_noop_inplace(self.r[1], self.A[1], self.A[1], out=self.r[0])

        if self.sanity_checks:
            if not sp.allclose(self.r[0], 1, atol=1E-12, rtol=1E-12):
                log.warning("Sanity Fail in restore_LCF!: r_0 is bad / norm failure")
                log.warning("r_0 = %s", self.r[0].squeeze().real)
            
            for n in xrange(1, self.N + 1):
                l = tm.eps_l_noop(self.l[n - 1], self.A[n], self.A[n])
                if not sp.allclose(l, self.l[n], atol=1E-11, rtol=1E-11):
                    log.warning("Sanity Fail in restore_LCF!: l_%u is bad (off by %g)", n, la.norm(l - self.l[n]))
                    log.warning((l - self.l[n]).diagonal().real)
예제 #4
0
    def matvec(self, v):
        x = v.reshape((self.D, self.D))

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

        return res.ravel()
예제 #5
0
    def matvec(self, v):
        x = v.reshape((self.D, self.D))

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

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

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

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

        return (
            res.copy().ravel()
        )  # apparently we can't reuse the memory we return (seems to blow up lgmres), so we make a copy
예제 #6
0
 def matvec(self, v):
     x = v.reshape((self.D, self.D))
     
     if self.left: #Multiplying from the left, but x is a col. vector, so use mat_dagger
         Ehx = tm.eps_l_noop_inplace(x, self.A1, self.A2, self.out)
         if self.pseudo:
             QEQhx = Ehx - self.l * m.adot(self.r, x)
             res = x - sp.exp(-1.j * self.p) * QEQhx
         else:
             res = x - sp.exp(-1.j * self.p) * Ehx
     else:
         Ex = tm.eps_r_noop_inplace(x, self.A1, self.A2, self.out)
         if self.pseudo:
             QEQx = Ex - self.r * m.adot(self.l, x)
             res = x - sp.exp(1.j * self.p) * QEQx
         else:
             res = x - sp.exp(1.j * self.p) * Ex
     
     return res.ravel()
예제 #7
0
    def matvec(self, v):
        x = v.reshape((self.D, self.D))
        
        res = self.tmp
        out = self.out
        res[:] = x
        
        if self.left: #Multiplying from the left, but x is a col. vector, so use mat_dagger
            for k in xrange(len(self.A1)):
                out = tm.eps_l_noop_inplace(res, self.A1[k], self.A2[k], out)
                tmp = res
                res = out
                out = tmp
                
            if self.pseudo:
                out[:] = self.lL
                out *= m.adot(self.rL, x)
                res -= out
                res *= -sp.exp(-1.j * self.p)
                res += x
            else:
                res *= -sp.exp(-1.j * self.p)
                res += x
        else:
            for k in xrange(len(self.A1) - 1, -1, -1):
                out = tm.eps_r_noop_inplace(res, self.A1[k], self.A2[k], out)
                tmp = res
                res = out
                out = tmp
                
            if self.pseudo:
                out[:] = self.rL 
                out *= m.adot(self.lL, x)
                res -= out
                res *= -sp.exp(1.j * self.p)
                res += x
            else:
                res *= -sp.exp(1.j * self.p)
                res += x

        return res.copy().ravel() #apparently we can't reuse the memory we return (seems to blow up lgmres), so we make a copy
예제 #8
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()
예제 #9
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  
예제 #10
0
    def restore_LCF(self):
        Gm1 = sp.eye(self.D[0],
                     dtype=self.typ)  #This is actually just the number 1
        for n in xrange(1, self.N):
            self.l[n], G, Gi = tm.restore_LCF_l(
                self.A[n],
                self.l[n - 1],
                Gm1,
                zero_tol=self.zero_tol,
                sanity_checks=self.sanity_checks)
            Gm1 = G

        #Now do A[N]...
        #Apply the remaining G[N - 1] from the previous step.
        for s in xrange(self.q[self.N]):
            self.A[self.N][s] = Gm1.dot(self.A[self.N][s])

        #Now finish off
        tm.eps_l_noop_inplace(self.l[self.N - 1],
                              self.A[self.N],
                              self.A[self.N],
                              out=self.l[self.N])

        #normalize
        GNi = 1. / sp.sqrt(self.l[self.N].squeeze().real)
        self.A[self.N] *= GNi
        self.l[self.N][:] = 1

        if self.sanity_checks:
            lN = tm.eps_l_noop(self.l[self.N - 1], self.A[self.N],
                               self.A[self.N])
            if not sp.allclose(lN, 1, atol=1E-12, rtol=1E-12):
                log.warning(
                    "Sanity Fail in restore_LCF!: l_N is bad / norm failure")

        #diag r
        Gi = sp.eye(self.D[self.N], dtype=self.typ)
        for n in xrange(self.N, 1, -1):
            self.r[n - 1], Gm1, Gm1_i = tm.restore_LCF_r(
                self.A[n], self.r[n], Gi, self.sanity_checks)
            Gi = Gm1_i

        #Apply remaining G1i to A[1]
        for s in xrange(self.q[1]):
            self.A[1][s] = self.A[1][s].dot(Gi)

        #Deal with final, scalar r[0]
        tm.eps_r_noop_inplace(self.r[1], self.A[1], self.A[1], out=self.r[0])

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

            for n in xrange(1, self.N + 1):
                l = tm.eps_l_noop(self.l[n - 1], self.A[n], self.A[n])
                if not sp.allclose(l, self.l[n], atol=1E-11, rtol=1E-11):
                    log.warning(
                        "Sanity Fail in restore_LCF!: l_%u is bad (off by %g)",
                        n, la.norm(l - self.l[n]))
                    log.warning((l - self.l[n]).diagonal().real)
예제 #11
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()
예제 #12
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
예제 #13
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
예제 #14
0
    def calc_BHB_prereq(self, tdvp, tdvp2):
        """Calculates prerequisites for the application of the effective Hamiltonian in terms of tangent vectors.
        
        This is called (indirectly) by the self.excite.. functions.
        
        Parameters
        ----------
        tdvp2: EvoMPS_TDVP_Uniform
            Second state (may be the same, or another ground state).
            
        Returns
        -------
        A lot of stuff.
        """
        l = tdvp.l[0]
        r_ = tdvp2.r[0]
        r__sqrt = tdvp2.r_sqrt[0]
        r__sqrt_i = tdvp2.r_sqrt_i[0]
        A = tdvp.A[0]
        A_ = tdvp2.A[0]

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

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

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

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

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

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

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

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

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

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

        elif self.ham_sites == 3:
            return