comparison pyCSalgos/NESTA/NESTA.py @ 45:7524d7749456

Began implementing NESTA, not finished
author nikcleju
date Tue, 29 Nov 2011 18:13:17 +0000
parents
children 88f0ebe1667a
comparison
equal deleted inserted replaced
44:0b469b7ea552 45:7524d7749456
1 # -*- coding: utf-8 -*-
2 """
3 Created on Tue Nov 29 16:55:20 2011
4
5 @author: ncleju
6 """
7
8 import numpy
9 import math
10
11 #function [xk,niter,residuals,outputData,opts] =NESTA(A,At,b,muf,delta,opts)
12 def NESTA(A,At,b,muf,delta,opts=None):
13 # [xk,niter,residuals,outputData] =NESTA(A,At,b,muf,delta,opts)
14 #
15 # Solves a L1 minimization problem under a quadratic constraint using the
16 # Nesterov algorithm, with continuation:
17 #
18 # min_x || U x ||_1 s.t. ||y - Ax||_2 <= delta
19 #
20 # Continuation is performed by sequentially applying Nesterov's algorithm
21 # with a decreasing sequence of values of mu0 >= mu >= muf
22 #
23 # The primal prox-function is also adapted by accounting for a first guess
24 # xplug that also tends towards x_muf
25 #
26 # The observation matrix A is a projector
27 #
28 # Inputs: A and At - measurement matrix and adjoint (either a matrix, in which
29 # case At is unused, or function handles). m x n dimensions.
30 # b - Observed data, a m x 1 array
31 # muf - The desired value of mu at the last continuation step.
32 # A smaller mu leads to higher accuracy.
33 # delta - l2 error bound. This enforces how close the variable
34 # must fit the observations b, i.e. || y - Ax ||_2 <= delta
35 # If delta = 0, enforces y = Ax
36 # Common heuristic: delta = sqrt(m + 2*sqrt(2*m))*sigma;
37 # where sigma=std(noise).
38 # opts -
39 # This is a structure that contains additional options,
40 # some of which are optional.
41 # The fieldnames are case insensitive. Below
42 # are the possible fieldnames:
43 #
44 # opts.xplug - the first guess for the primal prox-function, and
45 # also the initial point for xk. By default, xplug = At(b)
46 # opts.U and opts.Ut - Analysis/Synthesis operators
47 # (either matrices of function handles).
48 # opts.normU - if opts.U is provided, this should be norm(U)
49 # otherwise it will have to be calculated (potentially
50 # expensive)
51 # opts.MaxIntIter - number of continuation steps.
52 # default is 5
53 # opts.maxiter - max number of iterations in an inner loop.
54 # default is 10,000
55 # opts.TolVar - tolerance for the stopping criteria
56 # opts.stopTest - which stopping criteria to apply
57 # opts.stopTest == 1 : stop when the relative
58 # change in the objective function is less than
59 # TolVar
60 # opts.stopTest == 2 : stop with the l_infinity norm
61 # of difference in the xk variable is less
62 # than TolVar
63 # opts.TypeMin - if this is 'L1' (default), then
64 # minimizes a smoothed version of the l_1 norm.
65 # If this is 'tv', then minimizes a smoothed
66 # version of the total-variation norm.
67 # The string is case insensitive.
68 # opts.Verbose - if this is 0 or false, then very
69 # little output is displayed. If this is 1 or true,
70 # then output every iteration is displayed.
71 # If this is a number p greater than 1, then
72 # output is displayed every pth iteration.
73 # opts.fid - if this is 1 (default), the display is
74 # the usual Matlab screen. If this is the file-id
75 # of a file opened with fopen, then the display
76 # will be redirected to this file.
77 # opts.errFcn - if this is a function handle,
78 # then the program will evaluate opts.errFcn(xk)
79 # at every iteration and display the result.
80 # ex. opts.errFcn = @(x) norm( x - x_true )
81 # opts.outFcn - if this is a function handle,
82 # then then program will evaluate opts.outFcn(xk)
83 # at every iteration and save the results in outputData.
84 # If the result is a vector (as opposed to a scalar),
85 # it should be a row vector and not a column vector.
86 # ex. opts.outFcn = @(x) [norm( x - xtrue, 'inf' ),...
87 # norm( x - xtrue) / norm(xtrue)]
88 # opts.AAtinv - this is an experimental new option. AAtinv
89 # is the inverse of AA^*. This allows the use of a
90 # matrix A which is not a projection, but only
91 # for the noiseless (i.e. delta = 0) case.
92 # opts.USV - another experimental option. This supercedes
93 # the AAtinv option, so it is recommended that you
94 # do not define AAtinv. This allows the use of a matrix
95 # A which is not a projection, and works for the
96 # noisy ( i.e. delta > 0 ) case.
97 # opts.USV should contain three fields:
98 # opts.USV.U is the U from [U,S,V] = svd(A)
99 # likewise, opts.USV.S and opts.USV.V are S and V
100 # from svd(A). S may be a matrix or a vector.
101 #
102 # Outputs:
103 # xk - estimate of the solution x
104 # niter - number of iterations
105 # residuals - first column is the residual at every step,
106 # second column is the value of f_mu at every step
107 # outputData - a matrix, where each row r is the output
108 # from opts.outFcn, if supplied.
109 # opts - the structure containing the options that were used
110 #
111 # Written by: Jerome Bobin, Caltech
112 # Email: bobin@acm.caltech.edu
113 # Created: February 2009
114 # Modified (version 1.0): May 2009, Jerome Bobin and Stephen Becker, Caltech
115 # Modified (version 1.1): Nov 2009, Stephen Becker, Caltech
116 #
117 # NESTA Version 1.1
118 # See also Core_Nesterov
119
120 #---------------------
121 # Original Matab code:
122 #
123 #if nargin < 6, opts = []; end
124 #if isempty(opts) && isnumeric(opts), opts = struct; end
125 #
126 ##---- Set defaults
127 #fid = setOpts('fid',1);
128 #Verbose = setOpts('Verbose',true);
129 #function printf(varargin), fprintf(fid,varargin{:}); end
130 #MaxIntIter = setOpts('MaxIntIter',5,1);
131 #TypeMin = setOpts('TypeMin','L1');
132 #TolVar = setOpts('tolvar',1e-5);
133 #[U,U_userSet] = setOpts('U', @(x) x );
134 #if ~isa(U,'function_handle')
135 # Ut = setOpts('Ut',[]);
136 #else
137 # Ut = setOpts('Ut', @(x) x );
138 #end
139 #xplug = setOpts('xplug',[]);
140 #normU = setOpts('normU',[]); # so we can tell if it's been set
141 #
142 #residuals = []; outputData = [];
143 #AAtinv = setOpts('AAtinv',[]);
144 #USV = setOpts('USV',[]);
145 #if ~isempty(USV)
146 # if isstruct(USV)
147 # Q = USV.U; # we can't use "U" as the variable name
148 # # since "U" already refers to the analysis operator
149 # S = USV.S;
150 # if isvector(S), s = S; #S = diag(s);
151 # else s = diag(S); end
152 # #V = USV.V;
153 # else
154 # error('opts.USV must be a structure');
155 # end
156 #end
157 #
158 ## -- We can handle non-projections IF a (fast) routine for computing
159 ## the psuedo-inverse is available.
160 ## We can handle a nonzero delta, but we need the full SVD
161 #if isempty(AAtinv) && isempty(USV)
162 # # Check if A is a partial isometry, i.e. if AA' = I
163 # z = randn(size(b));
164 # if isa(A,'function_handle'), AAtz = A(At(z));
165 # else AAtz = A*(A'*z); end
166 # if norm( AAtz - z )/norm(z) > 1e-8
167 # error('Measurement matrix A must be a partial isometry: AA''=I');
168 # end
169 #end
170 #
171 ## -- Find a initial guess if not already provided.
172 ## Use least-squares solution: x_ref = A'*inv(A*A')*b
173 ## If A is a projection, the least squares solution is trivial
174 #if isempty(xplug) || norm(xplug) < 1e-12
175 # if ~isempty(USV) && isempty(AAtinv)
176 # AAtinv = Q*diag( s.^(-2) )*Q';
177 # end
178 # if ~isempty(AAtinv)
179 # if delta > 0 && isempty(USV)
180 # error('delta must be zero for non-projections');
181 # end
182 # if isa(AAtinv,'function_handle')
183 # x_ref = AAtinv(b);
184 # else
185 # x_ref = AAtinv * b;
186 # end
187 # else
188 # x_ref = b;
189 # end
190 #
191 # if isa(A,'function_handle')
192 # x_ref=At(x_ref);
193 # else
194 # x_ref = A'*x_ref;
195 # end
196 #
197 # if isempty(xplug)
198 # xplug = x_ref;
199 # end
200 # # x_ref itself is used to calculate mu_0
201 # # in the case that xplug has very small norm
202 #else
203 # x_ref = xplug;
204 #end
205 #
206 ## use x_ref, not xplug, to find mu_0
207 #if isa(U,'function_handle')
208 # Ux_ref = U(x_ref);
209 #else
210 # Ux_ref = U*x_ref;
211 #end
212 #switch lower(TypeMin)
213 # case 'l1'
214 # mu0 = 0.9*max(abs(Ux_ref));
215 # case 'tv'
216 # mu0 = ValMUTv(Ux_ref);
217 #end
218 #
219 ## -- If U was set by the user and normU not supplied, then calcuate norm(U)
220 #if U_userSet && isempty(normU)
221 # # simple case: U*U' = I or U'*U = I, in which case norm(U) = 1
222 # z = randn(size(xplug));
223 # if isa(U,'function_handle'), UtUz = Ut(U(z)); else UtUz = U'*(U*z); end
224 # if norm( UtUz - z )/norm(z) < 1e-8
225 # normU = 1;
226 # else
227 # z = randn(size(Ux_ref));
228 # if isa(U,'function_handle')
229 # UUtz = U(Ut(z));
230 # else
231 # UUtz = U*(U'*z);
232 # end
233 # if norm( UUtz - z )/norm(z) < 1e-8
234 # normU = 1;
235 # end
236 # end
237 #
238 # if isempty(normU)
239 # # have to actually calculate the norm
240 # if isa(U,'function_handle')
241 # [normU,cnt] = my_normest(U,Ut,length(xplug),1e-3,30);
242 # if cnt == 30, printf('Warning: norm(U) may be inaccurate\n'); end
243 # else
244 # [mU,nU] = size(U);
245 # if mU < nU, UU = U*U'; else UU = U'*U; end
246 # # last resort is to call MATLAB's "norm", which is slow
247 # if norm( UU - diag(diag(UU)),'fro') < 100*eps
248 # # this means the matrix is diagonal, so norm is easy:
249 # normU = sqrt( max(abs(diag(UU))) );
250 # elseif issparse(UU)
251 # normU = sqrt( normest(UU) );
252 # else
253 # if min(size(U)) > 2000
254 # # norm(randn(2000)) takes about 5 seconds on my PC
255 # printf('Warning: calculation of norm(U) may be slow\n');
256 # end
257 # normU = sqrt( norm(UU) );
258 # end
259 # end
260 # end
261 # opts.normU = normU;
262 #end
263 #
264 #
265 #niter = 0;
266 #Gamma = (muf/mu0)^(1/MaxIntIter);
267 #mu = mu0;
268 #Gammat= (TolVar/0.1)^(1/MaxIntIter);
269 #TolVar = 0.1;
270 #
271 #for nl=1:MaxIntIter
272 #
273 # mu = mu*Gamma;
274 # TolVar=TolVar*Gammat; opts.TolVar = TolVar;
275 # opts.xplug = xplug;
276 # if Verbose, printf('\tBeginning #s Minimization; mu = #g\n',opts.TypeMin,mu); end
277 # [xk,niter_int,res,out,optsOut] = Core_Nesterov(...
278 # A,At,b,mu,delta,opts);
279 #
280 # xplug = xk;
281 # niter = niter_int + niter;
282 #
283 # residuals = [residuals; res];
284 # outputData = [outputData; out];
285 #
286 #end
287 #opts = optsOut;
288
289 # End of original Matab code:
290 #---------------------
291
292
293 #if isempty(opts) && isnumeric(opts), opts = struct; end
294
295 #---- Set defaults
296 #fid = setOpts('fid',1);
297 opts,Verbose,userSet = setOpts(opts,'Verbose',True);
298 #function printf(varargin), fprintf(fid,varargin{:}); end
299 opts,MaxIntIter,userSet = setOpts(opts,'MaxIntIter',5,1);
300 opts,TypeMin,userSet = setOpts(opts,'TypeMin','L1');
301 opts,TolVar,userSet = setOpts(opts,'tolvar',1e-5);
302 #[U,U_userSet] = setOpts('U', @(x) x );
303 opts,U,U_userSet = setOpts(opts,'U', lambda x: x );
304 #if ~isa(U,'function_handle')
305 if hasattr(U, '__call__'):
306 opts,Ut,userSet = setOpts(opts,'Ut',None)
307 else:
308 opts,Ut,userSet = setOpts(opts,'Ut', lambda x: x )
309 #end
310 opts,xplug,userSet = setOpts(opts,'xplug',None);
311 opts,normU,userSet = setOpts(opts,'normU',None); # so we can tell if it's been set
312
313 #residuals = []; outputData = [];
314 residuals = numpy.array([])
315 outputData = numpy.array([])
316 opts,AAtinv,userSet = setOpts(opts,'AAtinv',None);
317 opts,USV,userSet = setOpts(opts,'USV',None);
318 #if ~isempty(USV)
319 if len(USV.keys()):
320 #if isstruct(USV)
321
322 Q = USV['U'] # we can't use "U" as the variable name
323 # since "U" already refers to the analysis operator
324 S = USV['S']
325 if S.ndim is 1:
326 s = S
327 else:
328 s = numpy.diag(S)
329
330 #V = USV.V;
331 #else
332 # error('opts.USV must be a structure');
333 #end
334 #end
335
336 # -- We can handle non-projections IF a (fast) routine for computing
337 # the psuedo-inverse is available.
338 # We can handle a nonzero delta, but we need the full SVD
339 #if isempty(AAtinv) && isempty(USV)
340 if (AAtinv is None) and (USV is None):
341 # Check if A is a partial isometry, i.e. if AA' = I
342 #z = randn(size(b));
343 z = numpy.random.randn(b.shape)
344 #if isa(A,'function_handle'), AAtz = A(At(z));
345 #else AAtz = A*(A'*z); end
346 if hasattr(A, '__call__'):
347 AAtz = A(At(z))
348 else:
349 #AAtz = A*(A'*z)
350 AAtz = numpy.dot(A, numpy.dot(A.T,z))
351
352 #if norm( AAtz - z )/norm(z) > 1e-8
353 if numpy.linalg.norm(AAtz - z) / numpy.linalg.norm(z) > 1e-8:
354 #error('Measurement matrix A must be a partial isometry: AA''=I');
355 print 'Measurement matrix A must be a partial isometry: AA''=I'
356 raise
357 #end
358 #end
359
360 # -- Find a initial guess if not already provided.
361 # Use least-squares solution: x_ref = A'*inv(A*A')*b
362 # If A is a projection, the least squares solution is trivial
363 #if isempty(xplug) || norm(xplug) < 1e-12
364 if xplug is None or numpy.linalg.norm(xplug) < 1e-12:
365 #if ~isempty(USV) && isempty(AAtinv)
366 if USV is not None and AAtinv is None:
367 #AAtinv = Q*diag( s.^(-2) )*Q';
368 AAtinv = numpy.dot(Q, numpy.dot(numpy.diag(s ** -2), Q.T))
369 #end
370 #if ~isempty(AAtinv)
371 if AAtinv is not None:
372 #if delta > 0 && isempty(USV)
373 if delta > 0 and USV is None:
374 #error('delta must be zero for non-projections');
375 print 'delta must be zero for non-projections'
376 raise
377 #end
378 #if isa(AAtinv,'function_handle')
379 if hasattr(AAtinv,'__call__'):
380 x_ref = AAtinv(b)
381 else:
382 x_ref = numpy.dot(AAtinv , b)
383 #end
384 else:
385 x_ref = b
386 #end
387
388 #if isa(A,'function_handle')
389 if hasattr(A,'__call__'):
390 x_ref=At(x_ref);
391 else:
392 #x_ref = A'*x_ref;
393 x_ref = numpy.dot(A.T, x_ref)
394 #end
395
396 #if isempty(xplug)
397 if xplug is None:
398 xplug = x_ref;
399 #end
400 # x_ref itself is used to calculate mu_0
401 # in the case that xplug has very small norm
402 else:
403 x_ref = xplug;
404 #end
405
406 # use x_ref, not xplug, to find mu_0
407 #if isa(U,'function_handle')
408 if hasattr(U,'__call__'):
409 Ux_ref = U(x_ref);
410 else:
411 Ux_ref = numpy.dot(U,x_ref)
412 #end
413 #switch lower(TypeMin)
414 # case 'l1'
415 # mu0 = 0.9*max(abs(Ux_ref));
416 # case 'tv'
417 # mu0 = ValMUTv(Ux_ref);
418 #end
419 if TypeMin.lower() == 'l1':
420 mu0 = 0.9*max(abs(Ux_ref))
421 elif TypeMin.lower() == 'tv':
422 #mu0 = ValMUTv(Ux_ref);
423 print 'Nic: TODO: not implemented yet'
424 raise
425
426 # -- If U was set by the user and normU not supplied, then calcuate norm(U)
427 #if U_userSet && isempty(normU)
428 if U_userSet and normU is None:
429 # simple case: U*U' = I or U'*U = I, in which case norm(U) = 1
430 #z = randn(size(xplug));
431 z = numpy.random.randn(xplug.shape)
432 #if isa(U,'function_handle'), UtUz = Ut(U(z)); else UtUz = U'*(U*z); end
433 if hasattr(U,'__call__'):
434 UtUz = Ut(U(z))
435 else:
436 UtUz = numpy.dot(U.T, numpy.dot(U,z))
437
438 if numpy.linalg.norm( UtUz - z )/numpy.linalg.norm(z) < 1e-8:
439 normU = 1;
440 else:
441 z = numpy.random.randn(Ux_ref.shape)
442 #if isa(U,'function_handle'):
443 if hasattr(U,'__call__'):
444 UUtz = U(Ut(z));
445 else:
446 #UUtz = U*(U'*z);
447 UUtz = numpy.dot(U, numpy.dot(U.T,z))
448 #end
449 if numpy.linalg.norm( UUtz - z )/numpy.linalg.norm(z) < 1e-8:
450 normU = 1;
451 #end
452 #end
453
454 #if isempty(normU)
455 if normU is None:
456 # have to actually calculate the norm
457 #if isa(U,'function_handle')
458 if hasattr(U,'__call__'):
459 #[normU,cnt] = my_normest(U,Ut,length(xplug),1e-3,30);
460 normU,cnt = my_normest(U,Ut,xplug.size,1e-3,30)
461 #if cnt == 30, printf('Warning: norm(U) may be inaccurate\n'); end
462 if cnt == 30:
463 print 'Warning: norm(U) may be inaccurate'
464 else:
465 mU,nU = U.shape
466 if mU < nU:
467 UU = numpy.dot(U,U.T)
468 else:
469 UU = numpy.dot(U.T,U)
470 # last resort is to call MATLAB's "norm", which is slow
471 #if norm( UU - diag(diag(UU)),'fro') < 100*eps
472 if numpy.linalg.norm( UU - numpy.diag(numpy.diag(UU)),'fro') < 100*numpy.finfo(float).eps:
473 # this means the matrix is diagonal, so norm is easy:
474 #normU = sqrt( max(abs(diag(UU))) );
475 normU = math.sqrt( max(abs(numpy.diag(UU))) )
476
477 # Nic: TODO: sparse not implemented
478 #elif issparse(UU)
479 # normU = sqrt( normest(UU) );
480 else:
481 if min(U.shape) > 2000:
482 # norm(randn(2000)) takes about 5 seconds on my PC
483 #printf('Warning: calculation of norm(U) may be slow\n');
484 print 'Warning: calculation of norm(U) may be slow'
485 #end
486 normU = math.sqrt( numpy.linalg.norm(UU) );
487 #end
488 #end
489 #end
490 #opts.normU = normU;
491 opts['normU'] = normU
492 #end
493
494 niter = 0;
495 Gamma = (muf/mu0)**(1.0/MaxIntIter);
496 mu = mu0;
497 Gammat = (TolVar/0.1)**(1.0/MaxIntIter);
498 TolVar = 0.1;
499
500 #for nl=1:MaxIntIter
501 for n1 in numpy.arange(MaxIntIter):
502
503 mu = mu*Gamma;
504 TolVar=TolVar*Gammat;
505 opts['TolVar'] = TolVar;
506 opts['xplug'] = xplug;
507 #if Verbose, printf('\tBeginning #s Minimization; mu = #g\n',opts.TypeMin,mu); end
508 if Verbose:
509 #printf('\tBeginning #s Minimization; mu = #g\n',opts.TypeMin,mu)
510 print ' Beginning', opts['TypeMin'],'Minimization; mu =',mu
511
512 #[xk,niter_int,res,out,optsOut] = Core_Nesterov(A,At,b,mu,delta,opts);
513 xk,niter_int,res,out,optsOut = Core_Nesterov(A,At,b,mu,delta,opts)
514
515 xplug = xk.copy();
516 niter = niter_int + niter;
517
518 #residuals = [residuals; res];
519 residuals = numpy.hstack((residuals,res))
520 #outputData = [outputData; out];
521 outputData = numpy.hstack((outputData, out))
522
523 #end
524 opts = optsOut.copy()
525
526 return xk,niter,residuals,outputData,opts
527
528
529
530 #---- internal routine for setting defaults
531 #function [var,userSet] = setOpts(field,default,mn,mx)
532 def setOpts(opts,field,default,mn=None,mx=None):
533
534 var = default
535 # has the option already been set?
536 #if ~isfield(opts,field)
537 if field in opts.keys():
538 # see if there is a capitalization problem:
539 #names = fieldnames(opts);
540 #for i = 1:length(names)
541 for key in opts.keys():
542 #if strcmpi(names{i},field)
543 if key.lower() == field.lower():
544 #opts.(field) = opts.(names{i});
545 opts[field] = opts[key]
546 #opts = rmfield(opts,names{i});
547 del opts[key]
548 break
549 #end
550 #end
551 #end
552
553 #if isfield(opts,field) && ~isempty(opts.(field))
554 if field in opts.keys() and (opts[field] is not None):
555 #var = opts.(field); # override the default
556 var = opts[field]
557 userSet = True
558 else:
559 userSet = False
560 #end
561 # perform error checking, if desired
562 #if nargin >= 3 && ~isempty(mn)
563 if mn is not None:
564 if var < mn:
565 #printf('Variable #s is #f, should be at least #f\n',...
566 # field,var,mn); error('variable out-of-bounds');
567 print 'Variable',field,'is',var,', should be at least',mn
568 raise
569 #end
570 #end
571 #if nargin >= 4 && ~isempty(mx)
572 if mx is not None:
573 if var > mx:
574 #printf('Variable #s is #f, should be at least #f\n',...
575 # field,var,mn); error('variable out-of-bounds');
576 print 'Variable',field,'is',var,', should be at most',mx
577 raise
578 #end
579 #end
580 #opts.(field) = var;
581 opts[field] = var
582
583 return opts,var,userSet
584
585 # Nic: TODO: implement TV
586 #---- internal routine for setting mu0 in the tv minimization case
587 #function th=ValMUTv(x)
588 # #N = length(x);n = floor(sqrt(N));
589 # N = b.size
590 # n = floor(sqrt(N))
591 # Dv = spdiags([reshape([-ones(n-1,n); zeros(1,n)],N,1) ...
592 # reshape([zeros(1,n); ones(n-1,n)],N,1)], [0 1], N, N);
593 # Dh = spdiags([reshape([-ones(n,n-1) zeros(n,1)],N,1) ...
594 # reshape([zeros(n,1) ones(n,n-1)],N,1)], [0 n], N, N);
595 # D = sparse([Dh;Dv]);
596 #
597 #
598 # Dhx = Dh*x;
599 # Dvx = Dv*x;
600 #
601 # sk = sqrt(abs(Dhx).^2 + abs(Dvx).^2);
602 # th = max(sk);
603 #
604 #end
605
606 #end #-- end of NESTA function
607
608 ############ POWER METHOD TO ESTIMATE NORM ###############
609 # Copied from MATLAB's "normest" function, but allows function handles, not just sparse matrices
610 #function [e,cnt] = my_normest(S,St,n,tol, maxiter)
611 def my_normest(S,St,n,tol=1e-6, maxiter=20):
612 #MY_NORMEST Estimate the matrix 2-norm via power method.
613 #if nargin < 4, tol = 1.e-6; end
614 #if nargin < 5, maxiter = 20; end
615 #if isempty(St)
616 if S is None:
617 St = S # we assume the matrix is symmetric;
618 #end
619 x = numpy.ones(n);
620 cnt = 0;
621 e = numpy.linalg.norm(x);
622 #if e == 0, return, end
623 if e == 0:
624 return e,cnt
625 x = x/e;
626 e0 = 0;
627 while abs(e-e0) > tol*e and cnt < maxiter:
628 e0 = e;
629 Sx = S(x);
630 #if nnz(Sx) == 0
631 if (Sx!=0).sum() == 0:
632 Sx = numpy.random.rand(Sx.size);
633 #end
634 e = numpy.linalg.norm(Sx);
635 x = St(Sx);
636 x = x/numpy.linalg.norm(x);
637 cnt = cnt+1;
638 #end
639 #end