-
Notifications
You must be signed in to change notification settings - Fork 5
/
SA.m
129 lines (123 loc) · 4.29 KB
/
SA.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
function [x,fval,exitflag] = SA(f,x,options,varargin)
% SA Solves a system of equations by successive approximation
%
% SA solves a system of equations by iterating on the evaluations of the
% equations: x[i] = x[i-1]+dx[i-1] until norm(f(x[i]))<=TolFun+RelTolFun*norm(f(x[0])),
% where dx = lambda*f(x).
%
% To enhance convergence SA uses a backtracking line search that divides dx by 2
% until norm(f(x+dx)) decreases with respect to norm(f(x)) or until MaxSteps
% iterations have been done.
%
% X = SA(F,X0) tries to solve the system of equations F(X)=0 and
% start at the vector X0. F accepts a vector X and return a vector
% of equation values F evaluated at X. SA returns the vector X the
% root of F.
%
% X = SA(F,X0,OPTIONS) solves the problem using the options defined
% in the structure OPTIONS. Fields can be
% Display : 1 to display results of each iteration, 0 (default) if not
% lambda : adjustment parameter (default: 1)
% MaxIter : maximum number of iterations (default: 1000)
% MaxSteps : maximum number of backstepping iterations (default: 3)
% RelTolFun : relative convergence tolerance (default: sqrt(eps))
% TolFun : absolute convergence tolerance (default: sqrt(eps))
%
% X = SA(F,X0,OPTIONS,VARARGIN) provides additional arguments for
% F, which, in this case, takes the following form: F(X,VARARGIN).
%
% [X,FVAL] = SA(F,X0,...) returns the value of the equations F at X.
%
% [X,FVAL,EXITFLAG] = SA(F,X0,...) returns EXITFLAG that describes
% the exit conditions. Possible values listed below.
% 1 : SA converged to a root
% 0 : Failure to converge because of too many iterations or equations not
% defined at starting point
% Copyright (C) 2011-2016 Christophe Gouel
% Licensed under the Expat license, see LICENSE.txt
%% Initialization
defaultopt = struct( ...
'Display' , 0 ,...
'lambda' , 1 ,...
'MaxIter' , 1000 ,...
'MaxSteps' , 3 ,...
'RelTolFun', sqrt(eps),...
'TolFun' , sqrt(eps));
if nargin < 3 || isempty(options)
options = defaultopt;
else
options = catstruct(defaultopt,options);
end
lambda = options.lambda;
MaxIter = options.MaxIter;
MaxSteps = max(1,options.MaxSteps);
RelTolFun = options.RelTolFun;
Display = options.Display;
TolFun = options.TolFun;
fval = feval(f,x,varargin{:});
isdomerr = any(reshape(isinf(fval) | (imag(fval)~=0) | isnan(fval),[],1));
if isdomerr
exitflag = 0;
if Display
fprintf(1,'Equations not defined at starting point\n');
end
return
end
fnrm = norm(fval(:));
stop_tol = TolFun + RelTolFun*fnrm;
it = 0;
if Display
fprintf(1,'Successive approximation\n');
fprintf(1,' Major\t Minor\tLipschitz\t Residual\n');
fprintf(1,'%7i\t%6i\t \t%9.2E (Input point)\n',0,0,fnrm);
end
%% Iterations
while(fnrm > stop_tol && it < MaxIter)
it = it+1;
dx = lambda*fval;
%% Backstepping
for itback=1:MaxSteps
fvalnew = feval(f,x+dx,varargin{:});
fnrmnew = norm(fvalnew(:));
isnotdomerr = ~any(reshape(isinf(fvalnew) | (imag(fvalnew)~=0) | isnan(fvalnew),...
[],1));
if (fnrmnew<fnrm && isnotdomerr) || itback==MaxSteps
%% End of backstepping because of success or maximum iteration
k = norm(fvalnew-fval)/norm(dx);
fval = fvalnew;
fnrm = fnrmnew;
x = x+dx;
if Display, fprintf(1,'%7i\t%6i\t%8.4f\t%9.2E\n',it,itback,k,fnrm); end
break
end
if itback>1 && fnrmold<fnrmnew
%% End of backstepping because it does not improve residual
k = norm(fvalold-fval)/norm(dx*2);
fval = fvalold;
fnrm = fnrmold;
x = x+dx*2;
if Display, fprintf(1,'%7i\t%6i\t%9.4f\t%8.2E\n',it,itback-1,k,fnrm); end
break
end
fvalold = fvalnew;
fnrmold = fnrmnew;
dx = dx/2;
end % itback
end %it
%% Output treatment
if it==MaxIter
exitflag = 0;
if Display
fprintf(1,'Too many iterations\n');
end
else
exitflag = 1;
if Display
fprintf(1,'Solution found');
if fnrm < TolFun
fprintf(1,' - Residual lower than absolute tolerance\n');
else
fprintf(1,' - Residual lower than relative tolerance\n');
end
end
end