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_nameto create aSolverNameobject and callsolve!. - Make sure that
solve!is not allocating. - Accept the following keyword arguments (
Tis float type andVis 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. Seeatolabove.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.0means nothing and1means 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_statusto updatestatsbefore starting the method loop, and at the end of every iteration. - Call the
callbackafter runningset_status!in both places. - Define
done = stats.status != :unknownand 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 fromSolverCoreto 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.