![]() | |||||||||
| |||||||||
Apply an integer fixing heuristic to a MIP problem Description We take the power generation problem stored in hpw15.mat which seeks to optimise the operating pattern of a group of electricity generators. We solve this MIP with a very loose integer tolerance and then fix all binary and integer variables to their rounded integer values, changing both their lower and upper bounds. We then solve the resulting LP. The results are displayed on screen and the problem statistics stored in a logfile.
Source Files Data Files roundint.c /*********************************************************************** Xpress Optimizer Examples ========================= file roundint.c ``````````````` Apply an integer fixing heuristic to a MIP problem. The program also demonstrates the use of the integer solution callback. Description: We take the power generation problem stored in hpw15.mat which seeks to optimise the operating pattern of a group of electricity generators. We solve this MIP with a very loose integer tolerance and then fix all binary and integer variables to their rounded integer values, changing both their lower and upper bounds. We then solve the resulting LP. The results are displayed on screen and the problem statistics stored in a logfile. (c) 2017 Fair Isaac Corporation ***********************************************************************/ #include <stdio.h> #include <stdlib.h> #include "xprs.h" /* Optimizer header file */ XPRSprob probg; #define TOL 0.3 /* Integer tolerance */ void XPRS_CC intsol(XPRSprob, void* data); void XPRS_CC optimizermsg(XPRSprob prob, void* data, const char *sMsg,int nLen,int nMsgLvl); void errormsg(const char *sSubName,int nLineNo,int nErrCode); int main() { int nReturn; /* Return value of Optimizer subroutine */ int nOptimizerVersion; /* Optimizer version number */ char sProblem[]="hpw15"; /* Problem name */ char sLogFile[]="roundint.log"; /* Log file name */ int nExpiry; int nCol; /* Number of columns */ /* Global problem information */ int nGlEnt; /* Number of global entities: binary, integer, semi-continuous and partial integer variables */ int nSet; /* Number of S1 and S2 sets */ int *pGlInd; /* Column indices of the global entities */ char *pGlType; /* Global entity types /* Bound changes */ int *pBndInd; /* Column indices of the bounds to be changed */ char *pBndType; /* New bound types - always 'B', since both the upper and lower bounds are to be changed */ double *pBndVal; /* New bound values */ int nBnd; /* Bound counter */ int i; /* Loop counter */ int j; /* Holder for the bound indices */ /* Solution information */ double *x,*y; /* MIP and LP solution values */ double dObjVal; /* Objective function value */ char banner[256]; /* Initialise Optimizer */ nReturn=XPRSinit(NULL); XPRSgetbanner(banner); printf("%s",banner); if (nReturn == 8) return(1); nReturn=XPRScreateprob(&probg); if (nReturn != 0 && nReturn != 32) errormsg("XPRScreateprob",__LINE__,nReturn); /* Tell Optimizer to call optimizermsg whenever a message is output */ nReturn=XPRSsetcbmessage(probg,optimizermsg,NULL); /* Get and display the Optimizer version number */ if (nReturn=XPRSgetintcontrol(probg,XPRS_VERSION,&nOptimizerVersion)) errormsg("XPRSgetintcontrol",__LINE__,nReturn); printf("Xpress Optimiser Subroutine Library Release %.2f\n\n", (float)nOptimizerVersion/100); /* Disable cuts - or the optimal solution will be found at the top node and the integer solution callback will hardly be used */ if (nReturn=XPRSsetintcontrol(probg,XPRS_CUTSTRATEGY,0)) errormsg("XPRSsetintcontrol",__LINE__,nReturn); /* Read the problem file */ if (nReturn=XPRSreadprob(probg,sProblem,"")) errormsg("XPRSreadprob",__LINE__,nReturn); /*** Solve MIP with loose integer tolerance ***/ /* Set integer feasibility tolerance */ if (nReturn=XPRSsetdblcontrol(probg,XPRS_MIPTOL,TOL)) errormsg("XPRSsetdblcontrol",__LINE__,nReturn); /* Tell Optimizer to print out global information at each node and call intsol whenever an integer solution is found */ if (nReturn=XPRSsetintcontrol(probg,XPRS_MIPLOG,3)) errormsg("XPRSsetintcontrol",__LINE__,nReturn); nReturn=XPRSsetcbintsol(probg,&intsol,NULL); /* Get the number of columns */ if (nReturn=XPRSgetintattrib(probg,XPRS_COLS,&nCol)) errormsg("XPRSgetintattrib",__LINE__,nReturn); /* Allocate memory for MIP solution array and check for memory shortage */ x=malloc(nCol * sizeof(double)); if (!x) errormsg("malloc",__LINE__,-1); /* Solve the MIP problem and get the solution values */ printf("Applying an integer fixing heuristic to problem %s:-\n\n",sProblem); printf("Solving MIP with global:\n\n"); if (nReturn=XPRSmipoptimize(probg,"")) errormsg("XPRSmipoptimize",__LINE__,nReturn) ; if (nReturn=XPRSgetmipsol(probg,x,NULL)) errormsg("XPRSgetmipsol",__LINE__,nReturn); /*** Round off the values of all binary and integer variables ***/ /* Allocate memory for global entity arrays */ pGlInd=malloc(nCol * sizeof(int)); pGlType=malloc(nCol * sizeof(char)); if (!pGlInd || !pGlType) errormsg("malloc",__LINE__,-1); /* Retrieve global entity information */ if (nReturn=XPRSgetglobal(probg,&nGlEnt,&nSet,pGlType,pGlInd,NULL,NULL,NULL,NULL,NULL)) errormsg("XPRSgetglobal",__LINE__,nReturn); /* Allocate memory for bound arrays */ pBndInd=malloc(nGlEnt * sizeof(int)); pBndVal=malloc(nGlEnt * sizeof(double)); pBndType=malloc(nGlEnt * sizeof(char)); if (!pBndInd || !pBndVal || !pBndType) errormsg("malloc",__LINE__,-1); /* Initialise bound counter */ nBnd = 0; /* Go through global entities */ for(i=0; i<nGlEnt; i++) { /* Test whether each is a binary or integer variable */ if (pGlType[i] == 'B' || pGlType[i] == 'I') { /* Hold the index of the variable */ j = pGlInd[i]; /* Store the index, round the variable's value to the nearest integer, and reset both its upper and lower bounds */ pBndInd[nBnd]=j; pBndVal[nBnd]=(double) (int)(x[j]+0.5); pBndType[nBnd]='B'; nBnd++; } } /* Instruct Optimizer to change the bounds */ if (nReturn=XPRSchgbounds(probg,nBnd,pBndInd,pBndType,pBndVal)) errormsg("XPRSchgbounds",__LINE__,nReturn); printf("\nAfter global the %d binary and integer variables were fixed\n\n",nBnd); /*** Solve the resulting LP ***/ /* Allocate memory for LP solution array and check for memory shortage */ y=malloc(nCol * sizeof(double)); if (!y) errormsg("malloc",__LINE__,-1); /* Solve the LP and get the solution values */ if (nReturn=XPRSlpoptimize(probg,"")) errormsg("XPRSlpoptimize",__LINE__,nReturn); if (nReturn=XPRSgetlpsol(probg,y,NULL,NULL,NULL)) errormsg("XPRSgetlpsol",__LINE__,nReturn); /* Get and print the LP objective function value */ if (nReturn=XPRSgetdblattrib(probg,XPRS_LPOBJVAL,&dObjVal)) errormsg("XPRSgetdblattrib",__LINE__,nReturn); printf("After solving the LP the final objective value was %g\n\n",dObjVal); /* Print the non-zero MIP and corresponding LP solution values for comparison:*/ printf("The non-zero MIP and LP solution values are:\n\n"); for(i=0; i<nCol; i++) if(x[i]) printf(" x[%2d] = %5.1f %5.3g\n",i,x[i],y[i]); printf("\n"); /* Free memory, close files */ free(x); free(pGlInd); free(pGlType); free(pBndInd); free(pBndVal); free(pBndType); free(y); if (nReturn=XPRSdestroyprob(probg)) errormsg("XPRSdestroyprob",__LINE__,nReturn); if (nReturn=XPRSfree()) errormsg("XPRSfree",__LINE__,nReturn); return(0); } /**********************************************************************************\ * Name: intsol * * Purpose: Displays the objective value associated with a node in the global * * search. This function is called every time an integer solution has * * been found. * * Arguments: None * * Return Value: 0 * \**********************************************************************************/ void XPRS_CC intsol(XPRSprob prob, void* data) { int nReturn; /* Return value of Optimizer subroutine */ int nNode; /* Node number */ double dObjVal; /* Objective function value */ /* Get the node number */ if (nReturn=XPRSgetintattrib(prob,XPRS_NODES,&nNode)) errormsg("XPRSgetintattrib",__LINE__,nReturn); /* Get the objective function value */ if (nReturn=XPRSgetdblattrib(prob,XPRS_LPOBJVAL,&dObjVal)) errormsg("XPRSgetdblattrib",__LINE__,nReturn); /* Print the node number and the associated objective value */ printf(" Node %d (Objective value = %g)\n",nNode,dObjVal); return; } /**********************************************************************************\ * Name: optimizermsg * * Purpose: Display Optimizer error messages and warnings. * * Arguments: const char *sMsg Message string * * int nLen Message length * * int nMsgLvl Message type * * Return Type: None * \**********************************************************************************/ void XPRS_CC optimizermsg(XPRSprob prob, void* data, const char *sMsg,int nLen,int nMsgLvl) { switch (nMsgLvl) { /* Print Optimizer error messages and warnings */ case 4: /* error */ case 3: /* warning */ printf("%*s\n",nLen,sMsg); break; /* Ignore other messages */ case 2: /* dialogue */ case 1: /* information */ break; /* Exit and flush buffers */ default: fflush(NULL); break; } } /**********************************************************************************\ * Name: errormsg * * Purpose: Display error information about failed subroutines. * * Arguments: const char *sSubName Subroutine name * * int nLineNo Line number * * int nErrCode Error code * * Return Value: None * \**********************************************************************************/ void errormsg(const char *sSubName,int nLineNo,int nErrCode) { int nErrNo; /* Optimizer error number */ /* Print error message */ printf("The subroutine %s has failed on line %d\n",sSubName,nLineNo); /* Append the error code, if it exists */ if (nErrCode!=-1) printf("with error code %d\n",nErrCode); /* Append Optimizer error number, if available */ if (nErrCode==32) { XPRSgetintattrib(probg,XPRS_ERRORCODE,&nErrNo); printf("The Optimizer error number is: %d\n",nErrNo); } /* Free memory, close files and exit */ XPRSdestroyprob(probg); XPRSfree(); exit(nErrCode); }
| |||||||||
Copyright 2017 Fair Isaac Corporation. |