MATLAB Answers

Using a tolerance in X with fzero function (by default the tolerance is evaluated on Y axis).

최근 활동 John D'Errico 님이 편집함. 19 Oct 2019
Good morning,
I've been wondering how to modify the fzero function so that it evaluates tolerance in X instead of in Y.
Thank you for your help.

  댓글 수: 0

로그인 to comment.

답변 수: 2

Walter Roberson 님의 답변 19 Oct 2019

There is no mathematical way for fzero to be able to reliably detect that.
You are asking that if you are currently at position x and f(x) is not within tolerance of 0, but that somewhere within the range x+-delta f(x) = 0, then without figuring out where in that x-delta to x+delta range the root is, you want to stop.
Now, in some cases it might be possible to make that projection. However consider for example f(x) = exp(100000*x) - c . A mathematical solution might exist, but numerically this is very sensitive and small changes in x can lead to big changes in the value of the function. It is unlikely that you can reliably predict that a zero exists within the range without trying the endpoints of the range.
Perhaps what you want is the TolX option of fzero:
"Termination tolerance on x, a positive scalar. The default is eps, 2.2204e–16."

  댓글 수: 2

Thank you for answering.
Since tolerance is evaluated by default in Y, is there any way to just modify the value of TolY?. I thought TolFun would do the trick, but it does not work with fzero.
I have the same problem with the maximum number of iterations. I do
optnew= optimset('MaxIter', 10);
r=fzero(f,1,optnew)
but the algorithm doesn't stop when reaching that number of iterations.
https://www.mathworks.com/help/matlab/ref/fzero.html#btoc6lj-6
fzero ignores most options.
Generally speaking, fsolve is more flexible. However fsolve requires the optimization toolbox.

로그인 to comment.


John D'Errico 님의 답변 19 Oct 2019
John D'Errico 님이 편집함. 19 Oct 2019

Actually, if you check the docs for fzero, you will find it uses exactly 5 of the possible options properties - Display, FunValCheck, OutputFcn, PlotFcns, and TolX.
There is no use of TolFun at all, and only one of them concerns any kind of stopping criterion. It is also true that MaxIter is ignored.
My point however, is that in fact, fzero does look ONLY at x. It does not look at y, except to check there is a zero crossing in the interval of interest, and once it has a bracket around a root, to maintain a bracket around that zero crossing. That is, you are incorrect that the default is to evaluate the tolerance on the y axis. The only tolerance is on the x location.
Since the TolX behavior seems to be exactly what you are looking for, I'm not sure what to say.
Note that most functions will be fairly well behaved in one dimension. So as long as your objective is reasonably smooth, then fzero should exhibit quadratic convergence. So by the time fzero is confidant that it has converged to within the tolerance in X, it may have indeed converged to full double precision accuracy. However, it does use a protected algorithm, so if it perceives there is a problem, then it can essentially back off, giving it the behavior of bisection in the worst case. The above behavior is why I would in general recommend use of fzero to other codes like fsolve when used for one variable problems. At the same time, fsolve also offers some virtues. It allows various stopping criteria, and it is extensible to higher dimensional problems, and it is not so interested in having a bracket around a root, which fzero loves. But fsolve can be less robust than fzero, which is important.
You can see the behavior of fzero here:
>> fun = @(x) exp(x) - 2;
>> opts = optimset('fzero');
>> opts.TolX = 1.e-3;
>> opts.Display = 'iter';
>> [x0,fval,exitflag] = fzero(fun,[0,5],opts)
Func-count x f(x) Procedure
2 0 -1 initial
3 0.0339183 -0.9655 interpolation
4 0.976918 0.656258 interpolation
5 0.595325 -0.186379 interpolation
6 0.679728 -0.0266587 interpolation
7 0.693266 0.000237303 interpolation
8 0.693266 0.000237303 interpolation
Zero found in the interval [0, 5]
x0 =
0.69326582479805
fval =
0.000237302553222296
exitflag =
1
>> abs(x0 - log(2))
ans =
0.000118644238105148
So it did stop after 8 iterations, with an error close to the requested tolerance. But if I push the tolerance close enough to zero, the quadratic convergence takes over, now taking only 2 more iterations to give essentially full double precision accuracy.
>> opts.TolX = 1.e-12;
>> [x0,fval,exitflag] = fzero(fun,[0,5],opts)
Func-count x f(x) Procedure
2 0 -1 initial
3 0.0339183 -0.9655 interpolation
4 0.976918 0.656258 interpolation
5 0.595325 -0.186379 interpolation
6 0.679728 -0.0266587 interpolation
7 0.693266 0.000237303 interpolation
8 0.693146 -1.59561e-06 interpolation
9 0.693147 -9.46532e-11 interpolation
10 0.693147 0 interpolation
Zero found in the interval [0, 5]
x0 =
0.693147180559945
fval =
0
exitflag =
1
>> abs(x0 - log(2))
ans =
0

  댓글 수: 0

로그인 to comment.



Translated by