Пример #1
0
static int
dumpx (CPXENVptr env, CPXLPptr lp)
{
   int status = 0;
   CPXDIM cols, c;
   CPXSIZE surplus;
   char *name, buffer[8];
   double x;


   cols = CPXXgetnumcols (env, lp);
   for (c = 0; c < cols; ++c) {
      status = CPXXgetx (env, lp, &x, c, c);
      if ( status ) {
         fprintf (stderr,
                  "Failed to read value for column %d: %d\n", c, status);
         goto TERMINATE;
      }

      status = CPXXgetcolname (env, lp, &name, buffer, sizeof (buffer),
                              &surplus, c, c);
      if ( status ) {
         fprintf (stderr,
                  "Failed to read name for column %d: %d\n", c, status);
         goto TERMINATE;
      }

      printf ("%8s: %15.6f\n", name, x);
   }

 TERMINATE:

   return status;
} /* END dumpx */
static int
optimize_and_report (CPXENVptr env, CPXLPptr lp,
                     int *solstat_p, double *objval_p)
{
   int status = 0;
   
   double   x[NUMCOLS];
   double   pi[TOTROWS];
   double   slack[TOTROWS];
   double   dj[NUMCOLS];

   int      i, j;
   int      cur_numrows, cur_numcols;
   
   status = CPXXqpopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize QP.\n");
      goto TERMINATE;
   }

   status = CPXXsolution (env, lp, solstat_p, objval_p, x, pi, slack, dj);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }


   /* Write the output to the screen. */

   printf ("\nSolution status = %d\n", *solstat_p);
   printf ("Solution value  = %f\n\n", *objval_p);

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is, rather than using what was passed to CPXXcopylp.
      cur_numrows and cur_numcols store the current number of rows and
      columns, respectively.  */

   cur_numrows = CPXXgetnumrows (env, lp);
   cur_numcols = CPXXgetnumcols (env, lp);
   for (i = 0; i < cur_numrows; i++) {
      printf ("Row %d:  Slack = %10f  Pi = %10f\n", i, slack[i], pi[i]);
   }

   for (j = 0; j < cur_numcols; j++) {
      printf ("Column %d:  Value = %10f  Reduced cost = %10f\n",
              j, x[j], dj[j]);
   }

 TERMINATE:

   return (status);

}  /* END optimize_and_report */
Пример #3
0
static int
makeusercuts (CPXENVptr  env,
              CPXLPptr   lp,
              CUTINFOptr usercutinfo)
{
   int status = 0;

   CPXNNZ beg[] = {0, 2, 4, 6, 16, 26, 36, 46, 56};

   double val[] = 
   {1, -1, 
    1, -1, 
    1, -1, 
    2.08, 2.98, 3.47, 2.24, 2.08, 0.25, 0.25, 0.25, 0.25, 0.25,
    2.08, 2.98, 3.47, 2.24, 2.08, 0.25, 0.25, 0.25, 0.25, 0.25,
    2.08, 2.98, 3.47, 2.24, 2.08, 0.25, 0.25, 0.25, 0.25, 0.25,
    2.08, 2.98, 3.47, 2.24, 2.08, 0.25, 0.25, 0.25, 0.25, 0.25,
    2.08, 2.98, 3.47, 2.24, 2.08, 0.25, 0.25, 0.25, 0.25, 0.25};

   char const *varname[] = 
   {"X21", "X22", 
    "X22", "X23", 
    "X23", "X24",
    "X11", "X21", "X31", "X41", "X51",
    "W11", "W21", "W31", "W41", "W51",
    "X12", "X22", "X32", "X42", "X52",
    "W12", "W22", "W32", "W42", "W52",
    "X13", "X23", "X33", "X43", "X53",
    "W13", "W23", "W33", "W43", "W53",
    "X14", "X24", "X34", "X44", "X54",
    "W14", "W24", "W34", "W44", "W54",
    "X15", "X25", "X35", "X45", "X55",
    "W15", "W25", "W35", "W45", "W55"};

   double rhs[] = {0, 0, 0, 20.25, 20.25, 20.25, 20.25, 16.25};

   CPXNNZ *cutbeg = NULL;
   CPXDIM *cutind = NULL;
   double *cutval = NULL;
   double *cutrhs = NULL; 

   CPXDIM i, varind;
   CPXNNZ nz   = 56;
   CPXDIM cuts = 8;

   CPXDIM cur_numcols = CPXXgetnumcols (env, lp);

   usercutinfo->lp = lp;
   usercutinfo->numcols = cur_numcols;

   usercutinfo->x = malloc (cur_numcols * sizeof (*usercutinfo->x));
   if ( usercutinfo->x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   cutbeg = malloc ((cuts+1) * sizeof (*cutbeg));
   cutind = malloc (nz * sizeof (*cutind));
   cutval = malloc (nz * sizeof (*cutval));
   cutrhs = malloc (cuts * sizeof (*cutrhs));

   if ( cutbeg == NULL ||
        cutind == NULL ||
        cutval == NULL ||
        cutrhs == NULL   ) {
      fprintf (stderr, "No memory.\n");
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   } 
      
   for (i = 0; i < nz; i++) {
      status = CPXXgetcolindex (env, lp, varname[i], &varind);
      if ( status )  {
         fprintf (stderr,
                  "Failed to get index from variable name.\n");
         goto TERMINATE;
      }
      cutind[i] = varind;
      cutval[i] = val[i];
   }

   for (i = 0; i < cuts; i++) {
      cutbeg[i] = beg[i];
      cutrhs[i] = rhs[i];
   }
   cutbeg[cuts] = beg[cuts];

   usercutinfo->num      = cuts;
   usercutinfo->beg      = cutbeg;
   usercutinfo->ind      = cutind;
   usercutinfo->val      = cutval;
   usercutinfo->rhs      = cutrhs;

TERMINATE:

   if ( status ) {
      free_and_null ((char **) &cutbeg);
      free_and_null ((char **) &cutind);
      free_and_null ((char **) &cutval);
      free_and_null ((char **) &cutrhs);
   }
 
   return (status);

} /* END makeusercuts */
Пример #4
0
int
myoptimize (CPXENVptr env, CPXLPptr lp, double true_objval)
{
   int status = 0;
   int solstat = 0;

   CPXDIM j;
   double objval;
   double *x = NULL;
   CPXDIM cur_numcols = CPXXgetnumcols (env, lp);

   /* Optimize the problem and obtain solution */

   status = CPXXmipopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

   status = CPXXgetobjval (env, lp, &objval);
   if ( status ) {
      fprintf (stderr,"Failed to obtain objective value.\n");
      goto TERMINATE;
   }

   printf ("Objective value %.10g\n", objval);

   /* Allocate space for solution */

   x = malloc (cur_numcols * sizeof (*x));

   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   status = CPXXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }

   /* Write out the solution */

   for (j = 0; j < cur_numcols; j++) {
      if ( fabs (x[j]) > 1e-10 ) {
         char *colname[1];
         char namestore[6];
         CPXSIZE surplus = 0;
         status = CPXXgetcolname (env, lp, colname, namestore, 6,
                                 &surplus, j, j);
         if ( status ) {
            namestore[0] = 0;
            colname[0] = namestore;
         }
         printf ( "Column %3d (%5s):  Value = %17.10g\n", j, colname[0], x[j]);
      }
   }


TERMINATE:

   free_and_null ((char **) &x);

   return (status);
}
Пример #5
0
/*
 * The function returns a true value if the tested KKT conditions are
 * satisfied and false otherwise.
 */
