Example #1
0
    def setUp(self):  #TODO: Test rectangular x as well
        self.d = [2, 3]
        self.D = [2, 4, 3]

        self.l0 = sp.rand(self.D[0],
                          self.D[0]) + 1.j * sp.rand(self.D[0], self.D[0])
        self.r1 = sp.rand(self.D[1],
                          self.D[1]) + 1.j * sp.rand(self.D[1], self.D[1])
        self.r2 = sp.rand(self.D[2],
                          self.D[2]) + 1.j * sp.rand(self.D[2], self.D[2])

        self.ld0 = mm.simple_diag_matrix(
            sp.rand(self.D[0]) + 1.j * sp.rand(self.D[0]))
        self.rd1 = mm.simple_diag_matrix(
            sp.rand(self.D[1]) + 1.j * sp.rand(self.D[1]))
        self.rd2 = mm.simple_diag_matrix(
            sp.rand(self.D[2]) + 1.j * sp.rand(self.D[2]))

        self.eye0 = mm.eyemat(self.D[0], dtype=sp.complex128)
        self.eye1 = mm.eyemat(self.D[1], dtype=sp.complex128)
        self.eye2 = mm.eyemat(self.D[2], dtype=sp.complex128)

        self.A0 = sp.rand(self.d[0], self.D[0], self.D[0]) + 1.j * sp.rand(
            self.d[0], self.D[0], self.D[0])
        self.A1 = sp.rand(self.d[0], self.D[0], self.D[1]) + 1.j * sp.rand(
            self.d[0], self.D[0], self.D[1])
        self.A2 = sp.rand(self.d[1], self.D[1], self.D[2]) + 1.j * sp.rand(
            self.d[1], self.D[1], self.D[2])
        self.A3 = sp.rand(self.d[1], self.D[2], self.D[2]) + 1.j * sp.rand(
            self.d[1], self.D[2], self.D[2])

        self.B1 = sp.rand(self.d[0], self.D[0], self.D[1]) + 1.j * sp.rand(
            self.d[0], self.D[0], self.D[1])
        self.B2 = sp.rand(self.d[1], self.D[1], self.D[2]) + 1.j * sp.rand(
            self.d[1], self.D[1], self.D[2])

        self.E1_AB = make_E_noop(self.A1, self.B1)
        self.E2_AB = make_E_noop(self.A2, self.B2)

        self.op1s_1 = sp.rand(self.d[0],
                              self.d[0]) + 1.j * sp.rand(self.d[0], self.d[0])
        self.E1_op_AB = make_E_1s(self.A1, self.B1, self.op1s_1)

        self.op2s = sp.rand(self.d[0], self.d[1],
                            self.d[0], self.d[1]) + 1.j * sp.rand(
                                self.d[0], self.d[1], self.d[0], self.d[1])
        self.E12_op = make_E_2s(self.A1, self.A2, self.B1, self.B2, self.op2s)

        self.AA12 = tc.calc_AA(self.A1, self.A2)
        self.BB12 = tc.calc_AA(self.B1, self.B2)

        self.C_A12 = tc.calc_C_mat_op_AA(self.op2s, self.AA12)
        self.C_conj_B12 = tc.calc_C_conj_mat_op_AA(self.op2s, self.BB12)

        self.C01 = sp.rand(self.d[0], self.d[0],
                           self.D[0], self.D[1]) + 1.j * sp.rand(
                               self.d[0], self.d[0], self.D[0], self.D[1])
