-
Notifications
You must be signed in to change notification settings - Fork 0
/
inverseWishartSample.m
48 lines (37 loc) · 1.48 KB
/
inverseWishartSample.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
function [pcs_sample, stddev_sample] = inverseWishartSample(psi_pcs, psi_stddev, nu)
%INVERSEWISHARTSAMPLE Draw a single realization of an covariance matrix
%from an inverse Wishart distribution. Note that nu needs to be a natural
%number greater than p+1, where p is the number of principal components of
%psi
%
% Uses the pseudo-inverse for both inversion and "de-inversion".
%
% Input arguments:
% psi_pcs: Principal components of the scale matrix Psi
% psi_stddev: Standard deviations of the given principal components
% nu: Number of degrees of freedom. Must be greater than
% length(psi_stddev)+1
% cutoff (optional):
% Output parameters:
% pcs_sample: Principal components of the matrix realization
% stddev_sample: Standard deviation of the principal components.
psi_stddev = psi_stddev(psi_stddev > 1e-9);
p = length(psi_stddev);
if nu <= p+1
error('inverseWishartSample: Parameter nu must be greater than the number of principal components plus one');
end
psi_stddev = sqrt(nu-p-1)*psi_stddev(1:p);
invD = psi_pcs(:, 1:p)*diag(1./psi_stddev);
%Produce a Wishart-sample using the pseudo-inverse of the covariance matrix
sample = invD*randn(length(psi_stddev), nu);
%PCA
[pcs_sample, stddev_inv] = svd(sample, 0);
%Remove zeroes
stddev_inv = diag(stddev_inv);
stddev_inv = stddev_inv(1:p);
pcs_sample = pcs_sample(:, 1:p);
%de-invert
stddev_sample = 1./stddev_inv;
%Sort PCs by descending order
[stddev_sample, ind] = sort(stddev_sample, 'desc');
pcs_sample = pcs_sample(:, ind);