static int
checkkkt (CPXCENVptr env, CPXLPptr lp, CPXDIM const *cone, double tol)
{
   CPXDIM cols = CPXXgetnumcols (env, lp);
   CPXDIM rows = CPXXgetnumrows (env, lp);
   CPXDIM qcons = CPXXgetnumqconstrs (env, lp);
   double *dslack = NULL, *pi = NULL, *socppi = NULL;
   double *val = NULL, *rhs = NULL;
   CPXDIM *ind = NULL;
   char *sense = NULL;
   double *x = NULL, *slack = NULL, *qslack = NULL;
   double *sum = NULL;
   qbuf_type qbuf;
   CPXCHANNELptr resc, warnc, errc, logc;
   int ok = 0, skip = 0;
   int status;
   CPXDIM i, j, q;

   qbuf_init (&qbuf);

   /* Get the channels on which we may report. */
   if ( (status = CPXXgetchannels (env, &resc, &warnc, &errc, &logc)) != 0 )
      goto TERMINATE;

   /* Fetch results and problem data that we need to check the KKT
    * conditions.
    */
   CPXXmsg (logc, "Fetching results ... ");
   if ( (cols > 0 && (dslack = malloc (cols * sizeof (*dslack))) == NULL) ||
        (rows > 0 && (pi = malloc (rows * sizeof (*pi))) == NULL) ||
        (qcons > 0 && (socppi = malloc (qcons * sizeof (*socppi))) == NULL) ||
        (cols > 0 && (x = malloc (cols * sizeof (*x))) == NULL) ||
        (rows > 0 && (sense = malloc (rows * sizeof (*sense))) == NULL ) ||
        (rows > 0 && (slack = malloc (rows * sizeof (*slack))) == NULL ) ||
        (qcons > 0 && (qslack = malloc (qcons * sizeof (*qslack))) == NULL) ||
        (cols > 0 && (sum = malloc (cols * sizeof (*sum))) == NULL) ||
        (cols > 0 && (val = malloc (cols * sizeof (*val))) == NULL) ||
        (cols > 0 && (ind = malloc (cols * sizeof (*ind))) == NULL) ||
        (rows > 0 && (rhs = malloc (rows * sizeof (*rhs))) == NULL) )
   {
      CPXXmsg (errc, "Out of memory!\n");
      goto TERMINATE;
   }

   /* Fetch problem data. */
   if ( (status = CPXXgetsense (env, lp, sense, 0, rows - 1)) != 0 )
      goto TERMINATE;
   if ( (status = CPXXgetrhs (env, lp, rhs, 0, rows - 1)) != 0 )
      goto TERMINATE;

   /* Fetch solution information. */
   if ( (status = CPXXgetx (env, lp, x, 0, cols - 1)) != 0 )
      goto TERMINATE;
   if ( (status = CPXXgetpi (env, lp, pi, 0, rows - 1)) != 0 )
      goto TERMINATE;
   if ( (status = getsocpconstrmultipliers (env, lp, dslack, socppi)) != 0 )
      goto TERMINATE;
   if ( (status = CPXXgetslack (env, lp, slack, 0, rows - 1)) != 0 )
      goto TERMINATE;
   if ( (status = CPXXgetqconstrslack (env, lp, qslack, 0, qcons - 1)) != 0 )
      goto TERMINATE;
   CPXXmsg (logc, "ok.\n");

   /* Print out the solution data we just fetched. */
   CPXXmsg (resc, "x      = [");
   for (j = 0; j < cols; ++j)
      CPXXmsg (resc, " %+7.3f", x[j]);
   CPXXmsg (resc, " ]\n");
   CPXXmsg (resc, "dslack = [");
   for (j = 0; j < cols; ++j)
      CPXXmsg (resc, " %+7.3f", dslack[j]);
   CPXXmsg (resc, " ]\n");
   CPXXmsg (resc, "pi     = [");
   for (i = 0; i < rows; ++i)
      CPXXmsg (resc, " %+7.3f", pi[i]);
   CPXXmsg (resc, " ]\n");
   CPXXmsg (resc, "slack  = [");
   for (i = 0; i < rows; ++i)
      CPXXmsg (resc, " %+7.3f", slack[i]);
   CPXXmsg (resc, " ]\n");
   CPXXmsg (resc, "socppi = [");
   for (q = 0; q < qcons; ++q)
      CPXXmsg (resc, " %+7.3f", socppi[q]);
   CPXXmsg (resc, " ]\n");
   CPXXmsg (resc, "qslack = [");
   for (q = 0; q < qcons; ++q)
      CPXXmsg (resc, " %+7.3f", qslack[q]);
   CPXXmsg (resc, " ]\n");

   /* Test primal feasibility. */
   CPXXmsg (logc, "Testing primal feasibility ... ");
   /* This example illustrates the use of dual vectors returned by CPLEX
    * to verify dual feasibility, so we do not test primal feasibility
    * here. */
   CPXXmsg (logc, "ok.\n");

   /* Test dual feasibility.
    * We must have
    * - for all <= constraints the respective pi value is non-negative,
    * - for all >= constraints the respective pi value is non-positive,
    * - since all quadratic constraints are <= constraints the socppi
    *   value must be non-negative for all quadratic constraints,
    * - the dslack value for all non-cone variables must be non-negative.
    * Note that we do not support ranged constraints here.
    */
   CPXXmsg (logc, "Testing dual feasibility ... ");
   for (i = 0; i < rows; ++i) {
      switch (sense[i]) {
      case 'L':
         if ( pi[i] < -tol ) {
            CPXXmsg (errc, "<= row %d has invalid dual multiplier %f.\n",
                     i, pi[i]);
            goto TERMINATE;
         }
         break;
      case 'G':
         if ( pi[i] > tol ) {
            CPXXmsg (errc, ">= row %d has invalid dual multiplier %f.\n",
                     i, pi[i]);
            goto TERMINATE;
         }
         break;
      case 'E':
         /* Nothing to check here. */
         break;
      }
   }
   for (q = 0; q < qcons; ++q) {
      if ( socppi[q] < -tol ) {
         CPXXmsg (errc, "Quadratic constraint %d has invalid dual multiplier %f.\n",
                  q, socppi[q]);
         goto TERMINATE;
      }
   }
   for (j = 0; j < cols; ++j) {
      if ( cone[j] == NOT_IN_CONE && dslack[j] < -tol ) {
         CPXXmsg (errc, "dslack value for column %d is invalid: %f\n", j, dslack[j]);
         goto TERMINATE;
      }
   }
   CPXXmsg (logc, "ok.\n");

   /* Test complementary slackness.
    * For each constraint either the constraint must have zero slack or
    * the dual multiplier for the constraint must be 0. Again, we must
    * consider the special case in which a variable is not explicitly
    * contained in a second order cone constraint (conestat[j] == 0).
    */
   CPXXmsg (logc, "Testing complementary slackness ... ");
   for (i = 0; i < rows; ++i) {
      if ( fabs (slack[i]) > tol && fabs (pi[i]) > tol ) {
         CPXXmsg (errc, "Complementary slackness not satisfied for row %d (%f, %f)\n",
                  i, slack[i], pi[i]);
         goto TERMINATE;
      }
   }
   for (q = 0; q < qcons; ++q) {
      if ( fabs (qslack[q]) > tol && fabs (socppi[q]) > tol ) {
         CPXXmsg (errc, "Complementary slackness not satisfied for cone %d (%f, %f).\n",
                  q, qslack[q], socppi[q]);
         goto TERMINATE;
      }
   }
   for (j = 0; j < cols; ++j) {
      if ( cone[j] == NOT_IN_CONE ) {
         if ( fabs (x[j]) > tol && fabs (dslack[j]) > tol ) {
            CPXXmsg (errc, "Complementary slackness not satisfied for non-cone variable %f (%f, %f).\n",
                     j, x[j], dslack[j]);
            goto TERMINATE;
         }
      }
   }
   CPXXmsg (logc, "ok.\n");

   /* Test stationarity.
    * We must have
    *  c - g[i]'(X)*pi[i] = 0
    * where c is the objective function, g[i] is the i-th constraint of the
    * problem, g[i]'(x) is the derivate of g[i] with respect to x and X is the
    * optimal solution.
    * We need to distinguish the following cases:
    * - linear constraints g(x) = ax - b. The derivative of such a
    *   constraint is g'(x) = a.
    * - second order constraints g(x[1],...,x[n]) = -x[1] + |(x[2],...,x[n])|
    *   the derivative of such a constraint is
    *     g'(x) = (-1, x[2]/|(x[2],...,x[n])|, ..., x[n]/|(x[2],...,x[n])|
    *   (here |.| denotes the Euclidean norm).
    * - bound constraints g(x) = -x for variables that are not explicitly
    *   contained in any second order cone constraint. The derivative for
    *   such a constraint is g'(x) = -1.
    * Note that it may happen that the derivative of a second order cone
    * constraint is not defined at the optimal solution X (this happens if
    * X=0). In this case we just skip the stationarity test.
    */
   CPXXmsg (logc, "Testing stationarity ... ");
   /* Initialize sum = c. */
   if ( (status = CPXXgetobj (env, lp, sum, 0, cols - 1)) != 0 )
      goto TERMINATE;

   /* Handle linear constraints. */
   for (i = 0; i < rows; ++i) {
      CPXNNZ nz, surplus, beg;
      CPXNNZ n;

      status = CPXXgetrows (env, lp, &nz, &beg, ind, val, cols, &surplus,
                            i, i);
      if ( status != 0 )
         goto TERMINATE;
      for (n = 0; n < nz; ++n) {
         sum[ind[n]] -= pi[i] * val[n];
      }
   }
   /* Handle second order cone constraints. */
   for (q = 0; q < qcons; ++q) {
      double norm = 0.0;
      CPXNNZ n;

      if ( !getqconstr (env, lp, q, &qbuf) )
         goto TERMINATE;

      for (n = 0; n < qbuf.qnz; ++n) {
         if ( qbuf.qval[n] > 0 )
            norm += x[qbuf.qcol[n]] * x[qbuf.qcol[n]];
      }
      norm = sqrt (norm);
      if ( fabs (norm) <= tol ) {
         CPXXmsg (warnc, "WARNING: Cannot test stationarity at non-differentiable point.\n");
         skip = 1;
         break;
      }

      for (n = 0; n < qbuf.qnz; ++n) {
         if ( qbuf.qval[n] < 0 )
            sum[qbuf.qcol[n]] -= socppi[q];
         else
            sum[qbuf.qcol[n]] += socppi[q] * x[qbuf.qcol[n]] / norm;
      }
   }
   /* Handle variables that do not appear in any second order cone constraint.
    */
   for (j = 0; !skip && j < cols; ++j) {
      if ( cone[j] == NOT_IN_CONE ) {
         sum[j] -= dslack[j];
      }
   }

   /* Now test that all the entries in sum[] are 0.
    */
   for (j = 0; !skip && j < cols; ++j) {
      if ( fabs (sum[j]) > tol ) {
         CPXXmsg (errc, "Stationarity not satisfied at index %d: %f\n",
                  j, sum[j]);
         goto TERMINATE;
      }
   }
   CPXXmsg (logc, "ok.\n");

   CPXXmsg (logc, "KKT conditions are satisfied.\n");

   ok = 1;
 TERMINATE:
   if ( !ok )
      CPXXmsg (logc, "failed.\n");
   qbuf_clear (&qbuf);
   free (rhs);
   free (ind);
   free (val);
   free (sum);
   free (qslack);
   free (slack);
   free (sense);
   free (x);
   free (socppi);
   free (pi);
   free (dslack);

   return ok;
}
Пример #6
0
int
main (int  argc,
      char *argv[])
{
   int status = 0;

   /* Declare and allocate space for the variables and arrays where
      we will store the optimization results, including the status, 
      objective value, and variable values */
   
   int    solstat;
   double objval, relobj;
   double *x = NULL;
	 
   MYCB info;

   CPXENVptr env = NULL;
   CPXLPptr  lp  = NULL;
   CPXLPptr  lpclone = NULL;

   CPXDIM j;
   CPXDIM cur_numcols;

   /* Check the command line arguments */

   if ( argc != 2 ) {
      usage (argv[0]);
      goto TERMINATE;
   }

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no
      output, so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput parameter is set to CPX_ON */

   if ( env == NULL ) {
      char errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n",
               status);
      goto TERMINATE;
   }


   /* Turn on traditional search for use with control callbacks */

   status = CPXXsetintparam (env, CPXPARAM_MIP_Strategy_Search, CPX_MIPSEARCH_TRADITIONAL);
   if ( status )  goto TERMINATE;

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, argv[1]);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of 
      failure, an error message will have been written to the error 
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, argv[1], NULL);
   if ( status ) {
      fprintf (stderr,
               "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   /* We transfer a problem with semi-continuous or semi-integer
      variables to a MIP problem by adding variables and  
      constraints. So in MIP callbacks, the size of the problem
      is changed and this example won't work for such problems */

   if ( CPXXgetnumsemicont (env, lp) + CPXXgetnumsemiint (env, lp) ) {
      fprintf (stderr, 
         "Not for problems with semi-continuous or semi-integer variables.\n");
      goto TERMINATE;
   }

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is. cur_numcols store the current number 
      of columns */

   cur_numcols = CPXXgetnumcols (env, lp);

   x = malloc (cur_numcols * sizeof (*x));
   if ( x == NULL ) {
      fprintf (stderr, "Memory allocation failed.\n");
      goto TERMINATE;
   }

   /* Solve relaxation of MIP */

   /* Clone original model */

   lpclone = CPXXcloneprob (env, lp, &status);
   if ( status ) {
      fprintf (stderr, "Failed to clone problem.\n");
      goto TERMINATE;
   }

   /* Relax */

   status = CPXXchgprobtype (env, lpclone, CPXPROB_LP);
   if ( status ) {
      fprintf (stderr, "Failed to relax problem.\n");
      goto TERMINATE;
   }

   /* Solve LP relaxation of original model using "default"
      LP solver */

   status = CPXXlpopt (env, lpclone);
   if ( status ) {
      fprintf (stderr, "Failed to solve relaxation.\n");
      goto TERMINATE;
   }

   printf ("Solution status %d.\n", CPXXgetstat(env,lpclone));

   status = CPXXsolution (env, lpclone, NULL, &relobj, x, NULL,
                         NULL, NULL);
   if ( status ) {
      fprintf (stderr, "Failed to extract solution.\n");
      goto TERMINATE;
   }

   printf ("\nLP relaxation objective: %.4e\n\n", relobj);

   /* Set up solve callback */
   
   info.count = 0;
   info.mip   = lp;
   info.relx  = x;

   status = CPXXsetsolvecallbackfunc (env, &solvecallback,
                                     (void *) &info);
   if ( status ) {
      fprintf (stderr, "Failed to set solve callback.\n");
      goto TERMINATE;
   }

   /* Optimize the problem and obtain solution */

   status = CPXXmipopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

   status = CPXXgetobjval (env, lp, &objval);
   if ( status ) {
      fprintf (stderr,"Failed to obtain objective value.\n");
      goto TERMINATE;
   }

   printf ("Objective value %.10g\n", objval);

   status = CPXXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }

   /* Write out the solution */

   for (j = 0; j < cur_numcols; j++) {
      if ( fabs (x[j]) > 1e-10 ) {
         printf ( "Column %d:  Value = %17.10g\n", j, x[j]);
      }
   }
   

TERMINATE:

   /* Free the solution vector */

   free_and_null ((char **) &x);

   /* Free the problem as allocated by CPXXcreateprob and
      CPXXreadcopyprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n",
                  status);
      }
   }

   /* Free the cloned lp as allocated by CPXXcloneprob,
      if necessary */

   if ( lpclone != NULL ) {
      status = CPXXfreeprob (env, &lpclone);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n",
                  status);
      }
   }

   /* Free the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output, so the only 
         way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors 
         will be seen if the CPXPARAM_ScreenOutput parameter is set to 
         CPX_ON */

      if ( status ) {
         char errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

} /* END main */
Пример #7
0
int
main (int  argc,
      char *argv[])
{
   int status = 0;

   /* Declare and allocate space for the variables and arrays where
      we will store the optimization results, including the status, 
      objective value, and variable values */
   
   int    solstat;
   double objval;
   double *x = NULL;
   
   CPXENVptr env = NULL;
   CPXLPptr  lp = NULL;

   CPXDIM j;
   CPXDIM cur_numcols;
   int wantorig = 1;
   int nameind = 1;

   /* Check the command line arguments */

   if ( argc != 2 ) {
      if ( argc != 3         ||
           argv[1][0] != '-' ||
           argv[1][1] != 'r'   ) {
         usage (argv[0]);
         goto TERMINATE;
      }
      wantorig = 0;
      nameind = 2;
   }

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no
      output, so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput parameter is set to CPX_ON */

   if ( env == NULL ) {
      char errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n",
               status);
      goto TERMINATE;
   }

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, argv[nameind]);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of
      failure, an error message will have been written to the error
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, argv[nameind], NULL);
   if ( status ) {
      fprintf (stderr,
               "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   /* Set up to use MIP callbacks */

   status = CPXXsetnodecallbackfunc (env, userselectnode, NULL)  ||
            CPXXsetbranchcallbackfunc (env, usersetbranch, NULL) ||
            CPXXsetsolvecallbackfunc (env, usersolve, NULL);

   if ( wantorig ) {
      /* Assure linear mappings between the presolved and original
         models */

      status = CPXXsetintparam (env, CPXPARAM_Preprocessing_Linear, 0);
      if ( status )  goto TERMINATE;

      /* Let MIP callbacks work on the original model */

      status = CPXXsetintparam (env, CPXPARAM_MIP_Strategy_CallbackReducedLP,
                                CPX_OFF);
      if ( status )  goto TERMINATE;
   }

   /* Set MIP log interval to 1 */

   status = CPXXsetcntparam (env, CPXPARAM_MIP_Interval, 1);
   if ( status )  goto TERMINATE;

   /* Turn on traditional search for use with control callbacks */

   status = CPXXsetintparam (env, CPXPARAM_MIP_Strategy_Search,
                             CPX_MIPSEARCH_TRADITIONAL);
   if ( status )  goto TERMINATE;



   /* Optimize the problem and obtain solution */

   status = CPXXmipopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

   status  = CPXXgetobjval (env, lp, &objval);
   if ( status ) {
      fprintf (stderr,"Failed to obtain objective value.\n");
      goto TERMINATE;
   }

   printf ("Objective value %.10g\n", objval);

   cur_numcols = CPXXgetnumcols (env, lp);

   /* Allocate space for solution */

   x = malloc (cur_numcols * sizeof (*x));
   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   status = CPXXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }

   /* Write out the solution */ 

   for (j = 0; j < cur_numcols; j++) {
      if ( fabs (x[j]) > 1e-10 ) {
         printf ( "Column %d:  Value = %17.10g\n", j, x[j]);
      }
   }


TERMINATE:

   /* Free the solution vector */

   free_and_null ((char **) &x);

   /* Free the problem as allocated by CPXXcreateprob and
      CPXXreadcopyprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n",
                  status);
      }
   }

   /* Free the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output, so the only 
         way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors 
         will be seen if the CPXPARAM_ScreenOutput parameter is set to 
         CPX_ON */

      if ( status ) {
         char errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

} /* END main */
Пример #8
0
/* ********************************************************************** *
 *                                                                        *
 *    C A L C U L A T E   D U A L S   F O R   Q U A D   C O N S T R S     *
 *                                                                        *
 *    CPLEX does not give us the dual multipliers for quadratic           *
 *    constraints directly. This is because they may not be properly      *
 *    defined at the cone top and deciding whether we are at the cone     *
 *    top or not involves (problem specific) tolerance issues. CPLEX      *
 *    instead gives us all the values we need in order to compute the     *
 *    dual multipliers if we are not at the cone top.                     *
 *    Function getqconstrmultipliers() takes the following arguments:     *
 *    env       CPLEX environment that was used to create LP.             *
 *    lp        CPLEX problem object for which the dual multipliers are   *
 *              to be calculated.                                         *
 *    x         The optimal solution.                                     *
 *    qpi       Array that stores the dual multipliers upon success.      *
 *    zerotol   The tolerance that is used to decide whether a value      *
 *              if zero or not (used to decide about "cone top" or not).  *
 *                                                                        *
 * ********************************************************************** */
static int
getqconstrmultipliers (CPXCENVptr   env,
                       CPXCLPptr    lp,
                       double const *x,
                       double       *qpi,
                       double       zerotol)
{
   CPXDIM const cols = CPXXgetnumcols (env, lp);
   CPXDIM const numqs = CPXXgetnumqconstrs (env, lp);
   double *dense = NULL;
   double *grad = NULL;
   CPXDIM *slackind = NULL;
   double *slackval = NULL;
   int status = 0;
   CPXDIM i;

   if ( (dense = malloc (sizeof (*dense) * cols)) == NULL ||
        (grad = malloc (sizeof (*grad) * cols)) == NULL ||
        (slackind = malloc (sizeof (*slackind) * cols)) == NULL ||
        (slackval = malloc (sizeof (*slackval) * cols)) == NULL )
   {
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }

   /* Calculate dual multipliers for quadratic constraints from dual
    * slack vectors and optimal solutions.
    * The dual multiplier is essentially the dual slack divided
    * by the derivative evaluated at the optimal solution. If the optimal
    * solution is 0 then the derivative at this point is not defined (we are
    * at the cone top) and we cannot compute a dual multiplier.
    */
   for (i = 0; i < numqs; ++i) {
      CPXDIM j, k;
      CPXDIM surplus, len;
      int conetop;

      /* Clear out dense slack and gradient vector. */
      for (j = 0; j < cols; ++j) {
         dense[j] = 0.0;
         grad[j] = 0;
      }

      /* Get dual slack vector and expand it to a dense vector. */
      status = CPXXgetqconstrdslack (env, lp, i, &len, slackind, slackval,
                                     cols, &surplus);
      if ( status != 0 )
         goto TERMINATE;
      for (k = 0; k < len; ++k)
         dense[slackind[k]] = slackval[k];

      /* Compute value of derivative at optimal solution. */
      /* The derivative of a quadratic constraint x^TQx + a^Tx + b <= 0
       * is Q^Tx + Qx + a.
       */
      conetop = 1;
      for (k = quadbeg[i]; k < quadbeg[i] + quadnzcnt[i]; ++k) {
         if ( fabs (x[quadrow[k]]) > zerotol ||
              fabs (x[quadcol[k]]) > zerotol )
            conetop = 0;
         grad[quadcol[k]] += quadval[k] * x[quadrow[k]];
         grad[quadrow[k]] += quadval[k] * x[quadcol[k]];
      }
      for (j = linbeg[i]; j < linbeg[i] + linnzcnt[i]; ++j) {
         grad[linind[j]] += linval[j];
         if ( fabs (x[linind[j]]) > zerotol )
            conetop = 0;
      }

      if ( conetop ) {
         fprintf (stderr,
                  "#### WARNING: Cannot compute dual multipler at cone top!\n");
         status = CPXERR_BAD_ARGUMENT;
         goto TERMINATE;
      }
      else {
         int ok = 0;
         double maxabs = -1.0;

         /* Compute qpi[i] as slack/gradient.
          * We may have several indices to choose from and use the one
          * with largest absolute value in the denominator.
          */
         for (j = 0; j < cols; ++j) {
            if ( fabs (grad[j]) > zerotol ) {
               if ( fabs (grad[j]) > maxabs ) {
                  qpi[i] = dense[j] / grad[j];
                  maxabs = fabs (grad[j]);
               }
               ok = 1;
            }
         }
            
         if ( !ok ) {
            /* Dual slack is all 0. qpi[i] can be anything, just set
             * to 0. */
            qpi[i] = 0.0;
         }
      }
   }

 TERMINATE:
   free (slackval);
   free (slackind);
   free (grad);
   free (dense);

   return status;
}
Пример #9
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 */
Пример #10
0
int
main (int argc, char *argv[])
{
   int     uselogcallback = 0;
   LOGINFO myloginfo;

   int         usetimelimcallback = 0;
   TIMELIMINFO mytimeliminfo;

   int          useterminate = 0;
   volatile int terminator;

   CPXENVptr env = NULL;
   CPXLPptr  lp = NULL;
   int       solstat;
   int       status = 0;

   /* Check the command line arguments */

   if (( argc != 3 )                                         ||
       ( strchr ("lta", argv[2][0]) == NULL )  ) {
      usage (argv[0]);
      goto TERMINATE;
   }

   switch (argv[2][0]) {
      case 'l':
         uselogcallback = 1;
         break;
      case 't':
         usetimelimcallback = 1;
         break;
      case 'a':
         useterminate = 1;
         break;
      default:
         break;
   }

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

   if ( env == NULL ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr,
               "Failure to turn on screen indicator, error %d.\n", status);
      goto TERMINATE;
   }

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, argv[1]);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of
      failure, an error message will have been written to the error
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure.   */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, argv[1], NULL);
   if ( status ) {
      fprintf (stderr, "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }


   if ( usetimelimcallback ) {
      double t;
      status = CPXXgettime (env, &t);
      if ( status ) {
         fprintf (stderr, "Failed to initialize timer.\n");
         goto TERMINATE;
      }
      mytimeliminfo.acceptablegap = 10.0;
      mytimeliminfo.aborted       = 0;
      mytimeliminfo.timestart     = t;
      mytimeliminfo.timelim       = 1.0;

      status = CPXXsetinfocallbackfunc (env, timelimcallback, &mytimeliminfo);
      if ( status ) {
         fprintf (stderr, "Failed to set time limit callback function.\n");
         goto TERMINATE;
      }
   }
   else if ( uselogcallback ) {
      /* Set overall node limit in case callback conditions are not met */
      status = CPXXsetcntparam (env, CPXPARAM_MIP_Limits_Nodes, 5000);
      if ( status ) goto TERMINATE;

      status = CPXXgettime (env, &myloginfo.timestart);
      if ( status ) {
         fprintf (stderr, "Failed to query time.\n");
         goto TERMINATE;
      }
      status = CPXXgetdettime (env, &myloginfo.dettimestart);
      if ( status ) {
         fprintf (stderr, "Failed to query deterministic time.\n");
         goto TERMINATE;
      }
      myloginfo.numcols       = CPXXgetnumcols (env, lp);
      myloginfo.lastincumbent = CPXXgetobjsen (env, lp) * 1e+35;
      myloginfo.lastlog       = -10000;
      status = CPXXsetinfocallbackfunc (env, logcallback, &myloginfo);
      if ( status ) {
         fprintf (stderr, "Failed to set logging callback function.\n");
         goto TERMINATE;
      }
      /* Turn off CPLEX logging */
      status = CPXXsetintparam (env, CPXPARAM_MIP_Display, 0);
      if ( status )  goto TERMINATE;
   }
   else if ( useterminate) {
      status = CPXXsetterminate (env, &terminator);
      if ( status ) {
         fprintf (stderr, "Failed to set terminator.\n");
         goto TERMINATE;
      }
      /* Typically, you would pass the terminator variable to
         another thread or pass it to an interrupt handler,
         and  monitor for some event to occur.  When it does,
         set terminator to a non-zero value.
 
         To illustrate its use without creating a thread or
         an interrupt handler, terminate immediately by setting
         terminator before the solve.
      */
      terminator = 1;
   }

   /* Optimize the problem and obtain solution. */

   status = CPXXmipopt (env, lp);

   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

TERMINATE:

   /* Free up the problem as allocated by CPXXcreateprob, if necessary */

   if ( lp != NULL ) {
      int xstatus = CPXXfreeprob (env, &lp);
      if ( xstatus ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n", xstatus);
         status = xstatus;
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      int xstatus = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

      if ( status ) {
         char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
         status = xstatus;
      }
   }
 
   return (status);

}  /* END main */
Пример #11
0
int
main (int argc, char *argv[])
{
   int status = 0;

   /* Declare and allocate space for the variables and arrays where
      we will store the optimization results, including the status, 
      objective value, and variable values */
   
   int    solstat;
   double objval;
   double *x = NULL;
   
   CPXENVptr env = NULL;
   CPXLPptr  lp = NULL;

   CPXDIM j;
   CPXDIM cur_numcols;

   const char * datadir = argc <= 1 ? "../../../examples/data" : argv[1];
   char *noswot = NULL;

   noswot = (char *) malloc (strlen (datadir) + 1 + strlen("noswot.mps") + 1);
   sprintf (noswot, "%s/noswot.mps", datadir);

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no
      output, so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput parameter is set to CPX_ON */

   if ( env == NULL ) {
      char errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status != 0 ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n",
               status);
      goto TERMINATE;
   }
   CPXXsetcntparam (env, CPXPARAM_MIP_Interval, 1000);

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, "noswot");

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of
      failure, an error message will have been written to the error
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, noswot, NULL);
   if ( status ) {
      fprintf (stderr,
               "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   /* Set parameters */

   /* Assure linear mappings between the presolved and original
      models */

   status = CPXXsetintparam (env, CPXPARAM_Preprocessing_Linear, 0);
   if ( status )  goto TERMINATE;


   /* Create user cuts for noswot problem */

   status = addusercuts (env, lp); 
   if ( status )  goto TERMINATE;

   /* Optimize the problem and obtain solution */

   status = CPXXmipopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

   status = CPXXgetobjval (env, lp, &objval);
   if ( status ) {
      fprintf (stderr,"Failed to obtain objective value.\n");
      goto TERMINATE;
   }

   printf ("Objective value %.10g\n", objval);

   cur_numcols = CPXXgetnumcols (env, lp);

   /* Allocate space for solution */

   x = malloc (cur_numcols * sizeof (*x));
   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   status = CPXXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }

   /* Write out the solution */

   for (j = 0; j < cur_numcols; j++) {
      if ( fabs (x[j]) > 1e-10 ) {
         printf ("Column %d:  Value = %17.10g\n", j, x[j]);
      }
   }


TERMINATE:

   /* Free the filename */

   free_and_null ((char **) &noswot);

   /* Free the solution vector */

   free_and_null ((char **) &x);

   /* Free the problem as allocated by CPXXcreateprob and
      CPXXreadcopyprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n",
                  status);
      }
   }

   /* Free the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output, so the only 
         way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors 
         will be seen if the CPXPARAM_ScreenOutput parameter is set to 
         CPX_ON */

      if ( status ) {
         char errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

} /* END main */
int
main (int argc, char *argv[])
{
   /* Declare and allocate space for the variables and arrays where we will
      store the optimization results including the status, objective value,
      and variable values. */


   int      solstat;
   double   objval;
   double   *x     = NULL;

   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   int           status;
   CPXDIM        j;
   CPXDIM        cur_numcols;

   /* Check the command line arguments */

   if ( argc != 2 ) {
      usage (argv[0]);
      goto TERMINATE;
   }

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

   if ( env == NULL ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n", status);
      goto TERMINATE;
   }

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, argv[1]);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of 
      failure, an error message will have been written to the error 
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure.   */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, argv[1], NULL);
   if ( status ) {
      fprintf (stderr, "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }


   /* Optimize the problem and obtain solution. */

   status = CPXXmipopt (env, lp);

   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status %d.\n", solstat);

   status  = CPXXgetobjval (env, lp, &objval);

   if ( status ) {
      fprintf (stderr,"Failed to obtain objective value.\n");
      goto TERMINATE;
   }

   printf ("Objective value %.10g\n", objval);

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is. cur_numcols stores the current number 
      of columns. */

   cur_numcols = CPXXgetnumcols (env, lp);

   /* Allocate space for solution */

   x = malloc (cur_numcols*sizeof(*x));

   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   status = CPXXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }

   /* Write out the solution */

   for (j = 0; j < cur_numcols; j++) {
      printf ( "Column %d:  Value = %17.10g\n", j, x[j]);
   }

   
   
TERMINATE:

   /* Free up the solution */

   free_and_null ((char **) &x);

   /* Free up the problem as allocated by CPXXcreateprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

      if ( status ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

}  /* END main */
Пример #13
0
int
main (int argc, char *argv[])
{
   /* Declare and allocate space for the variables and arrays where we will
      store the optimization results including the status, objective value,
      maximum bound violation, variable values, and basis. */

   int      solnstat, solnmethod, solntype;
   double   objval, maxviol;
   double   *x     = NULL;
   int      *cstat = NULL;
   int      *rstat = NULL;

   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   int           status = 0;
   CPXDIM        j;
   CPXDIM        cur_numrows, cur_numcols;
   int           method;

   char          *basismsg;

   /* Check the command line arguments */

   if (( argc != 3 )                                           ||
       ( strchr ("podbn", argv[2][0]) == NULL )  ) {
      usage (argv[0]);
      goto TERMINATE;
   }

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

   if ( env == NULL ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n", status);
      goto TERMINATE;
   }

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, argv[1]);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of 
      failure, an error message will have been written to the error 
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure.   */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, argv[1], NULL);
   if ( status ) {
      fprintf (stderr, "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   if ( CPXXgetprobtype (env, lp) != CPXPROB_QP ) {
      fprintf (stderr, "Input file is not a QP.  Exiting.\n");
      goto TERMINATE;
   }

   /* Optimize the problem and obtain solution. */

   switch (argv[2][0]) {
      case 'o':
         method = CPX_ALG_AUTOMATIC;
         break;
      case 'p':
         method = CPX_ALG_PRIMAL;
         break;
      case 'd':
         method = CPX_ALG_DUAL;
         break;
      case 'n':
         method = CPX_ALG_NET;
         break;
      case 'b':
         method = CPX_ALG_BARRIER;
         break;
      default:
         method = CPX_ALG_NONE;
         break;
   }

   status = CPXXsetintparam (env, CPXPARAM_QPMethod, method);
   if ( status ) {
      fprintf (stderr, 
               "Failed to set the optimization method, error %d.\n", status);
      goto TERMINATE;
   }
   

   status = CPXXqpopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize QP.\n");
      goto TERMINATE;
   }

   solnstat = CPXXgetstat (env, lp);

   if      ( solnstat == CPX_STAT_UNBOUNDED ) {
      printf ("Model is unbounded\n");
      goto TERMINATE;
   }
   else if ( solnstat == CPX_STAT_INFEASIBLE ) {
      printf ("Model is infeasible\n");
      goto TERMINATE;
   }
   else if ( solnstat == CPX_STAT_INForUNBD ) {
      printf ("Model is infeasible or unbounded\n");
      goto TERMINATE;
   }

   status = CPXXsolninfo (env, lp, &solnmethod, &solntype, NULL, NULL);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution info.\n");
      goto TERMINATE;
   }
   printf ("Solution status %d, solution method %d\n", solnstat, solnmethod);

   if ( solntype == CPX_NO_SOLN ) {
      fprintf (stderr, "Solution not available.\n");
      goto TERMINATE;
   }
    
   status = CPXXgetobjval (env, lp, &objval);
   if ( status ) {
      fprintf (stderr, "Failed to obtain objective value.\n");
      goto TERMINATE;
   }
   printf ("Objective value %.10g.\n", objval);

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is.  cur_numrows and cur_numcols store the 
      current number of rows and columns, respectively.  */

   cur_numcols = CPXXgetnumcols (env, lp);
   cur_numrows = CPXXgetnumrows (env, lp);

   /* Retrieve basis, if one is available */

   if ( solntype == CPX_BASIC_SOLN ) {
      cstat = malloc (cur_numcols*sizeof(*cstat));
      rstat = malloc (cur_numrows*sizeof(*rstat));
      if ( cstat == NULL || rstat == NULL ) {
         fprintf (stderr, "No memory for basis statuses.\n");
         goto TERMINATE;
      }

      status = CPXXgetbase (env, lp, cstat, rstat);
      if ( status ) {
         fprintf (stderr, "Failed to get basis; error %d.\n", status);
         goto TERMINATE;
      }
   }
   else {
      printf ("No basis available\n");
   }


   /* Retrieve solution vector */

   x = malloc (cur_numcols*sizeof(*x));
   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution.\n");
      goto TERMINATE;
   }

   status = CPXXgetx (env, lp, x, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain primal solution.\n");
      goto TERMINATE;
   }


   /* Write out the solution */

   for (j = 0; j < cur_numcols; j++) {
      printf ( "Column %d:  Value = %17.10g", j, x[j]);
      if ( cstat != NULL ) {
         switch (cstat[j]) {
            case CPX_AT_LOWER:
               basismsg = "Nonbasic at lower bound";
               break;
            case CPX_BASIC:
               basismsg = "Basic";
               break;
            case CPX_AT_UPPER:
               basismsg = "Nonbasic at upper bound";
               break;
            case CPX_FREE_SUPER:
               basismsg = "Superbasic, or free variable at zero";
               break;
            default:
               basismsg = "Bad basis status";
               break;
         }
         printf ("  %s",basismsg);
      }
      printf ("\n");
   }

   /* Display the maximum bound violation. */

   status = CPXXgetdblquality (env, lp, &maxviol, CPX_MAX_PRIMAL_INFEAS);
   if ( status ) {
      fprintf (stderr, "Failed to obtain bound violation.\n");
      goto TERMINATE;
   }
   printf ("Maximum bound violation = %17.10g\n", maxviol);

   
