示例#1
0
    def _update_after_truncate(self, n_last_trunc, old_l, n_first_trunc,
                               old_r):
        if self.canonical_form == 'right':
            self.r[0][0, 0] = 1

            for n in xrange(1, self.N):
                self.l[n] = m.simple_diag_matrix(old_l[n].diag[-self.D[n]:],
                                                 dtype=self.typ)

            self.l[self.N][0, 0] = 1

            for n in xrange(self.N - 1, n_last_trunc - 1, -1):
                self.r[n] = m.eyemat(self.D[n], dtype=self.typ)

            self.calc_r(n_high=n_last_trunc - 1)
        else:
            self.l[0][0, 0] = 1

            for n in xrange(1, self.N):
                self.r[n] = m.simple_diag_matrix(old_r[n].diag[-self.D[n]:],
                                                 dtype=self.typ)

            self.r[0][0, 0] = 1

            for n in xrange(1, n_first_trunc):
                self.l[n] = m.eyemat(self.D[n], dtype=self.typ)

            self.calc_l(n_low=n_first_trunc)

        self.simple_renorm()
示例#2
0
 def _update_after_truncate(self, n_last_trunc, old_l, n_first_trunc, old_r):
     if self.canonical_form == 'right':
         self.r[0][0, 0] = 1
         
         for n in xrange(1, self.N):
             self.l[n] = m.simple_diag_matrix(old_l[n].diag[-self.D[n]:], dtype=self.typ)
             
         self.l[self.N][0, 0] = 1
         
         for n in xrange(self.N - 1, n_last_trunc - 1, - 1):
             self.r[n] = m.eyemat(self.D[n], dtype=self.typ)
             
         self.calc_r(n_high=n_last_trunc - 1)
     else:
         self.l[0][0, 0] = 1
         
         for n in xrange(1, self.N):
             self.r[n] = m.simple_diag_matrix(old_r[n].diag[-self.D[n]:], dtype=self.typ)
             
         self.r[0][0, 0] = 1
         
         for n in xrange(1, n_first_trunc):
             self.l[n] = m.eyemat(self.D[n], dtype=self.typ)
             
         self.calc_l(n_low=n_first_trunc)
         
     self.simple_renorm()
示例#3
0
    def _restore_CF_diag(self, dbg=False):
        nc = self.N_centre

        #Want: r[0 <= n < nc] diagonal
        Ui = sp.eye(self.D[nc], dtype=self.typ)
        for n in xrange(nc, 0, -1):
            self.r[n - 1], Um1, Um1_i = tm.restore_LCF_r(self.A[n], self.r[n],
                                                         Ui, sanity_checks=self.sanity_checks)
            Ui = Um1_i

        #Now U is U_0
        U = Um1
        for s in xrange(self.q[0]):
            self.uni_l.A[0][s] = U.dot(self.uni_l.A[0][s])
            self.uni_l.A[-1][s] = self.uni_l.A[-1][s].dot(Ui)
        self.uni_l.r[-1] = U.dot(self.uni_l.r[-1].dot(U.conj().T))

        #And now: l[nc <= n <= N] diagonal
        if dbg:
            Um1 = sp.eye(self.D[nc - 1], dtype=self.typ)
        else:
            Um1 = mm.eyemat(self.D[nc - 1], dtype=self.typ) #FIXME: This only works if l[nc - 1] is a special matrix type        
        for n in xrange(nc, self.N + 1):
            self.l[n], U, Ui = tm.restore_RCF_l(self.A[n], self.l[n - 1], Um1,
                                                sanity_checks=self.sanity_checks)
            Um1 = U

        #Now, Um1 = U_N
        Um1_i = Ui
        for s in xrange(self.q[0]):
            self.uni_r.A[0][s] = Um1.dot(self.uni_r.A[0][s])
            self.uni_r.A[-1][s] = self.uni_r.A[-1][s].dot(Um1_i)
        self.uni_r.l[-1] = Um1_i.conj().T.dot(self.uni_r.l[-1].dot(Um1_i))
示例#4
0
def restore_RCF_r_seq(A, r, GN=None, sanity_checks=False, sc_data=''):
    """Transforms a sequence of A[n]'s to obtain r[n - 1] = eye(D).
    
    Implements the condition for right-orthonormalization from sub-section
    3.1, theorem 1 of arXiv:quant-ph/0608197v2.
    
    Uses a reduced QR decomposition to avoid inverting anything explicity.
    
    Parameters
    ----------
    A : sequence of ndarray
        The parameter tensors for a sequence of sites [None, A1, A2,..., AN].
        The first entry is ignored so that the indices match up with r.
    r : sequence of ndarray or objects with array interface
        The matrices [r0, r1, r2,..., rN], where rN will not be changed, but is 
        used for sanity checks.
    GN : ndarray or scalar
        Initial right gauge transformation matrix for site N. Only needed when used
        as part of a larger transformation.
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
    sc_data : string
        A string to be appended to sanity check log messages.
    """
    assert len(A) == len(r), 'A and r must have the same length!'
    if GN is None:
        Gh = mm.eyemat(A[-1].shape[2], dtype=A[-1].dtype)
    else:
        Gh = GN.conj().T
    for n in xrange(len(A) - 1, 0, -1):
        q, Dm1, D = A[n].shape
        AG = sp.array([Gh.dot(As.conj().T) for As in A[n]]).reshape(
            (q * D, Dm1))
        Q, R = la.qr(AG, mode='economic')
        A[n] = sp.transpose(Q.conj().reshape((q, D, Dm1)), axes=(0, 2, 1))
        Gh = R

        r[n - 1] = mm.eyemat(Dm1, dtype=A[n].dtype)

        if sanity_checks:
            r_nm1_ = eps_r_noop(r[n], A[n], A[n])
            if not sp.allclose(r_nm1_, r[n - 1].A, atol=1E-13, rtol=1E-13):
                log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s",
                            la.norm(r_nm1_ - r[n - 1]), sc_data)

    return Gh.conj().T
示例#5
0
def restore_RCF_r_seq(A, r, GN=None, sanity_checks=False, sc_data=''):
    """Transforms a sequence of A[n]'s to obtain r[n - 1] = eye(D).
    
    Implements the condition for right-orthonormalization from sub-section
    3.1, theorem 1 of arXiv:quant-ph/0608197v2.
    
    Uses a reduced QR decomposition to avoid inverting anything explicity.
    
    Parameters
    ----------
    A : sequence of ndarray
        The parameter tensors for a sequence of sites [None, A1, A2,..., AN].
        The first entry is ignored so that the indices match up with r.
    r : sequence of ndarray or objects with array interface
        The matrices [r0, r1, r2,..., rN], where rN will not be changed, but is 
        used for sanity checks.
    GN : ndarray or scalar
        Initial right gauge transformation matrix for site N. Only needed when used
        as part of a larger transformation.
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
    sc_data : string
        A string to be appended to sanity check log messages.
    """
    assert len(A) == len(r), 'A and r must have the same length!'
    if GN is None:
        Gh = mm.eyemat(A[-1].shape[2], dtype=A[-1].dtype)
    else:
        Gh = GN.conj().T
    for n in xrange(len(A) - 1, 0, -1):
        q, Dm1, D = A[n].shape
        AG = sp.array([Gh.dot(As.conj().T) for As in A[n]]).reshape((q * D, Dm1))
        Q, R = la.qr(AG, mode='economic')
        A[n] = sp.transpose(Q.conj().reshape((q, D, Dm1)), axes=(0, 2, 1))
        Gh = R
        
        r[n - 1] = mm.eyemat(Dm1, dtype=A[n].dtype)
        
        if sanity_checks:
            r_nm1_ = eps_r_noop(r[n], A[n], A[n])
            if not sp.allclose(r_nm1_, r[n - 1].A, atol=1E-13, rtol=1E-13):
                log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s",
                            la.norm(r_nm1_ - r[n - 1]), sc_data)
        
    return Gh.conj().T
