-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMomConeExtremeRay.m
More file actions
82 lines (65 loc) · 2.03 KB
/
MomConeExtremeRay.m
File metadata and controls
82 lines (65 loc) · 2.03 KB
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
function out = MomConeExtremeRay(M,MomCone)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Decompose a pseudomoment matrix as a convex combination of extreme rays
% M: the given pseudomoment matrix
% MomCone: sedumi format describing the pseudo-moment cone
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N = size(M,1);
weights = [];
ranks = [];
rays = {};
while true
M = (M + M')/2;
[V,Lam] = sorteig(M);
lam = diag(Lam);
r = sum(lam > 1e-6); % rank of M
lam_pd = lam(lam >= 1e-6);
range = V(:,1:r);
Lam(Lam < 1e-6) = 0;
% M = V * Lam * V'; % clean the spectrum of M
if r == 1
fprintf("terminate: a rank-one extreme ray.\n");
break
end
%% minimize a random linear function on the face
ker = V(:,r+1:end);
Face = MomCone;
for i = 1:size(ker,2)
vi = ker(:,i);
Ai = vi * vi';
Face.At = [Face.At, sparse(Ai(:))];
Face.b = [Face.b; sparse(1,1)];
end
Face.c = randn(N^2,1);
prob = convert_sedumi2mosek(Face.At,...
Face.b,...
Face.c,...
Face.K);
[~,res] = mosekopt('minimize info',prob);
[Xopt,~,~,~] = recover_mosek_sol_blk(res,Face.blk);
ray = Xopt{1};
if norm(M - ray, 'fro') < 1e-3
fprintf("terminate: cannot be further decomposed.\n")
break
end
%% subtract the ray to decrease rank
[Vr,Lamr] = sorteig(ray);
lamr = diag(Lamr);
rr = sum(lamr > 1e-3); % rank of ray
Lamr(Lamr < 1e-3) = 0;
% ray = Vr * Lamr * Vr'; % clean the spectrum of ray
ray = (ray + ray')/2;
Lamhalf = diag(lam_pd .^ (-0.5));
ray_transform = Lamhalf * (range' * ray * range) * Lamhalf;
[~,sigs] = sorteig(ray_transform);
step = 1 / sigs(1,1);
weights = [weights; step];
ranks = [ranks; rr];
rays = [rays; {ray}];
%% update M
M = M - step * ray;
end
out.weights = weights;
out.ranks = ranks;
out.rays = rays;
end