Пример #1
0
static int
populatebycolumn (CPXENVptr env, CPXLPptr lp)
{
   int        status    = 0;
   double     obj[NUMCOLS];
   double     lb[NUMCOLS];
   double     ub[NUMCOLS];
   char const *colname[NUMCOLS];
   CPXNNZ     matbeg[NUMCOLS];
   CPXDIM     matind[NUMNZ];
   double     matval[NUMNZ];
   double     rhs[NUMROWS];
   char       sense[NUMROWS];
   char const *rowname[NUMROWS];

   /* To build the problem by column, create the rows, and then 
      add the columns. */

   status = CPXXchgobjsen (env, lp, CPX_MAX);  /* Problem is maximization */
   if ( status )  goto TERMINATE;

   /* Now create the new rows.  First, populate the arrays. */

   rowname[0] = "c1";
   sense[0]   = 'L';
   rhs[0]     = 20.0;

   rowname[1] = "c2";
   sense[1]   = 'L';
   rhs[1]     = 30.0;

   status = CPXXnewrows (env, lp, NUMROWS, rhs, sense, NULL, rowname);
   if ( status )   goto TERMINATE;

   /* Now add the new columns.  First, populate the arrays. */

       obj[0] = 1.0;      obj[1] = 2.0;           obj[2] = 3.0;

    matbeg[0] = 0;     matbeg[1] = 2;          matbeg[2] = 4;
      
    matind[0] = 0;     matind[2] = 0;          matind[4] = 0;
    matval[0] = -1.0;  matval[2] = 1.0;        matval[4] = 1.0;
 
    matind[1] = 1;     matind[3] = 1;          matind[5] = 1;
    matval[1] = 1.0;   matval[3] = -3.0;       matval[5] = 1.0;

        lb[0] = 0.0;       lb[1] = 0.0;           lb[2]  = 0.0;
        ub[0] = 40.0;      ub[1] = CPX_INFBOUND;  ub[2]  = CPX_INFBOUND;

   colname[0] = "x1"; colname[1] = "x2";      colname[2] = "x3";

   status = CPXXaddcols (env, lp, NUMCOLS, NUMNZ, obj, matbeg, matind,
                        matval, lb, ub, colname);
   if ( status )  goto TERMINATE;

TERMINATE:

   return (status);

}  /* END populatebycolumn */
Пример #2
0
static int
buildmodel (CPXENVptr env, CPXLPptr lp)
{

   CPXDIM colcnt = NUMVARS*NUMMONTHS*NUMPRODUCTS;

   double *obj     = NULL;
   double *lb      = NULL;
   double *ub      = NULL;
   char   *ctype   = NULL;
   CPXDIM *rmatind = NULL;
   double *rmatval = NULL;

   CPXDIM indicator;
   CPXNNZ rmatbeg[1];
   double rhs[1];
   char   sense[1];

   int    m, p;
   int    status = 0;

   status = CPXXchgobjsen (env, lp, CPX_MAX); /* Maximization problem */
   if ( status ) {
      fprintf (stderr, "Could not change objective sense.\n");
      goto TERMINATE;
   }

   rmatbeg[0] = 0;

   /* Allocate colcnt-sized arrays */

   obj     = malloc (colcnt * sizeof(*obj));
   lb      = malloc (colcnt * sizeof(*lb));
   ub      = malloc (colcnt * sizeof(*ub));
   ctype   = malloc (colcnt * sizeof(*ctype));
   rmatind = malloc (colcnt * sizeof(*rmatind));
   rmatval = malloc (colcnt * sizeof(*rmatval));

   if ( obj     == NULL ||
        lb      == NULL ||
        ub      == NULL ||
        ctype   == NULL ||
        rmatind == NULL ||
        rmatval == NULL   ) {
      fprintf (stderr, "Could not allocate colcnt arrays\n");
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }

   /* Create variables. For each month and each product, we have 3
      variables corresponding to the quantity used (semi-continuous),
      stored (continuous) and bought (continuous) and one binary
      variable indicating whether or not the product is used during
      this month. */

   for (m = 0; m < NUMMONTHS; m++) {
      for (p = 0; p < NUMPRODUCTS; p++) {

         /* The quantity bought is a continuous variable. It has a cost */

         obj[varindex(m, p, BUY)]    = -cost[m*NUMPRODUCTS + p];
         lb[varindex (m, p, BUY)]    = 0.0;
         ub[varindex (m, p, BUY)]    = CPX_INFBOUND;
         ctype[varindex (m, p, BUY)] = 'C';

         /* When an oil is used, the quantity must be at least 20
            tons. This is modeled as a semi-continuous variable. */

         obj[varindex (m, p, USE)]   = 0.0;
         lb[varindex (m, p, USE)]    = 20.0;
         ub[varindex (m, p, USE)]    = CPX_INFBOUND;
         ctype[varindex (m, p, USE)] = 'S';

         /* It is possible to store up to 1000 tons of each
            product. There are storage costs. */

         obj[varindex (m, p, STORE)]   = -5.0;
         lb[varindex (m, p, STORE)]    = 0.0;
         ub[varindex (m, p, STORE)]    = 1000.0;
         ctype[varindex (m, p, STORE)] = 'C';

         /* At the end, we must have exactly 500 tons of each
            product in storage. */

         if ( m == NUMMONTHS - 1 ) {
            lb[varindex (m, p, STORE)] = 500.0;
            ub[varindex (m, p, STORE)] = 500.0;
         }

         /* The variable indicating whether or not a product is
            used during a month is a binary variable. */

         obj[varindex (m, p, IS_USED)]   = 0.0;
         lb[varindex (m, p, IS_USED)]    = 0.0;
         ub[varindex (m, p, IS_USED)]    = 1.0;
         ctype[varindex (m, p, IS_USED)] = 'B';
      }
   }

   status = CPXXnewcols (env, lp, colcnt, obj, lb, ub, ctype, NULL);
   if ( status ) {
      fprintf (stderr, "Could not add new columns.\n");
      goto TERMINATE;
   }

   /* Constraints for each month */

   for (m = 0; m < NUMMONTHS; m++) {
      int totalindex;

      /* For each product, create an indicator constraint linking the
         quantity used and the binary variable indicating whether or
         not the product is used */

      for (p = 0; p < NUMPRODUCTS; p++) {
         indicator  = varindex (m, p, IS_USED);
         rmatind[0] = varindex (m, p, USE);
         rmatval[0] = 1.0;
         status = CPXXaddindconstr (env, lp, indicator, 1, 1, 0.0, 'L',
                                   rmatind, rmatval, NULL);
         if ( status ) {
            fprintf (stderr, "Could not add new indicator constraint.\n");
            goto TERMINATE;
         }
      }

      /* Not more than 200 tons of vegetable oil can be refined */

      rmatind[0] = varindex (m, VEGOIL1, USE);
      rmatind[1] = varindex (m, VEGOIL2, USE);
      rmatval[0] = 1.0;
      rmatval[1] = 1.0;
      rhs[0]     = 200.0;
      sense[0]   = 'L';
      status = CPXXaddrows (env, lp, 0, 1, 2, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);

      /* Not more than 250 tons of non-vegetable oil can be refined */

      rmatind[0] = varindex (m, OIL1, USE);
      rmatind[1] = varindex (m, OIL2, USE);
      rmatind[2] = varindex (m, OIL3, USE);
      rmatval[0] = 1.0;
      rmatval[1] = 1.0;
      rmatval[2] = 1.0;
      rhs[0]     = 250.0;
      sense[0]   = 'L';
      status = CPXXaddrows (env, lp, 0, 1, 3, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* Constraint on food composition */

      /* Add a variable corresponding to total quantity produced
         in a month */

      obj[0]   = 150.0;
      lb[0]    = 0.0;
      ub[0]    = CPX_INFBOUND;
      ctype[0] = 'C';

      status = CPXXnewcols (env, lp, 1, obj, lb, ub, ctype, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new columns.\n");
         goto TERMINATE;
      }
      totalindex = CPXXgetnumcols (env, lp) - 1;

      /* Total quantity = sum (quantities) */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, USE);
         rmatval[p] = 1.0;
      }
      rmatind[NUMPRODUCTS] = totalindex;
      rmatval[NUMPRODUCTS] = -1.0;
      rhs[0]               =  0.0;
      sense[0]             = 'E';
      status = CPXXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* Hardness constraints
          sum (quantity * hardness) >= 3 * total quantity
          sum (quantity * hardness) <= 6 * total quantity
      */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, USE);
         rmatval[p] = hardness[p];
      }
      rmatind[NUMPRODUCTS] = totalindex;
      rmatval[NUMPRODUCTS] = -3.0;
      rhs[0]               =  0.0;
      sense[0]             = 'G';
      status = CPXXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      rmatval[NUMPRODUCTS] = -6.0;
      sense[0]             = 'L';
      status = CPXXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* The food may never be made up of more than three oils */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, IS_USED);
         rmatval[p] = 1.0;
      }
      rhs[0]   = 3.0;
      sense[0] = 'L';
      status = CPXXaddrows (env, lp, 0, 1, NUMPRODUCTS, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* If product veg 1 or veg 2 is used then oil 3 must be used */

      indicator  = varindex (m, VEGOIL1, IS_USED);
      rmatind[0] = varindex (m, OIL3, USE);
      rmatval[0] = 1.0;
      status = CPXXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      indicator = varindex (m, VEGOIL2, IS_USED);
      status = CPXXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      if ( status ) {
         fprintf (stderr, "Could not add new indicator constraint.\n");
         goto TERMINATE;
      }

      /* We can store each product from one month to the next,
         starting with a stock of 500 tons */

      for (p = 0; p < NUMPRODUCTS; p++) {
         CPXNNZ n = 0;
         if ( m != 0 ) {
            rmatind[n]   = varindex (m-1, p, STORE); /* stored last month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, BUY);     /* bought this month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, USE);     /* used this month */
            rmatval[n++] = -1.0;
            rmatind[n]   = varindex (m, p, STORE);   /* stored this month */
            rmatval[n++] = -1.0;
            rhs[0]       = 0.0;
            sense[0]     = 'E';
         }
         else {
            rmatind[n]   = varindex (m, p, BUY);   /* bought this month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, USE);   /* used this month */
            rmatval[n++] = -1.0;
            rmatind[n]   = varindex (m, p, STORE); /* stored this month */
            rmatval[n++] = -1.0;
            rhs[0]       = -500.0;
            sense[0]     = 'E';
         }
         status = CPXXaddrows (env, lp, 0, 1, n, rhs,
                              sense, rmatbeg, rmatind, rmatval,
                              NULL, NULL);
         if ( status ) {
            fprintf (stderr, "Could not add new rows.\n");
            goto TERMINATE;
         }
      }
   }

 TERMINATE:

   free_and_null ((char **)&obj);
   free_and_null ((char **)&lb);
   free_and_null ((char **)&ub);
   free_and_null ((char **)&ctype);
   free_and_null ((char **)&rmatind);
   free_and_null ((char **)&rmatval);

   return (status);

}  /* END buildmodel */
Пример #3
0
static int 
rowsteel (int numprod, int tweeks, double const *rate,
          double const *inv0, double const *avail, double const *flatmarket,
          double const *prodcost, double const *invcost,
          double const *flatrevenue, CPXENVptr env, CPXLPptr lp)
{
   double *obj      = NULL;
   double *rhs      = NULL;
   char   *sense    = NULL;

   /* Row representation of the model */
   CPXNNZ *rmatbeg  = NULL;
   CPXDIM *rmatind  = NULL;
   double *rmatval  = NULL;

   CPXCHANNELptr  cpxerror = NULL;

   int    t,p;      /* Various loop counters */
   CPXDIM j;
   CPXNNZ k;

   int  status = 0;

   printf ("Building model by row.\n");

   status = CPXXgetchannels (env, NULL, NULL, &cpxerror, NULL);
   if ( status )  goto TERMINATE;

   /* Set the objective sense to be maximize */

   status = CPXXchgobjsen (env, lp, CPX_MAX);
   if ( status ) {
      CPXXmsg (cpxerror, "Could not change objective sense. Error %d\n",
               status);
      goto TERMINATE;
   }

   /* Set up the variables for the problem.  */

   /* Now fill in the bounds and the objective.  
    * For each variable type, we allocate a vector to hold the 
    * objective coefficients for one product, and multiple time
    * periods.  Note that we allocate and free the vector for
    * each decision variable type to maintain the locality of the code.
    */

   /* First, do the Make variables in (p,t) order.  The bounds are
    * (0, infinity), while the objective for Make[p][t] is -prodcost[p]
    */

   obj = malloc (tweeks*sizeof(*obj));
   if ( obj == NULL ) {
      status = -2;
      goto TERMINATE;
   }

   for (p = 0; p < numprod; p++) {
      for (t = 0; t < tweeks; t++) {
         obj[t]    = -prodcost[p];
      }
      status = CPXXnewcols (env, lp, tweeks, obj, NULL, NULL, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d. Error %d.\n",
                 "CPXXnewcols failed to add Make variables\n",
                 p, status);
         goto TERMINATE;
      }
   }

   /* Free up the obj array. */

   free (obj);  obj = NULL;
   
   /* Now do the Inv variables in (p,t) order. The bounds are
    * (0, infinity), while the objective for Inv[p][t] is -invcost[p]
    */

   obj = malloc (tweeks*sizeof(*obj));
   if ( obj == NULL ) {
      status = -2;
      goto TERMINATE;
   }

   for (p = 0; p < numprod; p++) {
      for (t = 0; t < tweeks; t++) {
         obj[t]    = -invcost[p];
      }
      status = CPXXnewcols (env, lp, tweeks, obj, NULL, NULL, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d. Error %d.\n",
                 "CPXXnewcols failed to add Inv variables\n",
                 p, status);
         goto TERMINATE;
      }
   }

   /* Free up the obj array. */

   free (obj);  obj = NULL;
   
   /* Now do the Sell[p][t] variables in (p,t) order.  The bounds on
    * Sell[p][t] are (0, flatmarket[p*tweeks+t]), and the objective
    * coefficient is flatrevenue[p*tweeks+t].  Because of this
    * structure, we do not need to allocate a temporary objective
    * coefficient array.  
    */

   for (p = 0; p < numprod; p++) {
      status = CPXXnewcols (env, lp, tweeks, &flatrevenue[p*tweeks], 
                           NULL, &flatmarket[p*tweeks], NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d. Error %d.\n",
                 "CPXXnewcols failed to add Make variables\n",
                 p, status);
         goto TERMINATE;
      }
   }

   /* Now generate the constraints.  */

   /* There are tweeks time constraints, each with numprod coefficients.
    * We allocate space for the sense values, and space to hold the matrix.
    * The rhs values are in avail, so there is no need to allocate rhs.
    */

   sense   = malloc (tweeks*sizeof(*sense));
   rmatbeg = malloc (tweeks*sizeof(*rmatbeg));
   rmatind = malloc (tweeks*numprod*sizeof(*rmatind));
   rmatval = malloc (tweeks*numprod*sizeof(*rmatval));

   if ( sense   == NULL ||
        rmatbeg == NULL ||
        rmatind == NULL ||
        rmatval == NULL   ) {
      status = -2;
      goto TERMINATE;
   }

   /* Now generate the time constraints.  The senses are all 'L'.
    * There are numprod  nonzeros in each of these constraints, 
    * with nonzero value (1/rate[p]) for variable Make[p][t]. */

   k = 0;   /* The count of the nonzeros */

   for (t = 0; t < tweeks; t++) {
      sense[t] = 'L';
      rmatbeg[t] = k;
      for (p = 0; p < numprod; p++) {
         rmatind[k] = p*tweeks + t;  /* Formula for Make variable */
         rmatval[k] = 1.0/rate[p];
         k++;
      }
   }

   status = CPXXaddrows (env, lp, 0, tweeks, k, avail, sense, 
                        rmatbeg, rmatind, rmatval, NULL, NULL);
   if ( status ) {
      CPXXmsg (cpxerror, 
              "CPXXaddrows failed to add time constraints. Error %d.\n",
              status);
      goto TERMINATE;
   }

   free (sense);   sense   = NULL;
   free (rmatbeg); rmatbeg = NULL;
   free (rmatind); rmatind = NULL;
   free (rmatval); rmatval = NULL;

   /* Allocate space for each product's balance constraints.  rhs
    * and sense are needed for each time period, and each constraint
    * balance[p,t] has 4 nonzeros. 
    */ 

   rhs     = malloc (tweeks*sizeof(*rhs));
   rmatbeg = malloc (tweeks*sizeof(*rmatbeg));
   rmatind = malloc (4*tweeks*sizeof(*rmatind));
   rmatval = malloc (4*tweeks*sizeof(*rmatval));

   if ( rhs     == NULL ||
        rmatbeg == NULL ||
        rmatind == NULL ||
        rmatval == NULL   ) {
      status = -2;
      goto TERMINATE;
   }

   /* Now generate the balance constraints.  Add rows by product.
    * The rhs values are -inv0[p] for the first time period,
    * and 0.0 otherwise.  The senses are all 'E'.
    * Handle t=0 specially.
    * Use order of variables Inv[t-1], Make, Inv[t], Sell so that
    * rmatind is in column order.
    */

   for (p = 0; p < numprod; p++) {
   
      k = 0;  /* Initialize the nonzero count for each product */

      for (t = 0; t < tweeks; t++) {
         rmatbeg[t] = k;
         if ( t > 0 ) {
            rhs[t]   = 0.0;
            j = (numprod+p)*tweeks + t-1;  /* Inv[p][t-1] index */
            rmatind[k] = j;
            rmatval[k] = 1.0;
            k++;
         }
         else {
            rhs[t] = -inv0[p];
         }
         rmatind[k] = p*tweeks + t;   /* Make[p][t] index */
         rmatval[k] = 1.0;
         k++;
         rmatind[k] = (numprod+p)*tweeks + t;  /* Inv[p][t] index */
         rmatval[k] = -1.0;
         k++;
         rmatind[k] = (2*numprod+p)*tweeks + t;  /* Sell[p][t] index */
         rmatval[k] = -1.0;
         k++;
      }
      /* Now add the rows to the problem */

      status = CPXXaddrows (env, lp, 0, tweeks, k, rhs, NULL, 
                           rmatbeg, rmatind, rmatval, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d. Error %d.\n",
                 "CPXXaddrows failed to add balance constraint\n",
                 p, status);
         goto TERMINATE;
      }
 
   }

   /* Free up arrays used to build balance constraints */

   free (rhs);     rhs   = NULL;
   free (rmatbeg); rmatbeg = NULL;  
   free (rmatind); rmatind = NULL;  
   free (rmatval); rmatval = NULL;  

