Ejemplo n.º 1
0
    def observe(self, obs_mesh, obs_V):
        __doc__ = Covariance.observe.__doc__

        ndim = obs_mesh.shape[1]
        nobs = obs_mesh.shape[0]


        if self.ndim is not None:
            if not ndim==self.ndim:
                raise ValueError, "Dimension of observation mesh is not equal to dimension of base mesh."
        else:
            self.ndim = ndim

        # bases_o is the basis evaluated on the observation mesh.
        basis_o = asmatrix(self.eval_basis(obs_mesh, regularize=False))

        # chol(basis_o.T * coef_cov * basis_o)
        chol_inner = self.coef_U * basis_o

        # chol(basis_o.T * coef_cov * basis_o + diag(obs_V)). Really should do this as low-rank update of covariance
        # of V.
        U, piv, m = ichol_basis(basis=chol_inner, nug=obs_V, reltol=self.relative_precision)


        U = asmatrix(U)
        piv_new = piv[:m]
        self.obs_piv = piv_new
        obs_mesh_new = obs_mesh[piv_new,:]

        self.Uo = U[:m,:m]

        # chol(basis_o.T * coef_cov * basis_o + diag(obs_V)) ^ -T * basis_o.T
        self.Uo_cov = trisolve(self.Uo, basis_o[:,piv[:m]].T, uplo='U', transa='T')

        # chol(basis_o.T * coef_cov * basis_o + diag(obs_V)).T.I * basis_o.T * coef_cov
        self.Uo_cov = self.Uo_cov * self.coef_cov

        # coef_cov -= coef_cov * basis_o * (basis_o.T * coef_cov * basis_o + diag(obs_V)).I * basis_o.T * coef_cov
        self.coef_cov -= self.Uo_cov.T * self.Uo_cov

        # coef_U = chol(coef_cov)
        U, m, piv = ichol_full(c=self.coef_cov, reltol=self.relative_precision)
        U = asmatrix(U)
        self.coef_U = U[:m,argsort(piv)]
        self.m = m

        return piv_new, obs_mesh_new, None
Ejemplo n.º 2
0
    def __init__(self, basis, coef_cov, relative_precision = 1.0E-15, **params):

        self.observed = False
        self.obs_mesh = None
        self.obs_V = None
        self.Uo = None
        self.obs_piv = None
        self.obs_len = None
        self.full_piv = None
        self.full_obs_mesh = None
        self.basiscov=True

        self.basis = ravel(basis)
        self.shape = self.get_shape_from_basis(basis)
        self.n = prod(self.shape)
        self.ndim = len(self.shape)


        self.relative_precision = relative_precision
        self.params = params

        if coef_cov.shape == self.shape:
            self.coef_cov = asmatrix(diag(coef_cov.ravel()))
        elif coef_cov.shape == self.shape*2:
            self.coef_cov = asmatrix(coef_cov.reshape((self.n, self.n)))
        else:
            raise ValueError, "Covariance tensor's shape must be basis.shape or basis.shape*2 (using tuple multiplication)."

        # Cholesky factor the covariance matrix of the coefficients.
        U, m, piv = ichol_full(c=self.coef_cov, reltol=relative_precision)
        self.coef_U = asmatrix(U[:m,argsort(piv)])

        # Rank of the coefficient covariance.
        self.unobs_m = m
        self.m = m

        # Record the unobserved Cholesky factor of the coefficient covariance.
        self.unobs_coef_U = self.coef_U.copy()
        self.observed = False
Ejemplo n.º 3
0
    def __init__(self, basis, coef_cov, relative_precision=1.0E-15, **params):

        self.observed = False
        self.obs_mesh = None
        self.obs_V = None
        self.Uo = None
        self.obs_piv = None
        self.obs_len = None
        self.full_piv = None
        self.full_obs_mesh = None
        self.basiscov = True

        self.basis = ravel(basis)
        self.shape = self.get_shape_from_basis(basis)
        self.n = prod(self.shape)
        self.ndim = len(self.shape)

        self.relative_precision = relative_precision
        self.params = params

        if coef_cov.shape == self.shape:
            self.coef_cov = asmatrix(diag(coef_cov.ravel()))
        elif coef_cov.shape == self.shape * 2:
            self.coef_cov = asmatrix(coef_cov.reshape((self.n, self.n)))
        else:
            raise ValueError, "Covariance tensor's shape must be basis.shape or basis.shape*2 (using tuple multiplication)."

        # Cholesky factor the covariance matrix of the coefficients.
        U, m, piv = ichol_full(c=self.coef_cov, reltol=relative_precision)
        self.coef_U = asmatrix(U[:m, argsort(piv)])

        # Rank of the coefficient covariance.
        self.unobs_m = m
        self.m = m

        # Record the unobserved Cholesky factor of the coefficient covariance.
        self.unobs_coef_U = self.coef_U.copy()
        self.observed = False
