Skip to content

Commit 6b58f42

Browse files
committed
Pull in MINPACK
1 parent a0788dd commit 6b58f42

18 files changed

+439
-59
lines changed

Project.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@ UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
3333
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
3434
FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce"
3535
LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891"
36+
MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9"
37+
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
3638
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3739

3840
[extensions]
3941
NonlinearSolveBandedMatricesExt = "BandedMatrices"
4042
NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt"
4143
NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim"
44+
NonlinearSolveMINPACKExt = "MINPACK"
45+
NonlinearSolveNLsolveExt = "NLsolve"
4246
NonlinearSolveZygoteExt = "Zygote"
4347

4448
[compat]
@@ -60,7 +64,9 @@ LeastSquaresOptim = "0.8"
6064
LineSearches = "7"
6165
LinearAlgebra = "<0.0.1, 1"
6266
LinearSolve = "2.12"
67+
MINPACK = "1.2"
6368
MaybeInplace = "0.1"
69+
NLsolve = "4.5"
6470
NaNMath = "1"
6571
NonlinearProblemLibrary = "0.1"
6672
Pkg = "1"
@@ -94,17 +100,19 @@ ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
94100
LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891"
95101
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
96102
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
103+
MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9"
104+
NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
97105
NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
98106
NonlinearProblemLibrary = "b7050fa9-e91f-4b37-bcee-a89a063da141"
99107
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
100108
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
101109
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
102-
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
103110
SparseDiffTools = "47a9eef4-7e08-11e9-0b38-333d64bd3804"
111+
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
104112
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
105113
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
106114
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
107115
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
108116

109117
[targets]
110-
test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs"]
118+
test = ["Aqua", "Enzyme", "BenchmarkTools", "SafeTestsets", "Pkg", "Test", "ForwardDiff", "StaticArrays", "Symbolics", "LinearSolve", "Random", "LinearAlgebra", "Zygote", "SparseDiffTools", "NonlinearProblemLibrary", "LeastSquaresOptim", "FastLevenbergMarquardt", "NaNMath", "BandedMatrices", "DiffEqBase", "StableRNGs", "MINPACK", "NLsolve"]

docs/Project.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@ IncompleteLU = "40713840-3770-5561-ab4c-a76e7d0d7895"
88
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
99
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
1010
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
11-
NonlinearSolveMINPACK = "c100e077-885d-495a-a2ea-599e143bf69d"
1211
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1312
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
14-
SciMLNLSolve = "e9a6253c-8580-4d32-9898-8661bb511710"
1513
SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7"
1614
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1715
SteadyStateDiffEq = "9672c7b4-1e72-59bd-8a11-6ac3964bc41f"
@@ -31,7 +29,6 @@ NonlinearSolve = "3"
3129
NonlinearSolveMINPACK = "0.1"
3230
Random = "<0.0.1, 1"
3331
SciMLBase = "2.4"
34-
SciMLNLSolve = "0.1"
3532
SimpleNonlinearSolve = "1"
3633
StaticArrays = "1"
3734
SteadyStateDiffEq = "2"

docs/make.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using Documenter, NonlinearSolve, SimpleNonlinearSolve, Sundials, SciMLNLSolve,
2-
NonlinearSolveMINPACK, SteadyStateDiffEq, SciMLBase, DiffEqBase
1+
using Documenter,
2+
NonlinearSolve, SimpleNonlinearSolve, Sundials,
3+
SteadyStateDiffEq, SciMLBase, DiffEqBase
34

45
cp("./docs/Manifest.toml", "./docs/src/assets/Manifest.toml", force = true)
56
cp("./docs/Project.toml", "./docs/src/assets/Project.toml", force = true)
@@ -9,7 +10,7 @@ include("pages.jl")
910
makedocs(sitename = "NonlinearSolve.jl",
1011
authors = "Chris Rackauckas",
1112
modules = [NonlinearSolve, SciMLBase, DiffEqBase, SimpleNonlinearSolve, Sundials,
12-
SciMLNLSolve, NonlinearSolveMINPACK, SteadyStateDiffEq],
13+
SteadyStateDiffEq],
1314
clean = true, doctest = false, linkcheck = true,
1415
linkcheck_ignore = ["https://twitter.com/ChrisRackauckas/status/1544743542094020615"],
1516
warnonly = [:missing_docs, :cross_references],

