-
Notifications
You must be signed in to change notification settings - Fork 5
/
broyden.m
108 lines (100 loc) · 3.11 KB
/
broyden.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
% BROYDEN Computes root of function via Broyden's Inverse Method
% Uses inverse Jacobian estimate and backstepping
% USAGE
% [x,fval,flag,it,fjacinv] = broyden(f,x,varargin)
% INPUTS
% f : name of function of form:
% fval=f(x,optional additional parameters)
% x : initial guess for root (d by 1)
% varargin: additional arguments for f [optional]
% OUTPUTS
% x : root of f (d by 1)
% fval : function value estimate (d by 1)
% flag : 0 if sucessful
% 1 if failed to converge
% 2 is inf or nan generated
% it : number of iterations performed
% fjacinv : inverse Jacobian estimate (d by d)
%
% Setable options (use OPTSET):
% maxit : maximum number of iterations
% tol : convergence tolerance
% maxsteps : maximum number of backsteps
% showiters : display results of each iteration
% initb : an initial inverse Jacobian approximation matrix
% initi : if initb is empty, use the identity matrix to initialize
% if 0, a numerical Jacobian will be used
% restarts : set to 0 to turn off the restarting feature (not recommended)
% usejac : set to 1 if f computes a Jacobian (avoids numerical derivatives)
% Copyright (c) 1997-2010, Paul L. Fackler & Mario J. Miranda
% paul_fackler@ncsu.edu, miranda.4@osu.edu
function [x,fval,flag,it,fjacinv] = broyden(f,x,varargin)
maxit = optget('broyden','maxit',100);
tol = optget('broyden','tol',sqrt(eps));
maxsteps = optget('broyden','maxsteps',25);
showiters = optget('broyden','showiters',0);
initb = optget('broyden','initb',[]);
initi = optget('broyden','initi',0);
restarts = optget('broyden','restarts',1);
usejac = optget('broyden','usejac',0);
flag=0;
if maxsteps<1, maxsteps=1; end
lineoptions.maxsteps=maxsteps;
if usejac && nargout(f)<2
usejac=false;
end
if isempty(initb)
if usejac
[fval,fjacinv] = feval(f,x,varargin{:});
fjacinv = inv(fjacinv);
elseif initi
fjacinv=eye(size(x,1));
else
fjacinv = fdjac(f,x,varargin{:});
fjacinv = inv(fjacinv);
end
else
fjacinv = full(initb);
end
fval = feval(f,x,varargin{:});
fnorm = norm(fval,inf);
for it=1:maxit
if fnorm<tol
return;
end
dx = -(fjacinv*fval);
if any(isnan(dx)|isinf(dx))
if nargout<3
warning('broyden:infs','Infinities or NaNs encountered in broyden')
return
else
flag=2; return;
end
end
% perform linesearch
[dx,fvalnew,fnormnew,lineflag,backstep]= ...
linesearch(f,x,dx,fnorm,lineoptions,varargin{:});
x = x+dx;
if lineflag>0 && restarts
if usejac
[fval,fjacinv] = feval(f,x,varargin{:});
fjacinv = inv(fjacinv);
elseif initi
fjacinv=eye(size(x,1));
else
fjacinv = fdjac(f,x,varargin{:});
fjacinv = inv(fjacinv);
end
else
temp = fjacinv*(fvalnew-fval);
fjacinv = fjacinv + (dx-temp)*((dx'*fjacinv)/(dx'*temp));
end
fval=fvalnew;
fnorm=fnormnew;
if showiters, fprintf('%4i %4i %6.2e\n',[it backstep fnorm]); end
end
if nargout<3
warning('broyden:nonconv','Failure to converge in broyden');
else
flag=1;
end