TERMINATE:

   /* Free up the basis and solution */

   free_and_null ((char **) &cstat);
   free_and_null ((char **) &rstat);
   free_and_null ((char **) &x);

   /* Free up the problem, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

      if ( status ) {
         char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

}  /* END main */
Пример #14
0
static int
makelazyconstraint (CPXENVptr  env,
                    CPXLPptr   lp,
                    CUTINFOptr lazyconinfo)
{
   int status = 0;

   CPXNNZ beg[] = {0, 5};
   double val[] = {1, 1, 1, 1, 1};
   char const *varname[] = { "W11", "W12", "W13", "W14", "W15" };
   double rhs[] = {3};

   CPXNNZ *cutbeg = NULL;
   CPXDIM *cutind = NULL;
   double *cutval = NULL;
   double *cutrhs = NULL; 

   CPXDIM i, varind;
   CPXNNZ nz   = 5;
   CPXDIM cuts = 1;

   CPXDIM cur_numcols = CPXXgetnumcols (env, lp);

   lazyconinfo->lp = lp;
   lazyconinfo->numcols = cur_numcols;

   lazyconinfo->x = malloc (cur_numcols * sizeof (*lazyconinfo->x));
   if ( lazyconinfo->x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   cutbeg = malloc ((cuts+1) * sizeof (*cutbeg));
   cutind = malloc (nz * sizeof (*cutind));
   cutval = malloc (nz * sizeof (*cutval));
   cutrhs = malloc (cuts * sizeof (*cutrhs));

   if ( cutbeg == NULL ||
        cutind == NULL ||
        cutval == NULL ||
        cutrhs == NULL   ) {
      fprintf (stderr, "No memory.\n");
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   } 
      
   for (i = 0; i < nz; i++) {
      status = CPXXgetcolindex (env, lp, varname[i], &varind);
      if ( status )  {
         fprintf (stderr,
                  "Failed to get index from variable name.\n");
         goto TERMINATE;
      }
      cutind[i] = varind;
      cutval[i] = val[i];
   }

   for (i = 0; i < cuts; i++) {
      cutbeg[i] = beg[i];
      cutrhs[i] = rhs[i];
   }
   cutbeg[cuts] = beg[cuts];

   lazyconinfo->num      = cuts;
   lazyconinfo->beg      = cutbeg;
   lazyconinfo->ind      = cutind;
   lazyconinfo->val      = cutval;
   lazyconinfo->rhs      = cutrhs;

TERMINATE:

   if ( status ) {
      free_and_null ((char **) &cutbeg);
      free_and_null ((char **) &cutind);
      free_and_null ((char **) &cutval);
      free_and_null ((char **) &cutrhs);
   }
 
   return (status);

} /* END makelazyconstraint */
int
main (int argc, char *argv[])
{
   /* Declare and allocate space for the variables and arrays where we will
      store the optimization results including the status, objective value,
      and variable values. */


   int      solstat;
   double   objval;
   double   incobjval;
   double   meanobjval;
   double   *x     = NULL;
   double   *incx  = NULL;
   int      numsol;
   int      numsolreplaced;
   int      numdiff;

   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   int           status;
   int           i;
   CPXDIM        j;
   CPXDIM        cur_numcols;

   /* Check the command line arguments */

   if ( argc != 2 ) {
      usage (argv[0]);
      goto TERMINATE;
   }

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

   if ( env == NULL ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr, 
               "Failure to turn on screen indicator, error %d.\n", status);
      goto TERMINATE;
   }

   /* Create the problem, using the filename as the problem name */

   lp = CPXXcreateprob (env, &status, argv[1]);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of 
      failure, an error message will have been written to the error 
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  Note that most CPLEX routines return
      an error code to indicate the reason for failure.   */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now read the file, and copy the data into the created lp */

   status = CPXXreadcopyprob (env, lp, argv[1], NULL);
   if ( status ) {
      fprintf (stderr, "Failed to read and copy the problem data.\n");
      goto TERMINATE;
   }

   /* Set the solution pool relative gap parameter to obtain solutions
      of objective value within 10% of the optimal */

   status = CPXXsetdblparam (env, CPXPARAM_MIP_Pool_RelGap, 0.1);
   if ( status ) {
      fprintf (stderr, 
               "Failed to set the solution pool relative gap, error %d.\n", 
               status);
      goto TERMINATE;
   }


   /* Optimize the problem and obtain multiple solutions. */

   status = CPXXpopulate (env, lp);

   if ( status ) {
      fprintf (stderr, "Failed to populate MIP.\n");
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("Solution status: %d.\n", solstat);

   status  = CPXXgetobjval (env, lp, &incobjval);

   if ( status ) {
      fprintf (stderr,
               "Failed to obtain objective value for the incumbent.\n");
      goto TERMINATE;
   }

   printf ("Objective value of the incumbent: %.10g\n", incobjval);

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is. cur_numcols stores the current number 
      of columns. */

   cur_numcols = CPXXgetnumcols (env, lp);

   /* Allocate space for solution */

   incx = malloc (cur_numcols*sizeof(*incx));

   if ( incx == NULL ) {
      fprintf (stderr, "No memory for solution values for the incumbent.\n");
      goto TERMINATE;
   }

   status = CPXXgetx (env, lp, incx, 0, cur_numcols-1);
   if ( status ) {
      fprintf (stderr, "Failed to obtain the incumbent.\n");
      goto TERMINATE;
   }

   /* Write out the incumbent */

   for (j = 0; j < cur_numcols; j++) {
      printf ("Incumbent: Column %d:  Value = %17.10g\n", j, incx[j]);
   }
   printf ("\n");

   /* Get the number of solutions in the solution pool */

   numsol = CPXXgetsolnpoolnumsolns (env, lp);   
   printf ("The solution pool contains %d solutions.\n", numsol);

   /* Some solutions are deleted from the pool because of the solution
      pool relative gap parameter */

   numsolreplaced = CPXXgetsolnpoolnumreplaced (env, lp);
   printf (
"%d solutions were removed due to the solution pool relative gap parameter.\n",
          numsolreplaced);

   printf ("In total, %d solutions were generated.\n",
           numsol + numsolreplaced);
   
   /* Get the average objective value of solutions in the solution
      pool */

   status = CPXXgetsolnpoolmeanobjval (env, lp, &meanobjval);
   printf ("The average objective value of the solutions is %.10g.\n\n",
          meanobjval);

   /* Write out the objective value of each solution and its
      difference to the incumbent */

   x = malloc (cur_numcols*sizeof(*x));
   if ( x == NULL ) {
      fprintf (stderr, "No memory for solution values.\n");
      goto TERMINATE;
   }

   printf ("Solution        Objective   Number of variables\n");
   printf ("                value       that differ compared to\n");
   printf ("                            the incumbent\n");
  

   for (i = 0; i < numsol; i++) {
      char namei[BUFSIZE];
      CPXSIZE surplus;

      /* Write out objective value */

      CPXXgetsolnpoolsolnname (env, lp, namei, BUFSIZE, &surplus, i);
      printf ("%-15s ", namei); 


      status = CPXXgetsolnpoolobjval (env, lp, i, &objval);
      if ( status ) {
         fprintf (stderr,
                  "Failed to obtain objective value for solution %d.\n", i);
         goto TERMINATE;
      }
      printf ("%.10g         ", objval);

      status = CPXXgetsolnpoolx (env, lp, i, x, 0, cur_numcols-1);
      if ( status ) {
         fprintf (stderr, "Failed to obtain solution %d.\n", i);
         goto TERMINATE;
      }
      
      /* Compute the number of variables that differ in the solution
         and in the incumbent */

      numdiff = 0;
      for (j = 0; j < cur_numcols; j++) {
         if ( fabs (x[j] - incx[j]) > EPSZERO )
            numdiff++;
      }      
      printf ("%d / %d\n", numdiff, cur_numcols);
   }

   
TERMINATE:

   /* Free up the solution */

   free_and_null ((char **) &incx);
   free_and_null ((char **) &x);

   /* Free up the problem as allocated by CPXXcreateprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

      if ( status ) {
         char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

}  /* END main */
Пример #16
0
int
main (int argc, char **argv)
{
   CPXENVptr env = NULL;
   CPXLPptr lp = NULL;
   char errbuf[CPXMESSAGEBUFSIZE];
   int status = 0;
   char const *vmconfig = NULL;
   char const *model = NULL;
   double objval;
   LOGINFO myloginfo;

#ifdef USE_MPI
   MPI_Init (&argc, &argv);
#endif

   if ( argc != 3 ) {
      usage (argv[0]);
      return -1;
   }
   
   vmconfig = argv[1];
   model = argv[2];

   /* Create a new CPLEX environment for each problem to solve.
    */
   env = CPXXopenCPLEX (&status);
   if ( env == NULL || status != 0 ) {
      fprintf (stderr, "Failed to open CPLEX: %s\n",
               CPXXgeterrorstring (NULL, status, errbuf));
      goto TERMINATE;
   }
   /* Load a virtual machine configuration.
    */
   status = CPXXreadcopyvmconfig (env, vmconfig);
   if ( status != 0 ) {
      fprintf (stderr, "Failed to load VMC %s: %s\n",
               vmconfig, CPXXgeterrorstring (env, status, errbuf));
      goto TERMINATE;
   }
   /* Create and input a problem.
    */
   lp = CPXXcreateprob (env, &status, model);
   if ( lp == NULL || status != 0 ) {
      fprintf (stderr, "Failed to create problem: %s\n",
               CPXXgeterrorstring (env, status, errbuf));
      goto TERMINATE;
   }
   status = CPXXreadcopyprob (env, lp, model, NULL);
   if ( status != 0 ) {
      fprintf (stderr, "Failed to read problem %s: %s\n",
               model, CPXXgeterrorstring (env, status, errbuf));
      goto TERMINATE;
   }
   /* Turn off CPLEX logging.
    */
   status = CPXXsetintparam (env, CPXPARAM_MIP_Display, 0);
   if ( status )  goto TERMINATE;
   /* Install an incumbent callback for logging.
    */
   status = CPXXgettime (env, &myloginfo.timestart);
   if ( status ) {
      fprintf (stderr, "Failed to query time.\n");
      goto TERMINATE;
   }
   status = CPXXgetdettime (env, &myloginfo.dettimestart);
   if ( status ) {
      fprintf (stderr, "Failed to query deterministic time.\n");
      goto TERMINATE;
   }
   myloginfo.numcols       = CPXXgetnumcols (env, lp);
   myloginfo.lastincumbent = CPXXgetobjsen (env, lp) * 1e+35;
   myloginfo.lastdettime   = -10000.0;
   status = CPXXsetinfocallbackfunc (env, logcallback, &myloginfo);
   if ( status ) {
      fprintf (stderr, "Failed to set logging callback function.\n");
      goto TERMINATE;
   }
   /* Solve the problem using parallel distributed MIP.
    */
   status = CPXXdistmipopt (env, lp);
   if ( status != 0 ) {
      fprintf (stderr, "Failed to optimize: %s\n",
               CPXXgeterrorstring (env, status, errbuf));
      goto TERMINATE;
   }
   /* Print some solution information.
    */
   status = CPXXgetobjval (env, lp, &objval);
   if ( status == CPXERR_NO_SOLN ) {
      printf ("No solution available.\n");
   }
   else if ( status == 0 ) {
      printf ("Solution value %f\n", objval);
   }
   else {
      fprintf (stderr, "Error %d: %s\n", status,
               CPXXgeterrorstring (env, status, errbuf));
   }
   printf ("Solution status %d\n", CPXXgetstat (env, lp));


 TERMINATE:
   CPXXfreeprob (env, &lp);
   CPXXcloseCPLEX (&env);

#ifdef USE_MPI
   CPXXfinalizeMPIworkers (-1, NULL, 0, NULL, 1);
   MPI_Finalize ();
#endif

   return status;
}
Пример #17
0
int
main(int argc, char **argv)
{
   int status;
   CPXENVptr *env;
   CPXLPptr *lp;
   char const *modelfile = NULL;
   CPXASYNCptr *handle;
   CPXENVGROUPptr group;
   int i;
   int jobs = 0;
   int active;
   int *finished;
   char const **machine;
   char cwd[MAX_PATH_LEN];
   char usrfunc[MAX_PATH_LEN];
   int frequency;
   double absgap = 1e-6;
   int bestidx;
   CPXDIM c, cols;
   double *x;
   enum {
      OUTPUT_SILENT, OUTPUT_PREFIXED, OUTPUT_LOG
   } output = OUTPUT_SILENT;

#if defined(USE_MPI)
   int numprocs, rank;

   MPI_Init(&argc, &argv);
   MPI_Comm_size (MPI_COMM_WORLD, &numprocs);
   if ( numprocs < 3 ) {
      fprintf (stderr, "Invalid number of processors (%d)\n", numprocs);
      abort ();
   }
   MPI_Comm_rank (MPI_COMM_WORLD, &rank);
   if ( rank != 0 ) {
      fprintf (stderr, "Master must have rank 0!\n");
      MPI_Finalize ();
      abort ();
   }
   machine = malloc (sizeof (*machine) * numprocs);
   if ( machine == NULL ) {
      fprintf (stderr, "Out of memory!\n");
      abort ();
   }
   for (i = 0; i < numprocs; ++i)
      machine[i] = "mpimachine";
   jobs = numprocs - 1;
#elif defined(USE_PROCESS)
   char const *bin = "./cplex";

   machine = malloc (sizeof (*machine) * argc);
   if ( machine == NULL ) {
      fprintf (stderr, "Out of memory!\n");
      abort ();
   }
#elif defined(USE_TCPIP)
   machine = malloc (sizeof (*machine) * argc);
   if ( machine == NULL ) {
      fprintf (stderr, "Out of memory!\n");
      abort ();
   }
#else
#   error "No transport type selected"
#endif


   /* Parse the command line. */
   for (i = 1; i < argc; ++i) {
      if ( strncmp (argv[i], "-model=", 7) == 0 )
         modelfile = argv[i] + 7;
#if defined(USE_MPI)
#elif defined(USE_PROCESS)
      else if ( strncmp (argv[i], "-machine=", 9) == 0 )
         machine[jobs++] = argv[i] + 9;
      else if ( strncmp (argv[i], "-bin=", 5) == 0 )
         bin = argv[i] + 5;
#elif defined(USE_TCPIP)
      else if ( strncmp (argv[i], "-address=", 9) == 0 )
         machine[jobs++] = argv[i];
#endif
      else if ( strncmp (argv[i], "-absgap=", 8) == 0 )
         absgap = strtod (argv[i] + 8, NULL);
      else if ( strcmp (argv[i], "-output-prefixed") == 0 )
         output = OUTPUT_PREFIXED;
      else if ( strcmp (argv[i], "-output-log") == 0 )
         output = OUTPUT_LOG;
   }

   /* Validate arguments.
    */
   if ( modelfile == NULL ) {
      fprintf (stderr, "No model file specified with -model=<modelfile>\n");
      abort ();
   }
   if ( jobs < 1 ) {
     fprintf (stderr, "Invalid job count %d\n", jobs);
     abort ();
   }

   /* Allocate working arrays. */
   if ( (env = malloc (sizeof (*env) * jobs)) == NULL ||
        (handle = malloc (sizeof (*handle) * jobs)) == NULL ||
        (lp = malloc (sizeof (*lp) * jobs)) == NULL ||
        (finished = calloc (jobs, sizeof (*finished))) == NULL ||
        (remotestats = calloc (jobs, sizeof (*remotestats))) == NULL )
   {
      fprintf (stderr, "Out of memory!\n");
      abort ();
   }

   /* Find the place at which to find the shared object that implements
    * the user function. On Windows the path to the current directory is
    * likely to contain blanks, so better quote it.
    */
   getcwd (cwd, sizeof (cwd));
   usrfunc[0] = 0;
#ifdef _WIN32
   strcat (usrfunc, "-libpath=\"");
   strcat (usrfunc, cwd);
   strcat (usrfunc, "\"");
#else
   strcat (usrfunc, "-libpath=");
   strcat (usrfunc, cwd);
#endif

   /* Create a remote object instances. */
   for (i = 0; i < jobs; ++i) {
      /* These values define how we connect to the remote object. It is
       * important to use a transport configuration that actually supports
       * disconnect/reconnect. For the "processtransport" this means to use
       * named pipes instead of anonymous pipes or stdio.
       */
      char const *transport;
      char const *args[16];
      int nextarg = 0;
      char *logpath = NULL;

#if defined(USE_MPI)
      char rankbuf[256];

      sprintf (rankbuf, "-remoterank=%d", i + 1);
      transport = "mpitransport";
      args[nextarg++] = rankbuf;
#elif defined(USE_PROCESS)
      char logbuf[1024];
      transport = "processtransport";
      /* If the machine is not "localhost" then use ssh to connect to
       * this machine. Otherwise just fork a process on the local
       * machine.
       */
      if ( machine[i] != NULL && strcmp (machine[i], "localhost") != 0 ) {
         args[nextarg++] = "/usr/bin/ssh";
         args[nextarg++] = machine[i];
      }
      args[nextarg++] = bin;
      args[nextarg++] = "-worker=process";
      if ( machine[i] != NULL )
         args[nextarg++] = "-stdio";
      else
         args[nextarg++] = "-namedpipes=.";
      args[nextarg++] = usrfunc;
      args[nextarg++] = "-userfunction=parmipopt_userfunction=REGISTER_USERFUNCTION";
      sprintf (logbuf, "-logfile=server%d.log", i);
      if ( (args[nextarg] = logpath = strdup (logbuf)) != NULL )
         ++nextarg;
#elif defined(USE_TCPIP)
      transport = "tcpiptransport";
      args[nextarg++] = machine[i];
#endif


      printf ("Creating env on %s\n", machine[i]);
      env[i] = CPXXopenCPLEXremote(transport, nextarg, args, &status);
      if ( status || env[i] == NULL ) {
         fprintf (stderr, "CPXXopenCPLEXremote: %d\n", status);
         abort ();
      }
      free (logpath);

      /* Enable output */
      switch (output) {
      case OUTPUT_SILENT:
         /* nothing */
         break;
      case OUTPUT_PREFIXED:
         {
            CPXCHANNELptr cres, cwar, cerr, clog;

            if ( (status = CPXXgetchannels (env[i], &cres, &cwar, &cerr, &clog)) != 0 ) {
               fprintf (stderr, "CPXXgetchannels: %d\n", status);
               abort ();
            }
            if ( (status = CPXXaddfuncdest (env[i], cres, env[i], printer)) != 0 ||
                 (status = CPXXaddfuncdest (env[i], cwar, env[i], printer)) != 0 ||
                 (status = CPXXaddfuncdest (env[i], clog, env[i], printer)) != 0 )
            {
               fprintf (stderr, "CPXXaddfpdest: %d\n", status);
               abort ();
            }
         }
         break;
      case OUTPUT_LOG:
         {
            if ( (status = CPXXsetintparam (env[i], CPXPARAM_ScreenOutput, CPX_ON)) != 0 ) {
               fprintf (stderr, "CPXXgetchannels: %d\n", status);
               abort ();
            }
         }
         break;
      }

      /* Create empty problem object for this remote solver. */
      printf ("Creating LP %d\n", i);
      lp[i] = CPXXcreateprob(env[i], &status, "problem");
      if ( status || lp[i] == NULL ) {
         fprintf (stderr, "CPXXcreateprob: %d\n", status);
         abort ();
      }

      /* Install and configure callbacks. */
      remotestats[i].env = env[i];
      remotestats[i].idx = i;
      if ( (status = CPXXsetinfohandler (env[i], infohandler, &remotestats[i])) != 0 ) {
         fprintf (stderr, "CPXXsetinfohandler: %d\n", status);
         abort ();
      }

      if ( (status = changeObjdiff (env[i], 1e-5)) != 0 ) {
         fprintf (stderr, "changeObjdiff: %d\n", status);
         abort ();
      }

      if ( (status = installCallback (env[i])) != 0 ) {
         fprintf (stderr, "installCallback: %d\n", status);
         abort ();
      }

      /* Apply predefined perameter settings for this solver. */
      applySettings (env[i], i);
   }

   /* Put all environments into one group so that we can use multicasts
    * on operations that are the same for all solvers and/or imply lots
    * of data exchange.
    */
   status = CPXXcreateenvgroup (&group, jobs, env);
   if ( status != 0 ) {
      fprintf (stderr, "CPXXcreateenvgroup: %d\n", status);
      abort ();
   }

   /* Read the model into all remote solver. */
   status = CPXXreadcopyprob_multicast (group, modelfile, NULL);
   if ( status != 0 ) {
      fprintf (stderr, "CPXXreadcopyprob_multicast: %d\n", status);
      abort ();
   }
   objsen = CPXXgetobjsen (env[0], lp[0]);

   /* We set the thread count for each solver to 1 so that we do not
    * run into problems if multiple solves are performed on the same
    * machine.
    */
   status = CPXXsetintparam_multicast (group, CPXPARAM_Threads, 1);
   if ( status != 0 ) {
      fprintf (stderr, "CPXXsetintparam_multicast: %d\n", status);
      abort ();
   }

   /* Start an asynchronous solve on each remote solver. */
   for (i = 0; i < jobs; ++i) {
      printf ("Solving %d\n", i);
      if ( (status = CPXXmipopt_async (env[i], lp[i], &handle[i])) != 0 ) {
         fprintf (stderr, "CPXXmipopt_async: %d\n", status);
         abort ();
      }
   }

   /* All solves are started. Loop until the stopping criterion is met. */
   active = jobs;
   frequency = 10000; /* Print current bounds every two seconds. */
   while (active > 0) {
      int running = 0;
      /* Check if we shold stop all solves.
       * We stop them if the absolute mipgap is reached.
       */
      if ( primal.valid && dual.valid &&
           ((objsen == CPX_MIN && dual.bound + absgap >= primal.bound) ||
            (objsen == CPX_MAX && dual.bound - absgap <= primal.bound)) )
      {
         printf ("Stopping criterion reached. Stopping all pending solves.\n");
         for (i = 0; i < jobs; ++i) {
            if ( !finished[i] )
               CPXXasynckill (handle[i]);
         }
         break;
      }
      if ( --frequency == 0 ) {
         printf ("dual=%f, primal=%f\n", dual.bound, primal.bound);
         frequency = 10000;
      }

      /* Loop over all solvers and test if they are still running. */
      for (i = 0; i < jobs; ++i) {
         if ( finished[i] )
            continue;
         CPXXasynctest (handle[i], &running);
         if ( !running ) {
            /* The job is finished. We have a solution, so kill all
             * others. */
            int j;
            --active;
            finished[i] = 1;
            printf ("First job (%d) is finished, killing the rest\n", i);
            for (j = 0; j < jobs; ++j) {
               if ( j != i )
                  CPXXasynckill (handle[j]);
            }
            break;
         }
      }
      millisleep (10);
   }

   /* All solves have finished. Join them. */
   for (i = 0; i < jobs; ++i) {
      double obj = -CPX_INFBOUND;
      int stat;
      
      status = CPXXmipopt_join (&handle[i]);
      if ( status ) {
         fprintf (stderr, "CPXXmipopt_join: %d\n", status);
         abort ();
      }

      status = CPXXgetobjval (env[i], lp[i], &obj);
      if ( status == CPXERR_NO_SOLN ) {
         /* No feasible solution found (yet) on this machine.
          * Just set objective function to a very big value
          */
         obj = (objsen == CPX_MIN) ? CPX_INFBOUND : -CPX_INFBOUND;
      }
      else if ( status ) {
         fprintf (stderr, "CPXXgetobjval: %d\n", status);
         abort ();
      }
      stat = CPXXgetstat (env[i], lp[i]);
      printf ("Job %d: %f, stat %d\n", i, obj, stat);
      printf ("\t%f, %f, %f\n", remotestats[i].dettime,
              remotestats[i].dual, remotestats[i].primal);

      if ( (status = removeCallback (env[i])) != 0 ) {
         fprintf (stderr, "removeCallback: %d\n", status);
         abort ();
      }
   }

   /* Fetch the x vector from the solver that produced the best
    * primal bound. */
   bestidx = primal.idx;
   cols = CPXXgetnumcols (env[bestidx], lp[bestidx]);
   if ( (x = malloc (cols * sizeof (*x))) == NULL ) {
      fprintf (stderr, "Out of memory!\n");
      abort ();
   }
   status = CPXXgetx (env[bestidx], lp[bestidx], x, 0, cols - 1);
   if ( status ) {
      fprintf (stderr, "CPXXgetx: %d\n", status);
      abort ();
   }
   printf ("Optimal solution:\n");
   for (c = 0; c < cols; ++c)
      printf ("x[%5d]: %f\n", c, x[c]);
   free (x);

   CPXXfreeenvgroup (&group);

   /* Close the CPLEX objects in _reverse_ order. */
   for (i = jobs - 1; i >= 0; --i)
      CPXXcloseCPLEX (&env[i]);
   free (remotestats);
   free (env);
   free (lp);
   free (handle);
   free (finished);
   free ((char **)machine);

#ifdef USE_MPI
   MPI_Finalize ();
#endif


   return 0;
}
Пример #18
0
int
main (int  argc, char *argv[])
{
   int status = 0;
   int solstat;

   /* 17 city problem */
   
   const char* filename = "../../../examples/data/atsp.dat";

   /* ATSP instance */

   double **arc_cost = NULL;
   CPXDIM num_nodes;

   /* data required to print the optimal ATSP tour */

   double objval;    
   CPXDIM num_x_cols;
   double *x = NULL; 
   CPXDIM i, j;
   CPXDIM *succ = NULL;

   /* Cplex environment and master ILP */

   CPXENVptr env = NULL;
   CPXLPptr  lp = NULL;

   /* Decide when Benders' cuts are going to be separated:
      0: only when a integer solution if found
         (i.e., wherefrom == CPX_CALLBACK_MIP_CUT_FEAS )
      1: even to cut-off fractional solutions, 
         at the end of the cplex cut-loop
         (i.e., wherefrom == CPX_CALLBACK_MIP_CUT_LAST || 
          wherefrom == CPX_CALLBACK_MIP_CUT_FEAS ) */
   
   int separate_fractional_solutions; 

   /* Cut callback data structure */
   
   USER_CBHANDLE user_cbhandle;
   user_cbhandle.env     = NULL;
   user_cbhandle.lp      = NULL;
   user_cbhandle.x       = NULL;
   user_cbhandle.indices = NULL;
   user_cbhandle.ray     = NULL;
   user_cbhandle.cutval  = NULL;
   user_cbhandle.cutind  = NULL;


   /* Check the command line arguments */

   if ( argc != 2 && argc != 3) {
      usage (argv[0]);
      goto TERMINATE;
   }

   if ( (argv[1][0] != '1' && argv[1][0] != '0') || 
        argv[1][1] != '\0' ) {
      usage (argv[0]);
      goto TERMINATE;
   }

   separate_fractional_solutions = ( argv[1][0] == '0' ? 0 : 1 );

   printf ("Benders' cuts separated to cut off: ");
   if ( separate_fractional_solutions ) {
      printf ("Integer and fractional infeasible solutions.\n");
   }
   else {
      printf ("Only integer infeasible solutions.\n");
   }
   fflush (stdout);

   if ( argc == 3 )  filename = argv[2];

   /* Read the ATSP instance */

   status = read_ATSP (filename, &arc_cost, &num_nodes);
   if ( status ) {
      fprintf (stderr, "Error in read_ATSP, status = %d\n", status);
      goto TERMINATE;
   }
   
   /* Init the CPLEX environment */

   env = CPXXopenCPLEX (&status);
   if ( env == NULL ) {
      fprintf (stderr, "Failure in CPXXopenCPLEX, status = %d.\n", status);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON); 
   if ( status ) {
      fprintf (stderr, "Failed to turn on screen indicator, status = %d.\n",
               status);
      goto TERMINATE;
   }

   /* Set MIP log interval to 1 */

   status = CPXXsetcntparam (env, CPXPARAM_MIP_Interval, 1);
   if ( status )  {
      fprintf (stderr,
             "Failed to set CPXPARAM_MIP_Interval, status = %d.\n", status);
      goto TERMINATE;
   }

   /* Create the master ILP */

   lp = CPXXcreateprob (env, &status, "master_ILP.lp");
   if ( lp == NULL ) {
      fprintf (stderr, "Failure in CPXXcreateprob, status = %d.\n", status);
      goto TERMINATE;
   }

   status = create_master_ILP (env, lp, arc_cost, num_nodes);
   if ( status ) {
      fprintf (stderr,
               "Failed to create the master ILP.\n");
      goto TERMINATE;
   }

   /* Init the cut callback data structure */

   status = init_user_cbhandle (&user_cbhandle, num_nodes, 
                                separate_fractional_solutions);
   if ( status ) {
      fprintf (stderr,
               "Failed to init the cut callback data structure, status = %d.\n", 
               status);
      goto TERMINATE;
   }

   /* Set up environment parameters to use the function benders_callback 
      as cut callback function */

   status = set_benders_callback (env, &user_cbhandle);
   if ( status ) {
      fprintf (stderr,
               "Failure in function set_benders_callback: status = %d.\n",
               status);
      goto TERMINATE;
   }

   /* Optimize the problem and obtain solution status */

   status = CPXXmipopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize MIP, status = %d.\n", status);
      goto TERMINATE;
   }

   solstat = CPXXgetstat (env, lp);
   printf ("\nSolution status: %d\n", solstat);

   /* Write out the objective value */ 

   if ( CPXXgetobjval (env, lp, &objval) ) {
      printf ("Failed to obtain objective value.\n");
   }
   else {
      printf ("Objective value: %17.10e\n", objval);
   }

   if ( solstat == CPXMIP_OPTIMAL ) {
    
      /* Write out the optimal tour */
      
      num_x_cols = CPXXgetnumcols (env, lp);
      x = malloc (num_x_cols * sizeof(*x));
      if ( x == NULL ) {
         fprintf (stderr, "No memory for x array.\n");
         status = -1;
         goto TERMINATE;
      }
      status = CPXXgetx (env, lp, x, 0, num_x_cols-1);
      if ( status ) {
         fprintf (stderr, "Failed to obtain solution, status = %d.\n", status);
         goto TERMINATE;
      }

      succ = malloc (num_nodes * sizeof(*succ));
      if ( succ == NULL ) {
         fprintf (stderr, "No memory for succ array.\n");
         status = -1;
         goto TERMINATE;
      }
      for (j = 0; j < num_nodes; ++j)
         succ[j] = -1;
      for (i = 0; i < num_nodes; ++i) {
         for (j = 0; j < num_nodes; ++j) {
            if ( fabs (x[i * num_nodes + j]) > 1e-03 )
               succ[i] = j;
         }
      }
      printf ("Optimal tour:\n");
      i = 0;
      while ( succ[i] != 0 ) {
         printf ("%d, ", i);
         i = succ[i];
      }
      printf ("%d\n", i);

   } 
   else {
      printf ("Solution status is not CPX_STAT_OPTIMAL\n");
   }
   
TERMINATE:

   /* Free the allocated memory if necessary */

   free_and_null ((char **) &x);
   free_and_null ((char **) &succ);

   if ( arc_cost != NULL ) {
      for (i = 0; i < num_nodes; ++i) {
         free_and_null ((char **) &(arc_cost[i]));
      }
   }
   free_and_null ((char **) &arc_cost);

   status = free_user_cbhandle (&user_cbhandle);
   if ( status ) {
      fprintf (stderr, "free_user_cbhandle failed, status = %d.\n",
               status);
   }
    
   if ( lp != NULL ) {
      int local_status = CPXXfreeprob (env, &lp);
      if ( local_status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n",
                  local_status);
         status = local_status;
      }
   }

   /* Free the CPLEX environment, if necessary */

   if ( env != NULL ) {
      int local_status = CPXXcloseCPLEX (&env);
      if ( local_status ) {
         fprintf (stderr, 
                  "Could not close CPLEX environment, status = %d.\n", 
                  local_status);
         status = local_status;
      }
   }
     
   return status;

} /* END main */
Пример #19
0
static int CPXPUBLIC 
rounddownheur (CPXCENVptr env,
               void       *cbdata,
               int        wherefrom, 
               void       *cbhandle,
               double     *objval_p,
               double     *x,
               int        *checkfeas_p,
               int        *useraction_p)
{
   int status = 0;
   
   int       j, cols;
   double    roundobjval;
   int       *feas = NULL;
   CPXCLPptr lp;
   double    *objcoefs = NULL;

   *useraction_p = CPX_CALLBACK_DEFAULT;

   /* Heuristic motivated by knapsack constrained problems.
      Rounding down all fractional values will give an integer
      solution that is feasible, since all constraints are <= 
      with positive coefficients */

   status = CPXXgetcallbacklp (env, cbdata, wherefrom, &lp);
   if ( status ) {
      fprintf (stdout, "Can't get lp pointer.");
      goto TERMINATE;
   }

   cols = CPXXgetnumcols (env, lp);
   if ( cols <= 0 ) {
      fprintf (stdout, "numcols = %d.", cols);
      status = CPXERR_CALLBACK;
      goto TERMINATE;
   }
   
   objcoefs = malloc (cols * sizeof (*objcoefs));
   feas     = malloc (cols * sizeof (*feas));
   if ( objcoefs == NULL || feas == NULL ) {
      fprintf (stdout, "Out of memory.");
      status = CPXERR_CALLBACK;
      goto TERMINATE;
   } 
 
   status = CPXXgetobj (env, lp, objcoefs, 0, cols-1);
   if ( status ) {
      fprintf (stdout, "Can't get objective.");
      goto TERMINATE;
   }

   status = CPXXgetcallbacknodeintfeas (env, cbdata, wherefrom, feas,
                                       0, cols-1);
   if ( status ) {
      fprintf (stdout,
               "Can't get variable feasible status for node.");
      goto TERMINATE;
   }

   roundobjval = *objval_p;
   for (j = 0; j < cols; j++) {

      /* Set the fractional variable to zero and update
         the objective value */

      if ( feas[j] == CPX_INTEGER_INFEASIBLE ) {
         roundobjval -= x[j] * objcoefs[j];
         x[j] = 0.0;
      }
   }
   *objval_p = roundobjval;

   /* Have CPLEX check the solution for integer feasibility */

   *checkfeas_p = 1;

   /* Tell CPLEX that a solution is being returned */

   *useraction_p = CPX_CALLBACK_SET;

TERMINATE:

   free_and_null ((char **) &objcoefs);
   free_and_null ((char **) &feas);  

   return (status);

} /* END rounddown */
Пример #20
0
static int CPXPUBLIC
usersetbranch (CPXCENVptr   env,
               void         *cbdata,
               int          wherefrom,
               void         *cbhandle,
               int          brtype,
               CPXDIM       sos,
               int          nodecnt,
               CPXDIM       bdcnt,
               const CPXDIM *nodebeg,
               const CPXDIM *indices,
               const char   *lu,
               const double *bd,
               const double *nodeest,
               int          *useraction_p)   
{
   int status = 0;
 
   CPXDIM   j, bestj = -1;
   CPXDIM   cols;
   double   maxobj = -CPX_INFBOUND;
   double   maxinf = -CPX_INFBOUND;
   double   xj_inf;
   double   xj_lo;
   double   objval;
   double   *x   = NULL;
   double   *obj = NULL;
   int      *feas = NULL;
 
   char     varlu[1];
   double   varbd[1];
   CPXCNT   seqnum1, seqnum2;
 
   CPXCLPptr lp;
 
   /* Initialize useraction to indicate no user action taken */
 
   *useraction_p = CPX_CALLBACK_DEFAULT;
 
   /* If CPLEX is choosing an SOS branch, take it */
 
   if ( sos >= 0 )  return (status);
 
   /* Get pointer to the problem */
 
   status = CPXXgetcallbacklp (env, cbdata, wherefrom, &lp);
   if ( status ) {
      fprintf (stdout, "Can't get LP pointer.\n");
      goto TERMINATE;
   }
 
   cols = CPXXgetnumcols (env, lp);
   if ( cols <= 0 ) {
      fprintf (stdout, "Can't get number of columns.\n");
      status = CPXERR_CALLBACK;
      goto TERMINATE;
   }
 
   /* Get solution values and objective coefficients */
 
   x    = malloc (cols * sizeof (*x));
   obj  = malloc (cols * sizeof (*obj));
   feas = malloc (cols * sizeof (*feas));
   if ( x     == NULL ||
        obj   == NULL ||
        feas  == NULL   ) {
      fprintf (stdout, "Out of memory.");
      status = CPXERR_CALLBACK;
      goto TERMINATE;
   }
 
   status = CPXXgetcallbacknodex (env, cbdata, wherefrom, x, 0,
                                  cols-1);
   if ( status ) {
      fprintf (stdout, "Can't get node solution.");
      goto TERMINATE;
   }
 
   status = CPXXgetcallbacknodeobjval (env, cbdata, wherefrom,
                                       &objval);
   if ( status ) {
      fprintf (stdout, "Can't get node objective value.");
      goto TERMINATE;
   }
 
   status = CPXXgetobj (env, lp, obj, 0, cols-1);
   if ( status ) {
      fprintf (stdout, "Can't get obj.");
      goto TERMINATE;
   }
 
   status = CPXXgetcallbacknodeintfeas (env, cbdata, wherefrom, feas,
                                        0, cols-1);
   if ( status ) {
      fprintf (stdout,
               "Can't get variable feasible status for node.");
      goto TERMINATE;
   }
 
   /* Branch on var with largest objective coefficient among those
      with largest infeasibility */
 
   for (j = 0; j < cols; j++) {
      if ( feas[j] == CPX_INTEGER_INFEASIBLE ) {
         xj_inf = x[j] - floor (x[j]);
         if ( xj_inf > 0.5 )  xj_inf = 1.0 - xj_inf;
 
         if ( xj_inf >= maxinf                            &&
              (xj_inf > maxinf || fabs (obj[j]) >= maxobj)  ) {
            bestj  = j;
            maxinf = xj_inf; 
            maxobj = fabs (obj[j]);
         }
      }
   }
 
   /* If there weren't any eligible variables, take default branch */
 
   if ( bestj < 0 ) {
      goto TERMINATE;
   }
 
   /* Now set up node descriptions */
 
   xj_lo = floor (x[bestj]);
 
   /* Up node */
 
   varlu[0] = 'L';
   varbd[0] = xj_lo + 1;
   status = CPXXbranchcallbackbranchbds (env, cbdata, wherefrom,
                                        1, &bestj, varlu, varbd,
                                        objval, NULL, &seqnum1);
   if ( status )  goto TERMINATE;
 
   /* Down node */
 
   varlu[0] = 'U';
   varbd[0] = xj_lo;
 
   status = CPXXbranchcallbackbranchbds (env, cbdata, wherefrom,
                                         1, &bestj, varlu, varbd,
                                         objval, NULL, &seqnum2);
   if ( status )  goto TERMINATE;
 
   /* Set useraction to indicate a user-specified branch */
 
   *useraction_p = CPX_CALLBACK_SET;
 
TERMINATE:
 
   free_and_null ((char **) &x);
   free_and_null ((char **) &obj);
   free_and_null ((char **) &feas); 
   return (status);
 
} /* END usersetbranch */
Пример #21
0
int
main (void)
{
   char     probname[16];  /* Problem name is max 16 characters */

   /* Declare and allocate space for the variables and arrays where we
      will store the optimization results including the status, objective
      value, variable values, dual values, row slacks and variable
      reduced costs. */

   int      solstat;
   double   objval;
   double   x[NUMCOLS];
   double   pi[NUMROWS];
   double   slack[NUMROWS];
   double   dj[NUMCOLS];


   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   int           status;
   CPXDIM        i, j;
   CPXDIM        cur_numrows, cur_numcols;
   char          errmsg[CPXMESSAGEBUFSIZE];

   CPXCHANNELptr  cpxerror   = NULL;
   CPXCHANNELptr  cpxwarning = NULL;
   CPXCHANNELptr  cpxresults = NULL;
   CPXCHANNELptr  ourchannel = NULL;

   char *errorlabel = "cpxerror";
   char *warnlabel  = "cpxwarning";
   char *reslabel   = "cpxresults";
   char *ourlabel   = "Our Channel";

   CPXFILEptr fpout  = NULL;


   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

   /* Since the message handler is yet to be set up, we'll call our
      messaging function directly to print out any errors  */

   if ( env == NULL ) {
      ourmsgfunc ("Our Message", "Could not open CPLEX environment.\n");
      goto TERMINATE;
   }

   /* Now get the standard channels.  If an error, just call our
      message function directly. */

   status = CPXXgetchannels (env, &cpxresults, &cpxwarning, &cpxerror, NULL);
   if ( status ) {
      ourmsgfunc ("Our Message", "Could not get standard channels.\n");
      CPXXgeterrorstring (env, status, errmsg);
      ourmsgfunc ("Our Message", errmsg);
      goto TERMINATE;
   }

   /* Now set up the error channel first.  The label will be "cpxerror" */

   status = CPXXaddfuncdest (env, cpxerror, errorlabel, ourmsgfunc);
   if ( status ) {
      ourmsgfunc ("Our Message", "Could not set up error message handler.\n");
      CPXXgeterrorstring (env, status, errmsg);
      ourmsgfunc ("Our Message", errmsg);
   }

   /* Now that we have the error message handler set up, all CPLEX
      generated errors will go through ourmsgfunc.  So we don't have
      to use CPXXgeterrorstring to determine the text of the message.
      We can also use CPXXmsg to do any other printing.  */

   status = CPXXaddfuncdest (env, cpxwarning, warnlabel, ourmsgfunc);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to set up handler for cpxwarning.\n");
      goto TERMINATE;
   }

   status = CPXXaddfuncdest (env, cpxresults, reslabel, ourmsgfunc);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to set up handler for cpxresults.\n");
      goto TERMINATE;
   }
   
   /* Now turn on the iteration display. */

   status = CPXXsetintparam (env, CPXPARAM_Simplex_Display, 2);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to turn on simplex display level.\n");
      goto TERMINATE;
   }

   /* Create the problem. */

   strcpy (probname, "example");
   lp = CPXXcreateprob (env, &status, probname);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of 
      failure, an error message will have been written to the error 
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  */

   if ( lp == NULL ) {
      CPXXmsg (cpxerror, "Failed to create LP.\n");
      goto TERMINATE;
   }

   /* Now populate the problem with the data. */

   status = populatebycolumn (env, lp);

   if ( status ) {
      CPXXmsg (cpxerror, "Failed to populate problem data.\n");
      goto TERMINATE;
   }


   /* Optimize the problem and obtain solution. */

   status = CPXXlpopt (env, lp);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to optimize LP.\n");
      goto TERMINATE;
   }

   status = CPXXsolution (env, lp, &solstat, &objval, x, pi, slack, dj);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to obtain solution.\n");
      goto TERMINATE;
   }


   /* Write the output to the screen.  We will also write it to a
      file as well by setting up a file destination and a function
      destination. */

   ourchannel = CPXXaddchannel (env);
   if ( ourchannel == NULL ) {
      CPXXmsg (cpxerror, "Failed to set up our private channel.\n");
      goto TERMINATE;
   }

   fpout = CPXXfopen ("lpex5.msg", "w");
   if ( fpout == NULL ) {
      CPXXmsg (cpxerror, "Failed to open lpex5.msg file for output.\n");
      goto TERMINATE;
   }
   status = CPXXaddfpdest (env, ourchannel, fpout);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to set up output file destination.\n");
      goto TERMINATE;
   }

   status = CPXXaddfuncdest (env, ourchannel, ourlabel, ourmsgfunc);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to set up our output function.\n");
      goto TERMINATE;
   }

   /* Now any message to channel ourchannel will go into the file 
      and into the file opened above. */

   CPXXmsg (ourchannel, "\nSolution status = %d\n", solstat);
   CPXXmsg (ourchannel, "Solution value  = %f\n\n", objval);

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is, rather than using sizes from when the problem
      was built.  cur_numrows and cur_numcols store the current number 
      of rows and columns, respectively.  */

   cur_numrows = CPXXgetnumrows (env, lp);
   cur_numcols = CPXXgetnumcols (env, lp);
   for (i = 0; i < cur_numrows; i++) {
      CPXXmsg (ourchannel, "Row %d:  Slack = %10f  Pi = %10f\n", 
              i, slack[i], pi[i]);
   }

   for (j = 0; j < cur_numcols; j++) {
      CPXXmsg (ourchannel, "Column %d:  Value = %10f  Reduced cost = %10f\n",
              j, x[j], dj[j]);
   }

   /* Finally, write a copy of the problem to a file. */

   status = CPXXwriteprob (env, lp, "lpex5.lp", NULL);
   if ( status ) {
      CPXXmsg (cpxerror, "Failed to write LP to disk.\n");
      goto TERMINATE;
   }
   
   
