Skip to content

Traits interface? #87

Description

@timholy

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions