Termination tolerance with fzero function

4 views (last 30 days)
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
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)

Sign in to comment.

Answers (1)

John D'Errico
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
FZERO Single-variable nonlinear zero finding. X = FZERO(FUN,X0) tries to find a zero of the function FUN near X0, if X0 is a scalar. It first finds an interval containing X0 where the function values of the interval endpoints differ in sign, then searches that interval for a zero. FUN is a function handle. FUN accepts real scalar input X and returns a real scalar function value F, evaluated at X. The value X returned by FZERO is near a point where FUN changes sign (if FUN is continuous), or NaN if the search fails. X = FZERO(FUN,X0), where X0 is a vector of length 2, assumes X0 is a finite interval where the sign of FUN(X0(1)) differs from the sign of FUN(X0(2)). An error occurs if this is not true. Calling FZERO with a finite interval guarantees FZERO will return a value near a point where FUN changes sign. X = FZERO(FUN,X0), where X0 is a scalar value, uses X0 as a starting guess. FZERO looks for an interval containing a sign change for FUN and containing X0. If no such interval is found, NaN is returned. In this case, the search terminates when the search interval is expanded until an Inf, NaN, or complex value is found. Note: if the option FunValCheck is 'on', then an error will occur if an NaN or complex value is found. X = FZERO(FUN,X0,OPTIONS) solves the equation with the default optimization parameters replaced by values in the structure OPTIONS, an argument created with the OPTIMSET function. See OPTIMSET for details. Used options are Display, TolX, FunValCheck, OutputFcn, and PlotFcns. X = FZERO(PROBLEM) finds the zero of a function defined in PROBLEM. PROBLEM is a structure with the function FUN in PROBLEM.objective, the start point in PROBLEM.x0, the options structure in PROBLEM.options, and solver name 'fzero' in PROBLEM.solver. [X,FVAL]= FZERO(FUN,...) returns the value of the function described in FUN, at X. [X,FVAL,EXITFLAG] = FZERO(...) returns an EXITFLAG that describes the exit condition. Possible values of EXITFLAG and the corresponding exit conditions are 1 FZERO found a zero X. -1 Algorithm terminated by output function. -3 NaN or Inf function value encountered during search for an interval containing a sign change. -4 Complex function value encountered during search for an interval containing a sign change. -5 FZERO may have converged to a singular point. -6 FZERO can not detect a change in sign of the function. [X,FVAL,EXITFLAG,OUTPUT] = FZERO(...) returns a structure OUTPUT with the number of function evaluations in OUTPUT.funcCount, the algorithm name in OUTPUT.algorithm, the number of iterations to find an interval (if needed) in OUTPUT.intervaliterations, the number of zero-finding iterations in OUTPUT.iterations, and the exit message in OUTPUT.message. Examples FUN can be specified using @: X = fzero(@sin,3) returns pi. X = fzero(@sin,3,optimset('Display','iter')) returns pi, uses the default tolerance and displays iteration information. FUN can be an anonymous function: X = fzero(@(x) sin(3*x),2) FUN can be a parameterized function. Use an anonymous function to capture the problem-dependent parameters: myfun = @(x,c) cos(c*x); % The parameterized function. c = 2; % The parameter. X = fzero(@(x) myfun(x,c),0.1) Limitations X = fzero(@(x) abs(x)+1, 1) returns NaN since this function does not change sign anywhere on the real axis (and does not have a zero as well). X = fzero(@tan,2) returns X near 1.5708 because the discontinuity of this function near the point X gives the appearance (numerically) that the function changes sign at X. See also ROOTS, FMINBND, FUNCTION_HANDLE. Documentation for fzero doc 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')
opts = struct with fields:
Display: 'notify' MaxFunEvals: [] MaxIter: [] TolFun: [] TolX: 2.2204e-16 FunValCheck: 'off' OutputFcn: [] PlotFcns: [] ActiveConstrTol: [] Algorithm: [] AlwaysHonorConstraints: [] DerivativeCheck: [] Diagnostics: [] DiffMaxChange: [] DiffMinChange: [] FinDiffRelStep: [] FinDiffType: [] GoalsExactAchieve: [] GradConstr: [] GradObj: [] HessFcn: [] Hessian: [] HessMult: [] HessPattern: [] HessUpdate: [] InitBarrierParam: [] InitTrustRegionRadius: [] Jacobian: [] JacobMult: [] JacobPattern: [] LargeScale: [] MaxNodes: [] MaxPCGIter: [] MaxProjCGIter: [] MaxSQPIter: [] MaxTime: [] MeritFunction: [] MinAbsMax: [] NoStopIfFlatInfeas: [] ObjectiveLimit: [] PhaseOneTotalScaling: [] Preconditioner: [] PrecondBandWidth: [] RelLineSrchBnd: [] RelLineSrchBndDuration: [] ScaleProblem: [] SubproblemAlgorithm: [] TolCon: [] TolConSQP: [] TolGradCon: [] TolPCG: [] TolProjCG: [] TolProjCGAbs: [] TypicalX: [] UseParallel: []
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)
xval = 0.3443
fval = -6.6613e-16
exitflag = 1
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 = -1.0287
fval = 0
exitflag = 1
[xval,fval,exitflag] = fzero(f,[1+eps,1e6],opts) % the upper solution
xval = 4.3606
fval = 0
exitflag = 1
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!
xval = 1.0000
fval = -5.0538e+15
exitflag = -5
fzero failed to find the solution at 0.3443... here. Why? It got lost at the singularity at x=1.

Categories

Find more on Optimization in Help Center and File Exchange

Products


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!