-
Notifications
You must be signed in to change notification settings - Fork 60
/
linop_normest.m
79 lines (76 loc) · 2.43 KB
/
linop_normest.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
function [ nxe, cnt ] = linop_normest( op, cmode, tol, maxiter )
%LINOP_NORMEST Estimates the operator norm.
% EST = LINOP_NORMEST( OP ) estimates the induced norm of the operator:
% || OP || = max_{||x||<=1} ||OP(X)||
% using a simple power method similar to the MATLAB NORMEST functon.
%
% When called with a single argument, LINOP_TEST begins with a real
% initial vector. To test complex operators, use the two-argument
% version LINOP_NORMEST( OP, cmode ), where:
% cmode = 'R2R': real input, real output
% cmode = 'R2C': real input, complex output
% cmode = 'C2R': imag input, imag output
% cmode = 'C2C': complex input, complex output
%
% LINOP_NORMEST( OP, CMODE, TOL, MAXITER ) stops the iteration when the
% relative change in the estimate is less than TOL, or after MAXITER
% iterations, whichever comes first.
%
% [ EST, CNT ] = LINOP_NORMEST( ... returns the estimate and the number
% of iterations taken, respectively.
if isnumeric( op ),
op = linop_matrix( op, 'C2C' );
elseif ~isa( op, 'function_handle' ),
error( 'Argument must be a function handle or matrix.' );
end
x_real = true;
if nargin >= 2 && ~isempty( cmode ),
switch upper( cmode ),
case { 'R2R', 'R2C' }, x_real = true;
case { 'C2R', 'C2C' }, x_real = false;
otherwise, error( 'Invalid cmode: %s', cmode );
end
end
if nargin < 3 || isempty( tol ),
tol = 1e-8;
end
if nargin < 4 || isempty( maxiter ),
maxiter = 50;
end
sz = op([],0);
if iscell( sz ),
sz = sz{1};
elseif ~isempty(sz)
sz = [sz(2),1];
else
% if the input is the identity, it may not have a size associated with it,
% so current behavior is to try an arbitrary size:
sz = [50,1];
end
cnt = 0;
nxe = 0;
while true,
if nxe == 0,
if x_real,
xx = randn(sz);
else
xx = randn(sz) + 1j*randn(sz);
end
nxe = sqrt( tfocs_normsq( xx ) );
end
yy = op( xx / max( nxe, realmin ), 1 );
nye = sqrt( tfocs_normsq( yy ) );
xx = op( yy / max( nye, realmin ), 2 );
nxe0 = nxe;
nxe = sqrt( tfocs_normsq( xx ) );
if abs( nxe - nxe0 ) < tol * max( nxe0, nxe ),
break;
end
cnt = cnt + 1;
if cnt >= maxiter,
break;
end
end
% TFOCS v1.3 by Stephen Becker, Emmanuel Candes, and Michael Grant.
% Copyright 2013 California Institute of Technology and CVX Research.
% See the file LICENSE for full license information.