def test_get_cholesky_inv_upper(test_mat): """test get_cholesky_inv with upper triangular""" A = test_mat.A.copy() A_i = test_mat.A_i.copy() chol_test_inv = get_cholesky_inv(A,lower=False) chol_test = get_cholesky_inv(A_i,lower=False) assert check_is_cholesky(chol_test_inv,A_i,lower=False,atol_rel=atol_rel_use,rtol=rtol_use) assert check_is_cholesky(chol_test,A,lower=False,atol_rel=atol_rel_use,rtol=rtol_use)
def perturb_and_project_covar(self, perturb_v, project_v, perturb_sigma2s): r"""get the variance (v.T).C_lw.v where v=\frac{\partial\bar{\delta}}{\delta_\alpha} in the given geometry""" perturb_v = np.ascontiguousarray(perturb_v.T) denom_result = np.zeros((perturb_v.shape[1], perturb_v.shape[1]), order='F') covar_result = np.zeros((project_v.shape[1], project_v.shape[1]), order='F') itr_ll = 0 for ll in range(0, self.n_l): n_k = self.C_compact[ll].shape[0] res = cholesky_inplace(self.C_compact[ll], inplace=False, lower=True, clean=False) n_break = n_k for _m_itr in range(0, self.lm_map[ll, 2].size): rhs1 = spl.blas.dtrmm(1., res, perturb_v[itr_ll:itr_ll + n_break], trans_a=True, lower=True) rhs2 = spl.blas.dtrmm(1., res, project_v[itr_ll:itr_ll + n_break], trans_a=True, lower=True) denom_result = spl.blas.dsyrk(1., rhs1, 1., denom_result, lower=True, trans=True) covar_result = spl.blas.dsyrk(1., rhs2, 1., covar_result, lower=True, trans=True) rhs1 = None rhs2 = None itr_ll += n_k res = None mult_mat = np.asfortranarray(np.diag( 1. / perturb_sigma2s)) + denom_result denom_result = None mult_mat_chol_inv = get_cholesky_inv(mult_mat, lower=True, inplace=False, clean=True) mult_mat = None pert_in = spl.blas.dtrmm(1., mult_mat_chol_inv, perturb_v.T, side=False, lower=True, trans_a=True) mult_mat_chol_inv = None proj_out = np.zeros_like(project_v, order='F') itr_ll = 0 for ll in range(0, self.n_l): n_k = self.C_compact[ll].shape[0] res = self.C_compact[ll] n_break = n_k for _m_itr in range(0, self.lm_map[ll, 2].size): proj_out[itr_ll:itr_ll + n_break] = spl.blas.dsymm( 1., res, project_v[itr_ll:itr_ll + n_break], lower=True) itr_ll += n_k res = None rhs_req = np.asfortranarray(np.dot(pert_in, proj_out)) mit_result = spl.blas.dsyrk( -1., rhs_req, 1., covar_result, lower=True, trans=True) #covar_result-np.dot(rhs_req.T,rhs_req) return covar_result, mit_result
def get_cov_cholesky(self, inplace=False, copy_output=False, internal=False): """get lower triangular cholesky decomposition of covariance inputs: inplace: if True, will mutate _internal_mat to be the cholesky decompostion of the covariance matrix copy_output: whether to copy the output matrix, to be safe from mutating _internal_mat later internal: should be True only if being called from another FisherMatrix routine, do not need to clean upper triangle""" #if _internal_mat changes must change internal state if inplace and not internal: self.switch_rep(REP_CHOL) if self.internal_state == REP_CHOL: if not self.silent: print( "FisherMatrix ", str(id(self)) + ": cholesky stored, size: " + str(self._internal_mat.nbytes / 10**6) + " megabytes") result = self._internal_mat else: if self.internal_state == REP_CHOL_INV: if not self.silent: print( "FisherMatrix " + str(id(self)), ": getting cholesky of covariance from its inverse, size: " + str(self._internal_mat.nbytes / 10**6) + " mb") result = invert_triangular(self._internal_mat, lower=True, inplace=inplace, clean=False) elif self.internal_state == REP_COVAR: if not self.silent: print( "FisherMatrix " + str(id(self)), ": getting cholesky from covariance directly: " + str(self._internal_mat.nbytes / 10**6) + " mb") result = cholesky_inplace(self._internal_mat, inplace=inplace, lower=True, clean=False) elif self.internal_state == REP_FISHER: if not self.silent: print( "FisherMatrix " + str(id(self)), ": getting cholesky of covariance from fisher, size: " + str(self._internal_mat.nbytes / 10**6) + " mb") result = get_cholesky_inv(self._internal_mat, lower=True, inplace=inplace, clean=False) else: raise ValueError("FisherMatrix " + str(id(self)) + ": unrecognized internal state " + str(self.internal_state)) if not self.silent: print( "FisherMatrix " + str(id(self)), ": found cholesky decomposition of covariance matrix, size: " + str(result.nbytes / 10**6) + " megabytes") if inplace: self._internal_mat = result self.internal_state = REP_CHOL #if not being requested internally to FisherMatrix, make sure the upper triangle is all zeros if not internal: result = clean_triangle(result, lower=True, inplace=True) if copy_output: return result.copy() else: return result
def perturb_fisher(self, vs, sigma2s, force_sherman=False): """add perturbation the fisher matrix in the form sigma2*v^Tv, use Sherman-Morrison formula/Woodbury Matrix identity to avoid inverting/for numerical stability""" if not self.silent: print("FisherMatrix ", id(self), " perturbing fisher matrix") #internal state must be fisher to add right now: could possibly be changed back if np.any(sigma2s < 0.): raise ValueError('perturbation must be positive semidefinite ' + str(sigma2s)) if self.internal_state == REP_FISHER or self.internal_state == REP_CHOL_INV: self.switch_rep(REP_FISHER) self._internal_mat = np.asfortranarray(self._internal_mat) self._internal_mat = spl.blas.dsyrk(1., (vs.T * np.sqrt(sigma2s)).T, 1., c=self._internal_mat, overwrite_c=True, trans=True, lower=True) else: self.switch_rep(REP_COVAR) self._internal_mat = np.asfortranarray(self._internal_mat) if force_sherman: for itr in range(0, sigma2s.size): v = vs[itr:itr + 1] lhs = spl.blas.dsymm(1., self._internal_mat, v.T, lower=True, overwrite_c=False, side=False) #use more numerically stable form for large sigma2s, although mathematically equivalent if sigma2s[itr] > 1.: mult = -1. / (1. / sigma2s[itr] + np.dot(v, lhs)[0, 0]) elif sigma2s[itr] > 0.: mult = -sigma2s[itr] / ( 1. + sigma2s[itr] * np.dot(v, lhs)[0, 0]) else: #don't bother perturbing the matrix if nothing to add continue self._internal_mat = spl.blas.dsyrk(mult, lhs, 1., c=self._internal_mat, lower=True, trans=False, overwrite_c=True) else: lhs1 = np.asfortranarray( spl.blas.dsymm(1., self._internal_mat, vs, lower=True, overwrite_c=False, side=True)) mult_mat = np.asfortranarray(np.diag( 1. / sigma2s)) + spl.blas.dgemm(1., vs, lhs1, trans_b=True) mult_mat_chol_inv = get_cholesky_inv(mult_mat, lower=True, inplace=False, clean=False) mult_mat = None lhs2 = spl.blas.dtrmm(1., mult_mat_chol_inv, lhs1, side=False, lower=True, trans_a=True) mult_mat_chol_inv = None lhs1 = None self._internal_mat = spl.blas.dsyrk(-1., lhs2, 1., self._internal_mat, trans=True, lower=True, overwrite_c=True) if not self.silent: print("FisherMatrix ", id(self), " finished perturbing fisher matrix")