comparison scripts/optimization/fsolve.m @ 8986:22c8272af34b

improvements to fsolve & family
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 17 Mar 2009 08:49:08 +0100
parents 20589a8f1a33
children 315828058e0d
comparison
equal deleted inserted replaced
8985:193804a4f82f 8986:22c8272af34b
70 ## @item 0 70 ## @item 0
71 ## Iteration limit exceeded. 71 ## Iteration limit exceeded.
72 ## @item -3 72 ## @item -3
73 ## The trust region radius became excessively small. 73 ## The trust region radius became excessively small.
74 ## @end table 74 ## @end table
75 ## 75 ##
76 ## Note: If you only have a single nonlinear equation of one variable, using 76 ## Note: If you only have a single nonlinear equation of one variable, using
77 ## @code{fzero} is usually a much better idea. 77 ## @code{fzero} is usually a much better idea.
78 ## @seealso{fzero, optimset} 78 ## @seealso{fzero, optimset}
79 ##
80 ## Note about user-supplied jacobians:
81 ## As an inherent property of the algorithm, jacobian is always requested for a
82 ## solution vector whose residual vector is already known, and it is the last
83 ## accepted successful step. Often this will be one of the last two calls, but
84 ## not always. If the savings by reusing intermediate results from residual
85 ## calculation in jacobian calculation are significant, the best strategy is to
86 ## employ OutputFcn: After a vector is evaluated for residuals, if OutputFcn is
87 ## called with that vector, then the intermediate results should be saved for
88 ## future jacobian evaluation, and should be kept until a jacobian evaluation
89 ## is requested or until outputfcn is called with a different vector, in which
90 ## case they should be dropped in favor of this most recent vector. A short
91 ## example how this can be achieved follows:
92 ## @example
93 ## function [fvec, fjac] = my_optim_func (x, optimvalues, state)
94 ## persistent sav = [], sav0 = [];
95 ## if (nargin == 1)
96 ## ## evaluation call
97 ## if (nargout == 1)
98 ## sav0.x = x; # mark saved vector
99 ## ## calculate fvec, save results to sav0.
100 ## elseif (nargout == 2)
101 ## ## calculate fjac using sav.
102 ## endif
103 ## else
104 ## ## outputfcn call.
105 ## if (all (x == sav0.x))
106 ## sav = sav0;
107 ## endif
108 ## ## maybe output iteration status etc.
109 ## endif
110 ## endfunction
111 ##
112 ## ## ....
113 ##
114 ## fsolve (@my_optim_func, x0, optimset ("OutputFcn", @my_optim_func, @dots{}))
115 ## @end example
116 ###
79 ## @end deftypefn 117 ## @end deftypefn
80 118
81 ## PKG_ADD: __all_opts__ ("fsolve"); 119 ## PKG_ADD: __all_opts__ ("fsolve");
82 120
83 function [x, fvec, info, output, fjac] = fsolve (fcn, x0, options = struct ()) 121 function [x, fvec, info, output, fjac] = fsolve (fcn, x0, options = struct ())
127 factor = 100; 165 factor = 100;
128 ## FIXME: TypicalX corresponds to user scaling (???) 166 ## FIXME: TypicalX corresponds to user scaling (???)
129 autodg = true; 167 autodg = true;
130 168
131 niter = 1; 169 niter = 1;
132 nfev = 0; 170 nfev = 1;
133 171
134 x = x0(:); 172 x = x0(:);
135 info = 0; 173 info = 0;
174
175 ## Initial evaluation.
176 fvec = fcn (reshape (x, xsiz));
177 fsiz = size (fvec);
178 fvec = fvec(:);
179 fn = norm (fvec);
180 m = length (fvec);
181 n = length (x);
182
183 if (! isempty (outfcn))
184 optimvalues.iter = niter;
185 optimvalues.funccount = nfev;
186 optimvalues.fval = fn;
187 optimvalues.searchdirection = zeros (n, 1);
188 state = 'init';
189 stop = outfcn (x, optimvalues, state);
190 if (stop)
191 info = -1;
192 break;
193 endif
194 endif
195
196 nsuciter = 0;
136 197
137 ## Outer loop. 198 ## Outer loop.
138 while (niter < maxiter && nfev < maxfev && ! info) 199 while (niter < maxiter && nfev < maxfev && ! info)
139 200
140 ## Calculate function value and Jacobian (possibly via FD). 201 ## Calculate function value and Jacobian (possibly via FD).
143 [fvec, fjac] = fcn (reshape (x, xsiz)); 204 [fvec, fjac] = fcn (reshape (x, xsiz));
144 ## If the jacobian is sparse, disable Broyden updating. 205 ## If the jacobian is sparse, disable Broyden updating.
145 if (issparse (fjac)) 206 if (issparse (fjac))
146 updating = false; 207 updating = false;
147 endif 208 endif
209 fvec = fvec(:);
148 nfev ++; 210 nfev ++;
149 else 211 else
150 [fvec, fjac] = __fdjac__ (fcn, reshape (x, xsiz)); 212 fjac = __fdjac__ (fcn, reshape (x, xsiz), fvec);
151 nfev += 1 + length (x); 213 nfev += length (x);
152 endif 214 endif
153 fsiz = size (fvec);
154 fvec = fvec(:);
155 fn = norm (fvec);
156 m = length (fvec);
157 n = length (x);
158 215
159 ## For square and overdetermined systems, we update a QR 216 ## For square and overdetermined systems, we update a QR
160 ## factorization of the jacobian to avoid solving a full system in each 217 ## factorization of the jacobian to avoid solving a full system in each
161 ## step. In this case, we pass a triangular matrix to __dogleg__. 218 ## step. In this case, we pass a triangular matrix to __dogleg__.
162 useqr = updating && m >= n && n > 10; 219 useqr = updating && m >= n && n > 10;
197 ## jacobian, the Broyden updates are of little use, so maybe we could 254 ## jacobian, the Broyden updates are of little use, so maybe we could
198 ## skip them if a big disproportional change is expected. The question is, 255 ## skip them if a big disproportional change is expected. The question is,
199 ## of course, how to define the above terms :) 256 ## of course, how to define the above terms :)
200 endif 257 endif
201 258
259 lastratio = 0;
202 nfail = 0; 260 nfail = 0;
203 nsuc = 0; 261 nsuc = 0;
204 ## Inner loop. 262 ## Inner loop.
205 while (niter <= maxiter && nfev < maxfev && ! info) 263 while (niter <= maxiter && nfev < maxfev && ! info)
206 264
247 prered = 0; 305 prered = 0;
248 ratio = 0; 306 ratio = 0;
249 endif 307 endif
250 308
251 ## Update delta. 309 ## Update delta.
252 if (ratio < 0.1) 310 if (ratio < min(max(0.1, lastratio), 0.9))
253 nsuc = 0; 311 nsuc = 0;
254 nfail ++; 312 nfail ++;
255 delta *= 0.5; 313 delta *= 0.5;
256 if (delta <= 1e1*macheps*xn) 314 if (delta <= 1e1*macheps*xn)
257 ## Trust region became uselessly small. 315 ## Trust region became uselessly small.
258 info = -3; 316 info = -3;
259 break; 317 break;
260 endif 318 endif
261 else 319 else
320 lastratio = ratio;
262 nfail = 0; 321 nfail = 0;
263 nsuc ++; 322 nsuc ++;
264 if (abs (1-ratio) <= 0.1) 323 if (abs (1-ratio) <= 0.1)
265 delta = 2*sn; 324 delta = 2*sn;
266 elseif (ratio >= 0.5 || nsuc > 1) 325 elseif (ratio >= 0.5 || nsuc > 1)
272 ## Successful iteration. 331 ## Successful iteration.
273 x += s; 332 x += s;
274 xn = norm (dg .* x); 333 xn = norm (dg .* x);
275 fvec = fvec1; 334 fvec = fvec1;
276 fn = fn1; 335 fn = fn1;
336 nsuciter ++;
277 endif 337 endif
278 338
279 niter ++; 339 niter ++;
280 340
281 ## FIXME: should outputfcn be only called after a successful iteration? 341 ## FIXME: should outputfcn be only called after a successful iteration?
319 info = 3; 379 info = 3;
320 endif 380 endif
321 endif 381 endif
322 382
323 ## Criterion for recalculating jacobian. 383 ## Criterion for recalculating jacobian.
324 if (! updating || nfail == 2) 384 if (! updating || nfail == 2 || nsuciter < 2)
325 break; 385 break;
326 endif 386 endif
327 387
328 ## Compute the scaled Broyden update. 388 ## Compute the scaled Broyden update.
329 if (useqr) 389 if (useqr)
345 ## Restore original shapes. 405 ## Restore original shapes.
346 x = reshape (x, xsiz); 406 x = reshape (x, xsiz);
347 fvec = reshape (fvec, fsiz); 407 fvec = reshape (fvec, fsiz);
348 408
349 output.iterations = niter; 409 output.iterations = niter;
410 output.successful = nsuciter;
350 output.funcCount = nfev; 411 output.funcCount = nfev;
351 412
352 endfunction 413 endfunction
353 414
354 ## An assistant function that evaluates a function handle and checks for 415 ## An assistant function that evaluates a function handle and checks for