What is an interface / wrapper? #79
Replies: 2 comments 4 replies
-
I think that, as dicussed in #62 (comment), the Julia interface to the algorithms of the PRIMA library implemented in PRIMA.jl is quite similar to the basic interface that you propose here perhaps with different default settings. Thanks to the expressiveness of Julia, I do not see the needs (for now) of a higher level interface. Except maybe the single optimizer which automatically choose the best method considering the contraints (as what you have done for Python). The only difficulty I can see is to check the signature of the user-defined function (which is different for COBYLA)/ |
Beta Was this translation helpful? Give feedback.
-
Something else that the high level interface can handle is the scaling of variables. I have open an issue here for the Julia interface to PRIMA algorithms with a proposition to cope with scaling. The proposition is not specific to the Julia case. The only remaining issue not handled by this proposition is the printing of the variables when |
Beta Was this translation helpful? Give feedback.
-
Consider a package that is implemented in C or Fortran. Take PRIMA as an example. As of September 2023, it is only implemented in modern Fortran. To make PRIMA available in other languages, we need to provide interfaces (or wrappers; I will not distinguish the two words in the sequel).
What is an interface?
In my opinion, there are two different types of interfaces, namely the basic interface and the advanced one, which will be detailed below.
Let us still take PRIMA as an example. It provides the following Fortran subroutines for solving nonlinear optimization problems without using derivatives.
Here,
calfun
is a callback function that evaluates the objective function (calcfc
evaluates the objective function and nonlinear constraints);x0
is the starting point;Aineq
andbineq
define the linear inequality constraints;Aeq
andbeq
define the linear equality constraints;xl
andxu
define that bound constraints;rhobeg
,rhoend
,ftarget
, andmaxfun
are some parameters needed by the solvers.Note that I have deliberately removed some arguments in the signature to make things simpler.
Suppose that we want to make these solvers available in MATLAB. So a MATLAB interface is needed.
Basic interface
The basic interface makes the above-mentioned solvers callable in MATLAB, providing the following MATLAB functions.
This is done by compiling the Fortran code using MEX provided by MathWorks.
Advanced interface
The basic interface is already nice. Users need to do the following when they want to use PRIMA to solve their problems.
calfun
orcalcfc
,x0
,xl
,xu
,Aineq
,bineq
,Aeq
,beq
, which ever applicable.rhobeg
,rhoend
,ftarget
, andmaxfun
.This seems not too difficult. However, in practice, things may not be so simple. Here are some examples.
newuoa
anduobyqa
can solve such a problem; indeed, the other three solvers can do it as well.rhobeg
,rhoend
,ftarget
, andmaxfun
represent and how to set them. Note that I have already simplified the problem here. In reality, the solvers have many more parameters ---cobyla
has more than 20. It will be challenging and tedious to set all the parameters properly.The advanced interface is another layer between the basic interface and the users, handling all these problems in a user-friendly way.
Take the MATLAB interface of PRIMA as an example. The interface wraps everything under a single MATLAB function
prima
. This function has the following features.prima
has the same signature as the MATLAB functionfmincon
from MathWorks, so users do not need to learn how to use prima. Basically, they just need to changefmincon
to prima in their existing MATLAB code. That's all.prima
selects the solver according to the problem unless the user specifies the solver by setting theAlgorithm
option. If the solver specified by the user is invalid or cannot solve the problem, a warning will be raised and a solver will be selected.prima
defaults the parameters to values that work well in general except for those set by the user. If the user sets a parameter improperly, then a warning will be raised and the default value will be taken.prima
preprocesses the inputs from the user before sending them to the solver. For example,lincoa
expectsx0
to be feasible. If the user provides an infeasible starting point, thenprima
will projectx0
to the feasible region before passing it tolincoa
. Otherwise,lincoa
will not behave properly. Indeed, points 2 and 3 above can also be regarded as part of the preprocessing.prima
postprocesses the outputs from the solver before returning them to the user. An important aspect of the postprocessing is to validate that the outputs are reasonable --- for example, the number of function evaluations is not more thanmaxfun
(the maximum number of function evaluations allowed). This is done only in the debugging mode, which is off by default and can be turned on by setting thedebug
option totrue
. If ever some outputs are invalid, an error will be raised in the debug mode, so that the user will be informed and may inform the developer.In the MATLAB interface of PRIMA, points 2, 3, and 4 are handled by
preprima
, while point 5 is done bypostprima
.prima
callspreprima
before solving the problem, and callspostprima
afterward.With an advanced interface like
prima
, users only need to focus on the definition of the optimization problem, at which they should be experts. The setup of the solver needs minimum care.What should we do in other languages (Python, Julia, R, ...)?
Ideally, we should provide the advanced interface elaborated above.
However, this may take a bit of time, since many details need to be handled. Instead of doing things in one shot, we should first produce the basic interface, and then work out the advanced one gradually. In some languages (Julia, for example), the basic interface can be generated automatically. The advanced one, however, does need a human being to handcraft with some care and patience.
The basic interface can also be used to integrate our solvers into existing libraries, e.g., SciPy in Python and Optimization.jl in Julia. In this scenario, these libraries will likely handle the inputs and outputs in a systematic and mature way. So we only need to code a thin wrapper between the basic interface and the library to make them understand each other. This is much easier to produce than a user-friendly interface for humans.
Beta Was this translation helpful? Give feedback.
All reactions