Run a benchmark with NLSProblems.jl

In this more advanced tutorial, we use the problems from NLSProblems to run a benchmark for unconstrained problems. The tutorial will use:

  • CaNNOLeS: This package provides a solver for equality-constrained nonlinear least squares.
  • JSOSolvers: This package provides optimization solvers in pure Julia for unconstrained and bound-constrained optimization.
  • NLPModelsJuMP: This package convert JuMP model in NLPModel format.
  • SolverBenchmark: This package provides general tools for benchmarking solvers.
using CaNNOLeS, JSOSolvers, NLPModels, NLPModelsJuMP, NLSProblems, SolverBenchmark

We select the problems from NLSProblems.

problems = (eval(problem)() for problem ∈ filter(x -> x != :NLSProblems, names(NLSProblems)))
Base.Generator{Vector{Symbol}, Main.var"#1#3"}(Main.var"#1#3"(), [:BNST2, :BNST3, :LVcon501, :LVcon502, :LVcon503, :LVcon504, :LVcon511, :LVcon512, :LVcon513, :LVcon514  …  :tp354, :tp355, :tp358, :tp370, :tp371, :tp372, :tp373, :tp379, :tp394, :tp395])

We also define a dictionary of solvers that will be used for our benchmark. We consider here JSOSolvers.lbfgs, JSOSolvers.trunk, and cannoles.

solvers = Dict(
  :lbfgs => model -> lbfgs(model, mem=5, atol=1e-5, rtol=0.0),
  :trunk => model -> trunk(model, atol=1e-5, rtol=0.0),
  :cannoles => model -> cannoles(model, atol=1e-5, rtol=0.0),
)
Dict{Symbol, Function} with 3 entries:
  :trunk    => #6
  :cannoles => #7
  :lbfgs    => #5

The function SolverBenchmark.bmak_solvers will run all the problems on the specified solvers and store the results in a DataFrame. At this stage, we discard the problems that have constraints or bounds using !unconstrained(prob), and those that are too large or too small with get_nvar(prob) > 100 || get_nvar(prob) < 5.

stats = bmark_solvers(
  solvers, problems,
  skipif=prob -> (!unconstrained(prob) || get_nvar(prob) > 100 || get_nvar(prob) < 5),
)
Dict{Symbol, DataFrames.DataFrame} with 3 entries:
  :trunk    => 40×39 DataFrame…
  :cannoles => 40×43 DataFrame…
  :lbfgs    => 40×39 DataFrame

We can explore the results solver by solver in stats[:lbfgs] and stats[:trunk], or get a profile wall using SolverBenchmark.profile_solvers.

cols = [:id, :name, :nvar, :objective, :dual_feas, :neval_obj, :neval_grad, :neval_hess, :iter, :elapsed_time, :status]
header = Dict(
  :nvar => "n",
  :objective => "f(x)",
  :dual_feas => "‖∇f(x)‖",
  :neval_obj => "# f",
  :neval_grad => "# ∇f",
  :neval_hess => "# ∇²f",
  :elapsed_time => "t",
)

for solver ∈ keys(solvers)
  pretty_stats(stats[solver][!, cols], hdr_override=header)
