# NonlinearSolve Falsi algorithm: Unexpected ReturnCode

I’m observing unexpected behavior in `SimpleNonlinearSolve`/`NonlinearSolve`’s algorithm `Falsi` (an algorithm for finding roots of nonlinear functions). I expect `Falsi` to return a successful return code if it converged, and an unsuccessful one if it couldn’t.

Here is a MWE that contradicts this behavior: For f(x) = 1, `Falsi` shouldn’t be able to converge, and for f(x) = x, `Falsi` should converge with result x=0. Here, exactly the opposite happens:

``````using SimpleNonlinearSolve, SciMLBase.ReturnCode
np1 = IntervalNonlinearProblem((x, p) -> 1., (0., 1.))
sol1 = solve(np1, Falsi(); abstol=1e-10)
SciMLBase.successful_retcode(sol1)  # returns true (FloatingPointLimit)
np2 = IntervalNonlinearProblem((x, p) -> x, (-1., 1.))
sol2 = solve(np2, Falsi(); abstol=1e-10)
SciMLBase.successful_retcode(sol2)  # returns false (MaxIters)
``````

Executed using `SciMLBase` v1.94.0 and `SimpleNonlinearSolve` v0.1.18.

Is there something I’m missing/misusing here? I guess I could check for `sign(sol.left) == sign(sol.right)` as a workaround to see if a root could be found.

Falsi is not always numerically stable. We are switching the defaults and recommendations towards ITP which should just be better.

``````using SimpleNonlinearSolve, SciMLBase.ReturnCode
np1 = IntervalNonlinearProblem((x, p) -> 1., (0., 1.))
sol1 = solve(np1, ITP(); abstol=1e-10)
SciMLBase.successful_retcode(sol1)  # returns true (FloatingPointLimit)
``````

ITP mixes bisection and falsi to have the guarantees of Bisection but with the speedup potential of Falsi. See:

The docs haven’t updated with all of this yet, but I hope it does soon because it’ll be the best choice for almost all situations.

I think there’s still a bug here. Falsi should converge in 1 step for linear equations.

1 Like