Consider this a PSA about an important breakign change that NLsolve 3.0.0 ships with.
Upon running METADATA’s CIBot we found out that the breaking change in NLsolve 3.0.0 did indeed cause some robotics packages to fail, so please verify in your private code that you are not using NLsolve in a way that will break before updating.
So what is the breaking change?
The breaking change is one that has been asked for be many users, and relates to the discussion around mutation of the residual vector of the system you’re solving with nlsolve
(or the convenience function fixedpoint
for fixedpoints). Consider the following
using NLsolve
julia> f(F, x) = copyto!(F, (log(x[1]), log(x[2])+1.0)
f (generic function with 1 method)
julia> nlsolve(f, [1.5, 0.5])
Results of Nonlinear Solver Algorithm
* Algorithm: Trust-region with dogleg and autoscaling
* Starting Point: [1.5, 0.5]
* Zero: [1.0, 0.367879]
* Inf-norm of residuals: 0.000000
* Iterations: 4
* Convergence: true
* |x - x'| < 0.0e+00: false
* |f(x)| < 1.0e-08: true
* Function Calls (f): 5
* Jacobian Calls (df/dx): 5
(phew, it worked)
Some users, in some circumstances, find the mutating interface annoying. It’s mainly there for performance issues, but what if your calculations inside the function outweigh such considerations on the solver side and you think it makes for ugly code? You’d rather write
f(x) = log.(x) .+ [0.0, 1.0]
nlsolve(f, [1.5, 0.5])
With NLsolve you can, as we’ll try to detect if a method is available of f
that accepts the x0
guess passed to nlsolve
. Consider the following (notice I changed the shift to be negative)
julia> f(x) = log.(x) .- [0.0, 1.0]
f (generic function with 2 methods)
julia> nlsolve(f, [1.5, 0.5])
Results of Nonlinear Solver Algorithm
* Algorithm: Trust-region with dogleg and autoscaling
* Starting Point: [1.5, 0.5]
* Zero: [1.0, 2.71828]
* Inf-norm of residuals: 0.000000
* Iterations: 6
* Convergence: true
* |x - x'| < 0.0e+00: false
* |f(x)| < 1.0e-08: true
* Function Calls (f): 7
* Jacobian Calls (df/dx): 7
Before, this would require the user to have written
nlsolve(f, x0; inplace = false)
This automatic detection does come at a small price. If you have both inplace and outofplace versions of f
(so two methods of f
), you now have to opt-in for the mutating method to be used (remember that had a shift of +1 to the second element)
julia> nlsolve(f, [1.5, 0.5]; inplace=true)
Results of Nonlinear Solver Algorithm
* Algorithm: Trust-region with dogleg and autoscaling
* Starting Point: [1.5, 0.5]
* Zero: [1.0, 0.367879]
* Inf-norm of residuals: 0.000000
* Iterations: 4
* Convergence: true
* |x - x'| < 0.0e+00: false
* |f(x)| < 1.0e-08: true
* Function Calls (f): 5
* Jacobian Calls (df/dx): 5
Of course, in most cases this can be avoided by following the f!
convention often used in Julia.
Happy solving and remember to give a star if you use and like NLsolve!
pkofod