Mercurial > hg > pycsalgos
comparison matlab/NESTA/fastProjection.m @ 46:88f0ebe1667a
Finished NESTA implementation. Not tested yet
author | nikcleju |
---|---|
date | Tue, 29 Nov 2011 22:06:20 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
45:7524d7749456 | 46:88f0ebe1667a |
---|---|
1 function [x,k,l] = fastProjection( U, S, V, y, b, epsilon, lambda0, DISP ) | |
2 % [x,niter,lambda] = fastProjection(U, S, V, y, b, epsilon, [lambda0], [DISP] ) | |
3 % | |
4 % minimizes || x - y || | |
5 % such that || Ax - b || <= epsilon | |
6 % | |
7 % where USV' = A (i.e the SVD of A) | |
8 % | |
9 % The optional input "lambda0" is a guess for the Lagrange parameter | |
10 % | |
11 % Warning: for speed, does not calculate A(y) to see if x = y is feasible | |
12 % | |
13 % NESTA Version 1.1 | |
14 % See also Core_Nesterov | |
15 | |
16 % Written by Stephen Becker, September 2009, srbecker@caltech.edu | |
17 | |
18 DEBUG = true; | |
19 if nargin < 8 | |
20 DISP = false; | |
21 end | |
22 % -- Parameters for Newton's method -- | |
23 MAXIT = 70; | |
24 TOL = 1e-8 * epsilon; | |
25 % TOL = max( TOL, 10*eps ); % we can't do better than machine precision | |
26 | |
27 m = size(U,1); | |
28 n = size(V,1); | |
29 mn = min([m,n]); | |
30 if numel(S) > mn^2, S = diag(diag(S)); end % S should be a small square matrix | |
31 r = size(S); | |
32 if size(U,2) > r, U = U(:,1:r); end | |
33 if size(V,2) > r, V = V(:,1:r); end | |
34 | |
35 s = diag(S); | |
36 s2 = s.^2; | |
37 | |
38 % What we want to do: | |
39 % b = b - A*y; | |
40 % bb = U'*b; | |
41 | |
42 % if A doesn't have full row rank, then b may not be in the range | |
43 if size(U,1) > size(U,2) | |
44 bRange = U*(U'*b); | |
45 bNull = b - bRange; | |
46 epsilon = sqrt( epsilon^2 - norm(bNull)^2 ); | |
47 end | |
48 b = U'*b - S*(V'*y); % parenthesis is very important! This is expensive. | |
49 | |
50 % b2 = b.^2; | |
51 b2 = abs(b).^2; % for complex data | |
52 bs2 = b2.*s2; | |
53 epsilon2 = epsilon^2; | |
54 | |
55 % The following routine need to be fast | |
56 % For efficiency (at cost of transparency), we are writing the calculations | |
57 % in a way that minimize number of operations. The functions "f" | |
58 % and "fp" represent f and its derivative. | |
59 | |
60 % f = @(lambda) sum( b2 .*(1-lambda*s2).^(-2) ) - epsilon^2; | |
61 % fp = @(lambda) 2*sum( bs2 .*(1-lambda*s2).^(-3) ); | |
62 if nargin < 7, lambda0 = 0; end | |
63 l = lambda0; oldff = 0; | |
64 one = ones(m,1); | |
65 alpha = 1; % take full Newton steps | |
66 for k = 1:MAXIT | |
67 % make f(l) and fp(l) as efficient as possible: | |
68 ls = one./(one-l*s2); | |
69 ls2 = ls.^2; | |
70 ls3 = ls2.*ls; | |
71 ff = b2.'*ls2; % should be .', not ', even for complex data | |
72 ff = ff - epsilon2; | |
73 fpl = 2*( bs2.'*ls3 ); % should be .', not ', even for complex data | |
74 % ff = f(l); % this is a little slower | |
75 % fpl = fp(l); % this is a little slower | |
76 d = -ff/fpl; | |
77 if DISP, fprintf('%2d, lambda is %5.2f, f(lambda) is %.2e, f''(lambda) is %.2e\n',... | |
78 k,l,ff,fpl ); end | |
79 if abs(ff) < TOL, break; end % stopping criteria | |
80 l_old = l; | |
81 if k>2 && ( abs(ff) > 10*abs(oldff+100) ) %|| abs(d) > 1e13 ) | |
82 l = 0; alpha = 1/2; | |
83 % oldff = f(0); | |
84 oldff = sum(b2); oldff = oldff - epsilon2; | |
85 if DISP, disp('restarting'); end | |
86 else | |
87 if alpha < 1, alpha = (alpha+1)/2; end | |
88 l = l + alpha*d; | |
89 oldff = ff; | |
90 if l > 0 | |
91 l = 0; % shouldn't be positive | |
92 oldff = sum(b2); oldff = oldff - epsilon2; | |
93 end | |
94 end | |
95 if l_old == l && l == 0 | |
96 if DISP, disp('Making no progress; x = y is probably feasible'); end | |
97 break; | |
98 end | |
99 end | |
100 % if k == MAXIT && DEBUG, disp('maxed out iterations'); end | |
101 if l < 0 | |
102 xhat = -l*s.*b./( 1 - l*s2 ); | |
103 x = V*xhat + y; | |
104 else | |
105 % y is already feasible, so no need to project | |
106 l = 0; | |
107 x = y; | |
108 end |