TERMINATE:

   if ( rmatbeg != NULL )   free ( rmatbeg );
   if ( rmatind != NULL )   free ( rmatind );
   if ( rmatval != NULL )   free ( rmatval );
   if ( rhs     != NULL )   free ( rhs );
   if ( sense   != NULL )   free ( sense );
   if ( obj     != NULL )   free ( obj );

   return (status);

} /* END rowsteel */
Пример #4
0
/* This function creates the following model:
 *   Minimize
 *    obj: x1 + x2 + x3 + x4 + x5 + x6
 *   Subject To
 *    c1: x1 + x2      + x5      = 8
 *    c2:           x3 + x5 + x6 = 10
 *    q1: [ -x1^2 + x2^2 + x3^2 ] <= 0
 *    q2: [ -x4^2 + x5^2 ] <= 0
 *   Bounds
 *    x2 Free
 *    x3 Free
 *    x5 Free
 *   End
 * which is a second order cone program in standard form.
 * The function returns a true value on success and false on error.
 * The function also sets up *cone_p as follows:
 * (*cone_p)[j] >= 0              Column j is contained in a cone constraint
 *                                and is the cone head variable of that
 *                                constraint. The index of the respective
 *                                quadratic constraint is given by (*cone_p)[j].
 * (*cone_p)[j] = NOT_CONE_HEAD   Column j is contained in a cone constraint
 *                                but is not the cone head variable of that
 *                                constraint.
 * (*cone_p)[j] = NOT_IN_CONE     Column j is not contained in any cone
 *                                constraint.
 */