Ejemplo n.º 4
0
    def cholesky(self, x, apply_pivot = True, observed=True, nugget=None, regularize=True):
        """

        U = C.cholesky(x[, observed=True, nugget=None])


        {'pivots': piv, 'U': U} = \
        C.cholesky(x, apply_pivot = False[, observed=True, nugget=None])


        Computes incomplete Cholesky factorization of self(x,x).


        :Arguments:

            -   `x`: The input array on which to evaluate the covariance.

            -   `apply_pivot`: A flag. If it's set to 'True', it returns a
                matrix U (not necessarily triangular) such that U.T*U=C(x,x).
                If it's set to 'False', the return value is a dictionary.
                Item 'pivots' is a vector of pivots, and item 'U' is an
                upper-triangular matrix (not necessarily square) such that
                U[:,argsort(piv)].T * U[:,argsort(piv)] = C(x,x).

            -   `observed`: If 'True', any observations are taken into account
                when computing the Cholesky factor. If not, the unobserved
                version of self is used.

            -   `nugget`: The 'nugget' parameter, which will essentially be
                added to the diagonal of C(x,x) before Cholesky factorizing.
        """

        if regularize:
            x=regularize_array(x)

        # Number of points in x.
        N_new = x.shape[0]

        # Special fast version for single points.
        if N_new==1:
            U=asmatrix(sqrt(self.__call__(x, regularize = False, observed = observed)))
            # print U
            if not apply_pivot:
                return {'pivots': array([0]), 'U': U}
            else:
                return U

        C = self.__call__(x, x, regularize=False, observed=observed)
        if nugget is not None:
            for i in xrange(N_new):
                C[i,i] += nugget[i]


        # =======================================
        # = Call to Fortran function ichol_full =
        # =======================================
        U, m, piv = ichol_full(c=C, reltol=self.relative_precision)

        U = asmatrix(U)

        # Arrange output matrix and return.
        if m<0:
            raise ValueError, "Matrix does not appear to be positive semidefinite"

        if not apply_pivot:
            # Useful for self.observe and Realization.__call__. U is upper triangular.
            U = U[:m,:]
            return {'pivots': piv, 'U': U}

        else:
            # Useful for users. U.T*U = C(x,x)
            return U[:m,argsort(piv)]
