FICO
FICO Xpress Optimization Examples Repository
FICO Optimization Community FICO Xpress Optimization Home
Back to examples browserPrevious exampleNext example

Modify problem: add an extra variable within an additional constraint

Description
We take the trimloss problem described in trimloss.mat, in which each integer variable x(p) represents the number of rolls cut to pattern p. We define a new integer variable y=SUM(p)x(p) and add the associated constraint
            x(1)+x(2)+...+x(N)-y = 0
We do this by first adding a row containing the (unitary) coefficients of the x(p), and then a column corresponding to y. We output the revised matrix to a file and then solve the revised MIP, giving y the highest branching priority. Finally, we output the solution, both to the screen and to an ASCII solution file.


Source Files

Data Files





trimloss.c

/***********************************************************************
   Xpress Optimizer Examples
   =========================

   file trimloss.c
   ```````````````
   Modify a problem by adding an extra variable within an additional
   constraint.

   We take a trimloss problem in which each integer variable x(p)
   represents the number of rolls cut to pattern p.
   We define a new integer variable y=SUM(p)x(p) and add the associated
   constraint
                           x(1)+x(2)+...+x(N)-y = 0
   We do this by first adding a row containing the (unitary)
   coefficients of the x(p), and then a column corresponding to y.
   We output the revised matrix to a file and then solve the revised
   MIP, giving y the highest branching priority. Finally, we output
   the solution, both to the screen and to an ASCII solution file.

   (c) 2017 Fair Isaac Corporation
***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xprs.h"                 /* Optimizer header file */