static int
createmodel (CPXENVptr env, CPXLPptr lp, CPXDIM **cone_p)
{
   /* Column data. */
   static double const obj[]        = {  1.0,  1.0,  1.0,  1.0,  1.0,  1.0 };
   static double const lb[]         = {  0.0, -INF, -INF,  0.0, -INF,  0.0 };
   static double const ub[]         = {  INF,  INF,  INF,  INF,  INF,  INF };
   static char const *const cname[] = { "x1", "x2", "x3", "x4", "x5", "x6" };

   /* Row data. */
   static double const rval[]       = { 1.0, 1.0, 1.0,    1.0, 1.0, 1.0 };
   static CPXDIM const rind[]       = {   0,   1,   4,      2,   4,   5 };
   static CPXNNZ const rbeg[]       = {   0,                3           };
   static double const rhs[]        = { 8.0,             10.0           };
   static char const sense[]        = { 'E',              'E'           };
   static char const *const rname[] = { "c1",             "c2"          };

   /* Data for second order cone constraints. */
   static double const qval[]  = { -1.0, 1.0, 1.0 }; /* Same for all Q cons. */
   static double const qrhs    = 0.0;                /* Same for all Q cons. */
   static char const qsense    = 'L';                /* Same for all Q cons. */
   static CPXDIM const qind1[] = { 0, 1, 2 };
   static CPXDIM const qind2[] = { 3, 4 };

   int status;
   int ok = 0;
   CPXDIM *cone = NULL;

   CPXCHANNELptr errc;

   /* Get the channel for printing error messages. */
   if ( (status = CPXXgetchannels (env, NULL, NULL, &errc, NULL)) != 0 )
      goto TERMINATE;

   cone = malloc ((sizeof (obj) / sizeof (obj[0])) * sizeof (*cone));
   if ( cone == NULL ) {
      CPXXmsg (errc, "Out of memory!\n");
      goto TERMINATE;
   }

   status = CPXXchgobjsen (env, lp, CPX_MIN);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXXnewcols (env, lp, sizeof (obj) / sizeof (obj[0]),
                         obj, lb, ub, NULL, cname);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXXaddrows (env, lp, 0, sizeof (rhs) / sizeof (rhs[0]),
                         sizeof (rval) / sizeof (rval[0]), rhs, sense,
                         rbeg, rind, rval, NULL, rname);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXXaddqconstr (env, lp, 0, sizeof (qind1) / sizeof (qind1[0]),
                            qrhs, qsense, NULL, NULL,
                            qind1, qind1, qval, "q1");
   if ( status != 0 )
      goto TERMINATE;
   cone[0] = 0;
   cone[1] = NOT_CONE_HEAD;
   cone[2] = NOT_CONE_HEAD;
   status = CPXXaddqconstr (env, lp, 0, sizeof (qind2) / sizeof (qind2[0]),
                            qrhs, qsense, NULL, NULL,
                            qind2, qind2, qval, "q2");
   if ( status != 0 )
      goto TERMINATE;
   cone[3] = 1;
   cone[4] = NOT_CONE_HEAD;

   cone[5] = NOT_IN_CONE;

   ok = 1;
 TERMINATE:
   if ( !ok )
      free (cone);

   *cone_p = cone;

   return ok;
}
Пример #5
0
static int 
colsteel (int numprod, int tweeks, double const *rate,
          double const *inv0, double const *avail, double const *flatmarket,
          double const *prodcost, double const *invcost,
          double const *flatrevenue, CPXENVptr env, CPXLPptr lp)
{
   double *obj      = NULL;
   char   *sense    = NULL;
   CPXNNZ *cmatbeg  = NULL;
   CPXDIM *cmatind  = NULL;
   double *cmatval  = NULL;
   double *lb       = NULL;
   double *ub       = NULL;

   CPXCHANNELptr  cpxerror = NULL;

   int    t,p;      /* Various loop counters */
   CPXNNZ k;

   int  status = 0;

   printf ("Building model by column.\n");

   status = CPXXgetchannels (env, NULL, NULL, &cpxerror, NULL);
   if ( status )  goto TERMINATE;

   /* Set the objective sense to be maximize */

   status = CPXXchgobjsen (env, lp, CPX_MAX);
   if ( status ) {
      CPXXmsg (cpxerror, "Could not change objective sense. Error %d\n",
               status);
      goto TERMINATE;
   }

   /* Set up the constraints for the problem */

   /* First do the time constraints.  Allocate space for a sense array. */

   sense = malloc (tweeks*sizeof(*sense));
   if ( sense == NULL ) {
      status = -2;
      goto TERMINATE;
   }

   for (t = 0; t < tweeks; t++) {
      sense[t] = 'L';
   }

   status = CPXXnewrows (env, lp, tweeks, avail, sense, NULL, NULL);
   if ( status ) {
      CPXXmsg (cpxerror, 
              "CPXXnewrows failed to add time constraints.  Error %d\n",
              status);
      goto TERMINATE;
   }

   /* Free up the temporary sense array */
   free (sense);  sense = NULL;

   /* Now do the balance constraints.  
      Can do this without temporary arrays, because the only nonzero
      is the negative of the inventory levels.  */

   for (p = 0; p < numprod; p++) {
      double  temprhs = -inv0[p];

      /* Fill in the initial inventory level */
      status   = CPXXnewrows (env, lp, 1, &temprhs, NULL, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d.  Error %d.\n", 
                 "CPXXnewrows failed to add initial inventory constraint\n",
                 p, status);
         goto TERMINATE;
      }

      /* The remaining balance constraints have 0.0 as the rhs value,
         and are equality constraints.  No need to specify the arrays */

      status   = CPXXnewrows (env, lp, tweeks-1, NULL, NULL, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d.  Error %d.\n", 
                 "CPXXnewrows failed to add other inventory constraints\n",
                 p, status);
         goto TERMINATE;
      }

   }

   /* Now, add the variables.  For each set of variables, we allocate
    * arrays to hold the data for the CPXXaddcols() calls, and then free
    * them up, so that each set of variables is maintained in a "local"
    * piece of code.
    */

   /* First, do the Make variables.  Each Make[p][t] variable has
    * objective coefficient -prodcost[p], and bounds of (0, +infinity).
    * Each Make[p][t] variable appears in the constraints 
    * time(t) and balance(p,t).
    * Create temporary arrays to hold the objective coefficients,
    * lower and upper bounds, and matrix coefficients for one product.
    */

   obj     = malloc (tweeks*sizeof(*obj));
   cmatbeg = malloc (tweeks*sizeof(*cmatbeg));
   cmatind = malloc (2*tweeks*sizeof(*cmatind));
   cmatval = malloc (2*tweeks*sizeof(*cmatval));

   if ( obj     == NULL ||
        cmatbeg == NULL ||
        cmatind == NULL ||
        cmatval == NULL   ) {
      status = -2;
      goto TERMINATE;
   }

   for (p = 0; p < numprod; p++) {
      k = 0;     /* Reset the nonzero count for each product */
      for (t = 0; t < tweeks; t++) {
         cmatbeg[t] = k;
         obj[t]     = -prodcost[p];
         cmatind[k] = t;
         cmatval[k] = 1.0/rate[p];
         k++;
         cmatind[k] = (p + 1)*tweeks + t;
         cmatval[k] = 1.0;
         k++;
      }
      status = CPXXaddcols (env, lp, tweeks, k, obj, cmatbeg, cmatind,
                           cmatval, NULL, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d.  Error %d.\n", 
                 "CPXXaddcols failed to add Make variables\n",
                 p, status);
         goto TERMINATE;
      }
   }

   /* Free up allocated memory used to add Make variables */

   free (obj);     obj = NULL;
   free (cmatbeg); cmatbeg = NULL;
   free (cmatind); cmatind = NULL;
   free (cmatval); cmatval = NULL;
   
   /* Now do the Inv variables in (p,t) order.  Each Inv[p][t] variable
    * has objective coefficient -invcost[p], and bounds of (0, +infinity).
    * If t is not tweeks-1, then Inv[p][t] appears in constraints
    *   balance(p,t) and balance(p,t+1).
    * If t is tweeks-1, then Inv[p][t] appears only in
    *   constraint balance(p,t).
    * Create temporary arrays to hold the objective coefficients,
    * lower and upper bounds, and matrix coefficients for one product.
    */

   obj     = malloc (tweeks*sizeof(*obj));
   cmatbeg = malloc (tweeks*sizeof(*cmatbeg));
   cmatind = malloc (2*tweeks*sizeof(*cmatind));
   cmatval = malloc (2*tweeks*sizeof(*cmatval));

   if ( obj     == NULL ||
        cmatbeg == NULL ||
        cmatind == NULL ||
        cmatval == NULL   ) {
      status = -2;
      goto TERMINATE;
   }

   for (p = 0; p < numprod; p++) {
      k = 0;   /* Reset the nonzero count for each product */
      for (t = 0; t < tweeks; t++) {
         obj[t]     = -invcost[p];
         cmatbeg[t] = k;
         cmatind[k] = (p+1)*tweeks + t;
         cmatval[k] = -1.0;
         k++;
         cmatind[k] = (p+1)*tweeks + t+1;
         cmatval[k] = 1.0;
         k++;
      }
      /* Now repair the coefficient for t=tweeks-1 by passing k-1 as
       * the number of nonzeros, so that the last coefficient is 
       * ignored. 
       */
      status = CPXXaddcols (env, lp, tweeks, k-1, obj, cmatbeg, cmatind,
                           cmatval, NULL, NULL, NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d.  Error %d.\n", 
                 "CPXXaddcols failed to add Inv variables\n",
                 p, status);
         goto TERMINATE;
      }
   }

   /* Free up allocated memory used to add Inv variables */

   free (obj);     obj = NULL;
   free (cmatbeg); cmatbeg = NULL;
   free (cmatind); cmatind = NULL;
   free (cmatval); cmatval = NULL;
   

   /* Now do the Sell[p][t] variables.  The objective coefficients of
    * Sell[p][t] is flatrevenue[p*tweeks+t], which means that
    * we can pull the objective coefficients from the slice of that
    * array.  The lower bounds are 0.0, and the upper bounds are
    * flatmarket[p*tweeks+t], which means that we can pull the
    * upper bounds from the slice of that array.  Each Sell variable
    * appears only in the balance(p,t) constraint. 
    * Create temporary arrays to hold the bounds, and matrix 
    * coefficients for one product.
    */

   cmatbeg = malloc (tweeks*sizeof(*cmatbeg));
   cmatind = malloc (tweeks*sizeof(*cmatind));
   cmatval = malloc (tweeks*sizeof(*cmatval));

   if ( cmatbeg == NULL ||
        cmatind == NULL ||
        cmatval == NULL   ) {
      status = -2;
      goto TERMINATE;
   }


   for (p = 0; p < numprod; p++) {
      k = 0;     /* Reset the nonzero count for each product */
      for (t = 0; t < tweeks; t++) {
         cmatbeg[t] = k;
         cmatind[k] = (p+1)*tweeks + t;
         cmatval[k] = -1.0;
         k++;
      }
      status = CPXXaddcols (env, lp, tweeks, k, &flatrevenue[p*tweeks], 
                           cmatbeg, cmatind, cmatval, NULL, 
                           &flatmarket[p*tweeks], NULL);
      if ( status ) {
         CPXXmsg (cpxerror, "%sfor product %d.  Error %d.\n", 
                 "CPXXaddcols failed to add Sell variables\n",
                 p, status);
         goto TERMINATE;
      }

   }

   /* Free up allocated memory used to add Sell variables */

   free (lb);      lb  = NULL;
   free (cmatbeg); cmatbeg = NULL;
   free (cmatind); cmatind = NULL;
   free (cmatval); cmatval = NULL;

TERMINATE:

   if ( obj     != NULL )   free ( obj );
   if ( sense   != NULL )   free ( sense );
   if ( cmatbeg != NULL )   free ( cmatbeg );
   if ( cmatind != NULL )   free ( cmatind );
   if ( cmatval != NULL )   free ( cmatval );
   if ( lb      != NULL )   free ( lb );
   if ( ub      != NULL )   free ( ub );

   return (status);

} /* END colsteel */