示例#6
0
def restore_LCF_l(A, lm1, Gm1, sanity_checks=False, zero_tol=1E-15):
    if Gm1 is None:
        GhGm1 = lm1
    else:
        GhGm1 = Gm1.conj().T.dot(lm1.dot(Gm1))

    M = eps_l_noop(GhGm1, A, A)

    G, Gi, new_D = herm_fac_with_inv(M,
                                     zero_tol=zero_tol,
                                     return_rank=True,
                                     sanity_checks=sanity_checks)

    if Gm1 is None:
        Gm1 = G

    if sanity_checks:
        if new_D == A.shape[2]:
            eye = sp.eye(A.shape[2])
        else:
            eye = mm.simple_diag_matrix(np.append(np.zeros(A.shape[2] - new_D),
                                                  np.ones(new_D)),
                                        dtype=A.dtype)
        if not sp.allclose(G.dot(Gi), eye, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_LCF_l!: Bad GT!")

    for s in xrange(A.shape[0]):
        A[s] = Gm1.dot(A[s]).dot(Gi)

    if new_D == A.shape[2]:
        l = mm.eyemat(A.shape[2], A.dtype)
    else:
        l = mm.simple_diag_matrix(np.append(np.zeros(A.shape[2] - new_D),
                                            np.ones(new_D)),
                                  dtype=A.dtype)

    if sanity_checks:
        lm1_ = mm.eyemat(A.shape[1], A.dtype)

        l_ = eps_l_noop(lm1_, A, A)
        if not sp.allclose(l_, l.A, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_LCF_l!: l is bad")
            log.warning(la.norm(l_ - l))

    return l, G, Gi
示例#7
0
def restore_LCF_l_seq(A, l, G0=None, sanity_checks=False, sc_data=''):
    """Transforms a sequence of A[n]'s to obtain l[n] = eye(D).
    
    Implements the condition for left-orthonormalization.
    
    Uses a reduced QR (RQ) decomposition to avoid inverting anything explicity.
    
    Parameters
    ----------
    A : sequence of ndarray
        The parameter tensors for a sequence of sites [None, A1, A2,..., AN].
        The first entry is ignored so that the indices match up with l.
    l : sequence of ndarray or objects with array interface
        The matrices [l0, l1, l2,..., lN], where l0 will not be changed, but is 
        used for sanity checks.
    G0 : ndarray or scalar
        Initial left gauge transformation matrix for site 0. Only needed when used
        as part of a larger transformation.
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
    sc_data : string
        A string to be appended to sanity check log messages.
    """
    if G0 is None:
        G = mm.eyemat(A[1].shape[1], dtype=A[1].dtype)
    else:
        G = G0

    for n in xrange(1, len(A)):
        q, Dm1, D = A[n].shape
        GA = sp.array([G.dot(As) for As in A[n]])
        GA = GA.reshape((q * Dm1, D))
        Q, G = la.qr(GA, mode='economic')
        A[n] = Q.reshape((q, Dm1, D))
        
        l[n] = mm.eyemat(D, dtype=A[n].dtype)
        
        if sanity_checks:
            l_ = eps_l_noop(l[n - 1], A[n], A[n])
            if not sp.allclose(l_, l[n].A, atol=1E-13, rtol=1E-13):
                log.warning("Sanity Fail in restore_LCF_l_seq!: l is bad")
                log.warning(la.norm(l_ - l[n].A))
        
    return G
示例#8
0
def restore_LCF_l_seq(A, l, G0=None, sanity_checks=False, sc_data=''):
    """Transforms a sequence of A[n]'s to obtain l[n] = eye(D).
    
    Implements the condition for left-orthonormalization.
    
    Uses a reduced QR (RQ) decomposition to avoid inverting anything explicity.
    
    Parameters
    ----------
    A : sequence of ndarray
        The parameter tensors for a sequence of sites [None, A1, A2,..., AN].
        The first entry is ignored so that the indices match up with l.
    l : sequence of ndarray or objects with array interface
        The matrices [l0, l1, l2,..., lN], where l0 will not be changed, but is 
        used for sanity checks.
    G0 : ndarray or scalar
        Initial left gauge transformation matrix for site 0. Only needed when used
        as part of a larger transformation.
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
    sc_data : string
        A string to be appended to sanity check log messages.
    """
    if G0 is None:
        G = mm.eyemat(A[1].shape[1], dtype=A[1].dtype)
    else:
        G = G0

    for n in xrange(1, len(A)):
        q, Dm1, D = A[n].shape
        GA = sp.array([G.dot(As) for As in A[n]])
        GA = GA.reshape((q * Dm1, D))
        Q, G = la.qr(GA, mode='economic')
        A[n] = Q.reshape((q, Dm1, D))

        l[n] = mm.eyemat(D, dtype=A[n].dtype)

        if sanity_checks:
            l_ = eps_l_noop(l[n - 1], A[n], A[n])
            if not sp.allclose(l_, l[n].A, atol=1E-13, rtol=1E-13):
                log.warning("Sanity Fail in restore_LCF_l_seq!: l is bad")
                log.warning(la.norm(l_ - l[n].A))

    return G
示例#9
0
def restore_LCF_l(A, lm1, Gm1, sanity_checks=False, zero_tol=1E-15):
    if Gm1 is None:
        GhGm1 = lm1
    else:
        GhGm1 = Gm1.conj().T.dot(lm1.dot(Gm1))

    M = eps_l_noop(GhGm1, A, A)
    
    G, Gi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, 
                                     sanity_checks=sanity_checks)

    if Gm1 is None:
        Gm1 = G

    if sanity_checks:
        if new_D == A.shape[2]:
            eye = sp.eye(A.shape[2])
        else:
            eye = mm.simple_diag_matrix(np.append(np.zeros(A.shape[2] - new_D),
                                                   np.ones(new_D)), dtype=A.dtype)
        if not sp.allclose(G.dot(Gi), eye, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_LCF_l!: Bad GT!")

    for s in xrange(A.shape[0]):
        A[s] = Gm1.dot(A[s]).dot(Gi)

    if new_D == A.shape[2]:
        l = mm.eyemat(A.shape[2], A.dtype)
    else:
        l = mm.simple_diag_matrix(np.append(np.zeros(A.shape[2] - new_D),
                                                np.ones(new_D)), dtype=A.dtype)

    if sanity_checks:
        lm1_ = mm.eyemat(A.shape[1], A.dtype)

        l_ = eps_l_noop(lm1_, A, A)
        if not sp.allclose(l_, l.A, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_LCF_l!: l is bad")
            log.warning(la.norm(l_ - l))

    return l, G, Gi
示例#10
0
    def restore_RCF_r(self):
        G_n_i = None
        for n in reversed(xrange(1, self.N + 2)):
            G_n_i, G_n = self.restore_ONR_n(n, G_n_i)

            self.r[n - 1] = mm.eyemat(self.D[n - 1], self.typ)

            if self.sanity_checks:
                r_n = mm.eyemat(self.D[n], self.typ)

                r_nm1 = self.eps_r(n, r_n)
                if not sp.allclose(r_nm1, self.r[n - 1].A, atol=1E-13, rtol=1E-13):
                    print "Sanity Fail in restore_RCF_r!: r_%u is bad" % (n - 1)
                    print la.norm(r_nm1 - self.r[n - 1])

        #self.r[self.N + 1] = self.r[self.N]

        #Now G_n_i contains g_0_i
        for s in xrange(self.q[0]): #Note: This does not change the scale of A[0]
            self.A[0][s] = mm.mmul(G_n, self.A[0][s], G_n_i)

        self.u_gnd_l.r = mm.mmul(G_n, self.u_gnd_l.r, mm.H(G_n))
        self.l[0] = mm.mmul(mm.H(G_n_i), self.l[0], G_n_i)
示例#11
0
 def _init_arrays(self):
     self.A = sp.empty((self.N + 1), dtype=sp.ndarray) #Elements 1..N
     
     self.r = sp.empty((self.N + 1), dtype=sp.ndarray) #Elements 0..N
     self.l = sp.empty((self.N + 1), dtype=sp.ndarray)        
     
     self.r[0] = sp.zeros((self.D[0], self.D[0]), dtype=self.typ, order=self.odr)  
     self.l[0] = m.eyemat(self.D[0], dtype=self.typ)
 
     for n in xrange(1, self.N + 1):
         self.r[n] = sp.zeros((self.D[n], self.D[n]), dtype=self.typ, order=self.odr)
         self.l[n] = sp.zeros((self.D[n], self.D[n]), dtype=self.typ, order=self.odr)
         self.A[n] = sp.zeros((self.q[n], self.D[n - 1], self.D[n]), dtype=self.typ, order=self.odr)
         
     sp.fill_diagonal(self.r[self.N], 1.)        
示例#12
0
 def _init_arrays(self):
     self.A = sp.empty((self.N + 1), dtype=sp.ndarray) #Elements 1..N
     
     self.r = sp.empty((self.N + 1), dtype=sp.ndarray) #Elements 0..N
     self.l = sp.empty((self.N + 1), dtype=sp.ndarray)        
     
     self.r[0] = sp.zeros((self.D[0], self.D[0]), dtype=self.typ, order=self.odr)  
     self.l[0] = m.eyemat(self.D[0], dtype=self.typ)
 
     for n in xrange(1, self.N + 1):
         self.r[n] = sp.zeros((self.D[n], self.D[n]), dtype=self.typ, order=self.odr)
         self.l[n] = sp.zeros((self.D[n], self.D[n]), dtype=self.typ, order=self.odr)
         self.A[n] = sp.zeros((self.q[n], self.D[n - 1], self.D[n]), dtype=self.typ, order=self.odr)
         
     sp.fill_diagonal(self.r[self.N], 1.)        
示例#13
0
    def truncate(self, newD, update=True):
        assert newD < self.D, 'new bond-dimension must be smaller!'
        
        tmp_A = self.A
        tmp_l = self.l.diag
        
        self._init_arrays(newD, self.q)
        
        if self.symm_gauge:
            self.l = m.simple_diag_matrix(tmp_l[:self.D], dtype=self.typ)
            self.r = m.simple_diag_matrix(tmp_l[:self.D], dtype=self.typ)
            self.A = tmp_A[:, :self.D, :self.D]
        else:
            self.l = m.simple_diag_matrix(tmp_l[-self.D:], dtype=self.typ)
            self.r = m.eyemat(self.D, dtype=self.typ)
            self.A = tmp_A[:, -self.D:, -self.D:]
            
        self.l_before_CF = self.l.A
        self.r_before_CF = self.r.A

        if update:
            self.update()
示例#14
0
    def _restore_CF_diag(self, dbg=False):
        nc = self.N_centre

        #Want: r[0 <= n < nc] diagonal
        Ui = sp.eye(self.D[nc], dtype=self.typ)
        for n in xrange(nc, 0, -1):
            self.r[n - 1], Um1, Um1_i = tm.restore_LCF_r(
                self.A[n], self.r[n], Ui, sanity_checks=self.sanity_checks)
            Ui = Um1_i

        #Now U is U_0
        U = Um1
        for s in xrange(self.q[0]):
            self.uni_l.A[0][s] = U.dot(self.uni_l.A[0][s])
            self.uni_l.A[-1][s] = self.uni_l.A[-1][s].dot(Ui)
        self.uni_l.r[-1] = U.dot(self.uni_l.r[-1].dot(U.conj().T))

        #And now: l[nc <= n <= N] diagonal
        if dbg:
            Um1 = sp.eye(self.D[nc - 1], dtype=self.typ)
        else:
            Um1 = mm.eyemat(
                self.D[nc - 1], dtype=self.typ
            )  #FIXME: This only works if l[nc - 1] is a special matrix type
        for n in xrange(nc, self.N + 1):
            self.l[n], U, Ui = tm.restore_RCF_l(
                self.A[n],
                self.l[n - 1],
                Um1,
                sanity_checks=self.sanity_checks)
            Um1 = U

        #Now, Um1 = U_N
        Um1_i = Ui
        for s in xrange(self.q[0]):
            self.uni_r.A[0][s] = Um1.dot(self.uni_r.A[0][s])
            self.uni_r.A[-1][s] = self.uni_r.A[-1][s].dot(Um1_i)
        self.uni_r.l[-1] = Um1_i.conj().T.dot(self.uni_r.l[-1].dot(Um1_i))
示例#15
0
    def _restore_CF_diag(self):
        nc = self.N_centre

        self.S_hc = sp.zeros((self.N + 1), dtype=sp.complex128)

        #Want: r[0 <= n < nc] diagonal
        Ui = sp.eye(self.D[nc], dtype=self.typ)
        for n in xrange(nc, 0, -1):
            self.r[n - 1], Um1, Um1_i = tm.restore_LCF_r(self.A[n], self.r[n],
                                                         Ui, sanity_checks=self.sanity_checks)

            self.S_hc[n - 1] = -sp.sum(self.r[n - 1].diag * sp.log2(self.r[n - 1].diag))

            Ui = Um1_i

        #Now U is U_0
        U = Um1
        for s in xrange(self.q[0]):
            self.A[0][s] = U.dot(self.A[0][s]).dot(Ui)
        self.uni_l.r = U.dot(self.uni_l.r.dot(U.conj().T))

        #And now: l[nc <= n <= N] diagonal
        Um1 = mm.eyemat(self.D[nc - 1], dtype=self.typ)
        for n in xrange(nc, self.N + 1):
            self.l[n], U, Ui = tm.restore_RCF_l(self.A[n], self.l[n - 1], Um1,
                                                sanity_checks=self.sanity_checks)

            self.S_hc[n] = -sp.sum(self.l[n].diag * sp.log2(self.l[n].diag))

            Um1 = U

        #Now, Um1 = U_N
        Um1_i = Ui
        for s in xrange(self.q[0]):
            self.A[self.N + 1][s] = Um1.dot(self.A[self.N + 1][s]).dot(Um1_i)
        self.uni_r.l = Um1_i.conj().T.dot(self.uni_r.l.dot(Um1_i))
示例#16
0
 def restore_RCF(self, start=-1, 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.
     
     FIXME: Currently, "start" only affects the ON_R stage!
     
     Parameters
     ----------
     start : int
         The rightmost site to start from (defaults to N)
     update_l : bool
         Whether to call calc_l() after completion (defaults to True)
     normalize : bool
         Whether to also attempt to enforce the condition for A[1], which normalizes the state.
     diag_l : bool
         Whether to put l in diagonal form (defaults to True)
     """   
     if start < 1:
         start = self.N
     
     G_n_i = sp.eye(self.D[start], dtype=self.typ) #This is actually just the number 1
     for n in reversed(xrange(2, start + 1)):
         G_n_i = self.restore_ONR_n(n, G_n_i)
         self.eps_r(n, self.r[n], out=self.r[n - 1]) #Update r[n - 1], which should, ideally, now equal 1
         #self.r[n - 1][:] = sp.eye(self.D[n - 1])
         #self.r[n - 1] = m.eyemat(self.D[n - 1], dtype=self.typ)
         #print self.r[n - 1]
         if self.sanity_checks and not diag_l:
             r_nm1 = self.eps_r(n, m.eyemat(self.D[n], self.typ))
             if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12):
                 print "Sanity Fail in restore_RCF!: r_%u is bad" % n
     
     #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
     self.eps_r(1, self.r[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 = self.eps_r(1, self.r[1])
             if not sp.allclose(r0, 1, atol=1E-12, rtol=1E-12):
                 print "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):
             x = m.mmul(m.H(G_nm1), self.l[n - 1], G_nm1)
             M = self.eps_l(n, x)
             ev, EV = la.eigh(M)
             
             G_n_i = EV
             self.l[n][:] = sp.diag(ev)
             #self.l[n] = m.simple_diag_matrix(sp.array(ev, dtype=self.typ))
             
             for s in xrange(self.q[n]):                
                 self.A[n][s] = m.mmul(G_nm1, self.A[n][s], G_n_i)
             
             if self.sanity_checks:
                 l = self.eps_l(n, self.l[n - 1])
                 if not sp.allclose(l, self.l[n]):
                     print "Sanity Fail in restore_RCF!: l_%u is bad" % n
             
             G_nm1 = m.H(EV)
         
         #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]
         self.eps_l(n, self.l[n - 1], out=self.l[n])
         
         if self.sanity_checks:
             if not sp.allclose(self.l[self.N].real, 1, atol=1E-12, rtol=1E-12):
                 print "Sanity Fail in restore_RCF!: l_N is bad / norm failure"
                 print "l_N = " + str(self.l[self.N].squeeze().real)
             
             for n in xrange(1, self.N + 1):
                 r_nm1 = self.eps_r(n, m.eyemat(self.D[n], self.typ))
                 if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12):
                     print "Sanity Fail in restore_RCF!: r_%u is bad" % n
                 
         return True #FIXME: This OK?
     elif update_l:
         res = self.calc_l()
         return res
     else:
         return True
示例#17
0
def restore_RCF_r(A,
                  r,
                  G_n_i,
                  zero_tol=1E-15,
                  sanity_checks=False,
                  sc_data=''):
    """Transforms a single A[n] to obtain r[n - 1] = eye(D).

    Implements the condition for right-orthonormalization from sub-section
    3.1, theorem 1 of arXiv:quant-ph/0608197v2.

    This function must be called for each n in turn, starting at N + 1,
    passing the gauge transformation matrix from the previous step
    as an argument.

    Finds a G[n-1] such that orthonormalization is fulfilled for n.

    If rank-deficiency is encountered, the result fulfills the orthonormality
    condition in the occupied subspace with the zeros at the top-left
    (for example r = diag([0, 0, 1, 1, 1, 1, 1])).

    Parameters
    ----------
    A : ndarray
        The parameter tensor for the nth site A[n].
    r : ndarray or object with array interface
        The matrix r[n].
    G_n_i : ndarray
        The inverse gauge transform matrix for site n obtained in the previous step (for n + 1).
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
    zero_tol : float
        Tolerance for detecting zeros.
            
    Returns
    -------
    r_nm1 : ndarray or simple_diag_matrix or eyemat
        The new matrix r[n - 1].
    G_nm1 : ndarray
        The gauge transformation matrix for the site n - 1.
    G_n_m1_i : ndarray
        The inverse gauge transformation matrix for the site n - 1.
    """
    if G_n_i is None:
        GGh_n_i = r
    else:
        GGh_n_i = G_n_i.dot(r.dot(G_n_i.conj().T))

    M = eps_r_noop(GGh_n_i, A, A)

    X, Xi, new_D = herm_fac_with_inv(M,
                                     zero_tol=zero_tol,
                                     return_rank=True,
                                     sanity_checks=sanity_checks)

    G_nm1 = Xi.conj().T
    G_nm1_i = X.conj().T

    if G_n_i is None:
        G_n_i = G_nm1_i

    if sanity_checks:
        #GiG may not be equal to eye in the case of rank-deficiency,
        #but the rest should lie in the null space of A.
        GiG = G_nm1_i.dot(G_nm1)
        As = np.sum(A, axis=0)
        if not sp.allclose(
                GiG.dot(As).dot(G_n_i), As.dot(G_n_i), atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_RCF_r!: Bad GT! %s %s",
                        la.norm(GiG.dot(As).dot(G_n_i) - As.dot(G_n_i)),
                        sc_data)

    for s in xrange(A.shape[0]):
        A[s] = G_nm1.dot(A[s]).dot(G_n_i)

    if new_D == A.shape[1]:
        r_nm1 = mm.eyemat(A.shape[1], A.dtype)
    else:
        r_nm1 = sp.zeros((A.shape[1]), dtype=A.dtype)
        r_nm1[-new_D:] = 1
        r_nm1 = mm.simple_diag_matrix(r_nm1, dtype=A.dtype)

    if sanity_checks:
        r_nm1_ = G_nm1.dot(M).dot(G_nm1.conj().T)
        if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13):
            log.warning(
                "Sanity Fail in restore_RCF_r!: r != g old_r gH! %s %s",
                la.norm(r_nm1_ - r_nm1), sc_data)

        r_nm1_ = eps_r_noop(r, A, A)
        if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s",
                        la.norm(r_nm1_ - r_nm1), sc_data)

    return r_nm1, G_nm1, G_nm1_i
示例#18
0
    def restore_RCF(self, dbg=False):
        if dbg:
            self.calc_l()
            self.calc_r()
            print "BEFORE..."
            h_before, h_left_before, h_right_before = self.restore_RCF_dbg()

            print (h_left_before, h_before, h_right_before)

        self.restore_RCF_r()

        if dbg:
            self.calc_l()
            print "MIDDLE..."
            h_mid, h_left_mid, h_right_mid = self.restore_RCF_dbg()

            print (h_left_mid, h_mid, h_right_mid)

        fac = 1 / self.l[0].trace().real
        if dbg:
            print "Scale l[0]: %g" % fac
        self.l[0] *= fac
        self.u_gnd_l.r *= 1/fac

        self.restore_RCF_l()

        if dbg:
            print "Uni left:"
        self.u_gnd_l.A = self.A[0]
        self.u_gnd_l.l = self.l[0]
        self.u_gnd_l.calc_lr() #Ensures largest ev of E=1
        self.l[0] = self.u_gnd_l.l #No longer diagonal!
        self.A[0] = self.u_gnd_l.A
        if self.sanity_checks:
            if not sp.allclose(self.l[0], sp.diag(sp.diag(self.l[0])), atol=1E-12, rtol=1E-12):
                print "Sanity Fail in restore_RCF!: True l[0] not diagonal!"
        self.l[0] = mm.simple_diag_matrix(sp.diag(self.l[0]))

        fac = 1 / sp.trace(self.l[0]).real
        if dbg:
            print "Scale l[0]: %g" % fac
        self.l[0] *= fac
        self.u_gnd_l.r *= 1/fac

        self.u_gnd_l.l = self.l[0]

        if dbg:
            print "Uni right:"
        self.u_gnd_r.A = self.A[self.N + 1]
        self.u_gnd_r.r = self.r[self.N]
        self.u_gnd_r.calc_lr() #Ensures largest ev of E=1
        self.r[self.N] = self.u_gnd_r.r
        self.A[self.N + 1] = self.u_gnd_r.A
        if self.sanity_checks:
            if not sp.allclose(self.r[self.N], sp.eye(self.D[self.N]), atol=1E-12, rtol=1E-12):
                print "Sanity Fail in restore_RCF!: True r[N] not eye!"
        self.r[self.N] = mm.eyemat(self.D[self.N], dtype=self.typ)
        self.u_gnd_r.r = self.r[self.N]
        self.r[self.N + 1] = self.r[self.N]

        self.l[self.N + 1][:] = self.eps_l(self.N + 1, self.l[self.N])

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

            r_nm1 = self.r[self.N + 1]
            for n in reversed(xrange(1, self.N + 2)):
                r_nm1 = self.eps_r(n, r_nm1)
                if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_RCF!: r_%u is bad" % (n - 1)
        if dbg:
            print "AFTER..."
            h_after, h_left_after, h_right_after = self.restore_RCF_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)
示例#19
0
    def restore_CF(self, ret_g=False):
        if self.symm_gauge:
            self.restore_SCF()
        else:
            #First get G such that r = eye
            G = la.cholesky(self.r, lower=True)
            G_i = m.invtr(G, lower=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)

            if self.sanity_checks:
                M = np.zeros_like(self.r)
                for s in xrange(self.q):
                    M += m.mmul(self.A[s], m.H(self.A[s]))            
                
                self.r = m.mmul(G_i, self.r, m.H(G_i))
                
                if not np.allclose(M, self.r, 
                                   rtol=self.itr_rtol*self.check_fac,
                                   atol=self.itr_atol*self.check_fac):
                    print "Sanity check failed: RestoreRCF, bad M."
                    print "Off by: " + str(la.norm(M - self.r))
                    
                if not np.allclose(self.r, np.eye(self.D),
                                   rtol=self.itr_rtol*self.check_fac,
                                   atol=self.itr_atol*self.check_fac):
                    print "Sanity check failed: r not identity."
                    print "Off by: " + str(la.norm(np.eye(self.D) - self.r))
                
                l = self.eps_l(self.l)
                r = self.eps_r(self.r)
                
                if not np.allclose(r, self.r,
                                   rtol=self.itr_rtol*self.check_fac, 
                                   atol=self.itr_atol*self.check_fac):
                    print "Sanity check failed: Restore_RCF, bad r!"
                    print "Off by: " + str(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):
                    print "Sanity check failed: Restore_RCF, bad l!"
                    print "Off by: " + str(la.norm(l - self.l))
        
            self.r = m.eyemat(self.D, dtype=self.typ)
        
        if ret_g:
            return G, G_i
        else:
            return
示例#20
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   
示例#21
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
示例#22
0
def restore_RCF_r(A, r, G_n_i, zero_tol=1E-15, sanity_checks=False, sc_data=''):
    """Transforms a single A[n] to obtain r[n - 1] = eye(D).

    Implements the condition for right-orthonormalization from sub-section
    3.1, theorem 1 of arXiv:quant-ph/0608197v2.

    This function must be called for each n in turn, starting at N + 1,
    passing the gauge transformation matrix from the previous step
    as an argument.

    Finds a G[n-1] such that orthonormalization is fulfilled for n.

    If rank-deficiency is encountered, the result fulfills the orthonormality
    condition in the occupied subspace with the zeros at the top-left
    (for example r = diag([0, 0, 1, 1, 1, 1, 1])).

    Parameters
    ----------
    A : ndarray
        The parameter tensor for the nth site A[n].
    r : ndarray or object with array interface
        The matrix r[n].
    G_n_i : ndarray
        The inverse gauge transform matrix for site n obtained in the previous step (for n + 1).
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
    zero_tol : float
        Tolerance for detecting zeros.
            
    Returns
    -------
    r_nm1 : ndarray or simple_diag_matrix or eyemat
        The new matrix r[n - 1].
    G_nm1 : ndarray
        The gauge transformation matrix for the site n - 1.
    G_n_m1_i : ndarray
        The inverse gauge transformation matrix for the site n - 1.
    """
    if G_n_i is None:
        GGh_n_i = r
    else:
        GGh_n_i = G_n_i.dot(r.dot(G_n_i.conj().T))

    M = eps_r_noop(GGh_n_i, A, A)
    
    X, Xi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, 
                                     sanity_checks=sanity_checks)
                                     
    G_nm1 = Xi.conj().T
    G_nm1_i = X.conj().T

    if G_n_i is None:
        G_n_i = G_nm1_i

    if sanity_checks:     
        #GiG may not be equal to eye in the case of rank-deficiency,
        #but the rest should lie in the null space of A.
        GiG = G_nm1_i.dot(G_nm1)
        As = np.sum(A, axis=0)
        if not sp.allclose(GiG.dot(As).dot(G_n_i), 
                           As.dot(G_n_i), atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_RCF_r!: Bad GT! %s %s",
                        la.norm(GiG.dot(As).dot(G_n_i) - As.dot(G_n_i)), sc_data)

    for s in xrange(A.shape[0]):
        A[s] = G_nm1.dot(A[s]).dot(G_n_i)

    if new_D == A.shape[1]:
        r_nm1 = mm.eyemat(A.shape[1], A.dtype)
    else:
        r_nm1 = sp.zeros((A.shape[1]), dtype=A.dtype)
        r_nm1[-new_D:] = 1
        r_nm1 = mm.simple_diag_matrix(r_nm1, dtype=A.dtype)

    if sanity_checks:
        r_nm1_ = G_nm1.dot(M).dot(G_nm1.conj().T)
        if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_RCF_r!: r != g old_r gH! %s %s",
                        la.norm(r_nm1_ - r_nm1), sc_data)
        
        r_nm1_ = eps_r_noop(r, A, A)
        if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13):
            log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s",
                        la.norm(r_nm1_ - r_nm1), sc_data)

    return r_nm1, G_nm1, G_nm1_i
示例#23
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