comparison scripts/optimization/fsolve.m @ 11587:c792872f8942

all script files: untabify and strip trailing whitespace
author John W. Eaton <jwe@octave.org>
date Thu, 20 Jan 2011 17:35:29 -0500
parents fd0a3ac60b0e
children b9a89ca0fb75
comparison
equal deleted inserted replaced
11586:12df7854fa7c 11587:c792872f8942
23 ## @deftypefnx {Function File} {[@var{x}, @var{fvec}, @var{info}, @var{output}, @var{fjac}] =} fsolve (@var{fcn}, @dots{}) 23 ## @deftypefnx {Function File} {[@var{x}, @var{fvec}, @var{info}, @var{output}, @var{fjac}] =} fsolve (@var{fcn}, @dots{})
24 ## Solve a system of nonlinear equations defined by the function @var{fcn}. 24 ## Solve a system of nonlinear equations defined by the function @var{fcn}.
25 ## @var{fcn} should accept a vector (array) defining the unknown variables, 25 ## @var{fcn} should accept a vector (array) defining the unknown variables,
26 ## and return a vector of left-hand sides of the equations. Right-hand sides 26 ## and return a vector of left-hand sides of the equations. Right-hand sides
27 ## are defined to be zeros. 27 ## are defined to be zeros.
28 ## In other words, this function attempts to determine a vector @var{x} such 28 ## In other words, this function attempts to determine a vector @var{x} such
29 ## that @code{@var{fcn} (@var{x})} gives (approximately) all zeros. 29 ## that @code{@var{fcn} (@var{x})} gives (approximately) all zeros.
30 ## @var{x0} determines a starting guess. The shape of @var{x0} is preserved 30 ## @var{x0} determines a starting guess. The shape of @var{x0} is preserved
31 ## in all calls to @var{fcn}, but otherwise it is treated as a column vector. 31 ## in all calls to @var{fcn}, but otherwise it is treated as a column vector.
32 ## @var{options} is a structure specifying additional options. 32 ## @var{options} is a structure specifying additional options.
33 ## Currently, @code{fsolve} recognizes these options: 33 ## Currently, @code{fsolve} recognizes these options:
34 ## @code{"FunValCheck"}, @code{"OutputFcn"}, @code{"TolX"}, 34 ## @code{"FunValCheck"}, @code{"OutputFcn"}, @code{"TolX"},
35 ## @code{"TolFun"}, @code{"MaxIter"}, @code{"MaxFunEvals"}, 35 ## @code{"TolFun"}, @code{"MaxIter"}, @code{"MaxFunEvals"},
36 ## @code{"Jacobian"}, @code{"Updating"}, @code{"ComplexEqn"} 36 ## @code{"Jacobian"}, @code{"Updating"}, @code{"ComplexEqn"}
37 ## @code{"TypicalX"}, @code{"AutoScaling"} and @code{"FinDiffType"}. 37 ## @code{"TypicalX"}, @code{"AutoScaling"} and @code{"FinDiffType"}.
38 ## 38 ##
39 ## If @code{"Jacobian"} is @code{"on"}, it specifies that @var{fcn}, 39 ## If @code{"Jacobian"} is @code{"on"}, it specifies that @var{fcn},
40 ## called with 2 output arguments, also returns the Jacobian matrix 40 ## called with 2 output arguments, also returns the Jacobian matrix
41 ## of right-hand sides at the requested point. @code{"TolX"} specifies 41 ## of right-hand sides at the requested point. @code{"TolX"} specifies
42 ## the termination tolerance in the unknown variables, while 42 ## the termination tolerance in the unknown variables, while
43 ## @code{"TolFun"} is a tolerance for equations. Default is @code{1e-7} 43 ## @code{"TolFun"} is a tolerance for equations. Default is @code{1e-7}
44 ## for both @code{"TolX"} and @code{"TolFun"}. 44 ## for both @code{"TolX"} and @code{"TolFun"}.
45 ## 45 ##
46 ## If @code{"AutoScaling"} is on, the variables will be automatically scaled 46 ## If @code{"AutoScaling"} is on, the variables will be automatically scaled
47 ## according to the column norms of the (estimated) Jacobian. As a result, 47 ## according to the column norms of the (estimated) Jacobian. As a result,
48 ## TolF becomes scaling-independent. By default, this option is off, because 48 ## TolF becomes scaling-independent. By default, this option is off, because
49 ## it may sometimes deliver unexpected (though mathematically correct) results. 49 ## it may sometimes deliver unexpected (though mathematically correct) results.
50 ## 50 ##
51 ## If @code{"Updating"} is "on", the function will attempt to use Broyden 51 ## If @code{"Updating"} is "on", the function will attempt to use Broyden
52 ## updates to update the Jacobian, in order to reduce the amount of Jacobian 52 ## updates to update the Jacobian, in order to reduce the amount of Jacobian
53 ## calculations. 53 ## calculations.
54 ## If your user function always calculates the Jacobian (regardless of number 54 ## If your user function always calculates the Jacobian (regardless of number
55 ## of output arguments), this option provides no advantage and should be set to 55 ## of output arguments), this option provides no advantage and should be set to
56 ## false. 56 ## false.
57 ## 57 ##
58 ## @code{"ComplexEqn"} is @code{"on"}, @code{fsolve} will attempt to solve 58 ## @code{"ComplexEqn"} is @code{"on"}, @code{fsolve} will attempt to solve
59 ## complex equations in complex variables, assuming that the equations possess a 59 ## complex equations in complex variables, assuming that the equations possess a
60 ## complex derivative (i.e., are holomorphic). If this is not what you want, 60 ## complex derivative (i.e., are holomorphic). If this is not what you want,
61 ## should unpack the real and imaginary parts of the system to get a real 61 ## should unpack the real and imaginary parts of the system to get a real
62 ## system. 62 ## system.
63 ## 63 ##
64 ## For description of the other options, see @code{optimset}. 64 ## For description of the other options, see @code{optimset}.
65 ## 65 ##
66 ## On return, @var{fval} contains the value of the function @var{fcn} 66 ## On return, @var{fval} contains the value of the function @var{fcn}
67 ## evaluated at @var{x}, and @var{info} may be one of the following values: 67 ## evaluated at @var{x}, and @var{info} may be one of the following values:
68 ## 68 ##
69 ## @table @asis 69 ## @table @asis
70 ## @item 1 70 ## @item 1
71 ## Converged to a solution point. Relative residual error is less than 71 ## Converged to a solution point. Relative residual error is less than
72 ## specified by TolFun. 72 ## specified by TolFun.
73 ## 73 ##
74 ## @item 2 74 ## @item 2
75 ## Last relative step size was less that TolX. 75 ## Last relative step size was less that TolX.
76 ## 76 ##
77 ## @item 3 77 ## @item 3
78 ## Last relative decrease in residual was less than TolF. 78 ## Last relative decrease in residual was less than TolF.
79 ## 79 ##
80 ## @item 0 80 ## @item 0
81 ## Iteration limit exceeded. 81 ## Iteration limit exceeded.
82 ## 82 ##
83 ## @item -3 83 ## @item -3
84 ## The trust region radius became excessively small. 84 ## The trust region radius became excessively small.
85 ## @end table 85 ## @end table
86 ## 86 ##
87 ## Note: If you only have a single nonlinear equation of one variable, using 87 ## Note: If you only have a single nonlinear equation of one variable, using
88 ## @code{fzero} is usually a much better idea. 88 ## @code{fzero} is usually a much better idea.
89 ## @seealso{fzero, optimset} 89 ## @seealso{fzero, optimset}
90 ## 90 ##
91 ## Note about user-supplied Jacobians: 91 ## Note about user-supplied Jacobians:
92 ## As an inherent property of the algorithm, Jacobian is always requested for a 92 ## As an inherent property of the algorithm, Jacobian is always requested for a
120 ## ## maybe output iteration status, etc. 120 ## ## maybe output iteration status, etc.
121 ## endif 121 ## endif
122 ## endfunction 122 ## endfunction
123 ## 123 ##
124 ## ## @dots{}. 124 ## ## @dots{}.
125 ## 125 ##
126 ## fsolve (@@user_func, x0, optimset ("OutputFcn", @@user_func, @dots{})) 126 ## fsolve (@@user_func, x0, optimset ("OutputFcn", @@user_func, @dots{}))
127 ## @end example 127 ## @end example
128 ## @end deftypefn 128 ## @end deftypefn
129 129
130 ## PKG_ADD: __all_opts__ ("fsolve"); 130 ## PKG_ADD: __all_opts__ ("fsolve");
141 return; 141 return;
142 endif 142 endif
143 143
144 if (nargin < 2 || nargin > 3 || ! ismatrix (x0)) 144 if (nargin < 2 || nargin > 3 || ! ismatrix (x0))
145 print_usage (); 145 print_usage ();
146 endif 146 endif
147 147
148 if (ischar (fcn)) 148 if (ischar (fcn))
149 fcn = str2func (fcn, "global"); 149 fcn = str2func (fcn, "global");
150 elseif (iscell (fcn)) 150 elseif (iscell (fcn))
151 fcn = @(x) make_fcn_jac (x, fcn{1}, fcn{2}); 151 fcn = @(x) make_fcn_jac (x, fcn{1}, fcn{2});
373 endif 373 endif
374 endif 374 endif
375 375
376 ## Tests for termination conditions. A mysterious place, anything 376 ## Tests for termination conditions. A mysterious place, anything
377 ## can happen if you change something here... 377 ## can happen if you change something here...
378 378
379 ## The rule of thumb (which I'm not sure M*b is quite following) 379 ## The rule of thumb (which I'm not sure M*b is quite following)
380 ## is that for a tolerance that depends on scaling, only 0 makes 380 ## is that for a tolerance that depends on scaling, only 0 makes
381 ## sense as a default value. But 0 usually means uselessly long 381 ## sense as a default value. But 0 usually means uselessly long
382 ## iterations, so we need scaling-independent tolerances wherever 382 ## iterations, so we need scaling-independent tolerances wherever
383 ## possible. 383 ## possible.
406 break; 406 break;
407 endif 407 endif
408 408
409 ## Compute the scaled Broyden update. 409 ## Compute the scaled Broyden update.
410 if (useqr) 410 if (useqr)
411 u = (fvec1 - q*w) / sn; 411 u = (fvec1 - q*w) / sn;
412 v = dg .* ((dg .* s) / sn); 412 v = dg .* ((dg .* s) / sn);
413 413
414 ## Update the QR factorization. 414 ## Update the QR factorization.
415 [q, r] = qrupdate (q, r, u, v); 415 [q, r] = qrupdate (q, r, u, v);
416 else 416 else
442 fx = fun (x); 442 fx = fun (x);
443 jx = []; 443 jx = [];
444 endif 444 endif
445 445
446 if (! complexeqn && ! (isreal (fx) && isreal (jx))) 446 if (! complexeqn && ! (isreal (fx) && isreal (jx)))
447 error ("fsolve:notreal", "fsolve: non-real value encountered"); 447 error ("fsolve:notreal", "fsolve: non-real value encountered");
448 elseif (complexeqn && ! (isnumeric (fx) && isnumeric(jx))) 448 elseif (complexeqn && ! (isnumeric (fx) && isnumeric(jx)))
449 error ("fsolve:notnum", "fsolve: non-numeric value encountered"); 449 error ("fsolve:notnum", "fsolve: non-numeric value encountered");
450 elseif (any (isnan (fx(:)))) 450 elseif (any (isnan (fx(:))))
451 error ("fsolve:isnan", "fsolve: NaN value encountered"); 451 error ("fsolve:isnan", "fsolve: NaN value encountered");
452 endif 452 endif
453 endfunction 453 endfunction
454 454
455 function [fx, jx] = make_fcn_jac (x, fcn, fjac) 455 function [fx, jx] = make_fcn_jac (x, fcn, fjac)
456 fx = fcn (x); 456 fx = fcn (x);
457 if (nargout == 2) 457 if (nargout == 2)
458 jx = fjac (x); 458 jx = fjac (x);
459 endif 459 endif
460 endfunction 460 endfunction
461 461
462 %!function retval = f (p) 462 %!function retval = f (p)
463 %! x = p(1); 463 %! x = p(1);
464 %! y = p(2); 464 %! y = p(2);
465 %! z = p(3); 465 %! z = p(3);
466 %! retval = zeros (3, 1); 466 %! retval = zeros (3, 1);
467 %! retval(1) = sin(x) + y**2 + log(z) - 7; 467 %! retval(1) = sin(x) + y**2 + log(z) - 7;
493 %! [x, fval, info] = fsolve (@f, [-1, 1, 2, -1]); 493 %! [x, fval, info] = fsolve (@f, [-1, 1, 2, -1]);
494 %! assert (info > 0); 494 %! assert (info > 0);
495 %! assert (norm (x - x_opt, Inf) < tol); 495 %! assert (norm (x - x_opt, Inf) < tol);
496 %! assert (norm (fval) < tol); 496 %! assert (norm (fval) < tol);
497 497
498 %!function retval = f (p) 498 %!function retval = f (p)
499 %! x = p(1); 499 %! x = p(1);
500 %! y = p(2); 500 %! y = p(2);
501 %! z = p(3); 501 %! z = p(3);
502 %! retval = zeros (3, 1); 502 %! retval = zeros (3, 1);
503 %! retval(1) = sin(x) + y**2 + log(z) - 7; 503 %! retval(1) = sin(x) + y**2 + log(z) - 7;
512 %! [x, fval, info] = fsolve (@f, [ 0.5; 2.0; 2.5 ]); 512 %! [x, fval, info] = fsolve (@f, [ 0.5; 2.0; 2.5 ]);
513 %! assert (info > 0); 513 %! assert (info > 0);
514 %! assert (norm (x - x_opt, Inf) < tol); 514 %! assert (norm (x - x_opt, Inf) < tol);
515 %! assert (norm (fval) < tol); 515 %! assert (norm (fval) < tol);
516 516
517 %!function retval = f (p) 517 %!function retval = f (p)
518 %! x = p(1); 518 %! x = p(1);
519 %! y = p(2); 519 %! y = p(2);
520 %! z = p(3); 520 %! z = p(3);
521 %! retval = zeros (3, 1); 521 %! retval = zeros (3, 1);
522 %! retval(1) = sin(x) + y**2 + log(z) - 7; 522 %! retval(1) = sin(x) + y**2 + log(z) - 7;
539 %! x = 0:.5:5; 539 %! x = 0:.5:5;
540 %! noise = 1e-5 * sin (100*x); 540 %! noise = 1e-5 * sin (100*x);
541 %! y = exp (-a0*x) + b0 + noise; 541 %! y = exp (-a0*x) + b0 + noise;
542 %! c_opt = [a0, b0]; 542 %! c_opt = [a0, b0];
543 %! tol = 1e-5; 543 %! tol = 1e-5;
544 %! 544 %!
545 %! [c, fval, info, output] = fsolve (@(c) (exp(-c(1)*x) + c(2) - y), [0, 0]); 545 %! [c, fval, info, output] = fsolve (@(c) (exp(-c(1)*x) + c(2) - y), [0, 0]);
546 %! assert (info > 0); 546 %! assert (info > 0);
547 %! assert (norm (c - c_opt, Inf) < tol); 547 %! assert (norm (c - c_opt, Inf) < tol);
548 %! assert (norm (fval) < norm (noise)); 548 %! assert (norm (fval) < norm (noise));
549 549
554 %! y(3) = x(1) * x(2) - x(3)^2 + (3+2i); 554 %! y(3) = x(1) * x(2) - x(3)^2 + (3+2i);
555 555
556 %!test 556 %!test
557 %! x_opt = [-1+i, 1-i, 2+i]; 557 %! x_opt = [-1+i, 1-i, 2+i];
558 %! x = [i, 1, 1+i]; 558 %! x = [i, 1, 1+i];
559 %! 559 %!
560 %! [x, f, info] = fsolve (@cfun, x, optimset ("ComplexEqn", "on")); 560 %! [x, f, info] = fsolve (@cfun, x, optimset ("ComplexEqn", "on"));
561 %! tol = 1e-5; 561 %! tol = 1e-5;
562 %! assert (norm (f) < tol); 562 %! assert (norm (f) < tol);
563 %! assert (norm (x - x_opt, Inf) < tol); 563 %! assert (norm (x - x_opt, Inf) < tol);
564 564