Interpreting the results of 'fsolve'

26 views (last 30 days)
Hi,
I have a system of 11 nonlinear equations to solve for 11 unknowns. I use the 'fsolve' function with the following code:
% Solve for equilibrium
clear all
zg = [0.08;0.001;0.3;0.3;0.2;0.2;1.0;0.5;2.0;25.0;8.0];
options=optimset('TolFun' , 1e-5,'Display','iter', 'TolX' , 1e-5, 'MaxFunEvals' , 1e+15, 'MaxIter' , 1e+15);
[z,fval] = fsolve(@FUN,zg,options);
function fval=FUN(z)
cm = min(z(1),0);
.
.
.
fval(1) = cm - (((ps*c_bar) + ((beta*Nm)/(1-beta))...;
.
.
.
When I run the code, I get the following:
"Equation solved, inaccuracy possible.
The vector of function values is near zero, as measured by the value
of the function tolerance. However, the last step was ineffective.
fsolve stopped because the sum of squared function values, r, changed by 9.999919e-11
relative to its initial value; this is less than max(options.FunctionTolerance^2,eps) = 1.000000e-10.
r = 1.777152e-04, is less than sqrt(options.FunctionTolerance) = 3.162278e-03."
The final row of my options shows the following information:
Iteration: 330969
Func-count: 3971629
f(x): 0.000177715
Norm of step: 2.17841e-08
First-order optimality: 0.0101
Trust region: 0.562
What does this mean? Does it mean that the vector of residuals has fallen below the tolerance level? If not, how can I change this? Can I trust the variable solutions that is computed for me?
Thank you!

Accepted Answer

Torsten
Torsten on 25 May 2023
Moved: Torsten on 25 May 2023
Can I trust the variable solutions that is computed for me?
An error norm of 0.000177715 is not bad, but "fsolve" couldn't do better near the point it converged to. So doubts remain whether "fsolve" converged towards a root of your system of equations.
Don't interprete too much in what is written out by "fsolve", but trust in your physical intuition whether the results make sense. Even if "fsolve" had written out the message that a solution has been found, you still had to judge whether this solution is "correct" in the sense that it's physical.
And try to avoid such settings
cm = min(z(1),0);
that make your functions non-differentiable with respect to z(1). Use
cm = -z(1)^2
, e.g. instead.
  3 Comments
Matt J
Matt J on 25 May 2023
It didn't give you cm=0.08. It gave you z(1)=0.08 because that was the value of your initial point zg(1) and there is no gradient at zg(1)=0.08 to help the solver know how to adjust it.
Torsten
Torsten on 25 May 2023
In principle, you start with an infeasible value for z(1) because according to your setting
cm = min(z(1),0);
z(1) should be negative to make sense in your computation.

Sign in to comment.

More Answers (2)

Walter Roberson
Walter Roberson on 25 May 2023
You are trying to solve multiple equations simultaneously. fsolve() has found a location that is looking pretty good, but fsolve() cannot tell the difference between three cases:
  1. the case where all of the functions can indeed be solved simultaneously somewhere very close to the current location, but due to round-off error or nonlinearity, fsolve() cannot figure out exactly where before it hit the tolerances that tell it to give up on the task. In such a case reducing the tolerances might help you pin down the locations more precisely.. but honestly in such a situation it often does not matter since you probably won't get exact zeros out of all the functions simultaneously anyhow just due to round-off problems
  2. the case where at least one of the functions only approaches close to zero but has no true root. For example (x-pi)^2 + 1e-14 has no true root. In such a case, reducing the tolerance might potentially allow fsolve() to detect a false root, maybe. If it detected false root in this case it would probably give up but with a different exit code. When fsolve() gets this close to thinking it has a solution, it probably isn't going to recover to find a true solution (I wouldn't say impossible, if a true solution were quite close to a false solution.) (Functions with asymptopes at zero might have no true root.)
  3. the case where there just are not simultaneous solutions but two almost-solutions are close together. x(5) being one value might be needed to solve equation #7, but x(5) being 1e-12 higher might be needed to solve equation #10 . Decreasing the tolerance might potentially allow fsolve() to detect that it is a false solution. In such a situation, recovery to find a true solution is unlikely.
  2 Comments
Selim Elbadri
Selim Elbadri on 25 May 2023
Thank you for your response!
How is the message I got above different from the message below:
Equation solved, solver stalled.
fsolve stopped because the relative size of the current step is less than the
value of the step size tolerance squared and the vector of function values
is near zero as measured by the value of the function tolerance.
fsolve stopped because the relative norm of the current step, 9.115249e-11, is less than
max(options.StepTolerance^2,eps) = 1.000000e-10. The sum of squared function values,
r = 5.901040e-08, is less than sqrt(options.FunctionTolerance) = 3.162278e-03.
Walter Roberson
Walter Roberson on 25 May 2023
In this newer message, the step size was actively being reduced when the solver gave up, but the step size reached the configured lower limit.
In the original message, the step size had not yet reached its limit, but the change in function value was small enough that the solver gave up.

Sign in to comment.


Matt J
Matt J on 25 May 2023
Edited: Matt J on 25 May 2023
It means fsolve thinks it found a solution. Whether you can "trust" the solution is an open-ended question. It depends on the appropriateness of your tolerance settings and whether your initial guess was sufficiently close to the global solution.

Tags

Community Treasure Hunt

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

Start Hunting!