示例#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_LCF_r(A, r, Gi, sanity_checks=False):
    if Gi is None:
        x = r
    else:
        x = Gi.dot(r.dot(Gi.conj().T))

    M = eps_r_noop(x, A, A)
    ev, EV = la.eigh(M) #wraps lapack routines, which return eigenvalues in ascending order
    
    if sanity_checks:
        assert np.all(ev == np.sort(ev)), "unexpected eigenvalue ordering"
    
    rm1 = mm.simple_diag_matrix(ev, dtype=A.dtype)
    Gm1 = EV.conj().T

    if Gi is None:
        Gi = EV #for left uniform case
        r = rm1 #for sanity check

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

    if sanity_checks:
        rm1_ = eps_r_noop(r, A, A)
        if not sp.allclose(rm1_, rm1, atol=1E-12, rtol=1E-12):
            log.warning("Sanity Fail in restore_LCF_r!: r is bad!")
            log.warning(la.norm(rm1_ - rm1))

    Gm1_i = EV

    return rm1, Gm1, Gm1_i
示例#4
0
def restore_LCF_r(A, r, Gi, sanity_checks=False):
    if Gi is None:
        x = r
    else:
        x = Gi.dot(r.dot(Gi.conj().T))

    M = eps_r_noop(x, A, A)
    ev, EV = la.eigh(
        M)  #wraps lapack routines, which return eigenvalues in ascending order

    if sanity_checks:
        assert np.all(ev == np.sort(ev)), "unexpected eigenvalue ordering"

    rm1 = mm.simple_diag_matrix(ev, dtype=A.dtype)
    Gm1 = EV.conj().T

    if Gi is None:
        Gi = EV  #for left uniform case
        r = rm1  #for sanity check

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

    if sanity_checks:
        rm1_ = eps_r_noop(r, A, A)
        if not sp.allclose(rm1_, rm1, atol=1E-12, rtol=1E-12):
            log.warning("Sanity Fail in restore_LCF_r!: r is bad!")
            log.warning(la.norm(rm1_ - rm1))

    Gm1_i = EV

    return rm1, Gm1, Gm1_i
示例#5
0
def calc_BB_2s(Y, Vlh, Vrh_p1, l_si_m1, r_si_p1, dD_max=16, sv_tol=1E-14):
    try:
        U, sv, Vh = la.svd(Y)
    except la.LinAlgError:
        return None, None, 0

    dDn = min(sp.count_nonzero(sv > sv_tol), dD_max)

    sv = mm.simple_diag_matrix(sv[:dDn])

    ss = sv.sqrt()

    Z1 = ss.dot_left(U[:, :dDn])

    Z2 = ss.dot(Vh[:dDn, :])

    BB12n = sp.zeros((Vlh.shape[0], l_si_m1.shape[0], dDn), dtype=Y.dtype)

    for s in xrange(Vlh.shape[0]):
        BB12n[s] = l_si_m1.dot(Vlh[s].conj().T).dot(Z1)

    BB21np1 = sp.zeros((Vrh_p1.shape[0], dDn, Vrh_p1.shape[1]), dtype=Y.dtype)

    try:
        for s in xrange(Vrh_p1.shape[0]):
            BB21np1[s] = r_si_p1.dot_left(Z2.dot(Vrh_p1[s].conj().T))
    except AttributeError:
        for s in xrange(Vrh_p1.shape[0]):
            BB21np1[s] = Z2.dot(Vrh_p1[s].conj().T).dot(r_si_p1)

    return BB12n, BB21np1, dDn
