User error handling
In this section we use a small, infeasible problem to demonstrate how the error handling and all printed messages produced by BCL can be intercepted by the user's program. This is done by defining the corresponding BCL callback functions and changing the error handling flag. If error handling by BCL is disabled, then the definition of the error callback replaces the necessity to check for the return values of the BCL functions called by a program.
User error handling may be required if a BCL program is embedded in some larger application or if the program is run under Windows from an application with windows. In all other cases it will usually be sufficient to use the error handling provided by BCL.
#include <stdio.h> #include <setjmp.h> #include <string.h> #include "xprb.h" jmp_buf model_failed; /* Marker for the longjump */ void modinf(XPRBprob prob) { XPRBvar x[3]; XPRBctr ctr[2], cobj; int i; for(i=0;i<2;i++) /* Create two integer variables */ x[i]=XPRBnewvar(prob, XPRB_UI, XPRBnewname("x_%d",i),0,100); /* Create the constraints: C1: 2x0 + 3x1 >= 41 C2: x0 + 2x1 = 13 */ ctr[0]=XPRBnewctr(prob,"C1",XPRB_G); XPRBaddterm(ctr[0],x[0],2); XPRBaddterm(ctr[0],x[1],3); XPRBaddterm(ctr[0],NULL,41); ctr[1]=XPRBnewctr(prob,"C2",XPRB_E); XPRBaddterm(ctr[1],x[0],1); XPRBaddterm(ctr[1],x[1],2); XPRBaddterm(ctr[1],NULL,13); /* Uncomment the following line to cause an error in the model that triggers the user error handling: */ /* x[2]=XPRBnewvar(prob, XPRB_UI, "x_2", 10, 1); */ /* Objective: minimize x0+x1 */ cobj = XPRBnewctr(prob,"OBJ",XPRB_N); for(i=0;i<2;i++) XPRBaddterm(cobj, x[i], 1); XPRBsetobj(prob,cobj); /* Select objective function */ XPRBsetsense(prob,XPRB_MINIM); /* Obj. sense: minimization */ XPRBprintprob(prob); /* Print current problem */ XPRBlpoptimize(prob,""); /* Solve the LP */ XPRBprintf(prob, "problem status: %d LP status: %d MIP status: %d\n", XPRBgetprobstat(prob), XPRBgetlpstat(prob), XPRBgetmipstat(prob)); /* This problem is infeasible, that means the following command will fail. It prints a warning if the message level is at least 2 */ XPRBprintf(prob, "Objective: %g\n", XPRBgetobjval(prob)); for(i=0;i<2;i++) /* Print solution values */ XPRBprintf(prob, "%s:%g, ", XPRBgetvarname(x[i]), XPRBgetsol(x[i])); XPRBprintf(prob, "\n"); } /**** User error handling function ****/ void XPRB_CC usererror(XPRBprob prob, void *vp, int num, int type, const char *t) { printf("BCL error %d: %s\n", num, t); if(type==XPRB_ERR) longjmp(model_failed,1); } /**** User printing function ****/ void XPRB_CC userprint(XPRBprob prob, void *vp, const char *msg) { static int rtsbefore=1; /* Print 'BCL output' whenever a new output line starts, otherwise continue to print the current line. */ if(rtsbefore) printf("BCL output: %s", msg); else printf("%s",msg); rtsbefore=(msg[strlen(msg)-1]=='\n'); } int main(int argc, char **argv) { XPRBprob prob; XPRBseterrctrl(0); /* Switch to error handling by the user's program */ XPRBsetmsglevel(NULL,2); /* Set the printing flag to printing errors and warnings */ XPRBdefcbmsg(NULL, userprint, NULL); /* Define the printing callback func. */ if((prob=XPRBnewprob("ExplInf"))==NULL) { /* Initialize a new problem in BCL */ fprintf(stderr,"I cannot create the problem\n"); return 1; } else if(setjmp(model_failed)) /* Set a marker at this point */ { fprintf(stderr,"I cannot build the problem\n"); XPRBdelprob(prob); /* Delete the part of the problem that has been created */ XPRBdefcberr(prob, NULL, NULL); /* Reset the error callback */ return 1; } else { XPRBdefcberr(prob, usererror, NULL); /* Define the error handling callback */ modinf(prob); /* Formulate and solve the problem */ XPRBdefcberr(prob, NULL, NULL); /* Reset the error callback */ return 0; } }
Since this example defines the printing level and the printing callback function before creating the problem (that is, before BCL is initialized), we pass NULL as first argument.
© 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.