TERMINATE:

   /* First check if ourchannel is open */

   if ( ourchannel != NULL ) {
      int  chanstat;
      chanstat = CPXXdelfuncdest (env, ourchannel, ourlabel, ourmsgfunc);
      if ( chanstat ) {
         strcpy (errmsg, "CPXXdelfuncdest failed.\n");
         ourmsgfunc ("Our Message", errmsg); 
         if (!status)  status = chanstat;
      }
      if ( fpout != NULL ) {
         chanstat = CPXXdelfpdest (env, ourchannel, fpout);
         if ( chanstat ) {
            strcpy (errmsg, "CPXXdelfpdest failed.\n");
            ourmsgfunc ("Our Message", errmsg);
            if (!status)  status = chanstat;
         }
         CPXXfclose (fpout);
      }

      chanstat = CPXXdelchannel (env, &ourchannel);
      if ( chanstat ) {
         strcpy (errmsg, "CPXXdelchannel failed.\n");
         ourmsgfunc ("Our Message", errmsg);
         if (!status)  status = chanstat;
      }
   }

   /* Free up the problem as allocated by CPXXcreateprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         strcpy (errmsg, "CPXXfreeprob failed.\n");
         ourmsgfunc ("Our Message", errmsg);
      }
   }

   /* Now delete our function destinations from the 3 CPLEX channels. */
   if ( cpxresults != NULL ) {
      int  chanstat;
      chanstat = CPXXdelfuncdest (env, cpxresults, reslabel, ourmsgfunc);
      if ( chanstat && !status ) {
         status = chanstat;
         strcpy (errmsg, "Failed to delete cpxresults function.\n");
         ourmsgfunc ("Our Message", errmsg);
      }
   }

   if ( cpxwarning != NULL ) {
      int  chanstat;
      chanstat = CPXXdelfuncdest (env, cpxwarning, warnlabel, ourmsgfunc);
      if ( chanstat && !status ) {
         status = chanstat;
         strcpy (errmsg, "Failed to delete cpxwarning function.\n");
         ourmsgfunc ("Our Message", errmsg);
      }
   }

   if ( cpxerror != NULL ) {
      int  chanstat;
      chanstat = CPXXdelfuncdest (env, cpxerror, errorlabel, ourmsgfunc);
      if ( chanstat && !status ) {
         status = chanstat;
         strcpy (errmsg, "Failed to delete cpxerror function.\n");
         ourmsgfunc ("Our Message", errmsg);
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

      if ( status ) {
         strcpy (errmsg, "Could not close CPLEX environment.\n");
         ourmsgfunc ("Our Message", errmsg);
         CPXXgeterrorstring (env, status, errmsg);
         ourmsgfunc ("Our Message", errmsg);
      }
   }
     
   return (status);

}  /* END main */
Пример #22
0
static int CPXPUBLIC
solvecallback (CPXCENVptr env,
               void       *cbdata,
               int        wherefrom,
               void       *userinfo,
               int        *useraction_p)
{
   int status = 0;

   int      lpstatus = 0;
   CPXLPptr nodelp   = NULL;
   double   *prex    = NULL;
   MYCBptr  mycbinfo = (MYCBptr) userinfo;
   CPXLPptr mip      = mycbinfo->mip;
   double   *relx    = mycbinfo->relx;
   CPXDIM   cols;
   int      prestat;

   *useraction_p = CPX_CALLBACK_DEFAULT;

   /* Only use callback for solving the root relaxation (node 0) */

   if ( mycbinfo->count > 0 ) {
      goto TERMINATE;
   }
   mycbinfo->count++;

   /* Extract the LP to be solved */

   status = CPXXgetcallbacknodelp (env, cbdata, wherefrom, &nodelp);
   if ( status ) goto TERMINATE;

   cols = CPXXgetnumcols (env, nodelp);

   prex = malloc (cols * sizeof (*prex));
   if ( prex == NULL ) {
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }

   /* Use MIP presolve to crush the original solution.  Note that
      MIP presolve can only crush primal solutions */

   status = CPXXgetprestat (env, mip, &prestat, NULL, NULL, NULL,
                           NULL);
   if ( status ) goto TERMINATE;

   /* If a presolved model exists, then relx is crushed down
      to prex, the corresponding solution for the presolved
      model; otherwise, prex is just a copy of relx */
   
   if ( prestat ) {
      status = CPXXcrushx (env, mip, relx, prex);
      if ( status ) goto TERMINATE;
   }
   else {
      memcpy (prex, relx, cols * sizeof (*relx));
   }

   /* Feed the crushed solution into 'nodelp' */

   status = CPXXcopystart (env, nodelp, NULL, NULL, prex, NULL,
                          NULL, NULL);

   /* Use primal to reoptimize, since we only have a primal
      solution */

   status = CPXXprimopt (env, nodelp);
   if ( status )  goto TERMINATE;

   lpstatus = CPXXgetstat (env, nodelp);
   if ( lpstatus == CPX_STAT_OPTIMAL        ||
        lpstatus == CPX_STAT_OPTIMAL_INFEAS ||
        lpstatus == CPX_STAT_INFEASIBLE       ) {
      *useraction_p = CPX_CALLBACK_SET;
   }
   
TERMINATE:

   free_and_null ((char **) &prex);

   return (status);

} /* END solvecallback */
Пример #23
0
int
main (int argc, char *argv[])
{
    CPXENVptr env = NULL;
    CPXLPptr  lp = NULL;
    int       status = 0;
    CPXDIM    j;
    CPXDIM    numcols;
    double    totinv;

    int       solstat;
    double    objval;
    double    *x = NULL;

    double    rrhs[1];
    char      rsense[1];
    CPXNNZ    rmatbeg[1];

    CPXDIM    *indices = NULL;
    double    *values = NULL;
    char      *namestore = NULL;
    char      **nameptr = NULL;
    CPXSIZE   surplus, storespace;

    const char * datadir = argc <= 1 ? "../../../examples/data" : argv[1];
    char *prod = NULL;

    prod = (char *) malloc (strlen (datadir) + 1 + strlen("prod.lp") + 1);
    sprintf (prod, "%s/prod.lp", datadir);

    /* Initialize the CPLEX environment */

    env = CPXXopenCPLEX (&status);

    /* If an error occurs, the status value indicates the reason for
       failure.  A call to CPXXgeterrorstring will produce the text of
       the error message.  Note that CPXXopenCPLEX produces no output,
       so the only way to see the cause of the error is to use
       CPXXgeterrorstring.  For other CPLEX routines, the errors will
       be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

    if ( env == NULL ) {
        char  errmsg[CPXMESSAGEBUFSIZE];
        fprintf (stderr, "Could not open CPLEX environment.\n");
        CPXXgeterrorstring (env, status, errmsg);
        fprintf (stderr, "%s", errmsg);
        goto TERMINATE;
    }

    /* Turn on output to the screen */

    status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
    if ( status ) {
        fprintf (stderr,
                 "Failure to turn on screen indicator, error %d.\n", status);
        goto TERMINATE;
    }

    /* Create the problem, using the filename as the problem name */

    lp = CPXXcreateprob (env, &status, "prod.lp");

    /* A returned pointer of NULL may mean that not enough memory
       was available or there was some other problem.  In the case of
       failure, an error message will have been written to the error
       channel from inside CPLEX.  In this example, the setting of
       the parameter CPXPARAM_ScreenOutput causes the error message to
       appear on stdout.  Note that most CPLEX routines return
       an error code to indicate the reason for failure.   */

    if ( lp == NULL ) {
        fprintf (stderr, "Failed to create LP.\n");
        goto TERMINATE;
    }

    /* Now read the file, and copy the data into the created lp */

    status = CPXXreadcopyprob (env, lp, prod, NULL);
    if ( status ) {
        fprintf (stderr, "Failed to read and copy the problem data.\n");
        goto TERMINATE;
    }

    /* Tell presolve to do only primal reductions,
       turn off simplex logging */

    status = CPXXsetintparam (env, CPXPARAM_Preprocessing_Reduce, 1);
    if ( status ) {
        fprintf (stderr, "Failed to set CPXPARAM_Preprocessing_Reduce: %d\n",
                 status);
        goto TERMINATE;
    }
    status = CPXXsetintparam (env, CPXPARAM_Simplex_Display, 0);
    if ( status ) {
        fprintf (stderr, "Failed to set CPXPARAM_Simplex_Display: %d\n", status);
        goto TERMINATE;
    }


    /* Optimize the problem and obtain solution. */

    status = CPXXlpopt (env, lp);
    if ( status ) {
        fprintf (stderr, "Failed to optimize profit LP.\n");
        goto TERMINATE;
    }

    solstat = CPXXgetstat (env, lp);
    status  = CPXXgetobjval (env, lp, &objval);

    if ( status || solstat != CPX_STAT_OPTIMAL ) {
        fprintf (stderr, "Solution failed. Status %d, solstat %d.\n",
                 status, solstat);
        goto TERMINATE;
    }
    printf ("Profit objective value is %g\n", objval);


    /* Allocate space for column names */

    numcols = CPXXgetnumcols (env, lp);
    if ( !numcols ) {
        fprintf (stderr, "No columns in problem\n");
        goto TERMINATE;
    }

    CPXXgetcolname (env, lp, NULL, NULL, 0, &surplus, 0, numcols-1);
    storespace = - surplus;

    namestore = malloc (storespace * sizeof(*namestore));
    nameptr   = malloc (numcols * sizeof(*nameptr));
    if ( namestore == NULL  ||  nameptr == NULL ) {
        fprintf (stderr, "No memory for column names\n");
        goto TERMINATE;
    }

    status = CPXXgetcolname (env, lp, nameptr, namestore, storespace,
                             &surplus, 0, numcols-1);
    if ( status ) {
        fprintf (stderr, "Failed to get column names\n");
        goto TERMINATE;
    }

    /* Allocate space for solution */

    x = malloc (numcols * sizeof(*x));

    if ( x == NULL ) {
        fprintf (stderr,"No memory for solution.\n");
        goto TERMINATE;
    }

    status = CPXXgetx (env, lp, x, 0, numcols-1);
    if ( status ) {
        fprintf (stderr, "Failed to obtain primal solution.\n");
        goto TERMINATE;
    }

    totinv = 0;
    for (j = 0; j < numcols; j++) {
        if ( !strncmp (nameptr[j], "inv", 3) )  totinv += x[j];
    }
    printf ("Inventory level under profit objective is %g\n", totinv);

    /* Allocate space for a constraint */

    indices = malloc (numcols * sizeof (*indices));
    values  = malloc (numcols * sizeof (*values));

    if ( indices == NULL  ||  values == NULL ) {
        fprintf (stderr, "No memory for constraint\n");
        goto TERMINATE;
    }

    /* Get profit objective and add it as a constraint */

    status = CPXXgetobj (env, lp, values, 0, numcols-1);
    if ( status ) {
        fprintf (stderr,
                 "Failed to get profit objective.  Status %d\n", status);
        goto TERMINATE;
    }
    for (j = 0; j < numcols; j++) {
        indices[j] = j;
    }

    rrhs[0]    = objval - fabs (objval) * 1e-6;
    rsense[0]  = 'G';
    rmatbeg[0] = 0;

    status = CPXXpreaddrows (env, lp, 1, numcols, rrhs, rsense,
                             rmatbeg, indices, values, NULL);

    if ( status ) {
        fprintf (stderr,
                 "Failed to add objective as constraint.  Status %d\n",
                 status);
        goto TERMINATE;
    }

    /* Set up objective to maximize negative of sum of inventory */

    totinv = 0;
    for (j = 0; j < numcols; j++) {
        if ( strncmp (nameptr[j], "inv", 3) ) {
            values[j] = 0.0;
        }
        else {
            values[j] = - 1.0;
        }
    }

    status = CPXXprechgobj (env, lp, numcols, indices, values);

    if ( status ) {
        fprintf (stderr,
                 "Failed to change to inventory objective.  Status %d\n",
                 status);
        goto TERMINATE;
    }

    status = CPXXlpopt (env, lp);
    if ( status ) {
        fprintf (stderr, "Optimization on inventory level failed. Status %d.\n",
                 status);
        goto TERMINATE;
    }

    solstat = CPXXgetstat (env, lp);
    status  = CPXXgetobjval (env, lp, &objval);
    if ( status  ||  solstat != CPX_STAT_OPTIMAL ) {
        fprintf (stderr, "Solution failed. Status %d, solstat %d.\n",
                 status, solstat);
        goto TERMINATE;
    }

    printf ("Inventory level after optimization is %g\n", -objval);


    status = CPXXgetx (env, lp, x, 0, numcols-1);
    if ( status ) {
        fprintf (stderr, "Failed to obtain primal solution.\n");
        goto TERMINATE;
    }

    /* Write out the solution */
    printf("Solution status: %d", solstat);
    printf ("\n");
    for (j = 0; j < numcols; j++) {
        printf ( "%s:  Value = %17.10g\n", nameptr[j], x[j]);
    }


TERMINATE:

    /* Free the filename */

    free_and_null ((char **) &prod);

    /* Free up the basis and solution */

    free_and_null ((char **) &indices);
    free_and_null ((char **) &values);
    free_and_null ((char **) &nameptr);
    free_and_null ((char **) &namestore);
    free_and_null ((char **) &x);


    /* Free up the problem, if necessary */

    if ( lp != NULL ) {
        status = CPXXfreeprob (env, &lp);
        if ( status ) {
            fprintf (stderr, "CPXXfreeprob failed, error code %d.\n", status);
        }
    }

    /* Free up the CPLEX environment, if necessary */

    if ( env != NULL ) {
        status = CPXXcloseCPLEX (&env);

        /* Note that CPXXcloseCPLEX produces no output,
           so the only way to see the cause of the error is to use
           CPXXgeterrorstring.  For other CPLEX routines, the errors will
           be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

        if ( status ) {
            char  errmsg[CPXMESSAGEBUFSIZE];
            fprintf (stderr, "Could not close CPLEX environment.\n");
            CPXXgeterrorstring (env, status, errmsg);
            fprintf (stderr, "%s", errmsg);
        }
    }

    return (status);

}  /* END main */
Пример #24
0
int
main (void)
{
   /* Declare pointers for the variables and arrays that will contain
      the data which define the LP problem.  The setproblemdata() routine
      allocates space for the problem data.  */

   char     *probname = NULL;
   CPXDIM   numcols;
   CPXDIM   numrows;
   int      objsen;
   double   *obj = NULL;
   double   *rhs = NULL;
   char     *sense = NULL;
   CPXNNZ   *matbeg = NULL;
   CPXDIM   *matcnt = NULL;
   CPXDIM   *matind = NULL;
   double   *matval = NULL;
   double   *lb = NULL;
   double   *ub = NULL;
   CPXNNZ   *qmatbeg = NULL;
   CPXDIM   *qmatcnt = NULL;
   CPXDIM   *qmatind = NULL;
   double   *qmatval = NULL;

   /* Declare and allocate space for the variables and arrays where we
      will store the optimization results including the status, objective
      value, variable values, dual values, row slacks and variable
      reduced costs. */

   int      solstat;
   double   objval;
   double   x[NUMCOLS];
   double   pi[NUMROWS];
   double   slack[NUMROWS];
   double   dj[NUMCOLS];


   CPXENVptr     env = NULL;
   CPXLPptr      lp = NULL;
   int           status;
   CPXDIM        i, j;
   CPXDIM        cur_numrows, cur_numcols;

   /* Initialize the CPLEX environment */

   env = CPXXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXXgeterrorstring will produce the text of
      the error message.  Note that CPXXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXXgeterrorstring.  For other CPLEX routines, the errors will
      be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON.  */

   if ( env == NULL ) {
   char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment.\n");
      CPXXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXXsetintparam (env, CPXPARAM_ScreenOutput, CPX_ON);
   if ( status ) {
      fprintf (stderr,
               "Failure to turn on screen indicator, error %d.\n", status);
      goto TERMINATE;
   }

   /* Fill in the data for the problem.  */

   status = setproblemdata (&probname, &numcols, &numrows, &objsen, &obj,
                            &rhs, &sense, &matbeg, &matcnt, &matind,
                            &matval, &lb, &ub, &qmatbeg, &qmatcnt,
                            &qmatind, &qmatval);
   if ( status ) {
      fprintf (stderr, "Failed to build problem data arrays.\n");
      goto TERMINATE;
   }

   /* Create the problem. */

   lp = CPXXcreateprob (env, &status, probname);

   /* A returned pointer of NULL may mean that not enough memory
      was available or there was some other problem.  In the case of
      failure, an error message will have been written to the error
      channel from inside CPLEX.  In this example, the setting of
      the parameter CPXPARAM_ScreenOutput causes the error message to
      appear on stdout.  */

   if ( lp == NULL ) {
      fprintf (stderr, "Failed to create problem.\n");
      goto TERMINATE;
   }

   /* Now copy the LP part of the problem data into the lp */

   status = CPXXcopylp (env, lp, numcols, numrows, objsen, obj, rhs,
                       sense, matbeg, matcnt, matind, matval,
                       lb, ub, NULL);

   if ( status ) {
      fprintf (stderr, "Failed to copy problem data.\n");
      goto TERMINATE;
   }

   status = CPXXcopyquad (env, lp, qmatbeg, qmatcnt, qmatind, qmatval);
   if ( status ) {
      fprintf (stderr, "Failed to copy quadratic matrix.\n");
      goto TERMINATE;
   }


   /* Optimize the problem and obtain solution. */

   status = CPXXqpopt (env, lp);
   if ( status ) {
      fprintf (stderr, "Failed to optimize QP.\n");
      goto TERMINATE;
   }

   status = CPXXsolution (env, lp, &solstat, &objval, x, pi, slack, dj);
   if ( status ) {
      fprintf (stderr, "Failed to obtain solution.\n");
      goto TERMINATE;
   }


   /* Write the output to the screen. */

   printf ("\nSolution status = %d\n", solstat);
   printf ("Solution value  = %f\n\n", objval);

   /* The size of the problem should be obtained by asking CPLEX what
      the actual size is, rather than using what was passed to CPXXcopylp.
      cur_numrows and cur_numcols store the current number of rows and
      columns, respectively.  */

   cur_numrows = CPXXgetnumrows (env, lp);
   cur_numcols = CPXXgetnumcols (env, lp);
   for (i = 0; i < cur_numrows; i++) {
      printf ("Row %d:  Slack = %10f  Pi = %10f\n", i, slack[i], pi[i]);
   }

   for (j = 0; j < cur_numcols; j++) {
      printf ("Column %d:  Value = %10f  Reduced cost = %10f\n",
              j, x[j], dj[j]);
   }

   /* Finally, write a copy of the problem to a file. */

   status = CPXXwriteprob (env, lp, "qpex1.lp", NULL);
   if ( status ) {
      fprintf (stderr, "Failed to write LP to disk.\n");
      goto TERMINATE;
   }


TERMINATE:

   /* Free up the problem as allocated by CPXXcreateprob, if necessary */

   if ( lp != NULL ) {
      status = CPXXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */

   if ( env != NULL ) {
      status = CPXXcloseCPLEX (&env);

      /* Note that CPXXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXXgeterrorstring.  For other CPLEX routines, the errors will
         be seen if the CPXPARAM_ScreenOutput indicator is set to CPX_ON. */

      if ( status ) {
         char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }

   /* Free up the problem data arrays, if necessary. */

   free_and_null ((char **) &probname);
   free_and_null ((char **) &obj);
   free_and_null ((char **) &rhs);
   free_and_null ((char **) &sense);
   free_and_null ((char **) &matbeg);
   free_and_null ((char **) &matcnt);
   free_and_null ((char **) &matind);
   free_and_null ((char **) &matval);
   free_and_null ((char **) &lb);
   free_and_null ((char **) &ub);
   free_and_null ((char **) &qmatbeg);
   free_and_null ((char **) &qmatcnt);
   free_and_null ((char **) &qmatind);
   free_and_null ((char **) &qmatval);

   return (status);

}  /* END main */
Пример #25
0
/* CPLEX does not provide a function to directly get the dual multipliers
 * for second order cone constraint.
 * Example xqcpdual.c illustrates how the dual multipliers for a
 * quadratic constraint can be computed from that constraint's slack.
 * However, for SOCP we can do something simpler: we can read those
 * multipliers directly from the dual slacks for the
 * cone head variables. For a second order cone constraint
 *    x[1] >= |(x[2], ..., x[n])|
 * the dual multiplier is the dual slack value for x[1].
 */
static int
getsocpconstrmultipliers (CPXCENVptr env, CPXCLPptr lp,
                          double *dslack, double *socppi)
{
   int status = 0;
   CPXDIM const cols = CPXXgetnumcols (env, lp);
   CPXDIM const qs = CPXXgetnumqconstrs (env, lp);
   double *dense = NULL, *val = NULL;
   CPXDIM *ind = NULL;
   CPXDIM j, q;
   qbuf_type qbuf;

   qbuf_init (&qbuf);

   if ( (dense = malloc (sizeof (*dense) * cols)) == NULL ) {
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }

   /* First of all get the dual slack vector. This is the sum of
    * dual multipliers for bound constraints (as returned by CPXXgetdj())
    * and the per-constraint dual slack vectors (as returned by
    * CPXXgetqconstrdslack()).
    */

   /* Get dual multipliers for bound constraints. */
   if ( (status = CPXXgetdj (env, lp, dense, 0, cols - 1)) != 0 )
      goto TERMINATE;

   /* Create a dense vector that holds the sum of dual slacks for all
    * quadratic constraints.
    */
   if ( (val = malloc (cols * sizeof (val))) == NULL ||
        (ind = malloc (cols * sizeof (ind))) == NULL )
   {
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }
   for (q = 0; q < qs; ++q) {
      CPXDIM len = 0, surp;

      if ( (status = CPXXgetqconstrdslack (env, lp, q, &len, ind, val,
                                           cols, &surp)) != 0 )
         goto TERMINATE;
      for (j = 0; j < len; ++j) {
         dense[ind[j]] += val[j];
      }
   }

   /* Now go through the socp constraints. For each constraint find the
    * cone head variable (the one variable that has a negative coefficient)
    * and pick up its dual slack. This is the dual multiplier for the
    * constraint.
    */
   for (q = 0; q < qs; ++q) {
      if ( !getqconstr (env, lp, q, &qbuf) ) {
         status = CPXERR_BAD_ARGUMENT;
         goto TERMINATE;
      }
      for (j = 0; j < qbuf.qnz; ++j) {
         if ( qbuf.qval[j] < 0.0 ) {
            /* This is the cone head variable. */
            socppi[q] = dense[qbuf.qcol[j]];
            break;
         }
      }
   }

   /* If the caller wants to have the dual slack vector then copy it
    * to the output array.
    */
   if ( dslack != NULL )
      memcpy (dslack, dense, sizeof (*dslack) * cols);

 TERMINATE:
   free (ind);
   free (val);
   free (dense);

   qbuf_clear (&qbuf);

   return status;
}