示例#6
0
def calc_BB_2s(Y, Vlh, Vrh_p1, l_si_m1, r_si_p1, dD_max=16, sv_tol=1E-14):
    try:
        U, sv, Vh = la.svd(Y)
    except la.LinAlgError:
        return None, None, 0
    
    dDn = min(sp.count_nonzero(sv > sv_tol), dD_max)
    
    sv = mm.simple_diag_matrix(sv[:dDn])
    
    ss = sv.sqrt()
    
    Z1 = ss.dot_left(U[:, :dDn])
    
    Z2 = ss.dot(Vh[:dDn, :])
    
    BB12n = sp.zeros((Vlh.shape[0], l_si_m1.shape[0], dDn), dtype=Y.dtype)
    
    for s in xrange(Vlh.shape[0]):
        BB12n[s] = l_si_m1.dot(Vlh[s].conj().T).dot(Z1)
    
    BB21np1 = sp.zeros((Vrh_p1.shape[0], dDn, Vrh_p1.shape[1]), dtype=Y.dtype)
    
    try:
        for s in xrange(Vrh_p1.shape[0]):
            BB21np1[s] = r_si_p1.dot_left(Z2.dot(Vrh_p1[s].conj().T))
    except AttributeError:
        for s in xrange(Vrh_p1.shape[0]):
            BB21np1[s] = Z2.dot(Vrh_p1[s].conj().T).dot(r_si_p1)
        
    return BB12n, BB21np1, dDn
