How to link the library with a new solver?

This part assumes the reader went through the Design choices and libraries' internals page and is familiar with the user interface.

Intregrating a solver step by step.

Pre-requesite

The first step is determining if there is any interest in integrating the solver.

The solver should target one of the following optimization problem's:

  • Non-linear optimization
  • Linear optimization

...with or without constraints.

It should also support bounds and scales. If not, emulating them should be possible.

Integrating solvers that solve very different problems will likely not match the interface and lead to major changement in the package. These changes are beyond the scope of this document and should be discussed on the mailing-list.

Modifying the package.

Basically, adding a new solver means adding a new leaf in the solver hierarchy.

The new header and source files should be added in the src directory.

The naming convention is CamlCase, the name should be the solver's name suffixed by Solver.

It also should be pre-declared in the fwd.hh header.

A m4 macro should then be written to add a soft dependency against the library (ie: the bridge is built if the solver is available, if not the bridge is skipped). Please consult the Autoconf manual and the build-aux/cfsqp.m4 and build-aux/ipopt.m4 for more information.

Implementing the bridge.

The first step is choosing from which Solver you want to inherit from. The F parameters should be straight-forward: it is the kind of objective function you expect. For the constraints, there is two cases:

  • Constraint's type are unique: set C to const MyConstraintType* where MyConstraintType is the solver's constraints type.
  • If you want to discriminate your constriants into different categories, you will have to use a Boost.Variant. C should be: boost::variant<const MyConstraintType1*, const MyConstraintType2*>

Then, the solve method should be implemented in the bridge.

Following guidelines should be respected by any bridge:

  • Be sure to call reset if the result has to be recomputed the next time getMinimum is called.
  • Be sure that solve put the computed value in the result_ attribute.
  • Solver's arguments should be exposed to user through the class.
  • The solver should not display anything by default. If possible, use the print method to display internal state.

Conclusion

The dummy solver can be a good starting point for anyone who wants to add a new solver as the code can be considered as the minimum stub to get a compilable bridge. It should also be quite easy to understand.

To submit a new bridge, please post a patch on the project's mailing-list. To generate a patch with Git:

$ git diff HEAD > add_support_for_BRIDGENAME.patch

(replace BRIDGENAME by the name of the solver you are integrating). Then, post a message to the mailing-list. Please, prefix the object by the following tag:

   [PATCH] Add support for BRIDGENAME.