nikcleju@45
|
1 function [xk,niter,residuals,outputData,opts] = Core_Nesterov(...
|
nikcleju@45
|
2 A,At,b,mu,delta,opts)
|
nikcleju@45
|
3 % [xk,niter,residuals,outputData,opts] =Core_Nesterov(A,At,b,mu,delta,opts)
|
nikcleju@45
|
4 %
|
nikcleju@45
|
5 % Solves a L1 minimization problem under a quadratic constraint using the
|
nikcleju@45
|
6 % Nesterov algorithm, without continuation:
|
nikcleju@45
|
7 %
|
nikcleju@45
|
8 % min_x || U x ||_1 s.t. ||y - Ax||_2 <= delta
|
nikcleju@45
|
9 %
|
nikcleju@45
|
10 % If continuation is desired, see the function NESTA.m
|
nikcleju@45
|
11 %
|
nikcleju@45
|
12 % The primal prox-function is also adapted by accounting for a first guess
|
nikcleju@45
|
13 % xplug that also tends towards x_muf
|
nikcleju@45
|
14 %
|
nikcleju@45
|
15 % The observation matrix A is a projector
|
nikcleju@45
|
16 %
|
nikcleju@45
|
17 % Inputs: A and At - measurement matrix and adjoint (either a matrix, in which
|
nikcleju@45
|
18 % case At is unused, or function handles). m x n dimensions.
|
nikcleju@45
|
19 % b - Observed data, a m x 1 array
|
nikcleju@45
|
20 % muf - The desired value of mu at the last continuation step.
|
nikcleju@45
|
21 % A smaller mu leads to higher accuracy.
|
nikcleju@45
|
22 % delta - l2 error bound. This enforces how close the variable
|
nikcleju@45
|
23 % must fit the observations b, i.e. || y - Ax ||_2 <= delta
|
nikcleju@45
|
24 % If delta = 0, enforces y = Ax
|
nikcleju@45
|
25 % Common heuristic: delta = sqrt(m + 2*sqrt(2*m))*sigma;
|
nikcleju@45
|
26 % where sigma=std(noise).
|
nikcleju@45
|
27 % opts -
|
nikcleju@45
|
28 % This is a structure that contains additional options,
|
nikcleju@45
|
29 % some of which are optional.
|
nikcleju@45
|
30 % The fieldnames are case insensitive. Below
|
nikcleju@45
|
31 % are the possible fieldnames:
|
nikcleju@45
|
32 %
|
nikcleju@45
|
33 % opts.xplug - the first guess for the primal prox-function, and
|
nikcleju@45
|
34 % also the initial point for xk. By default, xplug = At(b)
|
nikcleju@45
|
35 % opts.U and opts.Ut - Analysis/Synthesis operators
|
nikcleju@45
|
36 % (either matrices of function handles).
|
nikcleju@45
|
37 % opts.normU - if opts.U is provided, this should be norm(U)
|
nikcleju@45
|
38 % opts.maxiter - max number of iterations in an inner loop.
|
nikcleju@45
|
39 % default is 10,000
|
nikcleju@45
|
40 % opts.TolVar - tolerance for the stopping criteria
|
nikcleju@45
|
41 % opts.stopTest - which stopping criteria to apply
|
nikcleju@45
|
42 % opts.stopTest == 1 : stop when the relative
|
nikcleju@45
|
43 % change in the objective function is less than
|
nikcleju@45
|
44 % TolVar
|
nikcleju@45
|
45 % opts.stopTest == 2 : stop with the l_infinity norm
|
nikcleju@45
|
46 % of difference in the xk variable is less
|
nikcleju@45
|
47 % than TolVar
|
nikcleju@45
|
48 % opts.TypeMin - if this is 'L1' (default), then
|
nikcleju@45
|
49 % minimizes a smoothed version of the l_1 norm.
|
nikcleju@45
|
50 % If this is 'tv', then minimizes a smoothed
|
nikcleju@45
|
51 % version of the total-variation norm.
|
nikcleju@45
|
52 % The string is case insensitive.
|
nikcleju@45
|
53 % opts.Verbose - if this is 0 or false, then very
|
nikcleju@45
|
54 % little output is displayed. If this is 1 or true,
|
nikcleju@45
|
55 % then output every iteration is displayed.
|
nikcleju@45
|
56 % If this is a number p greater than 1, then
|
nikcleju@45
|
57 % output is displayed every pth iteration.
|
nikcleju@45
|
58 % opts.fid - if this is 1 (default), the display is
|
nikcleju@45
|
59 % the usual Matlab screen. If this is the file-id
|
nikcleju@45
|
60 % of a file opened with fopen, then the display
|
nikcleju@45
|
61 % will be redirected to this file.
|
nikcleju@45
|
62 % opts.errFcn - if this is a function handle,
|
nikcleju@45
|
63 % then the program will evaluate opts.errFcn(xk)
|
nikcleju@45
|
64 % at every iteration and display the result.
|
nikcleju@45
|
65 % ex. opts.errFcn = @(x) norm( x - x_true )
|
nikcleju@45
|
66 % opts.outFcn - if this is a function handle,
|
nikcleju@45
|
67 % then then program will evaluate opts.outFcn(xk)
|
nikcleju@45
|
68 % at every iteration and save the results in outputData.
|
nikcleju@45
|
69 % If the result is a vector (as opposed to a scalar),
|
nikcleju@45
|
70 % it should be a row vector and not a column vector.
|
nikcleju@45
|
71 % ex. opts.outFcn = @(x) [norm( x - xtrue, 'inf' ),...
|
nikcleju@45
|
72 % norm( x - xtrue) / norm(xtrue)]
|
nikcleju@45
|
73 % opts.AAtinv - this is an experimental new option. AAtinv
|
nikcleju@45
|
74 % is the inverse of AA^*. This allows the use of a
|
nikcleju@45
|
75 % matrix A which is not a projection, but only
|
nikcleju@45
|
76 % for the noiseless (i.e. delta = 0) case.
|
nikcleju@45
|
77 % If the SVD of A is U*S*V', then AAtinv = U*(S^{-2})*U'.
|
nikcleju@45
|
78 % opts.USV - another experimental option. This supercedes
|
nikcleju@45
|
79 % the AAtinv option, so it is recommended that you
|
nikcleju@45
|
80 % do not define AAtinv. This allows the use of a matrix
|
nikcleju@45
|
81 % A which is not a projection, and works for the
|
nikcleju@45
|
82 % noisy ( i.e. delta > 0 ) case.
|
nikcleju@45
|
83 % opts.USV should contain three fields:
|
nikcleju@45
|
84 % opts.USV.U is the U from [U,S,V] = svd(A)
|
nikcleju@45
|
85 % likewise, opts.USV.S and opts.USV.V are S and V
|
nikcleju@45
|
86 % from svd(A). S may be a matrix or a vector.
|
nikcleju@45
|
87 % Outputs:
|
nikcleju@45
|
88 % xk - estimate of the solution x
|
nikcleju@45
|
89 % niter - number of iterations
|
nikcleju@45
|
90 % residuals - first column is the residual at every step,
|
nikcleju@45
|
91 % second column is the value of f_mu at every step
|
nikcleju@45
|
92 % outputData - a matrix, where each row r is the output
|
nikcleju@45
|
93 % from opts.outFcn, if supplied.
|
nikcleju@45
|
94 % opts - the structure containing the options that were used
|
nikcleju@45
|
95 %
|
nikcleju@45
|
96 % Written by: Jerome Bobin, Caltech
|
nikcleju@45
|
97 % Email: bobin@acm.caltech.edu
|
nikcleju@45
|
98 % Created: February 2009
|
nikcleju@45
|
99 % Modified: May 2009, Jerome Bobin and Stephen Becker, Caltech
|
nikcleju@45
|
100 % Modified: Nov 2009, Stephen Becker
|
nikcleju@45
|
101 %
|
nikcleju@45
|
102 % NESTA Version 1.1
|
nikcleju@45
|
103 % See also NESTA
|
nikcleju@45
|
104
|
nikcleju@45
|
105 %---- Set defaults
|
nikcleju@45
|
106 % opts = [];
|
nikcleju@45
|
107 fid = setOpts('fid',1);
|
nikcleju@45
|
108 function printf(varargin), fprintf(fid,varargin{:}); end
|
nikcleju@45
|
109 maxiter = setOpts('maxiter',10000,0);
|
nikcleju@45
|
110 TolVar = setOpts('TolVar',1e-5);
|
nikcleju@45
|
111 TypeMin = setOpts('TypeMin','L1');
|
nikcleju@45
|
112 Verbose = setOpts('Verbose',true);
|
nikcleju@45
|
113 errFcn = setOpts('errFcn',[]);
|
nikcleju@45
|
114 outFcn = setOpts('outFcn',[]);
|
nikcleju@45
|
115 stopTest = setOpts('stopTest',1,1,2);
|
nikcleju@45
|
116 U = setOpts('U', @(x) x );
|
nikcleju@45
|
117 if ~isa(U,'function_handle')
|
nikcleju@45
|
118 Ut = setOpts('Ut',[]);
|
nikcleju@45
|
119 else
|
nikcleju@45
|
120 Ut = setOpts('Ut', @(x) x );
|
nikcleju@45
|
121 end
|
nikcleju@45
|
122 xplug = setOpts('xplug',[]);
|
nikcleju@45
|
123 normU = setOpts('normU',1);
|
nikcleju@45
|
124
|
nikcleju@45
|
125 if delta < 0, error('delta must be greater or equal to zero'); end
|
nikcleju@45
|
126
|
nikcleju@45
|
127 if isa(A,'function_handle')
|
nikcleju@45
|
128 Atfun = At;
|
nikcleju@45
|
129 Afun = A;
|
nikcleju@45
|
130 else
|
nikcleju@45
|
131 Atfun = @(x) A'*x;
|
nikcleju@45
|
132 Afun = @(x) A*x;
|
nikcleju@45
|
133 end
|
nikcleju@45
|
134 Atb = Atfun(b);
|
nikcleju@45
|
135
|
nikcleju@45
|
136 AAtinv = setOpts('AAtinv',[]);
|
nikcleju@45
|
137 USV = setOpts('USV',[]);
|
nikcleju@45
|
138 if ~isempty(USV)
|
nikcleju@45
|
139 if isstruct(USV)
|
nikcleju@45
|
140 Q = USV.U; % we can't use "U" as the variable name
|
nikcleju@45
|
141 % since "U" already refers to the analysis operator
|
nikcleju@45
|
142 S = USV.S;
|
nikcleju@45
|
143 if isvector(S), s = S; S = diag(s);
|
nikcleju@45
|
144 else s = diag(S); end
|
nikcleju@45
|
145 V = USV.V;
|
nikcleju@45
|
146 else
|
nikcleju@45
|
147 error('opts.USV must be a structure');
|
nikcleju@45
|
148 end
|
nikcleju@45
|
149 if isempty(AAtinv)
|
nikcleju@45
|
150 AAtinv = Q*diag( s.^(-2) )*Q';
|
nikcleju@45
|
151 end
|
nikcleju@45
|
152 end
|
nikcleju@45
|
153 % --- for A not a projection (experimental)
|
nikcleju@45
|
154 if ~isempty(AAtinv)
|
nikcleju@45
|
155 if isa(AAtinv,'function_handle')
|
nikcleju@45
|
156 AAtinv_fun = AAtinv;
|
nikcleju@45
|
157 else
|
nikcleju@45
|
158 AAtinv_fun = @(x) AAtinv * x;
|
nikcleju@45
|
159 end
|
nikcleju@45
|
160
|
nikcleju@45
|
161 AtAAtb = Atfun( AAtinv_fun(b) );
|
nikcleju@45
|
162
|
nikcleju@45
|
163 else
|
nikcleju@45
|
164 % We assume it's a projection
|
nikcleju@45
|
165 AtAAtb = Atb;
|
nikcleju@45
|
166 AAtinv_fun = @(x) x;
|
nikcleju@45
|
167 end
|
nikcleju@45
|
168
|
nikcleju@45
|
169 if isempty(xplug)
|
nikcleju@45
|
170 xplug = AtAAtb;
|
nikcleju@45
|
171 end
|
nikcleju@45
|
172
|
nikcleju@45
|
173 %---- Initialization
|
nikcleju@45
|
174 N = length(xplug);
|
nikcleju@45
|
175 wk = zeros(N,1);
|
nikcleju@45
|
176 xk = xplug;
|
nikcleju@45
|
177
|
nikcleju@45
|
178
|
nikcleju@45
|
179 %---- Init Variables
|
nikcleju@45
|
180 Ak= 0;
|
nikcleju@45
|
181 Lmu = normU/mu;
|
nikcleju@45
|
182 yk = xk;
|
nikcleju@45
|
183 zk = xk;
|
nikcleju@45
|
184 fmean = realmin/10;
|
nikcleju@45
|
185 OK = 0;
|
nikcleju@45
|
186 n = floor(sqrt(N));
|
nikcleju@45
|
187
|
nikcleju@45
|
188 %---- Computing Atb
|
nikcleju@45
|
189 Atb = Atfun(b);
|
nikcleju@45
|
190 Axk = Afun(xk);% only needed if you want to see the residuals
|
nikcleju@45
|
191 % Axplug = Axk;
|
nikcleju@45
|
192
|
nikcleju@45
|
193
|
nikcleju@45
|
194 %---- TV Minimization
|
nikcleju@45
|
195 if strcmpi(TypeMin,'TV')
|
nikcleju@45
|
196 Lmu = 8*Lmu;
|
nikcleju@45
|
197 Dv = spdiags([reshape([-ones(n-1,n); zeros(1,n)],N,1) ...
|
nikcleju@45
|
198 reshape([zeros(1,n); ones(n-1,n)],N,1)], [0 1], N, N);
|
nikcleju@45
|
199 Dh = spdiags([reshape([-ones(n,n-1) zeros(n,1)],N,1) ...
|
nikcleju@45
|
200 reshape([zeros(n,1) ones(n,n-1)],N,1)], [0 n], N, N);
|
nikcleju@45
|
201 D = sparse([Dh;Dv]);
|
nikcleju@45
|
202 end
|
nikcleju@45
|
203
|
nikcleju@45
|
204
|
nikcleju@45
|
205 Lmu1 = 1/Lmu;
|
nikcleju@45
|
206 % SLmu = sqrt(Lmu);
|
nikcleju@45
|
207 % SLmu1 = 1/sqrt(Lmu);
|
nikcleju@45
|
208 lambdaY = 0;
|
nikcleju@45
|
209 lambdaZ = 0;
|
nikcleju@45
|
210
|
nikcleju@45
|
211 %---- setup data storage variables
|
nikcleju@45
|
212 [DISPLAY_ERROR, RECORD_DATA] = deal(false);
|
nikcleju@45
|
213 outputData = deal([]);
|
nikcleju@45
|
214 residuals = zeros(maxiter,2);
|
nikcleju@45
|
215 if ~isempty(errFcn), DISPLAY_ERROR = true; end
|
nikcleju@45
|
216 if ~isempty(outFcn) && nargout >= 4
|
nikcleju@45
|
217 RECORD_DATA = true;
|
nikcleju@45
|
218 outputData = zeros(maxiter, size(outFcn(xplug),2) );
|
nikcleju@45
|
219 end
|
nikcleju@45
|
220
|
nikcleju@45
|
221 for k = 0:maxiter-1,
|
nikcleju@45
|
222
|
nikcleju@45
|
223 %---- Dual problem
|
nikcleju@45
|
224
|
nikcleju@45
|
225 if strcmpi(TypeMin,'L1') [df,fx,val,uk] = Perform_L1_Constraint(xk,mu,U,Ut);end
|
nikcleju@45
|
226
|
nikcleju@45
|
227 if strcmpi(TypeMin,'TV') [df,fx] = Perform_TV_Constraint(xk,mu,Dv,Dh,D,U,Ut);end
|
nikcleju@45
|
228
|
nikcleju@45
|
229 %---- Primal Problem
|
nikcleju@45
|
230
|
nikcleju@45
|
231 %---- Updating yk
|
nikcleju@45
|
232
|
nikcleju@45
|
233 %
|
nikcleju@45
|
234 % yk = Argmin_x Lmu/2 ||x - xk||_l2^2 + <df,x-xk> s.t. ||b-Ax||_l2 < delta
|
nikcleju@45
|
235 % Let xp be sqrt(Lmu) (x-xk), dfp be df/sqrt(Lmu), bp be sqrt(Lmu)(b- Axk) and deltap be sqrt(Lmu)delta
|
nikcleju@45
|
236 % yk = xk + 1/sqrt(Lmu) Argmin_xp 1/2 || xp ||_2^2 + <dfp,xp> s.t. || bp - Axp ||_2 < deltap
|
nikcleju@45
|
237 %
|
nikcleju@45
|
238
|
nikcleju@45
|
239
|
nikcleju@45
|
240 cp = xk - 1/Lmu*df; % this is "q" in eq. (3.7) in the paper
|
nikcleju@45
|
241
|
nikcleju@45
|
242 Acp = Afun( cp );
|
nikcleju@45
|
243 if ~isempty(AAtinv) && isempty(USV)
|
nikcleju@45
|
244 AtAcp = Atfun( AAtinv_fun( Acp ) );
|
nikcleju@45
|
245 else
|
nikcleju@45
|
246 AtAcp = Atfun( Acp );
|
nikcleju@45
|
247 end
|
nikcleju@45
|
248
|
nikcleju@45
|
249 residuals(k+1,1) = norm( b-Axk); % the residual
|
nikcleju@45
|
250 residuals(k+1,2) = fx; % the value of the objective
|
nikcleju@45
|
251 %--- if user has supplied a function, apply it to the iterate
|
nikcleju@45
|
252 if RECORD_DATA
|
nikcleju@45
|
253 outputData(k+1,:) = outFcn(xk);
|
nikcleju@45
|
254 end
|
nikcleju@45
|
255
|
nikcleju@45
|
256 if delta > 0
|
nikcleju@45
|
257 if ~isempty(USV)
|
nikcleju@45
|
258 % there are more efficient methods, but we're assuming
|
nikcleju@45
|
259 % that A is negligible compared to U and Ut.
|
nikcleju@45
|
260 % Here we make the change of variables x <-- x - xk
|
nikcleju@45
|
261 % and df <-- df/L
|
nikcleju@45
|
262 dfp = -Lmu1*df; Adfp = -(Axk - Acp);
|
nikcleju@45
|
263 bp = b - Axk;
|
nikcleju@45
|
264 deltap = delta;
|
nikcleju@45
|
265 % Check if we even need to project:
|
nikcleju@45
|
266 if norm( Adfp - bp ) < deltap
|
nikcleju@45
|
267 lambdaY = 0; projIter = 0;
|
nikcleju@45
|
268 % i.e. projection = dfp;
|
nikcleju@45
|
269 yk = xk + dfp;
|
nikcleju@45
|
270 Ayk = Axk + Adfp;
|
nikcleju@45
|
271 else
|
nikcleju@45
|
272 lambdaY_old = lambdaY;
|
nikcleju@45
|
273 [projection,projIter,lambdaY] = fastProjection(Q,S,V,dfp,bp,...
|
nikcleju@45
|
274 deltap, .999*lambdaY_old );
|
nikcleju@45
|
275 if lambdaY > 0, disp('lambda is positive!'); keyboard; end
|
nikcleju@45
|
276 yk = xk + projection;
|
nikcleju@45
|
277 Ayk = Afun(yk);
|
nikcleju@45
|
278 % DEBUGGING
|
nikcleju@45
|
279 % if projIter == 50
|
nikcleju@45
|
280 % fprintf('\n Maxed out iterations at y\n');
|
nikcleju@45
|
281 % keyboard
|
nikcleju@45
|
282 % end
|
nikcleju@45
|
283 end
|
nikcleju@45
|
284 else
|
nikcleju@45
|
285 lambda = max(0,Lmu*(norm(b-Acp)/delta - 1));gamma = lambda/(lambda + Lmu);
|
nikcleju@45
|
286 yk = lambda/Lmu*(1-gamma)*Atb + cp - gamma*AtAcp;
|
nikcleju@45
|
287 % for calculating the residual, we'll avoid calling A()
|
nikcleju@45
|
288 % by storing A(yk) here (using A'*A = I):
|
nikcleju@45
|
289 Ayk = lambda/Lmu*(1-gamma)*b + Acp - gamma*Acp;
|
nikcleju@45
|
290 end
|
nikcleju@45
|
291 else
|
nikcleju@45
|
292 % if delta is 0, the projection is simplified:
|
nikcleju@45
|
293 yk = AtAAtb + cp - AtAcp;
|
nikcleju@45
|
294 Ayk = b;
|
nikcleju@45
|
295 end
|
nikcleju@45
|
296
|
nikcleju@45
|
297 % DEBUGGING
|
nikcleju@45
|
298 % if norm( Ayk - b ) > (1.05)*delta
|
nikcleju@45
|
299 % fprintf('\nAyk failed projection test\n');
|
nikcleju@45
|
300 % keyboard;
|
nikcleju@45
|
301 % end
|
nikcleju@45
|
302
|
nikcleju@45
|
303 %--- Stopping criterion
|
nikcleju@45
|
304 qp = abs(fx - mean(fmean))/mean(fmean);
|
nikcleju@45
|
305
|
nikcleju@45
|
306 switch stopTest
|
nikcleju@45
|
307 case 1
|
nikcleju@45
|
308 % look at the relative change in function value
|
nikcleju@45
|
309 if qp <= TolVar && OK; break;end
|
nikcleju@45
|
310 if qp <= TolVar && ~OK; OK=1; end
|
nikcleju@45
|
311 case 2
|
nikcleju@45
|
312 % look at the l_inf change from previous iterate
|
nikcleju@45
|
313 if k >= 1 && norm( xk - xold, 'inf' ) <= TolVar
|
nikcleju@45
|
314 break
|
nikcleju@45
|
315 end
|
nikcleju@45
|
316 end
|
nikcleju@45
|
317 fmean = [fx,fmean];
|
nikcleju@45
|
318 if (length(fmean) > 10) fmean = fmean(1:10);end
|
nikcleju@45
|
319
|
nikcleju@45
|
320
|
nikcleju@45
|
321
|
nikcleju@45
|
322 %--- Updating zk
|
nikcleju@45
|
323
|
nikcleju@45
|
324 apk =0.5*(k+1);
|
nikcleju@45
|
325 Ak = Ak + apk;
|
nikcleju@45
|
326 tauk = 2/(k+3);
|
nikcleju@45
|
327
|
nikcleju@45
|
328 wk = apk*df + wk;
|
nikcleju@45
|
329
|
nikcleju@45
|
330 %
|
nikcleju@45
|
331 % zk = Argmin_x Lmu/2 ||b - Ax||_l2^2 + Lmu/2||x - xplug ||_2^2+ <wk,x-xk>
|
nikcleju@45
|
332 % s.t. ||b-Ax||_l2 < delta
|
nikcleju@45
|
333 %
|
nikcleju@45
|
334
|
nikcleju@45
|
335 cp = xplug - 1/Lmu*wk;
|
nikcleju@45
|
336
|
nikcleju@45
|
337 Acp = Afun( cp );
|
nikcleju@45
|
338 if ~isempty( AAtinv ) && isempty(USV)
|
nikcleju@45
|
339 AtAcp = Atfun( AAtinv_fun( Acp ) );
|
nikcleju@45
|
340 else
|
nikcleju@45
|
341 AtAcp = Atfun( Acp );
|
nikcleju@45
|
342 end
|
nikcleju@45
|
343
|
nikcleju@45
|
344 if delta > 0
|
nikcleju@45
|
345 if ~isempty(USV)
|
nikcleju@45
|
346 % Make the substitution wk <-- wk/K
|
nikcleju@45
|
347
|
nikcleju@45
|
348 % dfp = (xplug - Lmu1*wk); % = cp
|
nikcleju@45
|
349 % Adfp= (Axplug - Acp);
|
nikcleju@45
|
350 dfp = cp; Adfp = Acp;
|
nikcleju@45
|
351 bp = b;
|
nikcleju@45
|
352 deltap = delta;
|
nikcleju@45
|
353 % dfp = SLmu*xplug - SLmu1*wk;
|
nikcleju@45
|
354 % bp = SLmu*b;
|
nikcleju@45
|
355 % deltap = SLmu*delta;
|
nikcleju@45
|
356
|
nikcleju@45
|
357 % See if we even need to project:
|
nikcleju@45
|
358 if norm( Adfp - bp ) < deltap
|
nikcleju@45
|
359 zk = dfp;
|
nikcleju@45
|
360 Azk = Adfp;
|
nikcleju@45
|
361 else
|
nikcleju@45
|
362 [projection,projIter,lambdaZ] = fastProjection(Q,S,V,dfp,bp,...
|
nikcleju@45
|
363 deltap, .999*lambdaZ );
|
nikcleju@45
|
364 if lambdaZ > 0, disp('lambda is positive!'); keyboard; end
|
nikcleju@45
|
365 zk = projection;
|
nikcleju@45
|
366 % zk = SLmu1*projection;
|
nikcleju@45
|
367 Azk = Afun(zk);
|
nikcleju@45
|
368
|
nikcleju@45
|
369 % DEBUGGING:
|
nikcleju@45
|
370 % if projIter == 50
|
nikcleju@45
|
371 % fprintf('\n Maxed out iterations at z\n');
|
nikcleju@45
|
372 % keyboard
|
nikcleju@45
|
373 % end
|
nikcleju@45
|
374 end
|
nikcleju@45
|
375 else
|
nikcleju@45
|
376 lambda = max(0,Lmu*(norm(b-Acp)/delta - 1));gamma = lambda/(lambda + Lmu);
|
nikcleju@45
|
377 zk = lambda/Lmu*(1-gamma)*Atb + cp - gamma*AtAcp;
|
nikcleju@45
|
378 % for calculating the residual, we'll avoid calling A()
|
nikcleju@45
|
379 % by storing A(zk) here (using A'*A = I):
|
nikcleju@45
|
380 Azk = lambda/Lmu*(1-gamma)*b + Acp - gamma*Acp;
|
nikcleju@45
|
381 end
|
nikcleju@45
|
382 else
|
nikcleju@45
|
383 % if delta is 0, this is simplified:
|
nikcleju@45
|
384 zk = AtAAtb + cp - AtAcp;
|
nikcleju@45
|
385 Azk = b;
|
nikcleju@45
|
386 end
|
nikcleju@45
|
387
|
nikcleju@45
|
388 % DEBUGGING
|
nikcleju@45
|
389 % if norm( Ayk - b ) > (1.05)*delta
|
nikcleju@45
|
390 % fprintf('\nAzk failed projection test\n');
|
nikcleju@45
|
391 % keyboard;
|
nikcleju@45
|
392 % end
|
nikcleju@45
|
393
|
nikcleju@45
|
394 %--- Updating xk
|
nikcleju@45
|
395
|
nikcleju@45
|
396 xkp = tauk*zk + (1-tauk)*yk;
|
nikcleju@45
|
397 xold = xk;
|
nikcleju@45
|
398 xk=xkp;
|
nikcleju@45
|
399 Axk = tauk*Azk + (1-tauk)*Ayk;
|
nikcleju@45
|
400
|
nikcleju@45
|
401 if ~mod(k,10), Axk = Afun(xk); end % otherwise slowly lose precision
|
nikcleju@45
|
402 % DEBUG
|
nikcleju@45
|
403 % if norm(Axk - Afun(xk) ) > 1e-6, disp('error with Axk'); keyboard; end
|
nikcleju@45
|
404
|
nikcleju@45
|
405 %--- display progress if desired
|
nikcleju@45
|
406 if ~mod(k+1,Verbose )
|
nikcleju@45
|
407 printf('Iter: %3d ~ fmu: %.3e ~ Rel. Variation of fmu: %.2e ~ Residual: %.2e',...
|
nikcleju@45
|
408 k+1,fx,qp,residuals(k+1,1) );
|
nikcleju@45
|
409 %--- if user has supplied a function to calculate the error,
|
nikcleju@45
|
410 % apply it to the current iterate and dislay the output:
|
nikcleju@45
|
411 if DISPLAY_ERROR, printf(' ~ Error: %.2e',errFcn(xk)); end
|
nikcleju@45
|
412 printf('\n');
|
nikcleju@45
|
413 end
|
nikcleju@45
|
414 if abs(fx)>1e20 || abs(residuals(k+1,1)) >1e20 || isnan(fx)
|
nikcleju@45
|
415 error('Nesta: possible divergence or NaN. Bad estimate of ||A''A||?');
|
nikcleju@45
|
416 end
|
nikcleju@45
|
417
|
nikcleju@45
|
418 end
|
nikcleju@45
|
419
|
nikcleju@45
|
420 niter = k+1;
|
nikcleju@45
|
421
|
nikcleju@45
|
422 %-- truncate output vectors
|
nikcleju@45
|
423 residuals = residuals(1:niter,:);
|
nikcleju@45
|
424 if RECORD_DATA, outputData = outputData(1:niter,:); end
|
nikcleju@45
|
425
|
nikcleju@45
|
426
|
nikcleju@45
|
427
|
nikcleju@45
|
428 %---- internal routine for setting defaults
|
nikcleju@45
|
429 function [var,userSet] = setOpts(field,default,mn,mx)
|
nikcleju@45
|
430 var = default;
|
nikcleju@45
|
431 % has the option already been set?
|
nikcleju@45
|
432 if ~isfield(opts,field)
|
nikcleju@45
|
433 % see if there is a capitalization problem:
|
nikcleju@45
|
434 names = fieldnames(opts);
|
nikcleju@45
|
435 for i = 1:length(names)
|
nikcleju@45
|
436 if strcmpi(names{i},field)
|
nikcleju@45
|
437 opts.(field) = opts.(names{i});
|
nikcleju@45
|
438 opts = rmfield(opts,names{i});
|
nikcleju@45
|
439 break;
|
nikcleju@45
|
440 end
|
nikcleju@45
|
441 end
|
nikcleju@45
|
442 end
|
nikcleju@45
|
443
|
nikcleju@45
|
444 if isfield(opts,field) && ~isempty(opts.(field))
|
nikcleju@45
|
445 var = opts.(field); % override the default
|
nikcleju@45
|
446 userSet = true;
|
nikcleju@45
|
447 else
|
nikcleju@45
|
448 userSet = false;
|
nikcleju@45
|
449 end
|
nikcleju@45
|
450
|
nikcleju@45
|
451 % perform error checking, if desired
|
nikcleju@45
|
452 if nargin >= 3 && ~isempty(mn)
|
nikcleju@45
|
453 if var < mn
|
nikcleju@45
|
454 printf('Variable %s is %f, should be at least %f\n',...
|
nikcleju@45
|
455 field,var,mn); error('variable out-of-bounds');
|
nikcleju@45
|
456 end
|
nikcleju@45
|
457 end
|
nikcleju@45
|
458 if nargin >= 4 && ~isempty(mx)
|
nikcleju@45
|
459 if var > mx
|
nikcleju@45
|
460 printf('Variable %s is %f, should be at least %f\n',...
|
nikcleju@45
|
461 field,var,mn); error('variable out-of-bounds');
|
nikcleju@45
|
462 end
|
nikcleju@45
|
463 end
|
nikcleju@45
|
464 opts.(field) = var;
|
nikcleju@45
|
465 end
|
nikcleju@45
|
466
|
nikcleju@45
|
467
|
nikcleju@45
|
468 end %% end of main Core_Nesterov routine
|
nikcleju@45
|
469
|
nikcleju@45
|
470
|
nikcleju@45
|
471 %%%%%%%%%%%% PERFORM THE L1 CONSTRAINT %%%%%%%%%%%%%%%%%%
|
nikcleju@45
|
472
|
nikcleju@45
|
473 function [df,fx,val,uk] = Perform_L1_Constraint(xk,mu,U,Ut)
|
nikcleju@45
|
474
|
nikcleju@45
|
475 if isa(U,'function_handle')
|
nikcleju@45
|
476 uk = U(xk);
|
nikcleju@45
|
477 else
|
nikcleju@45
|
478 uk = U*xk;
|
nikcleju@45
|
479 end
|
nikcleju@45
|
480 fx = uk;
|
nikcleju@45
|
481
|
nikcleju@45
|
482 uk = uk./max(mu,abs(uk));
|
nikcleju@45
|
483 val = real(uk'*fx);
|
nikcleju@45
|
484 fx = real(uk'*fx - mu/2*norm(uk)^2);
|
nikcleju@45
|
485
|
nikcleju@45
|
486 if isa(Ut,'function_handle')
|
nikcleju@45
|
487 df = Ut(uk);
|
nikcleju@45
|
488 else
|
nikcleju@45
|
489 df = U'*uk;
|
nikcleju@45
|
490 end
|
nikcleju@45
|
491 end
|
nikcleju@45
|
492
|
nikcleju@45
|
493 %%%%%%%%%%%% PERFORM THE TV CONSTRAINT %%%%%%%%%%%%%%%%%%
|
nikcleju@45
|
494
|
nikcleju@45
|
495 function [df,fx] = Perform_TV_Constraint(xk,mu,Dv,Dh,D,U,Ut)
|
nikcleju@45
|
496 if isa(U,'function_handle')
|
nikcleju@45
|
497 x = U(xk);
|
nikcleju@45
|
498 else
|
nikcleju@45
|
499 x = U*xk;
|
nikcleju@45
|
500 end
|
nikcleju@45
|
501 df = zeros(size(x));
|
nikcleju@45
|
502
|
nikcleju@45
|
503 Dhx = Dh*x;
|
nikcleju@45
|
504 Dvx = Dv*x;
|
nikcleju@45
|
505
|
nikcleju@45
|
506 tvx = sum(sqrt(abs(Dhx).^2+abs(Dvx).^2));
|
nikcleju@45
|
507 w = max(mu,sqrt(abs(Dhx).^2 + abs(Dvx).^2));
|
nikcleju@45
|
508 uh = Dhx ./ w;
|
nikcleju@45
|
509 uv = Dvx ./ w;
|
nikcleju@45
|
510 u = [uh;uv];
|
nikcleju@45
|
511 fx = real(u'*D*x - mu/2 * 1/numel(u)*sum(u'*u));
|
nikcleju@45
|
512 if isa(Ut,'function_handle')
|
nikcleju@45
|
513 df = Ut(D'*u);
|
nikcleju@45
|
514 else
|
nikcleju@45
|
515 df = U'*(D'*u);
|
nikcleju@45
|
516 end
|
nikcleju@45
|
517 end
|
nikcleju@45
|
518
|