XPRSprob probg;

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[]="..\\data\\trimloss";/* Problem name */
   char   sLogFile[]="trimloss.log";      /* Log file name */

   int    nRow;            /* Number of rows */
   int    nCol;            /* Number of columns */
   int    i;               /* Loop counter */

   /* New row variables */
   int    nNewRow = 1;     /* Number of new rows */
   int    nRowElem;        /* Number of non-zero elements in the new row */
   double *pRowVal;        /* Values of the new row elements */
   int    *pColInd;        /* Column indices of the new row elements */
   int    nRowStart[1];    /* Start position of the row in pRowVal */
   char   sRowType[1];     /* New row type */
   double dRHS[1];         /* New RHS value */
   char   sRowName[9];     /* New row name */

   /* New column variables */
   int    nNewCol = 1;     /* Number of new columns */
   int    nColElem;        /* Number of non-zero elements in the new column */
   double *pColVal;        /* Values of the new column elements */
   int    *pRowInd;        /* Row indices of the new column elements */
   int    nColStart[1];    /* Start position of the column in pColVal */
   double dObjCoef[1];     /* Objective coefficient of the new column */
   double dUpperBnd[1];    /* Upper bound on the new column */
   double dLowerBnd[1];    /* Lower bound on the new column */
   char   sColType[1];     /* New column type */
   int    nNewColInd[1];   /* New column index */
   int    nTypeChg = 1;    /* Number of column types to change - to make y
                              an integer variable */
   char   sColName[9];     /* New column name */
   int    nColPrior[1];    /* Branching priority of the new column */
   int    nExpiry;
   char   cOptMessage[200];
   int istudent;

   /* Solution variables */
   double dObjVal;         /* Objective value of the best integer solution found */
   double *x;              /* Primal solution values */

   char banner[256];

   /* Initialise Optimizer */
   nReturn=XPRSinit(NULL);
   XPRSgetbanner(banner); printf("%s",banner);
   if (nReturn == 8) return(1);
   istudent = (nReturn == 32); /* Check for student license */

   nReturn=XPRScreateprob(&probg);
   if (nReturn != 0 && nReturn != 32) errormsg("XPRScreateprob",__LINE__,nReturn);

   /* Remove and define log file */
   remove(sLogFile);
   if (nReturn=XPRSsetlogfile(probg,sLogFile)) errormsg("XPRSsetlogfile",__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);

   /* Turn off presolve and permit no cuts */
   if (nReturn=XPRSsetintcontrol(probg,XPRS_PRESOLVE,0)) errormsg("XPRSsetintcontrol",__LINE__,nReturn);
   if (nReturn=XPRSsetintcontrol(probg,XPRS_CUTSTRATEGY,0)) errormsg("XPRSsetintcontrol",__LINE__,nReturn);

   /* Read the problem file */
   if (nReturn=XPRSreadprob(probg,sProblem,"")) errormsg("XPRSreadprob",__LINE__,nReturn);

   /* Get the number of rows and columns */
   if (nReturn=XPRSgetintattrib(probg,XPRS_ROWS,&nRow)) errormsg("XPRSsetintcontrol",__LINE__,nReturn);
   if (nReturn=XPRSgetintattrib(probg,XPRS_COLS,&nCol)) errormsg("XPRSsetintcontrol",__LINE__,nReturn);

   /*** Construct and add the new row ***/

   /* Assign the number of new row elements*/
   nRowElem = nCol;

   /* Allocate memory for the new row arrays */
   pRowVal=malloc(nRowElem * sizeof(double));
   pColInd=malloc(nRowElem * sizeof(int));
   if (!pRowVal || !pColInd ) errormsg("malloc",__LINE__,-1);

   /* Construct the new row */
   dRHS[0]       = 0.0;
   nRowStart[0]  = 0;
   sRowType[0]   = 'E';
   /* Store the coefficents of the x(p) */
   for (i = 0; i < nCol; i++) {
      pRowVal[i] = 1.0;
      pColInd[i] = i;
   }

   /* Add the new row */
   if (nReturn=XPRSaddrows(probg,nNewRow,nRowElem,sRowType,dRHS,NULL,nRowStart,pColInd,
       pRowVal)) errormsg("XPRSaddrows",__LINE__,nReturn);

   /* Update the number of rows */
   if (nReturn=XPRSgetintattrib(probg,XPRS_ROWS,&nRow)) errormsg("XPRSsetintcontrol",__LINE__,nReturn);

   /* Add new row name */
   strcpy(sRowName,"NewRow");
   if (nReturn=XPRSaddnames(probg,1,sRowName,nRow-1,nRow-1))
       errormsg("XPRSaddnames",__LINE__,nReturn);

   /*** Construct and add the new column ***/

   /* Assign the number of new column elements*/
   nColElem = 1;

   /* Allocate memory for the new column arrays */
   pColVal=malloc(nColElem  * sizeof(double));
   pRowInd=malloc(nColElem  * sizeof(int));
   if (!pColVal || !pRowInd) errormsg("malloc",__LINE__,-1);

   /* Construct the new column */
   dObjCoef[0]  = 0.0;
   nColStart[0] = 0;
   pColVal[0]   = -1.0; /* the coefficent of -y */
   pRowInd[0]   = nRow-1;
   dLowerBnd[0] = 0.0;
   dUpperBnd[0] = 90;   /* the sum of the bounds on the x(p) */

   /* Add the new column */
   if (nReturn=XPRSaddcols(probg,nNewCol,nColElem,dObjCoef,nColStart,pRowInd,pColVal,
       dLowerBnd,dUpperBnd)) errormsg("XPRSaddcols",__LINE__,nReturn);

   /* Update the number of columns */
   if (nReturn=XPRSgetintattrib(probg,XPRS_COLS,&nCol)) errormsg("XPRSsetintcontrol",__LINE__,nReturn);

   /* Make the new column an integer variable */
   nTypeChg=1;
   nNewColInd[0]=nCol-1;
   sColType[0]= 'I';

   if (nReturn=XPRSchgcoltype(probg,nTypeChg,nNewColInd,sColType))
       errormsg("XPRSchgcoltype",__LINE__,nReturn);

   /* Add new column name */
   strcpy(sColName,"y");
   if (nReturn=XPRSaddnames(probg,2,sColName,nCol-1,nCol-1))
       errormsg("XPRSaddnames",__LINE__,nReturn);

   /*** Output the revised matrix ***/
   if ( ! istudent ) {
     if (nReturn=XPRSwriteprob(probg,"revised","")) errormsg("XPRSwriteprob",__LINE__,nReturn);
   }

   /*** Solve the revised MIP ***/

   /* Assign the y variable a high branching priority (1)
      - by default the original x(p) variables have low priority (500) */
   nColPrior[0] = 1;

   /* Load this directive */
   if (nReturn=XPRSloaddirs(probg,1,nNewColInd,nColPrior,NULL,NULL,NULL))
      errormsg("XPRSloaddirs",__LINE__,nReturn);

   /* Solve the MIP */
   printf("Solving problem %s:\n\n",sProblem);
   if (nReturn=XPRSminim(probg,"g")) errormsg("XPRSminim",__LINE__,nReturn);

   /* Get the objective value of the best integer solution found */
   if (nReturn=XPRSgetdblattrib(probg,XPRS_MIPOBJVAL,&dObjVal)) errormsg("XPRSgetdblattrib",__LINE__,nReturn);

   /* Allocate memory to the solution array */
   x=malloc(nCol*sizeof(double));
   if (!x) errormsg("malloc",__LINE__,-1);

   /* Get the primal solution values */
   if (nReturn=XPRSgetsol(probg,x,NULL,NULL,NULL)) errormsg("XPRSgetsol",__LINE__,nReturn);

   /* Display the objective and solution values */
   printf("   Minimum loss is %g\n\n",dObjVal);
   printf("   The solution values are\n");
   for(i = 0; i < nCol-1; i++)
      printf("        x(%d)=%g\n",i+1,x[i]);
   printf("        y = %g\n\n",x[nCol-1]);

   /* Save the solution to an ASCII file */
   if ( ! istudent ) {
     if (nReturn=XPRSwritesol(probg,"revised","")) errormsg("XPRSwritesol",__LINE__,nReturn);
   }

   /* Free memory and close files */
   free(pRowVal);
   free(pColInd);
   free(pColVal);
   free(pRowInd);
   free(x);
   if (nReturn=XPRSdestroyprob(probg)) errormsg("XPRSdestroyprob",__LINE__,nReturn);
   if (nReturn=XPRSfree()) errormsg("XPRSfree",__LINE__,nReturn);

   return 0;
   }


/**********************************************************************************\
* Name:         optimizermsg                                                          *
* Purpose:      To display Optimizer error messages and warnings.                       *
* Arguments:    const char *sMsg       Message string                              *
*               int nLen               Message length                              *
*               int nMsgLvl            Message type                                *
\**********************************************************************************/
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:      To 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);
}



Back to examples browserPrevious exampleNext example