annotate matlab/NESTA/Core_Nesterov.m @ 56:de6299dcb49e

Changed directory structure - part 5
author nikcleju
date Wed, 14 Dec 2011 14:51:35 +0000
parents 7524d7749456
children
rev   line source
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