end
┌────────┬───────┬────────┬───────────┬───────────┬────────┬────────┬────────┬────────┬───────────┬─────────────┐
│     id   name       n       f(x)    ‖∇f(x)‖     # f    # ∇f   # ∇²f    iter          t       status │
├────────┼───────┼────────┼───────────┼───────────┼────────┼────────┼────────┼────────┼───────────┼─────────────┤
│     15 │  NZF1 │     13 │  9.83e-20 │  1.70e-09 │      7 │      7 │      0 │      6 │  6.86e-02 │ first_order │
│     67 │ mgh17 │      5 │  2.81e-05 │  8.19e-06 │     78 │     25 │      0 │     24 │  1.33e-03 │ first_order │
│     68 │ mgh18 │      6 │  2.83e-03 │  8.53e-06 │     27 │     17 │      0 │     16 │  3.33e-04 │ first_order │
│     69 │ mgh19 │     11 │  4.38e-02 │  9.52e-06 │     75 │     38 │      0 │     38 │  8.93e-03 │ first_order │
│     70 │ mgh20 │      6 │  1.14e-03 │  6.36e-06 │     12 │     12 │      0 │     11 │  1.12e-03 │ first_order │
│     71 │ mgh21 │     20 │  2.00e-10 │  8.94e-06 │     35 │     18 │      0 │     18 │  1.33e-04 │ first_order │
│     72 │ mgh22 │     20 │  3.70e-10 │  3.01e-07 │     11 │     11 │      0 │     10 │  1.07e-04 │ first_order │
│     75 │ mgh25 │     10 │  7.96e-16 │  7.84e-07 │     10 │     10 │      0 │      9 │  4.79e-05 │ first_order │
│     76 │ mgh26 │     10 │  1.40e-05 │  6.58e-06 │    109 │     18 │      0 │     19 │  2.29e-03 │ first_order │
│     77 │ mgh27 │     10 │  4.46e-10 │  2.75e-06 │      6 │      6 │      0 │      5 │  3.79e-05 │ first_order │
│     78 │ mgh28 │     10 │  2.04e-16 │  3.98e-09 │      4 │      4 │      0 │      3 │  9.11e-05 │ first_order │
│     79 │ mgh29 │     10 │  2.59e-13 │  7.96e-07 │      4 │      4 │      0 │      3 │  1.22e-04 │ first_order │
│     80 │ mgh30 │     10 │  1.57e-12 │  6.32e-06 │      7 │      7 │      0 │      6 │  7.61e-05 │ first_order │
│     81 │ mgh31 │     10 │  1.97e-13 │  3.68e-06 │      8 │      8 │      0 │      7 │  1.05e-04 │ first_order │
│     82 │ mgh32 │     10 │  5.00e+00 │  8.81e-16 │      5 │      5 │      0 │      4 │  3.00e-05 │ first_order │
│     83 │ mgh33 │     10 │  2.32e+00 │  1.39e-09 │      2 │      2 │      0 │      1 │  1.91e-05 │ first_order │
│     84 │ mgh34 │     10 │  3.07e+00 │  4.16e-10 │      2 │      2 │      0 │      1 │  1.69e-05 │ first_order │
│    120 │ tp266 │      5 │  5.00e-01 │  9.36e-06 │     43 │     21 │      0 │     20 │  7.50e-04 │ first_order │
│    121 │ tp267 │      5 │  1.33e-03 │  6.91e-06 │    102 │     30 │      0 │     31 │  8.02e-04 │ first_order │
│    124 │ tp271 │      6 │  6.32e-14 │  3.82e-06 │      6 │      6 │      0 │      5 │  2.10e-05 │ first_order │
│    125 │ tp272 │      6 │  2.83e-03 │  8.53e-06 │     27 │     17 │      0 │     16 │  3.42e-04 │ first_order │
│    126 │ tp273 │      6 │  1.55e-14 │  1.91e-06 │     10 │     10 │      0 │      9 │  5.58e-05 │ first_order │
│    127 │ tp282 │     10 │  2.67e-17 │  4.26e-08 │    163 │     54 │      0 │     55 │  9.20e-04 │ first_order │
│    128 │ tp286 │     20 │  2.00e-10 │  8.94e-06 │     35 │     18 │      0 │     18 │  1.29e-04 │ first_order │
│    129 │ tp288 │     20 │  1.95e-08 │  7.66e-06 │     11 │     11 │      0 │     10 │  1.05e-04 │ first_order │
│    131 │ tp291 │     10 │  1.06e-08 │  3.66e-06 │     19 │     19 │      0 │     18 │  6.39e-05 │ first_order │
│    132 │ tp292 │     30 │  1.07e-08 │  8.99e-06 │     93 │     67 │      0 │     66 │  3.56e-04 │ first_order │
│    133 │ tp293 │     50 │  7.04e-09 │  8.04e-06 │    208 │    115 │      0 │    114 │  9.95e-04 │ first_order │
│    134 │ tp294 │      6 │  4.19e-13 │  6.68e-06 │     92 │     24 │      0 │     23 │  1.92e-04 │ first_order │
│    135 │ tp295 │     10 │  8.73e-11 │  9.53e-06 │    107 │     26 │      0 │     25 │  3.27e-04 │ first_order │
│    136 │ tp296 │     16 │  8.55e-12 │  8.17e-06 │    140 │     33 │      0 │     32 │  7.01e-04 │ first_order │
│    137 │ tp297 │     30 │  3.11e-13 │  9.63e-06 │    201 │     44 │      0 │     43 │  2.05e-03 │ first_order │
│    138 │ tp298 │     50 │  1.03e-12 │  8.14e-06 │    364 │     66 │      0 │     65 │  7.56e-03 │ first_order │
│    139 │ tp299 │    100 │  1.06e-10 │  8.39e-06 │    715 │    124 │      0 │    123 │  2.66e-02 │ first_order │
│    140 │ tp303 │     20 │  6.22e-14 │  9.45e-06 │      8 │      8 │      0 │      7 │  5.29e-05 │ first_order │
│    141 │ tp304 │     50 │  7.56e-21 │  1.27e-08 │     11 │     11 │      0 │     10 │  1.04e-04 │ first_order │
│    142 │ tp305 │    100 │  3.73e-21 │  2.51e-08 │     13 │     13 │      0 │     12 │  1.92e-04 │ first_order │
│    169 │ tp370 │      6 │  1.14e-03 │  6.36e-06 │     12 │     12 │      0 │     11 │  1.20e-03 │ first_order │
│    170 │ tp371 │      9 │  3.42e-06 │  7.69e-06 │     12 │     12 │      0 │     11 │  2.09e-03 │ first_order │
│    173 │ tp379 │     11 │  2.01e-02 │  9.49e-06 │     22 │     18 │      0 │     17 │  3.49e-03 │ first_order │
└────────┴───────┴────────┴───────────┴───────────┴────────┴────────┴────────┴────────┴───────────┴─────────────┘
┌────────┬───────┬────────┬───────────┬───────────┬────────┬────────┬────────┬────────┬───────────┬─────────────┐
│     id   name       n       f(x)    ‖∇f(x)‖     # f    # ∇f   # ∇²f    iter          t       status │
├────────┼───────┼────────┼───────────┼───────────┼────────┼────────┼────────┼────────┼───────────┼─────────────┤
│     15 │  NZF1 │     13 │  2.09e-11 │  7.33e-06 │      0 │      0 │      0 │     12 │  7.71e-02 │ first_order │
│     67 │ mgh17 │      5 │  3.85e-05 │  1.55e-06 │      0 │      0 │      0 │     17 │  9.28e-04 │ first_order │
│     68 │ mgh18 │      6 │  2.83e-03 │  1.16e-07 │      0 │      0 │      0 │     69 │  2.02e-03 │ first_order │
│     69 │ mgh19 │     11 │  1.37e-01 │  2.13e-06 │      0 │      0 │      0 │     35 │  6.64e-01 │ first_order │
│     70 │ mgh20 │      6 │  1.14e-03 │  7.21e-10 │      0 │      0 │      0 │      7 │  5.02e-01 │ first_order │
│     71 │ mgh21 │     20 │  2.03e-10 │  3.18e-06 │      0 │      0 │      0 │      3 │  4.01e-05 │ first_order │
│     72 │ mgh22 │     20 │  4.01e-07 │  1.47e-07 │      0 │      0 │      0 │     12 │  1.27e-04 │ first_order │
│     75 │ mgh25 │     10 │  1.49e-14 │  1.73e-06 │      0 │      0 │      0 │     12 │  5.22e-01 │ first_order │
│     76 │ mgh26 │     10 │  1.40e-05 │  9.67e-07 │      0 │      0 │      0 │     10 │  3.31e-04 │ first_order │
│     77 │ mgh27 │     10 │  1.01e-13 │  1.95e-08 │      0 │      0 │      0 │      7 │  8.61e-05 │ first_order │
│     78 │ mgh28 │     10 │  2.42e-13 │  2.14e-08 │      0 │      0 │      0 │      2 │  3.89e-05 │ first_order │
│     79 │ mgh29 │     10 │  3.82e-11 │  3.44e-06 │      0 │      0 │      0 │      2 │  1.09e-04 │ first_order │
│     80 │ mgh30 │     10 │  2.20e-20 │  3.09e-10 │      0 │      0 │      0 │      5 │  5.01e-05 │ first_order │
│     81 │ mgh31 │     10 │  4.36e-19 │  2.32e-09 │      0 │      0 │      0 │      7 │  1.19e-04 │ first_order │
│     82 │ mgh32 │     10 │  5.00e+00 │  2.44e-11 │      0 │      0 │      0 │      2 │  4.39e-05 │ first_order │
│     83 │ mgh33 │     10 │  2.32e+00 │  8.64e-06 │      0 │      0 │      0 │      1 │  2.22e-05 │ first_order │
│     84 │ mgh34 │     10 │  3.07e+00 │  8.43e-06 │      0 │      0 │      0 │      1 │  1.81e-05 │ first_order │
│    120 │ tp266 │      5 │  5.00e-01 │  6.10e-09 │      0 │      0 │      0 │      6 │  4.68e-01 │ first_order │
│    121 │ tp267 │      5 │  2.71e-02 │  4.65e-08 │      0 │      0 │      0 │     38 │  8.93e-04 │ first_order │
│    124 │ tp271 │      6 │  8.98e-13 │  6.06e-06 │      0 │      0 │      0 │      1 │  7.87e-06 │ first_order │
│    125 │ tp272 │      6 │  7.49e-14 │  1.93e-11 │      0 │      0 │      0 │     63 │  1.85e-03 │ first_order │
│    126 │ tp273 │      6 │  2.63e-22 │  1.26e-10 │      0 │      0 │      0 │     10 │  4.91e-05 │ first_order │
│    127 │ tp282 │     10 │  9.55e-11 │  5.33e-06 │      0 │      0 │      0 │     30 │  2.84e-04 │ first_order │
│    128 │ tp286 │     20 │  2.03e-10 │  3.18e-06 │      0 │      0 │      0 │      3 │  3.81e-05 │ first_order │
│    129 │ tp288 │     20 │  1.33e-09 │  2.43e-07 │      0 │      0 │      0 │     14 │  1.56e-04 │ first_order │
│    131 │ tp291 │     10 │  1.07e-10 │  9.30e-08 │      0 │      0 │      0 │     16 │  6.39e-05 │ first_order │
│    132 │ tp292 │     30 │  1.62e-10 │  1.31e-07 │      0 │      0 │      0 │     18 │  1.50e-04 │ first_order │
│    133 │ tp293 │     50 │  1.78e-10 │  1.42e-07 │      0 │      0 │      0 │     19 │  2.69e-04 │ first_order │
│    134 │ tp294 │      6 │  1.99e+00 │  2.23e-07 │      0 │      0 │      0 │     11 │  7.20e-05 │ first_order │
│    135 │ tp295 │     10 │  1.99e+00 │  3.86e-07 │      0 │      0 │      0 │     22 │  1.90e-04 │ first_order │
│    136 │ tp296 │     16 │  1.99e+00 │  2.28e-07 │      0 │      0 │      0 │     28 │  3.67e-04 │ first_order │
│    137 │ tp297 │     30 │  5.59e-20 │  2.20e-10 │      0 │      0 │      0 │     37 │  9.42e-04 │ first_order │
│    138 │ tp298 │     50 │  4.44e-13 │  4.07e-07 │      0 │      0 │      0 │     57 │  2.44e-03 │ first_order │
│    139 │ tp299 │    100 │  2.05e-24 │  1.59e-13 │      0 │      0 │      0 │    109 │  1.39e-02 │ first_order │
│    140 │ tp303 │     20 │  3.27e-13 │  8.09e-06 │      0 │      0 │      0 │     10 │  2.59e-04 │ first_order │
│    141 │ tp304 │     50 │  1.48e-20 │  4.29e-09 │      0 │      0 │      0 │     14 │  1.81e-03 │ first_order │
│    142 │ tp305 │    100 │  4.12e-23 │  4.54e-10 │      0 │      0 │      0 │     17 │  1.16e-02 │ first_order │
│    169 │ tp370 │      6 │  1.14e-03 │  7.21e-10 │      0 │      0 │      0 │      7 │  1.14e-03 │ first_order │
│    170 │ tp371 │      9 │  7.00e-07 │  3.29e-12 │      0 │      0 │      0 │      7 │  5.24e-01 │ first_order │
│    173 │ tp379 │     11 │  2.01e-02 │  1.95e-08 │      0 │      0 │      0 │     16 │  4.03e-03 │ first_order │
└────────┴───────┴────────┴───────────┴───────────┴────────┴────────┴────────┴────────┴───────────┴─────────────┘
┌────────┬───────┬────────┬───────────┬───────────┬────────┬────────┬────────┬────────┬───────────┬─────────────┐
│     id   name       n       f(x)    ‖∇f(x)‖     # f    # ∇f   # ∇²f    iter          t       status │
├────────┼───────┼────────┼───────────┼───────────┼────────┼────────┼────────┼────────┼───────────┼─────────────┤
│     15 │  NZF1 │     13 │  1.80e-14 │  5.06e-07 │     77 │     72 │      0 │     34 │  2.87e-03 │ first_order │
│     67 │ mgh17 │      5 │  2.73e-05 │  4.66e-06 │    460 │    414 │      0 │    190 │  3.54e-03 │ first_order │
│     68 │ mgh18 │      6 │  2.83e-03 │  1.86e-06 │    100 │     95 │      0 │     43 │  4.27e-04 │ first_order │
│     69 │ mgh19 │     11 │  4.38e-02 │  9.55e-06 │    738 │    726 │      0 │    342 │  2.28e-02 │ first_order │
│     70 │ mgh20 │      6 │  1.14e-03 │  7.36e-06 │    214 │    205 │      0 │     98 │  1.16e-01 │ first_order │
│     71 │ mgh21 │     20 │  1.46e-17 │  1.26e-08 │     63 │     55 │      0 │     25 │  1.06e-04 │ first_order │
│     72 │ mgh22 │     20 │  7.50e-11 │  3.54e-06 │    109 │    104 │      0 │     49 │  1.79e-04 │ first_order │
│     75 │ mgh25 │     10 │  4.99e-18 │  6.21e-08 │     49 │     35 │      0 │     16 │  5.51e-05 │ first_order │
│     76 │ mgh26 │     10 │  1.40e-05 │  5.83e-06 │     58 │     58 │      0 │     27 │  3.43e-04 │ first_order │
│     77 │ mgh27 │     10 │  1.55e-13 │  5.52e-08 │     42 │     38 │      0 │     17 │  4.60e-05 │ first_order │
│     78 │ mgh28 │     10 │  5.71e-11 │  8.68e-06 │    133 │    132 │      0 │     63 │  2.78e-04 │ first_order │
│     79 │ mgh29 │     10 │  4.52e-12 │  3.09e-06 │     12 │     12 │      0 │      5 │  9.20e-05 │ first_order │
│     80 │ mgh30 │     10 │  6.15e-13 │  6.11e-06 │     50 │     48 │      0 │     22 │  8.30e-05 │ first_order │
│     81 │ mgh31 │     10 │  1.53e+00 │  5.34e-06 │     60 │     56 │      0 │     26 │  1.78e-04 │ first_order │
│     82 │ mgh32 │     10 │  5.00e+00 │  5.58e-16 │      4 │      4 │      0 │      1 │  5.96e-06 │ first_order │
│     83 │ mgh33 │     10 │  2.32e+00 │  1.52e-11 │     21 │      7 │      0 │      2 │  1.38e-05 │ first_order │
│     84 │ mgh34 │     10 │  3.07e+00 │  6.08e-12 │     20 │      7 │      0 │      2 │  1.22e-05 │ first_order │
│    120 │ tp266 │      5 │  5.00e-01 │  5.89e-06 │     26 │     25 │      0 │     11 │  1.95e-04 │ first_order │
│    121 │ tp267 │      5 │  6.14e-07 │  8.46e-06 │     72 │     70 │      0 │     31 │  2.71e-04 │ first_order │
│    124 │ tp271 │      6 │  3.24e-14 │  3.03e-06 │     23 │     19 │      0 │      8 │  1.41e-05 │ first_order │
│    125 │ tp272 │      6 │  2.83e-03 │  1.86e-06 │    100 │     95 │      0 │     43 │  4.25e-04 │ first_order │
│    126 │ tp273 │      6 │  2.24e-13 │  7.75e-06 │     37 │     27 │      0 │     12 │  4.60e-05 │ first_order │
│    127 │ tp282 │     10 │  1.61e-13 │  3.72e-06 │    370 │    360 │      0 │    167 │  6.15e-04 │ first_order │
│    128 │ tp286 │     20 │  1.46e-17 │  1.26e-08 │     63 │     55 │      0 │     25 │  1.00e-04 │ first_order │
│    129 │ tp288 │     20 │  7.64e-10 │  6.55e-06 │    100 │     95 │      0 │     44 │  1.65e-04 │ first_order │
│    131 │ tp291 │     10 │  1.72e-08 │  5.32e-06 │     53 │     47 │      0 │     22 │  5.01e-05 │ first_order │
│    132 │ tp292 │     30 │  6.83e-09 │  6.60e-06 │     69 │     59 │      0 │     28 │  1.19e-04 │ first_order │
│    133 │ tp293 │     50 │  8.04e-09 │  5.31e-06 │     82 │     71 │      0 │     34 │  1.97e-04 │ first_order │
│    134 │ tp294 │      6 │  2.69e-14 │  4.40e-06 │    113 │    108 │      0 │     49 │  1.15e-04 │ first_order │
│    135 │ tp295 │     10 │  4.42e-13 │  7.32e-06 │    181 │    175 │      0 │     81 │  2.31e-04 │ first_order │
│    136 │ tp296 │     16 │  5.83e-14 │  4.99e-06 │    252 │    247 │      0 │    119 │  4.42e-04 │ first_order │
│    137 │ tp297 │     30 │  3.45e-12 │  9.09e-06 │    410 │    404 │      0 │    191 │  1.17e-03 │ first_order │
│    138 │ tp298 │     50 │  1.08e-13 │  5.84e-06 │    621 │    615 │      0 │    290 │  2.71e-03 │ first_order │
│    139 │ tp299 │    100 │  2.26e-12 │  7.21e-06 │   1149 │   1142 │      0 │    545 │  2.44e-02 │ first_order │
│    140 │ tp303 │     20 │  6.51e-15 │  2.44e-06 │     51 │     39 │      0 │     18 │  8.01e-05 │ first_order │
│    141 │ tp304 │     50 │  1.27e-14 │  6.57e-06 │     74 │     55 │      0 │     26 │  2.62e-04 │ first_order │
│    142 │ tp305 │    100 │  1.54e-17 │  3.31e-07 │    102 │     78 │      0 │     37 │  6.97e-04 │ first_order │
│    169 │ tp370 │      6 │  1.14e-03 │  7.05e-06 │    264 │    252 │      0 │    120 │  6.28e-03 │ first_order │
│    170 │ tp371 │      9 │  3.32e-06 │  8.97e-06 │   2591 │   2499 │      0 │   1171 │  1.26e-01 │ first_order │
│    173 │ tp379 │     11 │  2.01e-02 │  3.68e-06 │    345 │    344 │      0 │    165 │  1.05e-02 │ first_order │
└────────┴───────┴────────┴───────────┴───────────┴────────┴────────┴────────┴────────┴───────────┴─────────────┘
first_order(df) = df.status .== :first_order
unbounded(df) = df.status .== :unbounded
solved(df) = first_order(df) .| unbounded(df)
costnames = ["time", "obj + grad + hess"]
costs = [
  df -> .!solved(df) .* Inf .+ df.elapsed_time,
  df -> .!solved(df) .* Inf .+ df.neval_obj .+ df.neval_grad .+ df.neval_hess,
]

using Plots
gr()

profile_solvers(stats, costs, costnames)