docs/src/api/fastlevenbergmarquardt.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
# FastLevenbergMarquardt.jl
22

3-
This is a wrapper package for importing solvers from FastLevenbergMarquardt.jl into the
4-
SciML interface. Note that these solvers do not come by default, and thus one needs to
5-
install the package before using these solvers:
3+
This is a extension for importing solvers from FastLevenbergMarquardt.jl into the SciML
4+
interface. Note that these solvers do not come by default, and thus one needs to install
5+
the package before using these solvers:
66

77
```julia
88
using Pkg
99
Pkg.add("FastLevenbergMarquardt")
10-
using FastLevenbergMarquardt
10+
using FastLevenbergMarquardt, NonlinearSolve
1111
```
1212

13-
These methods can be used independently of the rest of NonlinearSolve.jl
14-
1513
## Solver API
1614

1715
```@docs

docs/src/api/leastsquaresoptim.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
# LeastSquaresOptim.jl
22

3-
This is a wrapper package for importing solvers from LeastSquaresOptim.jl into the SciML
3+
This is a extension for importing solvers from LeastSquaresOptim.jl into the SciML
44
interface. Note that these solvers do not come by default, and thus one needs to install
55
the package before using these solvers:
66

77
```julia
88
using Pkg
99
Pkg.add("LeastSquaresOptim")
10-
using LeastSquaresOptim
10+
using LeastSquaresOptim, NonlinearSolve
1111
```
1212

13-
These methods can be used independently of the rest of NonlinearSolve.jl
14-
1513
## Solver API
1614

1715
```@docs

docs/src/api/minpack.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
# MINPACK.jl
22

3-
This is a wrapper package for importing solvers from Sundials into the SciML interface.
4-
Note that these solvers do not come by default, and thus one needs to install the package
5-
before using these solvers:
3+
This is a extension for importing solvers from MINPACK into the SciML interface. Note that
4+
these solvers do not come by default, and thus one needs to install the package before using
5+
these solvers:
66

77
```julia
88
using Pkg
9-
Pkg.add("NonlinearSolveMINPACK")
10-
using NonlinearSolveMINPACK
9+
Pkg.add("MINPACK")
10+
using MINPACK, NonlinearSolve
1111
```
1212

13-
These methods can be used independently of the rest of NonlinearSolve.jl
14-
1513
## Solver API
1614