Ejemplo n.º 5
0
    def continue_cholesky(self, x, x_old, chol_dict_old, apply_pivot = True, observed=True, nugget=None, regularize=True, assume_full_rank=False):
        """

        U = C.continue_cholesky(x, x_old, chol_dict_old[, observed=True, nugget=None])


        {'pivots': piv, 'U': U} = \
        C.cholesky(x, x_old, chol_dict_old, apply_pivot = False[, observed=True, nugget=None])


        Computes incomplete Cholesky factorization of self(z,z). Here z is the
        concatenation of x and x_old. Assumes the Cholesky factorization of
        self(x_old, x_old) has already been computed.


        :Arguments:

            -   `x`: The input array on which to evaluate the Cholesky factorization.

            -   `x_old`: The input array on which the Cholesky factorization has been
                computed.

            -   `chol_dict_old`: A dictionary with kbasis_ys ['pivots', 'U']. Would be the
                output of either this method or C.cholesky().

            -   `apply_pivot`: A flag. If it's set to 'True', it returns a
                matrix U (not necessarily triangular) such that U.T*U=C(x,x).
                If it's set to 'False', the return value is a dictionary.
                Item 'pivots' is a vector of pivots, and item 'U' is an
                upper-triangular matrix (not necessarily square) such that
                U[:,argsort(piv)].T * U[:,argsort(piv)] = C(x,x).

            -   `observed`: If 'True', any observations are taken into account
                when computing the Cholesky factor. If not, the unobserved
                version of self is used.

            -   `nugget`: The 'nugget' parameter, which will essentially be
                added to the diagonal of C(x,x) before Cholesky factorizing.
        """
        if regularize:
            x=regularize_array(x)

        # Concatenation of the old points and new points.
        xtot = vstack((x_old,x))

        # Extract information from chol_dict_old.
        U_old = chol_dict_old['U']
        m_old = U_old.shape[0]
        piv_old = chol_dict_old['pivots']

        # Number of old points.
        N_old = x_old.shape[0]

        # Number of new points.
        N_new = x.shape[0]

        # Compute off-diagonal part of Cholesky factor
        offdiag = self.__call__(x=x_old[piv_old[:m_old],:], y=x, observed=observed, regularize=False)
        trisolve(U_old[:,:m_old],offdiag,uplo='U',transa='T', inplace=True)

        # Compute new diagonal part of Cholesky factor
        C_new = self.__call__(x=x, y=x, observed=observed, regularize=False)
        if nugget is not None:
            for i in xrange(N_new):
                C_new[i,i] += nugget[i]
        C_new -= offdiag.T*offdiag
        if not assume_full_rank:
            U_new, m_new, piv_new = ichol_full(c=C_new, reltol=self.relative_precision)
        else:
            U_new = cholesky(C_new).T
            m_new = U_new.shape[0]
            piv_new = arange(m_new)
        U_new = asmatrix(U_new[:m_new,:])
        U = asmatrix(zeros((m_new + m_old, N_old + N_new), dtype=float, order='F'))

        # Top portion of U
        U[:m_old, :m_old] = U_old[:,:m_old]
        U[:m_old,N_new+m_old:] = U_old[:,m_old:]
        offdiag=offdiag[:,piv_new]
        U[:m_old, m_old:N_new+m_old] = offdiag

        # Lower portion of U
        U[m_old:,m_old:m_old+N_new] = U_new
        if m_old < N_old and m_new > 0:
            offdiag_lower = self.__call__(  x=x[piv_new[:m_new],:],
                                            y=x_old[piv_old[m_old:],:], observed=observed, regularize=False)
            offdiag_lower -= offdiag[:,:m_new].T*U[:m_old,m_old+N_new:]
            trisolve(U_new[:,:m_new],offdiag_lower,uplo='U',transa='T', inplace=True)
            U[m_old:,m_old+N_new:] = offdiag_lower

        # Rank and pivots
        m=m_old+m_new
        piv=hstack((piv_old[:m_old],piv_new+N_old,piv_old[m_old:]))

        # Arrange output matrix and return.
        if m<0:
            raise ValueError, 'Matrix does not appear positive semidefinite.'

        if not apply_pivot:
            # Useful for self.observe. U is upper triangular.
            return {'pivots': piv, 'U': U}

        else:
            # Useful for the user. U.T * U = C(x,x).
            return U[:,argsort(piv)]
Ejemplo n.º 6
0
    def cholesky(self, x, apply_pivot = True, observed=True, nugget=None, regularize=True, rank_limit=0):
        """

        U = C.cholesky(x[, observed=True, nugget=None, rank_limit=0])

        {'pivots': piv, 'U': U} = \
        C.cholesky(x, apply_pivot = False[, observed=True, nugget=None])

        Computes incomplete Cholesky factorization of self(x,x).


        :Arguments:

            -   `x`: The input array on which to evaluate the covariance.

            -   `apply_pivot`: A flag. If it's set to 'True', it returns a
                matrix U (not necessarily triangular) such that U.T*U=C(x,x).
                If it's set to 'False', the return value is a dictionary.
                Item 'pivots' is a vector of pivots, and item 'U' is an
                upper-triangular matrix (not necessarily square) such that
                U[:,argsort(piv)].T * U[:,argsort(piv)] = C(x,x).

            -   `observed`: If 'True', any observations are taken into account
                when computing the Cholesky factor. If not, the unobserved
                version of self is used.

            -   `nugget`: The 'nugget' parameter, which will essentially be
                added to the diagonal of C(x,x) before Cholesky factorizing.

            -   `rank_limit`: If rank_limit > 0, the factor will have at most 
                rank_limit rows.
        """
        if rank_limit > 0:
            raise ValueError, 'NearlyFullRankCovariance does not accept a rank_limit argument. Use Covariance instead.'

        if regularize:
            x=regularize_array(x)

        # Number of points in x.
        N_new = x.shape[0]

        # Special fast version for single points.
        if N_new==1:
            V = self.__call__(x, regularize = False, observed = observed)
            if nugget is not None:
                V += nugget
            U=asmatrix(sqrt(V))
            # print U
            if not apply_pivot:
                return {'pivots': array([0]), 'U': U}
            else:
                return U

        C = self.__call__(x, x, regularize=False, observed=observed)
        if nugget is not None:
            for i in xrange(N_new):
                C[i,i] += nugget[i]


        # =======================================
        # = Call to Fortran function ichol_full =
        # =======================================
        U, m, piv = ichol_full(c=C, reltol=self.relative_precision)

        U = asmatrix(U)

        # Arrange output matrix and return.
        if m<0:
            raise ValueError, "Matrix does not appear to be positive semidefinite"

        if not apply_pivot:
            # Useful for self.observe and Realization.__call__. U is upper triangular.
            U = U[:m,:]
            return {'pivots': piv, 'U': U}

        else:
            # Useful for users. U.T*U = C(x,x)
            return U[:m,argsort(piv)]
