Normally I'd just hack this up and submit a PR, but I'm feeling short of time so will first float a suggestion and see what people think.
For nonlinear optimization, the API is good and flexible, but to me it still feels like there's more boilerplate required from the user than would be ideal. I'm wondering whether it would be better to define a traits-based API, e.g.,
abstract NLConstraintsType
immutable NLConstraintsNone <: NLConstraintsType end
immutable NLConstraintsJac <: NLConstraintsType end
immutable NLConstraintsJacProd <: NLConstraintsType end
nlconstraints(d::AbstractNLPEvaluator) = NLConstraintsJac() # default value
# fallback definition, so the user doesn't have to define this
SolverInterface.eval_g(d, g, x) = SolverInterface.eval_g(nlconstraints(d), d, g, x)
SolverInterface.eval_g(::NLConstraintsNone, d, g, x) = nothing
# do the same thing for jac_structure, eval_jac_g
...
so the user can define
MathProgBase.nlconstraints(::MyEvaluator) = NLConstraintsNone()
and then not have to worry about any of the g-related functions. Same strategy for the various Hessian options, etc. These would essentially replace initialize and features_available, at least as far as users are concerned, and as illustrated the more granular design reduces the need for boilerplate stub functions.
In my own code I do this via inheritance, e.g.,
abstract BoundsOnly <: SolverInterface.AbstractNLPEvaluator
SolverInterface.eval_g(::BoundsOnly, g, x) = nothing
but the traits-based mechanism is far better because it allows you to mix-and-match traits arbitrarily.
Normally I'd just hack this up and submit a PR, but I'm feeling short of time so will first float a suggestion and see what people think.
For nonlinear optimization, the API is good and flexible, but to me it still feels like there's more boilerplate required from the user than would be ideal. I'm wondering whether it would be better to define a traits-based API, e.g.,
so the user can define
and then not have to worry about any of the
g-related functions. Same strategy for the various Hessian options, etc. These would essentially replaceinitializeandfeatures_available, at least as far as users are concerned, and as illustrated the more granular design reduces the need for boilerplate stub functions.In my own code I do this via inheritance, e.g.,
but the traits-based mechanism is far better because it allows you to mix-and-match traits arbitrarily.