示例#7
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
示例#8
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
示例#9
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()
示例#10
0
    def restore_RCF_l(self):
        G_nm1 = None
        l_nm1 = self.l[0]
        for n in xrange(self.N + 1):
            if n == 0:
                x = l_nm1
            else:
                x = mm.mmul(mm.H(G_nm1), l_nm1, G_nm1)
            M = self.eps_l(n, x)
            ev, EV = la.eigh(M)

            self.l[n] = mm.simple_diag_matrix(ev, dtype=self.typ)
            G_n_i = EV

            if n == 0:
                G_nm1 = mm.H(EV) #for left uniform case
                l_nm1 = self.l[n] #for sanity check
                self.u_gnd_l.r = mm.mmul(G_nm1, self.u_gnd_l.r, G_n_i) #since r is not eye

            for s in xrange(self.q[n]):
                self.A[n][s] = mm.mmul(G_nm1, self.A[n][s], G_n_i)

            if self.sanity_checks:
                l = self.eps_l(n, l_nm1)
                if not sp.allclose(l, self.l[n], atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_RCF_l!: l_%u is bad" % n
                    print la.norm(l - self.l[n])

            G_nm1 = mm.H(EV)
            l_nm1 = self.l[n]

            if self.sanity_checks:
                if not sp.allclose(sp.dot(G_nm1, G_n_i), sp.eye(G_n_i.shape[0]),
                                   atol=1E-12, rtol=1E-12):
                    print "Sanity Fail in restore_RCF_l!: Bad GT for l_%u" % n

        #Now G_nm1 = G_N
        G_nm1_i = mm.H(G_nm1)
        for s in xrange(self.q[self.N + 1]):
            self.A[self.N + 1][s] = mm.mmul(G_nm1, self.A[self.N + 1][s], G_nm1_i)

        ##This should not be necessary if G_N is really unitary
        #self.r[self.N] = mm.mmul(G_nm1, self.r[self.N], mm.H(G_nm1))
        #self.r[self.N + 1] = self.r[self.N]
        self.u_gnd_r.l[:] = mm.mmul(mm.H(G_nm1_i), self.u_gnd_r.l, G_nm1_i)
        
        self.S_hc = sp.zeros((self.N), dtype=sp.complex128)
        for n in xrange(1, self.N + 1):
            self.S_hc[n-1] = -sp.sum(self.l[n].diag * sp.log2(self.l[n].diag))
示例#11
0
    def restore_SCF(self):
        X = la.cholesky(self.r, lower=True)
        Y = la.cholesky(self.l, lower=False)
        
        U, sv, Vh = la.svd(Y.dot(X))
        
        #s contains the Schmidt coefficients,
        lam = sv**2
        self.S_hc = - np.sum(lam * sp.log2(lam))
        
        S = m.simple_diag_matrix(sv, dtype=self.typ)
        Srt = S.sqrt()
        
        g = m.mmul(Srt, Vh, m.invtr(X, lower=True))
        
        g_i = m.mmul(m.invtr(Y, lower=False), U, Srt)
        
        for s in xrange(self.q):
            self.A[s] = m.mmul(g, self.A[s], g_i)
                
        if self.sanity_checks:
            Sfull = np.asarray(S)
            
            if not np.allclose(g.dot(g_i), np.eye(self.D)):
                print "Sanity check failed! Restore_SCF, bad GT!"
            
            l = m.mmul(m.H(g_i), self.l, g_i)
            r = m.mmul(g, self.r, m.H(g))
            
            if not np.allclose(Sfull, l):
                print "Sanity check failed: Restorce_SCF, left failed!"
                
            if not np.allclose(Sfull, r):
                print "Sanity check failed: Restorce_SCF, right failed!"
                
            l = self.eps_l(Sfull)
            r = self.eps_r(Sfull)
            
            if not np.allclose(Sfull, l, rtol=self.itr_rtol*self.check_fac, 
                               atol=self.itr_atol*self.check_fac):
                print "Sanity check failed: Restorce_SCF, left bad!"
                
            if not np.allclose(Sfull, r, rtol=self.itr_rtol*self.check_fac, 
                               atol=self.itr_atol*self.check_fac):
                print "Sanity check failed: Restorce_SCF, right bad!"

        self.l = S
        self.r = S
示例#12
0
def herm_fac_with_inv(A, lower=False, zero_tol=1E-15, return_rank=False, 
                      calc_inv=True, force_evd=False, 
                      sanity_checks=False, sc_data=''):
    """Factorizes a Hermitian matrix using either Cholesky or eigenvalue decomposition.
    
    Decomposes a Hermitian A as A = X*X or, if lower == True, A = XX*.
    
    Tries Cholesky first by default, then falls back to EVD if the matrix is 
    not positive-definite. If Cholesky decomposition is used, X is upper (or lower)
    triangular. For the EVD decomposition, the inverse becomes a pseudo-inverse
    and all eigenvalues below the zero-tolerance are set to zero.
    
    Parameters
    ----------
    A : ndarray
        The Hermitian matrix to be factorized.
    lower : bool
        Refers to Cholesky factorization. If True, factorize as A = XX*, otherwise as A = X*X
    zero_tol : float
        Tolerance for detection of zeros in EVD case.
    return_rank : bool
        Whether to return the rank of A. The detected rank is affected by zero_tol.
    calc_inv : bool
        Whether to calculate (and return) the inverse of the factor.
    force_evd : bool
        Whether to force eigenvalue instead of Cholesky decomposition.
    sanity_checks : bool
        Whether to perform soem basic sanity checks.
    """    
    if not force_evd:
        try:
            x = la.cholesky(A, lower=lower)
            if calc_inv:
                xi = mm.invtr(x, lower=lower)
            else:
                xi = None
            
            nonzeros = A.shape[0]
        except sp.linalg.LinAlgError: #this usually means a is not pos. def.
            force_evd = True
            
    if force_evd:
        ev, EV = la.eigh(A, turbo=True) #wraps lapack routines, which return eigenvalues in ascending order
        
        if sanity_checks:
            assert np.all(ev == np.sort(ev)), "Sanity fail in herm_fac_with_inv(): Unexpected eigenvalue ordering"
            
            if ev.min() < -zero_tol:
                log.warning("Sanity fail in herm_fac_with_inv(): Discarding negative eigenvalues! %s %s",
                            ev.min(), sc_data)
        
        nonzeros = np.count_nonzero(ev > zero_tol) 

        ev_sq = sp.zeros_like(ev, dtype=A.dtype)
        ev_sq[-nonzeros:] = sp.sqrt(ev[-nonzeros:])
        ev_sq = mm.simple_diag_matrix(ev_sq, dtype=A.dtype)
        
        if calc_inv:
            #Replace almost-zero values with zero and perform a pseudo-inverse
            ev_sq_i = sp.zeros_like(ev, dtype=A.dtype)
            ev_sq_i[-nonzeros:] = 1. / ev_sq[-nonzeros:]
            
            ev_sq_i = mm.simple_diag_matrix(ev_sq_i, dtype=A.dtype)        
                   
        xi = None
        if lower:
            x = ev_sq.dot_left(EV)
            if calc_inv:
                xi = ev_sq_i.dot(EV.conj().T)
        else:
            x = ev_sq.dot(EV.conj().T)
            if calc_inv:
                xi = ev_sq_i.dot_left(EV)
            
    if sanity_checks:
        if not sp.allclose(A, A.conj().T, atol=1E-13, rtol=1E-13):
            log.warning("Sanity fail in herm_fac_with_inv(): A is not Hermitian! %s %s",
                        la.norm(A - A.conj().T), sc_data)
        
        eye = sp.zeros((A.shape[0]), dtype=A.dtype)
        eye[-nonzeros:] = 1
        eye = mm.simple_diag_matrix(eye)
        
        if lower:
            if calc_inv:
                if not sp.allclose(xi.dot(x), eye, atol=1E-13, rtol=1E-13):
                    log.warning("Sanity fail in herm_fac_with_inv(): Bad left inverse! %s %s",
                                la.norm(xi.dot(x) - eye), sc_data)
                                
                if not sp.allclose(xi.dot(A).dot(xi.conj().T), eye, atol=1E-13, rtol=1E-13):
                    log.warning("Sanity fail in herm_fac_with_inv(): Bad A inverse! %s %s",
                                la.norm(xi.conj().T.dot(A).dot(xi) - eye), sc_data)
    
            if not sp.allclose(x.dot(x.conj().T), A, atol=1E-13, rtol=1E-13):
                log.warning("Sanity fail in herm_fac_with_inv(): Bad decomp! %s %s",
                            la.norm(x.dot(x.conj().T) - A), sc_data)
        else:
            if calc_inv:
                if not sp.allclose(x.dot(xi), eye, atol=1E-13, rtol=1E-13):
                    log.warning("Sanity fail in herm_fac_with_inv(): Bad right inverse! %s %s",
                                la.norm(x.dot(xi) - eye), sc_data)
                if not sp.allclose(xi.conj().T.dot(A).dot(xi), eye, atol=1E-13, rtol=1E-13):
                    log.warning("Sanity fail in herm_fac_with_inv(): Bad A inverse! %s %s",
                                la.norm(xi.conj().T.dot(A).dot(xi) - eye), sc_data)

    
            if not sp.allclose(x.conj().T.dot(x), A, atol=1E-13, rtol=1E-13):
                log.warning("Sanity fail in herm_fac_with_inv(): Bad decomp! %s %s",
                            la.norm(x.conj().T.dot(x) - A), sc_data)
                    
    if calc_inv:
        if return_rank:
            return x, xi, nonzeros
        else:
            return x, xi
    else:
        if return_rank:
            return x, nonzeros
        else:
            return x
示例#13
0
def restore_RCF_l(A, lm1, Gm1, sanity_checks=False):
    """Transforms a single A[n] to obtain diagonal l[n].

    Applied after restore_RCF_r(), this completes the full canonical form
    of sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2.

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

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

    The diagonal entries of l[n] are sorted in
    ascending order (for example l[n] = diag([0, 0, 0.1, 0.2, ...])).

    Parameters
    ----------
    A : ndarray
        The parameter tensor for the nth site A[n].
    lm1 : ndarray or object with array interface
        The matrix l[n - 1].
    Gm1 : ndarray
        The gauge transform matrix for site n obtained in the previous step (for n - 1).
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
        
    Returns
    -------
    l : ndarray or simple_diag_matrix
        The new, diagonal matrix l[n]. 
    G : ndarray
        The gauge transformation matrix for site n.
    G_i : ndarray
        Inverse of G.
    """
    if Gm1 is None:
        x = lm1
    else:
        x = Gm1.conj().T.dot(lm1.dot(Gm1))

    M = eps_l_noop(x, A, A)
    ev, EV = la.eigh(
        M)  #wraps lapack routines, which return eigenvalues in ascending order

    if sanity_checks:
        assert np.all(ev == np.sort(ev)), "unexpected eigenvalue ordering"

    l = mm.simple_diag_matrix(ev, dtype=A.dtype)
    G_i = EV

    if Gm1 is None:
        Gm1 = EV.conj().T  #for left uniform case
        lm1 = l  #for sanity check

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

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

    G = EV.conj().T

    return l, G, G_i
示例#14
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
示例#15
0
def herm_fac_with_inv(A,
                      lower=False,
                      zero_tol=1E-15,
                      return_rank=False,
                      calc_inv=True,
                      force_evd=False,
                      sanity_checks=False,
                      sc_data=''):
    """Factorizes a Hermitian matrix using either Cholesky or eigenvalue decomposition.
    
    Decomposes a Hermitian A as A = X*X or, if lower == True, A = XX*.
    
    Tries Cholesky first by default, then falls back to EVD if the matrix is 
    not positive-definite. If Cholesky decomposition is used, X is upper (or lower)
    triangular. For the EVD decomposition, the inverse becomes a pseudo-inverse
    and all eigenvalues below the zero-tolerance are set to zero.
    
    Parameters
    ----------
    A : ndarray
        The Hermitian matrix to be factorized.
    lower : bool
        Refers to Cholesky factorization. If True, factorize as A = XX*, otherwise as A = X*X
    zero_tol : float
        Tolerance for detection of zeros in EVD case.
    return_rank : bool
        Whether to return the rank of A. The detected rank is affected by zero_tol.
    calc_inv : bool
        Whether to calculate (and return) the inverse of the factor.
    force_evd : bool
        Whether to force eigenvalue instead of Cholesky decomposition.
    sanity_checks : bool
        Whether to perform soem basic sanity checks.
    """
    if not force_evd:
        try:
            x = la.cholesky(A, lower=lower)
            if calc_inv:
                xi = mm.invtr(x, lower=lower)
            else:
                xi = None

            nonzeros = A.shape[0]
        except sp.linalg.LinAlgError:  #this usually means a is not pos. def.
            force_evd = True

    if force_evd:
        ev, EV = la.eigh(
            A, turbo=True
        )  #wraps lapack routines, which return eigenvalues in ascending order

        if sanity_checks:
            assert np.all(
                ev == np.sort(ev)
            ), "Sanity fail in herm_fac_with_inv(): Unexpected eigenvalue ordering"

            if ev.min() < -zero_tol:
                log.warning(
                    "Sanity fail in herm_fac_with_inv(): Discarding negative eigenvalues! %s %s",
                    ev.min(), sc_data)

        nonzeros = np.count_nonzero(ev > zero_tol)

        ev_sq = sp.zeros_like(ev, dtype=A.dtype)
        ev_sq[-nonzeros:] = sp.sqrt(ev[-nonzeros:])
        ev_sq = mm.simple_diag_matrix(ev_sq, dtype=A.dtype)

        if calc_inv:
            #Replace almost-zero values with zero and perform a pseudo-inverse
            ev_sq_i = sp.zeros_like(ev, dtype=A.dtype)
            ev_sq_i[-nonzeros:] = 1. / ev_sq[-nonzeros:]

            ev_sq_i = mm.simple_diag_matrix(ev_sq_i, dtype=A.dtype)

        xi = None
        if lower:
            x = ev_sq.dot_left(EV)
            if calc_inv:
                xi = ev_sq_i.dot(EV.conj().T)
        else:
            x = ev_sq.dot(EV.conj().T)
            if calc_inv:
                xi = ev_sq_i.dot_left(EV)

    if sanity_checks:
        if not sp.allclose(A, A.conj().T, atol=1E-13, rtol=1E-13):
            log.warning(
                "Sanity fail in herm_fac_with_inv(): A is not Hermitian! %s %s",
                la.norm(A - A.conj().T), sc_data)

        eye = sp.zeros((A.shape[0]), dtype=A.dtype)
        eye[-nonzeros:] = 1
        eye = mm.simple_diag_matrix(eye)

        if lower:
            if calc_inv:
                if not sp.allclose(xi.dot(x), eye, atol=1E-13, rtol=1E-13):
                    log.warning(
                        "Sanity fail in herm_fac_with_inv(): Bad left inverse! %s %s",
                        la.norm(xi.dot(x) - eye), sc_data)

                if not sp.allclose(
                        xi.dot(A).dot(
                            xi.conj().T), eye, atol=1E-13, rtol=1E-13):
                    log.warning(
                        "Sanity fail in herm_fac_with_inv(): Bad A inverse! %s %s",
                        la.norm(xi.conj().T.dot(A).dot(xi) - eye), sc_data)

            if not sp.allclose(x.dot(x.conj().T), A, atol=1E-13, rtol=1E-13):
                log.warning(
                    "Sanity fail in herm_fac_with_inv(): Bad decomp! %s %s",
                    la.norm(x.dot(x.conj().T) - A), sc_data)
        else:
            if calc_inv:
                if not sp.allclose(x.dot(xi), eye, atol=1E-13, rtol=1E-13):
                    log.warning(
                        "Sanity fail in herm_fac_with_inv(): Bad right inverse! %s %s",
                        la.norm(x.dot(xi) - eye), sc_data)
                if not sp.allclose(
                        xi.conj().T.dot(A).dot(xi), eye, atol=1E-13,
                        rtol=1E-13):
                    log.warning(
                        "Sanity fail in herm_fac_with_inv(): Bad A inverse! %s %s",
                        la.norm(xi.conj().T.dot(A).dot(xi) - eye), sc_data)

            if not sp.allclose(x.conj().T.dot(x), A, atol=1E-13, rtol=1E-13):
                log.warning(
                    "Sanity fail in herm_fac_with_inv(): Bad decomp! %s %s",
                    la.norm(x.conj().T.dot(x) - A), sc_data)

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

        self.l = S
        self.r = S
        
        if ret_g:
            return g, g_i
        else:
            return
示例#17
0
def herm_sqrt_inv(x,
                  zero_tol=1E-15,
                  sanity_checks=False,
                  return_rank=False,
                  sc_data=''):
    if isinstance(x, mm.eyemat):
        x_sqrt = x
        x_sqrt_i = x
        rank = x.shape[0]
    else:
        try:
            ev = x.diag  #simple_diag_matrix
            EV = None
        except AttributeError:
            ev, EV = la.eigh(x)

        zeros = ev <= zero_tol  #throw away negative results too!

        ev_sqrt = sp.sqrt(ev)

        err = sp.seterr(divide='ignore', invalid='ignore')
        try:
            ev_sqrt_i = 1 / ev_sqrt
            ev_sqrt[zeros] = 0
            ev_sqrt_i[zeros] = 0
        finally:
            sp.seterr(divide=err['divide'], invalid=err['invalid'])

        if EV is None:
            x_sqrt = mm.simple_diag_matrix(ev_sqrt, dtype=x.dtype)
            x_sqrt_i = mm.simple_diag_matrix(ev_sqrt_i, dtype=x.dtype)
        else:
            B = mm.mmul_diag(ev_sqrt, EV.conj().T)
            x_sqrt = EV.dot(B)

            B = mm.mmul_diag(ev_sqrt_i, EV.conj().T)
            x_sqrt_i = EV.dot(B)

        rank = x.shape[0] - np.count_nonzero(zeros)

        if sanity_checks:
            if ev.min() < -zero_tol:
                log.warning(
                    "Sanity Fail in herm_sqrt_inv(): Throwing away negative eigenvalues! %s %s",
                    ev.min(), sc_data)

            if not np.allclose(x_sqrt.dot(x_sqrt), x):
                log.warning(
                    "Sanity Fail in herm_sqrt_inv(): x_sqrt is bad! %s %s",
                    la.norm(x_sqrt.dot(x_sqrt) - x), sc_data)

            if EV is None:
                nulls = sp.zeros(x.shape[0])
                nulls[zeros] = 1
                nulls = sp.diag(nulls)
            else:  #if we did an EVD then we use the eigenvectors
                nulls = EV.copy()
                nulls[:, sp.invert(zeros)] = 0
                nulls = nulls.dot(nulls.conj().T)

            eye = np.eye(x.shape[0])
            if not np.allclose(x_sqrt.dot(x_sqrt_i), eye - nulls):
                log.warning(
                    "Sanity Fail in herm_sqrt_inv(): x_sqrt_i is bad! %s %s",
                    la.norm(x_sqrt.dot(x_sqrt_i) - eye + nulls), sc_data)

    if return_rank:
        return x_sqrt, x_sqrt_i, rank
    else:
        return x_sqrt, x_sqrt_i
示例#18
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
示例#19
0
def herm_sqrt_inv(x, zero_tol=1E-15, sanity_checks=False, return_rank=False, sc_data=''):
    if isinstance(x,  mm.eyemat):
        x_sqrt = x
        x_sqrt_i = x
        rank = x.shape[0]
    else:
        try:
            ev = x.diag #simple_diag_matrix
            EV = None
        except AttributeError:
            ev, EV = la.eigh(x)
        
        zeros = ev <= zero_tol #throw away negative results too!
        
        ev_sqrt = sp.sqrt(ev)
        
        err = sp.seterr(divide='ignore', invalid='ignore')
        try:
            ev_sqrt_i = 1 / ev_sqrt
            ev_sqrt[zeros] = 0
            ev_sqrt_i[zeros] = 0
        finally:
            sp.seterr(divide=err['divide'], invalid=err['invalid'])
        
        if EV is None:
            x_sqrt = mm.simple_diag_matrix(ev_sqrt, dtype=x.dtype)
            x_sqrt_i = mm.simple_diag_matrix(ev_sqrt_i, dtype=x.dtype)
        else:
            B = mm.mmul_diag(ev_sqrt, EV.conj().T)
            x_sqrt = EV.dot(B)
            
            B = mm.mmul_diag(ev_sqrt_i, EV.conj().T)
            x_sqrt_i = EV.dot(B)
            
        rank = x.shape[0] - np.count_nonzero(zeros)
        
        if sanity_checks:
            if ev.min() < -zero_tol:
                log.warning("Sanity Fail in herm_sqrt_inv(): Throwing away negative eigenvalues! %s %s",
                            ev.min(), sc_data)
            
            if not np.allclose(x_sqrt.dot(x_sqrt), x):
                log.warning("Sanity Fail in herm_sqrt_inv(): x_sqrt is bad! %s %s",
                            la.norm(x_sqrt.dot(x_sqrt) - x), sc_data)
            
            if EV is None: 
                nulls = sp.zeros(x.shape[0])
                nulls[zeros] = 1
                nulls = sp.diag(nulls)
            else: #if we did an EVD then we use the eigenvectors
                nulls = EV.copy()
                nulls[:, sp.invert(zeros)] = 0
                nulls = nulls.dot(nulls.conj().T)
                
            eye = np.eye(x.shape[0])
            if not np.allclose(x_sqrt.dot(x_sqrt_i), eye - nulls):
                log.warning("Sanity Fail in herm_sqrt_inv(): x_sqrt_i is bad! %s %s",
                            la.norm(x_sqrt.dot(x_sqrt_i) - eye + nulls), sc_data)
    
    if return_rank:
        return x_sqrt, x_sqrt_i, rank
    else:
        return x_sqrt, x_sqrt_i
示例#20
0
def restore_RCF_l(A, lm1, Gm1, sanity_checks=False):
    """Transforms a single A[n] to obtain diagonal l[n].

    Applied after restore_RCF_r(), this completes the full canonical form
    of sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2.

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

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

    The diagonal entries of l[n] are sorted in
    ascending order (for example l[n] = diag([0, 0, 0.1, 0.2, ...])).

    Parameters
    ----------
    A : ndarray
        The parameter tensor for the nth site A[n].
    lm1 : ndarray or object with array interface
        The matrix l[n - 1].
    Gm1 : ndarray
        The gauge transform matrix for site n obtained in the previous step (for n - 1).
    sanity_checks : bool (False)
        Whether to perform additional sanity checks.
        
    Returns
    -------
    l : ndarray or simple_diag_matrix
        The new, diagonal matrix l[n]. 
    G : ndarray
        The gauge transformation matrix for site n.
    G_i : ndarray
        Inverse of G.
    """
    if Gm1 is None:
        x = lm1
    else:
        x = Gm1.conj().T.dot(lm1.dot(Gm1))

    M = eps_l_noop(x, A, A)
    ev, EV = la.eigh(M) #wraps lapack routines, which return eigenvalues in ascending order
    
    if sanity_checks:
        assert np.all(ev == np.sort(ev)), "unexpected eigenvalue ordering"
    
    l = mm.simple_diag_matrix(ev, dtype=A.dtype)
    G_i = EV

    if Gm1 is None:
        Gm1 = EV.conj().T #for left uniform case
        lm1 = l #for sanity check

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

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

    G = EV.conj().T

    return l, G, G_i
示例#21
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)
示例#22
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
示例#23
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