Ejemplo n.º 7
0
    def continue_cholesky(self, x, x_old, chol_dict_old, apply_pivot = True, observed=True, nugget=None, regularize=True, assume_full_rank=False, rank_limit=0):
        """

        U = C.continue_cholesky(x, x_old, chol_dict_old[, observed=True, nugget=None,
                rank_limit=0])


        Returns {'pivots': piv, 'U': U}


        Computes incomplete Cholesky factorization of self(z,z). Here z is the
        concatenation of x and x_old. Assumes the Cholesky factorization of
        self(x_old, x_old) has already been computed.


        :Arguments:

            -   `x`: The input array on which to evaluate the Cholesky factorization.

            -   `x_old`: The input array on which the Cholesky factorization has been
                computed.

            -   `chol_dict_old`: A dictionary with kbasis_ys ['pivots', 'U']. Would be the
                output of either this method or C.cholesky().

            -   `apply_pivot`: A flag. If it's set to 'True', it returns a
                matrix U (not necessarily triangular) such that U.T*U=C(x,x).
                If it's set to 'False', the return value is a dictionary.
                Item 'pivots' is a vector of pivots, and item 'U' is an
                upper-triangular matrix (not necessarily square) such that
                U[:,argsort(piv)].T * U[:,argsort(piv)] = C(x,x).

            -   `observed`: If 'True', any observations are taken into account
                when computing the Cholesky factor. If not, the unobserved
                version of self is used.

            -   `nugget`: The 'nugget' parameter, which will essentially be
                added to the diagonal of C(x,x) before Cholesky factorizing.
                
            -   `rank_limit`: If rank_limit > 0, the factor will have at most 
                rank_limit rows.
        """
        if regularize:
            x=regularize_array(x)

        if rank_limit > 0:
            raise ValueError, 'NearlyFullRankCovariance does not accept a rank_limit argument. Use Covariance instead.'

        if rank_limit > 0:
            raise ValueError, 'NearlyFullRankCovariance does not accept a rank_limit argument. Use Covariance instead.'

        # Concatenation of the old points and new points.
        xtot = vstack((x_old,x))

        # Extract information from chol_dict_old.
        U_old = chol_dict_old['U']
        m_old = U_old.shape[0]
        piv_old = chol_dict_old['pivots']

        # Number of old points.
        N_old = x_old.shape[0]

        # Number of new points.
        N_new = x.shape[0]

        # Compute off-diagonal part of Cholesky factor
        offdiag = self.__call__(x=x_old[piv_old[:m_old],:], y=x, observed=observed, regularize=False)
        trisolve(U_old[:,:m_old],offdiag,uplo='U',transa='T', inplace=True)

        # Compute new diagonal part of Cholesky factor
        C_new = self.__call__(x=x, y=x, observed=observed, regularize=False)
        if nugget is not None:
            for i in xrange(N_new):
                C_new[i,i] += nugget[i]
        C_new -= offdiag.T*offdiag
        if not assume_full_rank:
            U_new, m_new, piv_new = ichol_full(c=C_new, reltol=self.relative_precision)
        else:
            U_new = cholesky(C_new).T
            m_new = U_new.shape[0]
            piv_new = arange(m_new)
        U_new = asmatrix(U_new[:m_new,:])
        U = asmatrix(zeros((m_new + m_old, N_old + N_new), dtype=float, order='F'))

        # Top portion of U
        U[:m_old, :m_old] = U_old[:,:m_old]
        U[:m_old,N_new+m_old:] = U_old[:,m_old:]
        offdiag=offdiag[:,piv_new]
        U[:m_old, m_old:N_new+m_old] = offdiag

        # Lower portion of U
        U[m_old:,m_old:m_old+N_new] = U_new
        if m_old < N_old and m_new > 0:
            offdiag_lower = self.__call__(  x=x[piv_new[:m_new],:],
                                            y=x_old[piv_old[m_old:],:], observed=observed, regularize=False)
            offdiag_lower -= offdiag[:,:m_new].T*U[:m_old,m_old+N_new:]
            trisolve(U_new[:,:m_new],offdiag_lower,uplo='U',transa='T', inplace=True)
            U[m_old:,m_old+N_new:] = offdiag_lower

        # Rank and pivots
        m=m_old+m_new
        piv=hstack((piv_old[:m_old],piv_new+N_old,piv_old[m_old:]))

        # Arrange output matrix and return.
        if m<0:
            raise ValueError, 'Matrix does not appear positive semidefinite.'

        if not apply_pivot:
            # Useful for self.observe. U is upper triangular.
            if assume_full_rank:
                return {'pivots':piv,'U':U,'C_eval':C_new,'U_new':U_new}
            else:
                return {'pivots': piv, 'U': U}

        else:
            # Useful for the user. U.T * U = C(x,x).
            return U[:,argsort(piv)]
