Termination tolerance with fzero function
4 views (last 30 days)
Show older comments
I have a problem while using fzero function when there is termination tolerance value, but not initial guess. For example, my formula is K = x/(1-x)*sqrt(2*pt/(2+x)), and I convert as [x,fval]=fzero(@(x) x/(1-x)*sqrt(2*pt/(2+x)-K), but how can I determine the termination tolerance by using this? Should I indicate with optimset? If I use options=optimset('Display', 'final'), than can I put the value directly in fzero function? Thanks.
2 Comments
Torsten
on 5 Mar 2022
First try to make the code run - then change settings, if necessary.
You will have to change the call to fzero from
[x,fval]=fzero(@(x) x/(1-x)*sqrt(2*pt/(2+x)-K),x0)
to
[x,fval]=fzero(@(x) x/(1-x)*sqrt(2*pt/(2+x))-K,x0)
Answers (1)
John D'Errico
on 5 Mar 2022
Edited: John D'Errico
on 5 Mar 2022
As Torsten suggests, you cannot use fzero with no initial guess. In fact, fzero runs better with a bracket, than just a single guess. Since we don't know the value of pt, I cannot give a better example, so I'll pretend that pt has the value 17. Next, I'll point out that your code was missing a final closing parens from the sqrt.
Anyway, the first thing to do is to plot this, here as a surface function of both x and K. That will help you t ounderstand the issues.
pt = 17;
fun = @(x,K) x./(1-x).*sqrt(2*pt./(2+x))-K;
fsurf(fun)
xlabel x
ylabel K
There we should recognize that you function has a singularity at x=1, and that for x above 1, your function rises from -infinity towards zero.
But be careful, since when x is less than -2, we will have a complex result. So that plot was not truly acccurate. fplot plotted the real part only.
So, depending on the value of K, the solution of interest may lie above or below x==1. I've told fcontour to go only down as far as -2 in x.
H = fcontour(fun,[-2,10, -10,10]);
grid on
xlabel x
ylabel K
H.LevelList = 0;
Do you see that depending on the value of K here, your solution must lie along one of the blue curves in this plot? And for some values of K, there will be two solutions? (Ignore the vertical blue line, as that is where the singularity occurs. It is not really a true solution.)
The problem is, fzero will not know where to look, unless you explicitly tell it in which of those two half spaces to search in.
Note that all of this is completely independent from your question, which is about how to apply a tolerance on the solution. We can learn that by READING THE HELP FOR FZERO.
help fzero
If you scroll down in the help for fzero, you will see that the third argument for fzero are the options.
opts = optimset('fzero')
The only arguments that fzero will look at are are the 'Display', 'TolX', and 'FunValCheck', 'PlotFcns', and 'OutputFcn' options.
So now we can run fzero. I'll pass in the options struct I just created, so you can see how to use it.
Remember, that from the plot, when k is roughly above -2, the only root lies in the OPEN interval (-2,1)
pt = 17;
K = 2;
f = @(x) x./(1-x).*sqrt(2*pt./(2+x))-K;
[xval,fval,exitflag] = fzero(f,[-2+eps(2),1-eps],opts)
However, for negative values of K, roughly below -2, there will be two real solutions. We can find either of them, depending on which one we want.
K = -3;
f = @(x) x./(1-x).*sqrt(2*pt./(2+x))-K;
[xval,fval,exitflag] = fzero(f,[-2+eps(2),1-eps],opts) % the lower solution
[xval,fval,exitflag] = fzero(f,[1+eps,1e6],opts) % the upper solution
In any of those calls, I could have set the final tolerance on x by setting the value of opts.TolX to some other value.
But more importantly, you needed to specify the region of interest. And be careful! For example, suppose, with K == 2, I started fzero in the wrong place?
K = 2;
f = @(x) x./(1-x).*sqrt(2*pt./(2+x))-K;
[xval,fval,exitflag] = fzero(f,2,opts) % OOPS!
fzero failed to find the solution at 0.3443... here. Why? It got lost at the singularity at x=1.
0 Comments
See Also
Categories
Find more on Optimization in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
