/***********************************************************************
Xpress Optimizer Examples
=========================
file mipsolpool.c
`````````````````
Generate all solutions with the MIP solution pool
We take the power generation problem stored in hpw15.mps which seeks to
optimise the operating pattern of a group of electricity generators. We
solve the problem collecting all solutions found during the MIP search.
The optimal solution's objective and solution values are printed to
screen.
(c) 2017-2025 Fair Isaac Corporation
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "xprs.h" /* Optimizer header file */
/* Calls an Xpress optimizer function and checks the return code.
* If the call fails then the function
* - prints a short error message to stderr,
* - sets variable 'returnCode' to the error,
* - and branches to label 'cleanup'.
*/
#define CHECK_RETURN(call) do { \
int result_ = call; \
if ( result_ != 0 ) { \
fprintf(stderr, "Line %d: %s failed with %d\n", \
__LINE__, #call, result_); \
returnCode = result_; \
goto cleanup; \
} \
} while (0)
static void XPRS_CC messagecb(XPRSprob cbprob, void* cbdata,
const char *msg, int len, int msgtype);
int main(void) {
int returnCode = 0;
XPRSprob prob = NULL;
XPRSmipsolpool msp = NULL;
int i, nSols, nCols, iSolutionId, iSolutionIdStatus;
double dObj, dSol;
const char *sProblem = "../data/hpw15";
/* Initialize the optimizer. */
if ( XPRSinit("") != 0 ) {
char message[512];
XPRSgetlicerrmsg(message, sizeof(message));
fprintf(stderr, "Licensing error: %s\n", message);
return 1;
}
/* Create a new problem and immediately register a message handler.
* Once we have a message handler installed, errors will produce verbose
* error messages on the console and we can limit ourselves to minimal
* error handling in the code here.
*/
CHECK_RETURN( XPRScreateprob(&prob) );
CHECK_RETURN( XPRSaddcbmessage(prob, messagecb, NULL, 0) );
CHECK_RETURN( XPRS_msp_create(&msp) );
CHECK_RETURN( XPRS_msp_probattach(msp, prob) );
CHECK_RETURN( XPRSreadprob(prob, sProblem, "") );
CHECK_RETURN( XPRSmipoptimize(prob, "") );
CHECK_RETURN( XPRS_msp_getintattrib(msp, XPRS_MSP_SOLUTIONS, &nSols) );
if(nSols) {
CHECK_RETURN( XPRS_msp_getdblattribprobextreme(msp, prob, 0, &iSolutionId,
XPRS_MSP_SOLPRB_OBJ, &dObj) );
printf("Optimal Solution ID: %i\n", iSolutionId);
printf("Optimal Objective : %12.5f\n", dObj);
CHECK_RETURN( XPRS_msp_getintattribsol(msp, iSolutionId,
&iSolutionIdStatus,
XPRS_MSP_SOL_COLS, &nCols) );
for(i = 0; i < nCols; i++) {
CHECK_RETURN( XPRS_msp_getsol(msp, iSolutionId, &iSolutionIdStatus,
&dSol, i, i, NULL) );
printf("%3i = %12.5f\n", i, dSol);
}
}
cleanup:
if (returnCode > 0) {
/* There was an error with the solver. Get the error code and error message.
* If prob is still NULL then the error was in XPRScreateprob() and
* we cannot find more detailed error information.
*/
if (prob != NULL) {
int errorCode = -1;
char errorMessage[512] = {0};
XPRSgetintattrib(prob, XPRS_ERRORCODE, &errorCode);
XPRSgetlasterror(prob, errorMessage);
fprintf(stderr, "Error %d: %s\n", errorCode, errorMessage);
}
}
/* Free the resources (variables are initialized so that this is valid
* even in case of error).
*/
XPRSdestroyprob(prob);
XPRS_msp_destroy(msp);
XPRSfree();
return returnCode;
}
/* XPRS optimizer message callback */
void XPRS_CC messagecb(XPRSprob cbprob, void* cbdata,
const char *msg, int len, int msgtype)
{
(void)cbprob; /* unused (the problem for which the message is issued) */
(void)cbdata; /* unused (the data passed to XPRSaddcbmessage()) */
switch(msgtype)
{
case 4: /* error */
case 3: /* warning */
case 2: /* not used */
case 1: /* information */
printf("%*s\n", len, msg);
break;
default: /* exiting - buffers need flushing */
fflush(stdout);
break;
}
}
|