Generating names for matrix entries
An LP/MIP problem definition held in Mosel can be displayed on screen or exported to a file using the subroutine exportprob. Nevertheless, in particular while developing a solver interface it may be helpful to also have the possibility of writing out the matrix representation directly from the solver.
In our example implementation the matrix gets loaded into the solver through the call to optimization, so writing out the matrix needs to take place after this call:
setparam("myxp_loadnames", true) maximize(MyObj) writeprob("mymat.lp", "l")
When writing out a matrix for debugging purposes one might expect to be able to match the rows and columns to the Mosel modeling entities via their respective names. By default, Mosel does not generate any names for decision variables or constraints in order to maintain a low memory footprint. This feature needs to be added explicitly into the implementation of the loadmat routine that we have seen earlier in this chapter. After a call to the NI function genmpnames the resulting names are collected into the corresponding data structures that are expected by the solver library (uploading names for rows, columns, and SOS separately in the case of Xpress Optimizer).
static int slv_loadmat(XPRMcontext ctx,void *mipctx,mm_matrix *m) { s_slvpb *slpb; s_slvctx *slctx; int c,r; slpb=mipctx; slctx=slpb->slctx; /* Generate names for matrix elements */ if(slctx->options&OPT_LOADNAMES) mm->genmpnames(ctx,MM_KEEPOBJ,NULL,0); /* ... load the problem matrix into the solver ... */ /* Load names if requested */ if(!r && (slctx->options&OPT_LOADNAMES)) { char *names,*n; size_t totlen,totlen2; size_t l; totlen=0; for(c=0;c<m->ncol;c++) { l=strlen(mm->getmpname(ctx,MM_MPNAM_COL,c)); totlen+=l+1; } totlen2=0; for(c=0;c<m->nrow;c++) { l=strlen(mm->getmpname(ctx,MM_MPNAM_ROW,c)); totlen2+=l+1; } if(totlen<totlen2) totlen=totlen2; totlen2=0; for(c=0;c<m->nsos;c++) { l=strlen(mm->getmpname(ctx,MM_MPNAM_SOS,c)); totlen2+=l+1; } if(totlen<totlen2) totlen=totlen2; if((names=malloc(totlen))==NULL) mm->dispmsg(ctx,"myxprs: Not enough memory for loading the names.\n"); else { n=names; for(c=0;c<m->ncol;c++) n+=strlen(strcpy(n,mm->getmpname(ctx,MM_MPNAM_COL,c)))+1; if((r=XPRSaddnames(slpb->xpb,2,names,0,m->ncol-1))!=0) mm->dispmsg(ctx,"myxprs: Error when executing `addnames'.\n"); if(!r && (m->nrow>0)) { n=names; for(c=0;c<m->nrow;c++) n+=strlen(strcpy(n,mm->getmpname(ctx,MM_MPNAM_ROW,c)))+1; if((r=XPRSaddnames(slpb->xpb,1,names,0,m->nrow-1))!=0) mm->dispmsg(ctx,"myxprs: Error when executing `addnames'.\n"); } if(!r && (m->nsos>0)) { n=names; for(c=0;c<m->nsos;c++) n+=strlen(strcpy(n,mm->getmpname(ctx,MM_MPNAM_SOS,c)))+1; if((r=XPRSaddnames(slpb->xpb,3,names,0,m->nsos-1))!=0) mm->dispmsg(ctx,"myxprs: Error when executing `addnames'.\n"); } free(names); } } return r; }
In this subroutine, the loading of names is subject to the presence of the option flag LOADNAMES that is set via a new module parameter myxp_loadnames which is declared via the following entry in the table of parameters:
{"myxp_loadnames",XPRM_TYP_BOOL|XPRM_CPAR_READ|XPRM_CPAR_WRITE}
Implementing the 'writeprob' subroutine
The writeprob routine shown in the Mosel model extract at the beginning of this section needs to be declared in the table of subroutines structure by adding the following line to it:
{"writeprob",2103,XPRM_TYP_NOT,2,"ss",slvlc_writepb}
And the actual implementation in the function slvlc_writepb consists of a call the the solver's matrix output function, along with some error handling such as a check for write access to the specified location:
static int slvlc_writepb(XPRMcontext ctx,void *libctx) { s_slvpb *slpb; int rts; char *dname,*options; char ename[MM_MAXPATHLEN]; slpb=SLCTX2PB((s_slvctx*)libctx); dname=MM_POP_REF(ctx); options=MM_POP_REF(ctx); if((dname!=NULL)&& /* Make sure the file can be created */ (mm->pathcheck(ctx,dname,ename,MM_MAXPATHLEN,MM_RCHK_WRITE|MM_RCHK_IODRV)==0)) { slpb->saved_ctx=ctx; /* Save current context for callbacks */ rts=XPRSwriteprob(slpb->xpb,XNLSconvstrto(XNLS_ENC_FNAME,ename,-1,NULL),options); slpb->saved_ctx=NULL; if(rts) { mm->dispmsg(ctx,"myxprs: Error when executing `writeprob'.\n"); return RT_IOERR; } else return RT_OK; } else { mm->dispmsg(ctx,"myxprs: Cannot write to '%s'.\n",dname!=NULL?dname:""); return RT_IOERR; } }
© 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.