Example #2
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
Example #3
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
Example #4
0
 def setUp(self): #TODO: Test rectangular x as well
     self.d = [2, 3]
     self.D = [2, 4, 3]
     
     self.l0 = sp.rand(self.D[0], self.D[0]) + 1.j * sp.rand(self.D[0], self.D[0])
     self.r1 = sp.rand(self.D[1], self.D[1]) + 1.j * sp.rand(self.D[1], self.D[1])
     self.r2 = sp.rand(self.D[2], self.D[2]) + 1.j * sp.rand(self.D[2], self.D[2])
     
     self.ld0 = mm.simple_diag_matrix(sp.rand(self.D[0]) + 1.j * sp.rand(self.D[0]))
     self.rd1 = mm.simple_diag_matrix(sp.rand(self.D[1]) + 1.j * sp.rand(self.D[1]))
     self.rd2 = mm.simple_diag_matrix(sp.rand(self.D[2]) + 1.j * sp.rand(self.D[2]))
     
     self.eye0 = mm.eyemat(self.D[0], dtype=sp.complex128)
     self.eye1 = mm.eyemat(self.D[1], dtype=sp.complex128)
     self.eye2 = mm.eyemat(self.D[2], dtype=sp.complex128)
     
     self.A0 = sp.rand(self.d[0], self.D[0], self.D[0]) + 1.j * sp.rand(self.d[0], self.D[0], self.D[0])
     self.A1 = sp.rand(self.d[0], self.D[0], self.D[1]) + 1.j * sp.rand(self.d[0], self.D[0], self.D[1])
     self.A2 = sp.rand(self.d[1], self.D[1], self.D[2]) + 1.j * sp.rand(self.d[1], self.D[1], self.D[2])
     self.A3 = sp.rand(self.d[1], self.D[2], self.D[2]) + 1.j * sp.rand(self.d[1], self.D[2], self.D[2])
     
     self.B1 = sp.rand(self.d[0], self.D[0], self.D[1]) + 1.j * sp.rand(self.d[0], self.D[0], self.D[1])
     self.B2 = sp.rand(self.d[1], self.D[1], self.D[2]) + 1.j * sp.rand(self.d[1], self.D[1], self.D[2])
     
     self.E1_AB = make_E_noop(self.A1, self.B1)
     self.E2_AB = make_E_noop(self.A2, self.B2)
     
     self.op1s_1 = sp.rand(self.d[0], self.d[0]) + 1.j * sp.rand(self.d[0], self.d[0])
     self.E1_op_AB = make_E_1s(self.A1, self.B1, self.op1s_1)
     
     self.op2s = sp.rand(self.d[0], self.d[1], self.d[0], self.d[1]) + 1.j * sp.rand(self.d[0], self.d[1], self.d[0], self.d[1])
     self.E12_op = make_E_2s(self.A1, self.A2, self.B1, self.B2, self.op2s)
     
     self.AA12 = tc.calc_AA(self.A1, self.A2)
     self.BB12 = tc.calc_AA(self.B1, self.B2)
     
     self.C_A12 = tc.calc_C_mat_op_AA(self.op2s, self.AA12)
     self.C_conj_B12 = tc.calc_C_conj_mat_op_AA(self.op2s, self.BB12)
     
     self.C01 = sp.rand(self.d[0], self.d[0], self.D[0], self.D[1]) + 1.j * sp.rand(self.d[0], self.d[0], self.D[0], self.D[1])
Example #5
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

    if sanity_checks:
        eye = sp.eye(A.shape[1])
        if not sp.allclose(sp.dot(Gm1, Gm1_i), eye, atol=1E-12, rtol=1E-12):
            log.warning("Sanity Fail in restore_LCF_r!: Bad GT! (off by %g)",
                        la.norm(sp.dot(Gm1, Gm1_i) - eye))

    return rm1, Gm1, Gm1_i
Example #6
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

    if sanity_checks:
        eye = sp.eye(A.shape[1])
        if not sp.allclose(sp.dot(Gm1, Gm1_i), eye,
                           atol=1E-12, rtol=1E-12):
            log.warning("Sanity Fail in restore_LCF_r!: Bad GT! (off by %g)", la.norm(sp.dot(Gm1, Gm1_i) - eye))
            
    return rm1, Gm1, Gm1_i
Example #7
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
Example #8
0
def herm_fac_with_inv(A,
                      lower=False,
                      zero_tol=1E-15,
                      return_rank=False,
                      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.
    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)
            xi = mm.invtr(x, lower=lower)

            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:])

        #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)
        ev_sq = mm.simple_diag_matrix(ev_sq, dtype=A.dtype)

        if lower:
            x = ev_sq.dot_left(EV)
            xi = ev_sq_i.dot(EV.conj().T)
        else:
            x = ev_sq.dot(EV.conj().T)
            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 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(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)

            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)
        else:
            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(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 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 return_rank:
        return x, xi, nonzeros
    else:
        return x, xi
Example #9
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
Example #10
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

    if sanity_checks:
        eye = sp.eye(A.shape[2])
        if not sp.allclose(sp.dot(G, G_i), eye, atol=1E-12, rtol=1E-12):
            log.warning("Sanity Fail in restore_RCF_l!: Bad GT! (off by %g)",
                        la.norm(sp.dot(G, G_i) - eye))

    return l, G, G_i
Example #11
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
Example #12
0
def herm_fac_with_inv(A, lower=False, zero_tol=1E-15, return_rank=False, 
                      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.
    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)
            xi = mm.invtr(x, lower=lower)
            
            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:])
        
        #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)
        ev_sq = mm.simple_diag_matrix(ev_sq, dtype=A.dtype)
                   
        if lower:
            x = ev_sq.dot_left(EV)
            xi = ev_sq_i.dot(EV.conj().T)
        else:
            x = ev_sq.dot(EV.conj().T)
            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 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(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)
                
            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)
        else:
            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(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 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 return_rank:
        return x, xi, nonzeros
    else:
        return x, xi
Example #13
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
Example #14
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

    if sanity_checks:
        eye = sp.eye(A.shape[2])
        if not sp.allclose(sp.dot(G, G_i), eye,
                           atol=1E-12, rtol=1E-12):
            log.warning("Sanity Fail in restore_RCF_l!: Bad GT! (off by %g)", la.norm(sp.dot(G, G_i) - eye))
            
    return l, G, G_i