1715
```@docs

docs/src/api/nlsolve.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# NLsolve.jl
22

3-
This is a wrapper package for importing solvers from NLsolve.jl into the SciML interface.
4-
Note that these solvers do not come by default, and thus one needs to install the package
5-
before using these solvers:
3+
This is a extension for importing solvers from NLsolve.jl into the SciML interface. Note
4+
that these solvers do not come by default, and thus one needs to install the package before
5+
using these solvers:
66

77
```julia
88
using Pkg
9-
Pkg.add("SciMLNLSolve")
10-
using SciMLNLSolve
9+
Pkg.add("NLsolve")
10+
using NLSolve, NonlinearSolve
1111
```
1212

1313
## Solver API

docs/src/solvers/NonlinearLeastSquaresSolvers.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ And the choices for `linsolve` are:
5858
- `:cholesky`
5959
- `:lsmr` a conjugate gradient method (LSMR with diagonal preconditioner).
6060

61+
### MINPACK.jl
62+
63+
MINPACK.jl methods are fine for medium-sized nonlinear solves. They are the FORTRAN
64+
standard methods which are used in many places, such as SciPy. However, our benchmarks
65+
demonstrate that these methods are not robust or stable. In addition, they are slower
66+
than the standard methods and do not scale due to lack of sparse Jacobian support.
67+
Thus they are only recommended for benchmarking and testing code conversions.
68+
69+
- `CMINPACK()`: A wrapper for using the classic MINPACK method through [MINPACK.jl](https://github.com/sglyon/MINPACK.jl)
70+
71+
Submethod choices for this algorithm include:
72+
73+
- `:hybr`: Modified version of Powell's algorithm.
74+
- `:lm`: Levenberg-Marquardt.
75+
- `:lmdif`: Advanced Levenberg-Marquardt
76+
- `:hybrd`: Advanced modified version of Powell's algorithm
77+
6178
### Optimization.jl
6279

6380
`NonlinearLeastSquaresProblem`s can be converted into an `OptimizationProblem` and used

docs/src/solvers/NonlinearSystemSolvers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ computationally expensive than direct methods.
110110
close to the steady state.
111111
- `SSRootfind()`: Uses a NonlinearSolve compatible solver to find the steady state.
112112

113-
### SciMLNLSolve.jl
113+
### NLsolve.jl
114114

115115
This is a wrapper package for importing solvers from NLsolve.jl into the SciML interface.
116116

ext/NonlinearSolveMINPACKExt.jl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
module NonlinearSolveMINPACKExt
2+
3+
using NonlinearSolve, SciMLBase
4+
using MINPACK
5+
6+
function SciMLBase.__solve(prob::Union{NonlinearProblem{uType, iip},
7+
NonlinearLeastSquaresProblem{uType, iip}}, alg::CMINPACK, args...;
8+
abstol = 1e-6, maxiters = 100000, alias_u0::Bool = false,
9+
kwargs...) where {uType, iip}
10+
if prob.u0 isa Number
11+
u0 = [prob.u0]
12+
else
13+
u0 = NonlinearSolve.__maybe_unaliased(prob.u0, alias_u0)
14+
end
15+
16+
sizeu = size(prob.u0)
17+
p = prob.p
18+
19+
# unwrapping alg params
20+
show_trace = alg.show_trace
21+
tracing = alg.tracing
22+
io = alg.io
23+
24+
if !iip && prob.u0 isa Number
25+
f! = (du, u) -> (du .= prob.f(first(u), p); Cint(0))
26+
elseif !iip && prob.u0 isa Vector{Float64}
27+
f! = (du, u) -> (du .= prob.f(u, p); Cint(0))
28+
elseif !iip && prob.u0 isa AbstractArray
29+
f! = (du, u) -> (du .= vec(prob.f(reshape(u, sizeu), p)); Cint(0))
30+
elseif prob.u0 isa Vector{Float64}
31+
f! = (du, u) -> prob.f(du, u, p)
32+
else # Then it's an in-place function on an abstract array
33+
f! = (du, u) -> (prob.f(reshape(du, sizeu), reshape(u, sizeu), p); du = vec(du); 0)
34+
end
35+
36+
u = zero(u0)
37+
resid = NonlinearSolve.evaluate_f(prob, u)
38+
m = length(resid)
39+
40+
method = ifelse(alg.method === :auto,
41+
ifelse(prob isa NonlinearLeastSquaresProblem, :lm, :hydr), alg.method)
42+
43+
if SciMLBase.has_jac(prob.f)
44+
if !iip && prob.u0 isa Number
45+
g! = (du, u) -> (du .= prob.f.jac(first(u), p); Cint(0))
46+
elseif !iip && prob.u0 isa Vector{Float64}
47+
g! = (du, u) -> (du .= prob.f.jac(u, p); Cint(0))
48+
elseif !iip && prob.u0 isa AbstractArray
49+
g! = (du, u) -> (du .= vec(prob.f.jac(reshape(u, sizeu), p)); Cint(0))
50+
elseif prob.u0 isa Vector{Float64}
51+
g! = (du, u) -> prob.f.jac(du, u, p)
52+
else # Then it's an in-place function on an abstract array
53+
g! = function (du, u)
54+
prob.f.jac(reshape(du, sizeu), reshape(u, sizeu), p)
55+
du = vec(du)
56+
return CInt(0)
57+
end
58+
end
59+
original = MINPACK.fsolve(f!, g!, u0, m; tol = abstol, show_trace, tracing, method,
60+
iterations = maxiters, kwargs...)
61+
else
62+
original = MINPACK.fsolve(f!, u0, m; tol = abstol, show_trace, tracing, method,
63+
iterations = maxiters, kwargs...)
64+
end
65+
66+
u = reshape(original.x, size(u))
67+
resid = original.f
68+
retcode = original.converged ? ReturnCode.Success : ReturnCode.Failure
69+
70+
return SciMLBase.build_solution(prob, alg, u, resid; retcode, original)
71+
end
72+
73+
end

0 commit comments

Comments
 (0)