Example #1
0
static int
buildnetwork (CPXENVptr env, CPXLPptr lp)
{
   char     sense[NUMNODES];
   double   rhs[NUMNODES];
   int      ind[2];
   double   val[2];
   char     *name[1];
   char     buffer[100];

   int      i, j, varindex;
   int      zero = 0;
   double   dblzero = 0.0;
   double   dblone  = 1.0;
   char     binary = 'B';
   int      status = 0;

   /* Create constraint placeholders ---
        One constraint for each node (flow constraints)
   */

   for (i = 0; i < NUMNODES; i++) {
      rhs[i]   = demand[i];
      sense[i] = 'G';
   }
   status = CPXnewrows (env, lp, NUMNODES, rhs, sense, NULL, NULL);
   if ( status ) {
      fprintf (stderr, "Could not create new rows.\n");
      goto TERMINATE;
   }

   /* Add flow variables */

   for (j = 0; j < NUMEDGES; j++) {
      ind[0] = orig[j];  /* Flow leaves origin */
      val[0] = -1.0;
      ind[1] = dest[j];  /* Flow arrives at destination */
      val[1] =  1.0;

      name[0] = buffer;
      sprintf(buffer, "x%d%d", orig[j], dest[j]);

      status = CPXaddcols (env, lp, 1, 2, &unitcost[j], &zero, ind, val,
                           NULL, NULL, name);
      if ( status ) {
         fprintf (stderr, "Failed to add flow edge.\n");
         goto TERMINATE;
      }
   }

   /* Add fixed charge variables */
   for (j = 0; j < NUMEDGES; j++) {
      name[0] = buffer;
      sprintf(buffer, "f%d%d", orig[j], dest[j]);

      status = CPXaddcols (env, lp, 1, 0, &fixedcost[j], &zero, ind, val,
                           &dblzero, &dblone, name);
      if ( status ) {
         fprintf (stderr, "Failed to add fixed charge variable.\n");
         goto TERMINATE;
      }

      varindex = NUMEDGES+j;
      status = CPXchgctype (env, lp, 1, &varindex, &binary);
      if ( status ) {
         fprintf (stderr, "Failed to change variable type.\n");
         goto TERMINATE;
      }
      
   }

   /* Add indicator constraints --
        f = 0 -> x <= 0 */

   for (j = 0; j < NUMEDGES; j++) {
      varindex = j;
      sprintf(buffer, "indicator%d", j);

      status = CPXaddindconstr (env, lp, NUMEDGES+j, 1, 1, 
                                0.0, 'L', &varindex, &dblone, buffer);
      if ( status ) {
         fprintf (stderr, "Failed to add indicator constraint.");
         goto TERMINATE;
      }
   }
   
TERMINATE:

   return (status);

}  /* END buildnetwork */
Example #2
0
static int
buildmodel (CPXENVptr env, CPXLPptr lp)
{

   int    colcnt = NUMVARS*NUMMONTHS*NUMPRODUCTS;

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

   int    indicator;
   int    rmatbeg[1];
   double rhs[1];
   char   sense[1];

   int    m, p;
   int    status = 0;

   status = CPXchgobjsen (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     = (double *) malloc (colcnt * sizeof(double));
   lb      = (double *) malloc (colcnt * sizeof(double));
   ub      = (double *) malloc (colcnt * sizeof(double));
   ctype   = (char *)   malloc (colcnt * sizeof(char));
   rmatind = (int * )   malloc (colcnt * sizeof(int));
   rmatval = (double *) malloc (colcnt * sizeof(double));

   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 = CPXnewcols (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 = CPXaddindconstr (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 = CPXaddrows (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 = CPXaddrows (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 = CPXnewcols (env, lp, 1, obj, lb, ub, ctype, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new columns.\n");
         goto TERMINATE;
      }
      totalindex = CPXgetnumcols (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 = CPXaddrows (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 = CPXaddrows (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 = CPXaddrows (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 = CPXaddrows (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 = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      indicator = varindex (m, VEGOIL2, IS_USED);
      status = CPXaddindconstr (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++) {
         int 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 = CPXaddrows (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 */