JSO-compliant solvers
The following are JSO-compliance expectations and recommendations that are implemented in JuliaSmoothOptimizers.
Mandatory
- Create a function
solver_name(nlp::AbstractNLPModel; kwargs...)
that returns aGenericExecutionStats
.
Recommended
- Create a solver object
SolverName <: SolverCore.AbstractOptimizationSolver
. - Store all memory-allocating things inside this object. This includes vectors, matrices, and possibly other objects.
- One of these objects should be
solver.x
, that stores the current iterate. - Implement a constructor
SolverName(nlp; kwargs...)
. - Implement
SolverCore.solve!(solver, nlp::AbstractNLPModel, stats::GenericExecutionStats)
and changesolver_name
to create aSolverName
object and callsolve!
. - Make sure that
solve!
is not allocating. - Accept the following keyword arguments (
T
is float type andV
is the container type):x::V = nlp.meta.x0
: The starting point.atol::T = sqrt(eps(T))
: Absolute tolerance for the gradient. Use in conjunction with the relative tolerance below to check $\Vert \nabla f(x_k)\Vert \leq \epsilon_a + \epsilon_r\Vert \nabla f(x_0)\Vert$.rtol::T = sqrt(eps(T))
: Relative tolerance for the gradient. Seeatol
above.max_eval::Int = -1
: Maximum number of objective function evaluation plus constraint function evaluations. Negative number means unlimited.max_iter::Int = typemax(Int)
: Maximum number of iterations.max_time::Float64 = 30.0
: Maximum elapsed time.verbose::Int = 0
: Verbosity level.0
means nothing and1
means something. There are no rules on the level of verbosity yet.callback = (nlp, solver, stats) -> nothing
: A callback function to be called at the end of an iteration, before exit status are defined.
- Use
set_status!
andget_status
to updatestats
before starting the method loop, and at the end of every iteration. - Call the
callback
after runningset_status!
in both places. - Define
done = stats.status != :unknown
and loop withwhile !done
. - To check for logic errors and stop the method use
set_status!(stats, ...)
,done = true
, andcontinue
, where the second argument ofset_status!
is one of the statuses available in SolverCore.STATUSES. You can callSolverCore.show_statuses()
to see them. If you need more specific statuses, create an issue. - Use the
set_...!(stats, ...)
functions fromSolverCore
to update thestats
. For instance,set_objective!(stats, f)
,set_time!(stats, time() - start_time)
, andset_dual_residual!(stats, gnorm)
. - Don't log when
verbose == 0
. When logging, use@info log_header(...)
and@info log_row(...)
. - Write docstrings for
SolverName
. The format is still a bit loose.