def project_covar(self, v): r"""get the variance (v.T).C_lw.v where v=\frac{\partial\bar{\delta}}{\delta_\alpha} in the given geometry""" result = np.zeros((v.shape[1], 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): rhs = spl.blas.dtrmm(1., res, v[itr_ll:itr_ll + n_break], trans_a=True, lower=True) result = spl.blas.dsyrk(1., rhs, 1., result, lower=True, trans=True) rhs = None itr_ll += n_k res = None return mirror_symmetrize(result, lower=True, inplace=True)
def get_fisher(self, copy_output=False, inplace=False, internal=False): """get fisher matrix inputs: inplace: if True, will mutate _internal_mat to be the fisher 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_FISHER) if self.internal_state == REP_FISHER: if not self.silent: print("FisherMatrix " + str(id(self)) + ": retrieved fisher matrix from cache") result = self._internal_mat elif self.internal_state == REP_COVAR or self.internal_state == REP_CHOL: chol_cov = np.asfortranarray( self.get_cov_cholesky(copy_output=False, internal=True, inplace=inplace)) result, info = spl.lapack.dpotri(chol_cov, lower=True, overwrite_c=inplace) chol_cov = None if info != 0: raise RuntimeError('dpotri failed with error code ' + str(info)) else: if not self.silent: print("FisherMatrix " + str(id(self)) + ": fisher matrix cache miss") chol_res = np.asfortranarray( self.get_cov_cholesky_inv(copy_output=False, internal=True, inplace=inplace)) result, info = spl.lapack.dlauum(chol_res, lower=True, overwrite_c=inplace) chol_res = None if info != 0: raise RuntimeError('dlauum failed with error code ' + str(info)) if inplace: self._internal_mat = result self.internal_state = REP_FISHER #make sure symmetric if not for internal use by FisherMatrix if not internal: result = mirror_symmetrize(result, lower=True, inplace=True) if copy_output: return result.copy() else: return result
def get_covar(self, inplace=False, copy_output=False, internal=False): """get covariance matrix inputs: inplace: if True, will mutate _internal_mat to be 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_COVAR) if not self.silent: print("FisherMatrix " + str(id(self)) + ": getting covariance") if self.internal_state == REP_COVAR: if not self.silent: print("FisherMatrix " + str(id(self)) + ": covar retrieved from cache") result = self._internal_mat else: if not self.silent: print("FisherMatrix " + str(id(self)) + ": covar cache miss") chol_cov = self.get_cov_cholesky(inplace=inplace, internal=True, copy_output=False) #dlauum calculates L^TL but have LL^T cholesky convention, rot90s flip to correct convention result, info = spl.lapack.dlauum(np.asfortranarray( np.rot90(chol_cov, 2)), lower=False, overwrite_c=inplace) chol_cov = None if info != 0: raise RuntimeError('dlauum failed with error code ' + str(info)) result = np.rot90(result, 2) result = np.asfortranarray(result) #make sure guaranteed to change _internal_mat if inplace was true if inplace: self._internal_mat = result self.internal_state = REP_COVAR #make sure symmetric if not for internal use by FisherMatrix if not internal: result = mirror_symmetrize(result, lower=True, inplace=True) if copy_output: return result.copy() else: return result
def test_mirror_symmetrize(test_mat): """test cleaning matrix to be triangular""" #A should already be symmetric, so test on the non symmetric triangles A = test_mat.A.copy() AHL = np.tril(A.copy()) AHU = np.triu(A.copy()) AL1 = mirror_symmetrize(A.copy(),lower=True,inplace=False) AL2 = mirror_symmetrize(A.copy(),lower=True,inplace=True) AL3 = mirror_symmetrize(AHL.copy(),lower=True,inplace=False) AL4 = mirror_symmetrize(AHL.copy(),lower=True,inplace=True) AL5 = mirror_symmetrize(AHU.copy(),lower=True,inplace=False) AL6 = mirror_symmetrize(AHU.copy(),lower=True,inplace=True) assert np.all(AL1==AL1.T) assert np.all(AL2==AL2.T) assert np.all(AL3==AL3.T) assert np.all(AL4==AL4.T) assert np.all(AL5==AL5.T) assert np.all(AL6==AL6.T) assert np.all(np.tril(AL1)==np.tril(A)) assert np.all(np.tril(AL2)==np.tril(A)) assert np.all(np.tril(AL3)==np.tril(AHL)) assert np.all(np.tril(AL4)==np.tril(AHL)) assert np.all(np.tril(AL5)==np.tril(AHU)) assert np.all(np.tril(AL6)==np.tril(AHU)) AU1 = mirror_symmetrize(A.copy(),lower=False,inplace=False) AU2 = mirror_symmetrize(A.copy(),lower=False,inplace=True) AU3 = mirror_symmetrize(AHL.copy(),lower=False,inplace=False) AU4 = mirror_symmetrize(AHL.copy(),lower=False,inplace=True) AU5 = mirror_symmetrize(AHU.copy(),lower=False,inplace=False) AU6 = mirror_symmetrize(AHU.copy(),lower=False,inplace=True) assert np.all(AU1==AU1.T) assert np.all(AU2==AU2.T) assert np.all(AU3==AU3.T) assert np.all(AU4==AU4.T) assert np.all(AU5==AU5.T) assert np.all(AU6==AU6.T) assert np.all(np.triu(AU1)==np.triu(A)) assert np.all(np.triu(AU2)==np.triu(A)) assert np.all(np.triu(AU3)==np.triu(AHL)) assert np.all(np.triu(AU4)==np.triu(AHL)) assert np.all(np.triu(AU5)==np.triu(AHU)) assert np.all(np.triu(AU6)==np.triu(AHU))
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 mirror_symmetrize(covar_result, lower=True, inplace=True), mirror_symmetrize(mit_result, lower=True, inplace=True)
def contract_fisher(self, v1, v2, identical_inputs=False, return_fisher=False, destructive=False): """calculates (v1.T).Fisher matrix.v2 for getting variance/projecting to another basis inputs: v1,v2: vectors with one dimension aligned with _internal_mat identical_inputs: if True, assume v2=v1 and ignore v2 completely return_fisher: if True, return a FisherMatrix object destructive: if True, destroy the internal representation of self for a performance gain """ if not self.silent: print("FisherMatrix " + str(id(self)) + ": contracting fisher") if return_fisher and not identical_inputs: raise ValueError( 'cannot get FisherMatrix object if inputs not identical') if self.internal_state == REP_FISHER: if identical_inputs: right_res = spl.blas.dsymm(1., self._internal_mat, v1, lower=True) else: right_res = spl.blas.dsymm(1., self._internal_mat, v2, lower=True) if destructive: self._internal_mat = None result = np.dot(v1.T, right_res) right_res = None if identical_inputs and not return_fisher: result = mirror_symmetrize(result, lower=True, inplace=True) else: if self.internal_state == REP_COVAR: chol_cov = self.get_cov_cholesky(copy_output=False, inplace=destructive, internal=True) if destructive: self._internal_mat = None res1 = spl.solve_triangular(chol_cov, v1, lower=True, check_finite=DEBUG) if not identical_inputs: res2 = spl.solve_triangular(chol_cov, v2, lower=True, check_finite=DEBUG) chol_cov = None elif self.internal_state == REP_CHOL_INV: res1 = spl.blas.dtrmm(1., self._internal_mat, v1, lower=True, trans_a=False) if not identical_inputs: res2 = spl.blas.dtrmm(1., self._internal_mat, v2, lower=True, trans_a=False) elif self.internal_state == REP_CHOL: res1 = spl.solve_triangular(self._internal_mat, v1, lower=True, check_finite=DEBUG) if not identical_inputs: res2 = spl.solve_triangular(self._internal_mat, v2, lower=True, check_finite=DEBUG) else: raise ValueError('unknown internal state ' + str(self.internal_state)) if destructive: self._internal_mat = None if identical_inputs: result = spl.blas.dsyrk(1., np.asfortranarray(res1), lower=True, trans=True, overwrite_c=True) res1 = None if not return_fisher: result = mirror_symmetrize(result, lower=True, inplace=True) else: result = np.dot(res1.T, res2) res1 = None res2 = None if destructive: self._internal_mat = None if return_fisher: return FisherMatrix(result, input_type=REP_FISHER, initial_state=REP_FISHER, fix_input=False, silent=self.silent) else: return result