Skip to content

Commit 020c438

Browse files
committed
add matlab code for volume estimation of the set of correlation matrices
1 parent b1f3744 commit 020c438

26 files changed

+1028
-5
lines changed

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Authors:
1515
------------
1616

1717
#### Install Rcpp package
18-
18+
1919
* Install package-dependencies: `Rcpp`, `RcppEigen`, `BH`.
2020

2121
1. Then use devtools package to install `volesti` Rcpp package. In folder `/root/R-prog` Run:
@@ -116,7 +116,6 @@ The function prints the volume.
116116
`
117117
./vol -file <filename> -sample
118118
`
119-
120119
- The default settings are: `100` uniformly distributed points from the uniform distribution using billiard walk with walk length `1`.
121120
- You can use the following flags: i) `-walk_length <walk_length>` to set the walk length of the random walk, ii) `-N <number_of_points>` to set the number of points to sample, iii) `-boltz` to sample from the Boltzmann distribution, iv) `-rdhr` to sample with random directions Hit and Run, `-cdhr` to sample with coordinate directions Hit and Run, `-hmc` to sample with Hamiltonian Monte Carlo with reflections, `-temperature <variance_of_boltzmann_distribution>` to set the variance of the Boltzmann distribution.
122121

@@ -130,10 +129,16 @@ The function prints the sampled points.
130129
./vol -file <filename> -sdp
131130
`
132131
- The default settings are: `20` iterations are performed, with HMC sampling with walk length equal to `1`.
132+
133133
- You can use the following flags: i) `-N <number_of_iterations>` to set the number of iterations, ii) `-walk_length <walk_length>` to set the walk length of the random walk iii) `-rdhr` to sample with random directions Hit and Run, `-hmc` to sample with Hamiltonian Monte Carlo with reflections.
134134

135135
- Example:
136-
`./generate -n 10 -m 16`
137-
`./vol -file sdp_prob_10_16.txt -sdp -N 30 -hmc -walk_length 3`
138-
The function prints the values of the objective function of each iteration.
136+
`./generate -n 10 -m 16`
137+
`./vol -file sdp_prob_10_16.txt -sdp -N 30 -hmc -walk_length 3`
138+
The function prints the values of the objective function of each iteration.
139+
140+
141+
142+
## Volume estimation of correlation matrices (matlab code)
139143

144+
In folder `matlab_code` we include the matlab code to estimate the volume of correlation matrices. To use the main function `volume` use the script `volume_example`.

matlab_code/utils/get_billiard_L.m

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
function L = get_billiard_L(m, N)
2+
3+
n = m^2 / 2 - m/2;
4+
5+
[upper, lower] = initialize_sampler(m);
6+
x = zeros(n, 1);
7+
A = eye(m);
8+
B = zeros(m);
9+
10+
bc = ones(2 * n, 1);
11+
L = 0;
12+
13+
for j = 1:N
14+
v = get_direction(n);
15+
16+
%A(lower) = x;
17+
%q = triu(A',1);
18+
%A(upper) = q(upper);
19+
20+
B(lower) = v;
21+
q = triu(B',1);
22+
B(upper) = q(upper);
23+
24+
% compute the intersection of the line x + l*v with the
25+
% boundary of the convex set that contains the PSD matrices
26+
% with ones in the diagonal
27+
eigenvalues = eig(B, -A);
28+
l_max = 1 / max(eigenvalues);
29+
l_min = 1 / min(eigenvalues);
30+
31+
% compute the intersection of the line x + l*v with the
32+
% boundary of the hypercube [-1, 1]^n
33+
lambdas = [v; -v] ./ (bc - [x; -x]);
34+
l_max_temp = 1 / max(lambdas);
35+
l_min_temp = 1 / min(lambdas);
36+
37+
% decide which boundary the line hits first
38+
if (l_max_temp < l_max)
39+
l_max = l_max_temp;
40+
end
41+
if (l_min_temp > l_min)
42+
l_min = l_min_temp;
43+
end
44+
45+
if (L < (l_max + l_min))
46+
L = l_max + l_min;
47+
end
48+
49+
% pick a uniformly distributed point from the segment
50+
%lambda = l_min + rand * (l_max - l_min);
51+
52+
% update the current point of the random walk
53+
%x = x + lambda * v;
54+
55+
end
56+
57+
L = 4 * L;
58+
59+
end

matlab_code/utils/get_direction.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
function [v] = get_direction(n)
2+
3+
v = randn(n,1);
4+
v = v / norm(v);
5+
6+
end

matlab_code/utils/get_gradient.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function [s] = get_gradient(q)
2+
3+
s = nchoosek(q, 2);
4+
s = s(:,1) .* s(:,2);
5+
s = s / norm(s);
6+
7+
end
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function [upper, lower] = initialize_sampler(m)
2+
3+
At = zeros(m, m);
4+
upper = (1:size(At,1)).' < (1:size(At,2));
5+
lower = (1:size(At,1)).' > (1:size(At,2));
6+
7+
end

matlab_code/utils/randsphere.m

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function X = randsphere(m,n,r)
2+
3+
% This function returns an m by n array, X, in which
4+
% each of the m rows has the n Cartesian coordinates
5+
% of a random point uniformly-distributed over the
6+
% interior of an n-dimensional hypersphere with
7+
% radius r and center at the origin. The function
8+
% 'randn' is initially used to generate m sets of n
9+
% random variables with independent multivariate
10+
% normal distribution, with mean 0 and variance 1.
11+
% Then the incomplete gamma function, 'gammainc',
12+
% is used to map these points radially to fit in the
13+
% hypersphere of finite radius r with a uniform % spatial distribution.
14+
% Roger Stafford - 12/23/05
15+
16+
X = randn(m,n);
17+
s2 = sum(X.^2,2);
18+
X = X.*repmat(r*(gammainc(s2/2,n/2).^(1/n))./sqrt(s2),1,n);
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
function [points] = billiard_walk_intersection(m, J, L, R, N)
2+
3+
n = sum(sum(J>0));
4+
points = zeros(n, N);
5+
6+
[upper, ~] = initialize_sampler_vol(m);
7+
%x = zeros(n, 1);
8+
A = eye(m);
9+
B = zeros(m);
10+
11+
bc = ones(2 * n, 1);
12+
pos = 1:(2*n);
13+
pos = mod(pos, n);
14+
pos(pos==0) = n;
15+
16+
for i = 1:N
17+
18+
for jj = 1:3
19+
20+
T = -log(rand) * L;
21+
v = get_direction(n);
22+
23+
rho = 0;
24+
25+
while (true)
26+
27+
%A(lower) = x;
28+
%q = triu(A',1);
29+
%A(upper) = q(upper);
30+
31+
B(J) = v;
32+
q = triu(B',1);
33+
B(upper) = q(upper);
34+
35+
% compute the intersection of the line x + l*v with the
36+
% boundary of the convex set that contains the PSD matrices
37+
% with ones in the diagonal
38+
[Q, eigenvalues] = eig(B, -A);
39+
[max_eig, pos_max_eig] = max(diag(eigenvalues));
40+
l_max = 1 / max_eig;
41+
42+
x = A(J);
43+
44+
% compute the intersection of the line x + l*v with the
45+
% boundary of the hypercube [-1, 1]^n
46+
lambdas = [v; -v] ./ (bc - [x; -x]);
47+
[l_max_temp, pos_max] = max(lambdas);
48+
l_max_temp = 1 / l_max_temp;
49+
50+
vrc = v'*x;
51+
v2 = v'*v;
52+
rc2 = x'*x;
53+
54+
disc_sqrt = sqrt(vrc^2 - v2 * (rc2 - R^2));
55+
56+
lR_max = max((-vrc + disc_sqrt)/v2, (-vrc - disc_sqrt)/v2);
57+
58+
[l_max, lmax_ind] = min([l_max l_max_temp lR_max]);
59+
60+
% decide which boundary the line hits first
61+
if (lmax_ind == 2)
62+
%l_max = l_max_temp;
63+
% pick a uniformly distributed point from the segment
64+
lambda = 0.995 * l_max;
65+
66+
% update the current point of the random walk
67+
if (T <= l_max)
68+
%x = x + T * v;
69+
A = A + T * B;
70+
break;
71+
end
72+
A = A + lambda * B;
73+
%x = x + lambda * v;
74+
75+
%reflevt the ray
76+
%v = v - (2*AA(pos_max, :)*v)*AA(pos_max, :)'
77+
p = pos(pos_max);
78+
v(p) = -v(p);
79+
elseif (lmax_ind == 1)
80+
% pick a uniformly distributed point from the segment
81+
lambda = 0.995 * l_max;
82+
if (T <= l_max)
83+
%x = x + T * v;
84+
A = A + T* B;
85+
break;
86+
end
87+
s = get_gradient(Q(:, pos_max_eig));
88+
% update the current point of the random walk
89+
%x = x + lambda * v;
90+
A = A + lambda * B;
91+
%reflect the ray
92+
v = v - (2*(v'*s))*s;
93+
else
94+
lambda = 0.995 * l_max;
95+
if (T <= l_max)
96+
%x = x + T * v;
97+
A = A + T* B;
98+
break;
99+
end
100+
A = A + lambda * B;
101+
x = x + lambda * v;
102+
103+
x = x / norm(x);
104+
v = v - (2 * (v' * x)) * x;
105+
end
106+
rho = rho + 1;
107+
T = T - lambda;
108+
end
109+
end
110+
%A(lower) = x;
111+
%q = triu(A',1);
112+
%A(upper) = q(upper);
113+
x = A(J);
114+
points(:, i) = x;
115+
116+
%is_in = false;
117+
%if (norm(x) <= R2)
118+
% is_in = true;
119+
%end
120+
121+
%conv = update_window(ratio_parameters, is_in);
122+
123+
end
124+
125+
%ratio = ratio_parameters.count_in / ratio_parameters.tot_count;
126+
127+
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
function [conv, ratio, too_few] = check_convergence_for_ball(nu, X, r0, lb, ub, lastball)
2+
3+
conv = false;
4+
too_few = false;
5+
6+
N = size(X, 2);
7+
8+
mm = N / nu;
9+
countsIn = 0;
10+
ratios = [];
11+
12+
for i=1:N
13+
14+
x = X(:,i);
15+
16+
if (norm(x) <= r0)
17+
countsIn = countsIn + 1;
18+
end
19+
20+
if (mod(i, mm) == 0)
21+
ratios = [ratios countsIn/mm];
22+
countsIn = 0;
23+
end
24+
end
25+
26+
ratio = mean(ratios);
27+
t_a = tinv(0.90, nu);
28+
rs = std(ratios);
29+
T = rs * (t_a / sqrt(nu));
30+
31+
if (ratio > lb + T)
32+
if (lastball)
33+
conv = true;
34+
return
35+
end
36+
37+
if (ratio < ub + T)
38+
conv = true;
39+
return
40+
end
41+
return
42+
end
43+
too_few = true;
44+
45+
end
46+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
function [conv, ratio, too_few] = check_convergence_in_spectra(m, J, X, nu, lb, ub)
2+
3+
too_few = false;
4+
conv = false;
5+
6+
%n = sum(sum(J>0));
7+
8+
[upper, ~] = initialize_sampler_vol(m);
9+
A = eye(m);
10+
11+
N = size(X, 2);
12+
mm = N / nu;
13+
countsIn = 0;
14+
ratios = [];
15+
16+
for i=1:N
17+
18+
A(J) = X(:,i);
19+
q = triu(A',1);
20+
A(upper) = q(upper);
21+
22+
if (min(eig(A)) > 0)
23+
countsIn = countsIn + 1;
24+
end
25+
26+
if (mod(i, mm) == 0)
27+
ratios = [ratios countsIn/mm];
28+
countsIn = 0;
29+
if (length(ratios) > 1)
30+
31+
ratio = mean(ratios);
32+
t_a = tinv(0.995, nu);
33+
rs = std(ratios);
34+
T = rs * (t_a / sqrt(length(ratios)));
35+
36+
37+
%[h, ~] = ttest(ratios, lb, 'Alpha', 0.005, 'Tail', 'right');
38+
if (ratio + T < lb)
39+
too_few = true;
40+
conv = false;
41+
return
42+
end
43+
44+
%[h, ~] = ttest(ratios, ub, 'Alpha', 0.005, 'Tail', 'left');
45+
if (ratio - T > ub)
46+
conv = false;
47+
return
48+
end
49+
end
50+
end
51+
end
52+
53+
ratio = mean(ratios);
54+
t_a = tinv(0.95,nu);
55+
rs = std(ratios);
56+
T = rs * (t_a / sqrt(nu));
57+
58+
if (ratio > lb + T)
59+
if (ratio < ub - T)
60+
conv = true;
61+
return
62+
end
63+
conv = false;
64+
return
65+
end
66+
too_few = true;
67+
conv = false;
68+
69+
end
70+

0 commit comments

Comments
 (0)