forked from JuliaSmoothOptimizers/JSOTutorials.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.jmd
More file actions
102 lines (75 loc) · 3.52 KB
/
index.jmd
File metadata and controls
102 lines (75 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
---
title: "Comparing subsolvers for NLS solvers"
tags: ["solvers", "krylov", "benchmark", "least squares"]
author: "Tangi Migot"
---
# Comparing subsolvers for nonlinear least squares in JSOSolvers
This tutorial showcases some advanced features of solvers in JSOSolvers.
We benchmark different subsolvers used in the solver TRUNK for unconstrained nonlinear least squares problems.
The first step is to select a set of problems that are nonlinear least squares.
```julia
using JSOSolvers, ADNLPModels
using OptimizationProblems
using OptimizationProblems.ADNLPProblems
df = OptimizationProblems.meta
names = df[(df.objtype .== :least_squares) .& (df.contype .== :unconstrained), :name]
ad_problems = (eval(Meta.parse(problem))(use_nls = true) for problem ∈ names)
```
These problems are [`ADNLSModel`](https://github.com/JuliaSmoothOptimizers/ADNLPModels.jl) so derivatives are generated using automatic differentiation.
```julia
nls = first(ad_problems)
typeof(nls)
```
The solvers TRON and TRUNK are trust-region based methods that compute a search direction by means of solving iteratively a linear least squares problem.
For this task, several solvers are available.
```julia
JSOSolvers.trunkls_allowed_subsolvers
```
This benchmark could also be followed for the solver TRON where the following subsolvers are available.
```julia
JSOSolvers.tronls_allowed_subsolvers
```
These linear least squares solvers are implemented in the package [Krylov.jl](https://github.com/JuliaSmoothOptimizers/Krylov.jl).
For detailed descriptions of each subsolver's algorithm and when to use it, see the [Krylov.jl documentation](https://jso.dev/Krylov.jl/stable/).
We define a dictionary of the different solvers that will be benchmarked.
We consider here four variants of TRUNK using the different subsolvers.
For example, to call TRUNK with an explicit subsolver:
```julia
stats = trunk(nls, subsolver = :cgls)
```
The same subsolver selection pattern applies to TRON's least-squares specialization:
```julia
stats_tron = tron(nls, subsolver = :lsmr)
```
Now we define the solver dictionary for benchmarking:
```julia
solvers = Dict(
:trunk_cgls => model -> trunk(model, subsolver = :cgls),
:trunk_crls => model -> trunk(model, subsolver = :crls),
:trunk_lsqr => model -> trunk(model, subsolver = :lsqr),
:trunk_lsmr => model -> trunk(model, subsolver = :lsmr)
)
```
Using [`SolverBenchmark.jl`](https://github.com/JuliaSmoothOptimizers/SolverBenchmark.jl) functionalities, the solvers are executed over all the test problems.
```julia
using SolverBenchmark
stats = bmark_solvers(solvers, ad_problems)
```
The result is stored in a dictionary of `DataFrame` that can be used to analyze the results.
```julia
first_order(df) = df.status .== :first_order
unbounded(df) = df.status .== :unbounded
solved(df) = first_order(df) .| unbounded(df)
costnames = ["time"]
costs = [df -> .!solved(df) .* Inf .+ df.elapsed_time]
```
We compare the four variants based on their execution time.
More advanced comparisons could include the number of evaluations of the objective, gradient, or Hessian-vector products.
```julia
using Plots
gr()
profile_solvers(stats, costs, costnames)
```
The CRLS and CGLS variants are the ones solving more problems, and even though the difference is rather small the CGLS variant is consistently faster which seems to indicate that it is the most appropriate subsolver for TRUNK.
The size of the problems was rather small here, so this should be confirmed on larger instances.
Moreover, the results may vary depending on the origin of the test problems.