def random_cov(d, diff=None): """Generate random covariance matrix. Generates a random covariance matrix, or two dependent covariance matrices if the argument `diff` is given. """ S = 0.8*np.random.randn(d,d) copy_triu_to_tril(S) np.fill_diagonal(S,0) mineig = linalg.eigvalsh(S, eigvals=(0,0))[0] drand = 0.8*np.random.randn(d) if mineig < 0: S += np.diag(np.exp(drand)-mineig) else: S += np.diag(np.exp(drand)) if not diff: return S.T S2 = S * np.random.randint(2, size=(d,d))*np.exp(diff*np.random.randn(d,d)) copy_triu_to_tril(S2) np.fill_diagonal(S2,0) mineig = linalg.eigvalsh(S2, eigvals=(0,0))[0] drand += diff*np.random.randn(d) if mineig < 0: S2 += np.diag(np.exp(drand)-mineig) else: S2 += np.diag(np.exp(drand)) return S.T, S2.T
def random_cov(d, diff=None): """Generate random covariance matrix. Generates a random covariance matrix, or two dependent covariance matrices if the argument `diff` is given. """ S = 0.8 * np.random.randn(d, d) copy_triu_to_tril(S) np.fill_diagonal(S, 0) mineig = linalg.eigvalsh(S, eigvals=(0, 0))[0] drand = 0.8 * np.random.randn(d) if mineig < 0: S += np.diag(np.exp(drand) - mineig) else: S += np.diag(np.exp(drand)) if not diff: return S.T S2 = S * np.random.randint(2, size=(d, d)) * np.exp( diff * np.random.randn(d, d)) copy_triu_to_tril(S2) np.fill_diagonal(S2, 0) mineig = linalg.eigvalsh(S2, eigvals=(0, 0))[0] drand += diff * np.random.randn(d) if mineig < 0: S2 += np.diag(np.exp(drand) - mineig) else: S2 += np.diag(np.exp(drand)) return S.T, S2.T
def invert_normal_params(A, b=None, out_A=None, out_b=None, cho_form=False): """Invert moment parameters into natural parameters or vice versa. Switch between moment parameters (S,m) and natural parameters (Q,r) of a multivariate normal distribution. Providing (S,m) yields (Q,r) and vice versa. Parameters ---------- A : ndarray A symmetric positive-definite matrix to be inverted. Either the covariance matrix S or the precision matrix Q. b : {None, ndarray}, optional The mean vector m, the natural parameter vector r, or None (default) if `out_b` is not requested. out_A, out_b : {None, ndarray, 'in-place'}, optional Spesifies where the output is calculate into; None (default) indicates that a new array is created, providing a string 'in-place' overwrites the corresponding input array. cho_form : bool If True, `A` is assumed to be the upper Cholesky of the real S or Q. Returns ------- out_A, out_b : ndarray The corresponding output arrays (`out_A` in F-order). If `b` was not provided, `out_b` is None. Raises ------ LinAlgError If the provided array A is not positive definite. """ # Process parameters if not isinstance(out_A, np.ndarray) and out_A == 'in-place': out_A = A elif out_A is None: out_A = A.copy(order='F') else: np.copyto(out_A, A) if not out_A.flags['FARRAY']: # Convert from C-order to F-order by transposing (note symmetric) out_A = out_A.T if not out_A.flags['FARRAY'] and out_A.shape[0] > 1: raise ValueError('Provided array A is inappropriate') if not b is None: if not isinstance(out_b, np.ndarray) and out_b == 'in-place': out_b = b elif out_b is None: out_b = b.copy() else: np.copyto(out_b, b) else: out_b = None # Invert if not cho_form: cho = linalg.cho_factor(out_A, overwrite_a=True) else: # Already in upper Cholesky form cho = (out_A, False) if not out_b is None: linalg.cho_solve(cho, out_b, overwrite_b=True) _, info = dpotri_routine(out_A, overwrite_c=True) if info: # This should never occour if cho_factor was succesful ... I think raise linalg.LinAlgError( "dpotri LAPACK routine failed with error code {}".format(info)) # Copy the upper triangular into the bottom copy_triu_to_tril(out_A) return out_A, out_b
def invert_normal_params(A, b=None, out_A=None, out_b=None, cho_form=False): """Invert moment parameters into natural parameters or vice versa. Switch between moment parameters (S,m) and natural parameters (Q,r) of a multivariate normal distribution. Providing (S,m) yields (Q,r) and vice versa. Parameters ---------- A : ndarray A symmetric positive-definite matrix to be inverted. Either the covariance matrix S or the precision matrix Q. b : {None, ndarray}, optional The mean vector m, the natural parameter vector r, or None (default) if `out_b` is not requested. out_A, out_b : {None, ndarray, 'in_place'}, optional Spesifies where the output is calculate into; None (default) indicates that a new array is created, providing a string 'in_place' overwrites the corresponding input array. cho_form : bool If True, `A` is assumed to be the upper Cholesky of the real S or Q. Returns ------- out_A, out_b : ndarray The corresponding output arrays (`out_A` in F-order). If `b` was not provided, `out_b` is None. Raises ------ LinAlgError If the provided array A is not positive definite. """ # Process parameters if out_A == 'in_place': out_A = A elif out_A is None: out_A = A.copy(order='F') else: np.copyto(out_A, A) if not out_A.flags['FARRAY']: # Convert from C-order to F-order by transposing (note symmetric) out_A = out_A.T if not out_A.flags['FARRAY'] and out_A.shape[0] > 1: raise ValueError('Provided array A is inappropriate') if not b is None: if out_b == 'in_place': out_b = b elif out_b is None: out_b = b.copy() else: np.copyto(out_b, b) else: out_b = None # Invert if not cho_form: cho = linalg.cho_factor(out_A, overwrite_a=True) else: # Already in upper Cholesky form cho = (out_A, False) if not out_b is None: linalg.cho_solve(cho, out_b, overwrite_b=True) _, info = dpotri_routine(out_A, overwrite_c=True) if info: # This should never occour if cho_factor was succesful ... I think raise linalg.LinAlgError( "dpotri LAPACK routine failed with error code {}".format(info)) # Copy the upper triangular into the bottom copy_triu_to_tril(out_A) return out_A, out_b