-
Notifications
You must be signed in to change notification settings - Fork 11
/
forbes_hankel.m
80 lines (65 loc) · 1.71 KB
/
forbes_hankel.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
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
78
79
80
% FORBES_HANKEL
%
% FORBES_HANKEL(U, bx, r, mu, opt) solves
%
% minimize (1/2)||x-b||^2 + mu*sum(svd(H(x)U)
%
% or equivalently
%
% minimize (1/2)||x-b||^2 + mu*sum(svd(z))
% subject to H(x)U - z = 0
%
% Here, H(x) is a block Hankel matrix formed
% from x, and b and U come from measurements:
%
% U is a matrix such that U'U=I
% x is p by N+1 matrix
% U is N-r+1 by n matrix
% H(x) is p(r+1) by N-r+1 Hankel matrix
%
function out = forbes_hankel(U, b, r, mu, tol, freq, opt, out1)
p = size(b,1);
N = size(b,2)-1;
m = (r+1)*p;
n = size(U,2);
f = quadLoss(1, b);
g = nuclearNorm(m, n, mu);
A = opHankel(N, r, p, U);
if nargin < 8 || isempty(out1)
y0 = zeros(m,n);
else
y0 = out1.y;
end
opt.Lf = min(r+1,N-r+1); % squared norm of A
opt.term = @(prob, it, gam, cache_0, cache_x, ops) terminate_hankel(it, freq, cache_x, b, mu, tol);
out = forbes(f, g, y0, [], {A, -1, zeros(m, n)}, opt);
G = -A*out.x1;
nmEY = norm(out.x1-b,'fro')^2/2;
out.pobj = nmEY + mu*sum(svd(G));
end
function flag = terminate_hankel(it, freq, cache, b, mu, tol)
persistent pobj_best dobj_best;
if it == 1
pobj_best = +inf;
dobj_best = -inf;
end
flag = false;
if it <= 1 || mod(it, freq) ~= 0
return;
end
x = cache.gradf1res1x;
G = cache.gradf1x;
nmEY = norm(x-b,'fro')^2/2;
pobj = nmEY + mu*sum(svd(G));
if pobj < pobj_best
pobj_best = pobj;
end
dobj = -cache.FBE;
if dobj > dobj_best
dobj_best = dobj;
end
gap_rel = abs(pobj_best-dobj_best)/max(abs(dobj_best),1);
if gap_rel < tol
flag = true;
end
end