Ejemplo n.º 8
0
    def observe(self, obs_mesh, obs_V, output_type='o'):
        __doc__ = Covariance.observe.__doc__

        ndim = obs_mesh.shape[1]
        nobs = obs_mesh.shape[0]

        if self.ndim is not None:
            if not ndim == self.ndim:
                raise ValueError, "Dimension of observation mesh is not equal to dimension of base mesh."
        else:
            self.ndim = ndim

        # bases_o is the basis evaluated on the observation mesh.
        basis_o = asmatrix(self.eval_basis(obs_mesh, regularize=False))

        # chol(basis_o.T * coef_cov * basis_o)
        chol_inner = self.coef_U * basis_o

        if output_type == 's':
            C_eval = dot(chol_inner.T, chol_inner).copy('F')
            U_eval = linalg.cholesky(C_eval).T.copy('F')
            U = U_eval
            m = U_eval.shape[0]
            piv = arange(m)
        else:
            # chol(basis_o.T * coef_cov * basis_o + diag(obs_V)). Really should do this as low-rank update of covariance
            # of V.

            U, piv, m = ichol_basis(basis=chol_inner,
                                    nug=obs_V,
                                    reltol=self.relative_precision)

        U = asmatrix(U)
        piv_new = piv[:m]
        self.obs_piv = piv_new
        obs_mesh_new = obs_mesh[piv_new, :]

        self.Uo = U[:m, :m]

        # chol(basis_o.T * coef_cov * basis_o + diag(obs_V)) ^ -T * basis_o.T
        self.Uo_cov = trisolve(self.Uo,
                               basis_o[:, piv[:m]].T,
                               uplo='U',
                               transa='T')

        # chol(basis_o.T * coef_cov * basis_o + diag(obs_V)).T.I * basis_o.T * coef_cov
        self.Uo_cov = self.Uo_cov * self.coef_cov

        # coef_cov = coef_cov - coef_cov * basis_o * (basis_o.T * coef_cov * basis_o + diag(obs_V)).I * basis_o.T * coef_cov
        self.coef_cov = self.coef_cov - self.Uo_cov.T * self.Uo_cov

        # coef_U = chol(coef_cov)
        U, m, piv = ichol_full(c=self.coef_cov, reltol=self.relative_precision)
        U = asmatrix(U)
        self.coef_U = U[:m, argsort(piv)]
        self.m = m

        if output_type == 'o':
            return piv_new, obs_mesh_new

        if output_type == 's':
            return U_eval, C_eval, basis_o

        raise ValueError, 'Output type not recognized.'