Structures for passing information
A minimal implementation of a solver module needs to do the following:
- Modeling functionality:
- define subroutines to start an optimization run and retrieve solution values
- provide access to solver parameters
- if supported by the solver, provide support for handling multiple problems
- NI functionality:
- implement a reset and an unload service
- initialize the module and the required interface structures
To start with, let us take a look at the structures that are required for exchanging information between Mosel and the external program.
List of subroutines
The minimal set of entries for the list of subroutines would be just the calls to minimization/maximization. Our implementation adds a function to retrieve the problem status information, alternative spelling for the optimization routines, and it also provides the access routines for module control parameters that are required for the implementation of solver parameters.
static XPRMdsofct tabfct[]= { {"",XPRM_FCT_GETPAR,XPRM_TYP_NOT,0,NULL,slvlc_getpar}, {"",XPRM_FCT_SETPAR,XPRM_TYP_NOT,0,NULL,slvlc_setpar}, {"getprobstat",2000,XPRM_TYP_INT,0,NULL,slvlc_getpstat}, {"minimise",2100,XPRM_TYP_NOT,1,"c",slvlc_minim}, {"minimize",2100,XPRM_TYP_NOT,1,"c",slvlc_minim}, {"maximise",2101,XPRM_TYP_NOT,1,"c",slvlc_maxim}, {"maximize",2101,XPRM_TYP_NOT,1,"c",slvlc_maxim} };
List of parameters
In terms of an example, we provide access to a few controls of Xpress Optimizer, and the module also shows how to implement a verbosity flag, resulting in the following list of module parameters:
static struct /* Parameters published by this module */ { char *name; int type; } myxprsparams[]= { {"myxp_verbose",XPRM_TYP_BOOL|XPRM_CPAR_READ|XPRM_CPAR_WRITE}, {"myxp_maxtime",XPRM_TYP_INT|XPRM_CPAR_READ|XPRM_CPAR_WRITE}, {"myxp_lpstatus",XPRM_TYP_INT|XPRM_CPAR_READ}, {"myxp_lpobjval",XPRM_TYP_REAL|XPRM_CPAR_READ}, };
The problem and LP status parameters return values that are best implemented via module constants, such as:
static XPRMdsoconst tabconst[]= { XPRM_CST_INT("MYXP_INF",XPRM_PBINF), /* Mosel status codes */ XPRM_CST_INT("MYXP_OPT",XPRM_PBOPT), XPRM_CST_INT("MYXP_OTH",XPRM_PBOTH), XPRM_CST_INT("MYXP_UNF",XPRM_PBUNF), XPRM_CST_INT("MYXP_UNB",XPRM_PBUNB), XPRM_CST_INT("MYXP_LP_OPTIMAL",XPRS_LP_OPTIMAL), /* Solver status codes */ XPRM_CST_INT("MYXP_LP_INFEAS",XPRS_LP_INFEAS), XPRM_CST_INT("MYXP_LP_CUTOFF",XPRS_LP_CUTOFF) };
List of types
The list of types has a single entry: a solver module needs to extend the Mosel type mpproblem with its own implementation.
static XPRMdsotyp tabtyp[]= { {"mpproblem.mxp",1,XPRM_DTYP_PROB|XPRM_DTYP_APPND,slv_pb_create, slv_pb_delete,NULL,NULL,slv_pb_copy} };
The following structure implements the problem type for our module, Mosel will maintain one instance of this type for each mpproblem object.
typedef struct SlvPb { struct SlvCtx *slctx; /* Solver context */ XPRSprob xpb; int have; int is_mip; double *solval; /* Structures for storing solution values */ double *dualval; double *rcostval; double *slackval; XPRMcontext saved_ctx; /* Mosel context (used by callbacks) */ struct SlvPb *prev,*next; } s_slvpb;
A solver context definition is shown below in Section Module context.
List of services
The services PARAM and PARLST are required for the handling of module parameters, RESET and UNLOAD manage the access to the solver library.
static XPRMdsoserv tabserv[]= { {XPRM_SRV_PARAM, (void *)slv_findparam}, {XPRM_SRV_PARLST, (void *)slv_nextparam}, {XPRM_SRV_RESET, (void *)slv_reset}, {XPRM_SRV_UNLOAD, (void *)slv_quitlib} };
Module context
The module context holds the type ID for the extended mpproblem type, module options, and a list of references to the problems that have been created by this module:
typedef struct SlvCtx /* A context for this module */ { int pbid; /* ID of type "mpproblem.mxp" */ int options; /* Runtime options */ s_slvpb *probs; /* List of created problems */ } s_slvctx;
A specific interface structure required by the matrix generation is the following MIP solver interface definition that defines the shorthands to be used for identifying constraint and variable types and specifies the names of the functions for matrix generation, cleaning up solution information, and retrieving solution values for decision variables and constraints:
static mm_mipsolver xpress= {{'N','G','L','E','R','1','2'}, {'+','I','B','P','S','R'}, slv_loadmat, slv_clearsol, slv_getsol_v, slv_getsol_c};
Interface structure
The interface structure holds as usual the definition of the four tables (constants, subroutines, types, and services).
static XPRMdsointer dsointer= { sizeof(tabconst)/sizeof(XPRMdsoconst), tabconst, sizeof(tabfct)/sizeof(XPRMdsofct), tabfct, sizeof(tabtyp)/sizeof(XPRMdsotyp), tabtyp, sizeof(tabserv)/sizeof(XPRMdsoserv), tabserv };
Initialization function
The module initialization function performs the initialization of the solver library.
DSO_INIT myxprs_init(XPRMnifct nifct, int *interver,int *libver, XPRMdsointer **interf) { int r; *interver=XPRM_NIVERS; /* The interface version we are using */ *libver=XPRM_MKVER(0,0,1); /* The version of the module: 0.0.1 */ *interf=&dsointer; /* Our module interface structure */ r=XPRSinit(NULL); /* Initialize the solver */ if((r!=0)&&(r!=32)) { nifct->dispmsg(NULL,"myxprs: I cannot initialize Xpress Optimizer.\n"); return 1; } mm=nifct; /* Retrieve the Mosel NI function table */ return 0; }
© 2001-2019 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.