Example #1
0
/** MIP info callback that is registered with CPLEX.
 *  This callback picks up primal and dual bounds as well as the current
 *  deterministic time. If bounds changed then updated bounds are send
 *  to the master. Deterministic time stamps are always send to the master.
 */
static int CPXPUBLIC
infocallback (CPXCENVptr cbenv, void *cbdata, int wherefrom, void *cbhandle)
{
   CPXCENVptr env = static_cast<CPXCENVptr>(cbhandle);
   double dual, primal, ts;

   // Test if we have improved the primal bound and report if so.
   if ( CPXXgetcallbackinfo (cbenv, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_INTEGER, &primal) == 0 ) {
      if ( !best.havePrimal || fabs (best.primal - primal) > best.objdiff ) {
         best.havePrimal = true;
         best.primal = primal;
         (void)CPXXsendinfodouble (env, INFO_NEWPRIMAL, 1, &primal);
      }
   }

   // Test if we have improved the dual bound and report if so.
   if ( CPXXgetcallbackinfo (cbenv, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_REMAINING, &dual) == 0 ) {
      if ( !best.haveDual || fabs (best.dual - dual) > best.objdiff ) {
         best.haveDual = true;
         best.dual = dual;
         (void)CPXXsendinfodouble (env, INFO_NEWDUAL, 1, &dual);
      }
   }

   // Always report the current deterministic time.
   if ( CPXXgetdettime (cbenv, &ts) == 0 ) {
      (void)CPXXsendinfodouble (env, INFO_DETTIME, 1, &ts);
   }

   return 0;
}
Example #2
0
static int CPXPUBLIC
timelimcallback (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle)
{
   int status = 0;

   TIMELIMINFOptr info = (TIMELIMINFOptr) cbhandle;
   int            hasincumbent = 0;

   status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                CPX_CALLBACK_INFO_MIP_FEAS, &hasincumbent);
   if ( status )  goto TERMINATE;

   if ( !info->aborted  &&  hasincumbent ) {
      double gap;
      double timenow;

      status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                   CPX_CALLBACK_INFO_MIP_REL_GAP, &gap);
      if ( status )  goto TERMINATE;

      /* Turn the gap into a percentage */
      gap *= 100.0;

      status = CPXXgettime (env, &timenow);
      if ( status )  goto TERMINATE;

      if ( timenow - info->timestart > info->timelim  &&
           gap < info->acceptablegap                    ) {
         fprintf (stderr,
     "Good enough solution at time %.2fsec, gap = %g%%, quitting\n",
                  timenow - info->timestart, gap);

         /* callback may be called again during the clean up phase after the
            abort has been issued, so remember that abort processing has
            already occurred. */

         info->aborted = 1;

         /* nonzero status causes abort */

         status = 1;
      }
   }

TERMINATE:

   return (status);

} /* END timelimcallback */
Example #3
0
static int CPXPUBLIC 
userselectnode (CPXCENVptr env,
                void       *cbdata,
                int        wherefrom,
                void       *cbhandle,
                CPXCNT     *nodenum_p,
                int        *useraction_p)
{
   int status = 0;

   CPXCNT thisnode;
   CPXCNT nodesleft;
   CPXCNT bestnode = 0;
   CPXCNT depth;
   CPXCNT maxdepth = -1;
   double siinf;
   double maxsiinf = 0.0;

   /* Initialize useraction to indicate no user node selection */

   *useraction_p = CPX_CALLBACK_DEFAULT;

   /* Choose the node with the largest sum of infeasibilities among
      those at the greatest depth */

   status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                CPX_CALLBACK_INFO_NODES_LEFT_LONG,
                                &nodesleft);
   if ( status )  goto TERMINATE;

   for (thisnode = 0; thisnode < nodesleft; thisnode++) {
      status = CPXXgetcallbacknodeinfo (env, cbdata, wherefrom,
                                       thisnode,
                                       CPX_CALLBACK_INFO_NODE_DEPTH_LONG,
                                       &depth);
      if ( !status ) {
         status = CPXXgetcallbacknodeinfo (env, cbdata, wherefrom,
                                        thisnode,
                                        CPX_CALLBACK_INFO_NODE_SIINF,
                                        &siinf);
      }
      if ( status )  break;

      if ( (depth >= maxdepth)                   &&
           (depth > maxdepth || siinf > maxsiinf)  ) {
         bestnode = thisnode;
         maxdepth = depth;
         maxsiinf = siinf;
      }
   }

   *nodenum_p = bestnode;
   *useraction_p = CPX_CALLBACK_SET;

TERMINATE:

   return (status);

} /* END userselectnode */
Example #4
0
static int CPXPUBLIC 
usersolve (CPXCENVptr env,
           void       *cbdata,
           int        wherefrom,
           void       *cbhandle,
           int        *useraction_p)
{
   int      status = 0;
   CPXCNT   nodecount;
   CPXLPptr nodelp;

   *useraction_p = CPX_CALLBACK_DEFAULT;

   /* Get pointer to LP subproblem */

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

   /* Find out what node is being processed */

   status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                CPX_CALLBACK_INFO_NODE_COUNT_LONG,
                                &nodecount);
   if ( status )  goto TERMINATE;

   /* Solve initial node with primal, others with dual */

   if ( nodecount < 1 )  status = CPXXprimopt (env, nodelp);
   else                  status = CPXXdualopt (env, nodelp);

   /* If the solve was OK, set return to say optimization has
      been done in callback, otherwise return the CPLEX error
      code */

   if ( !status )  *useraction_p = CPX_CALLBACK_SET;

TERMINATE:

   return (status);

} /* END usersolve */
Example #5
0
/* Log new incumbents if they are at better than the old by a
 * relative tolerance of 1e-5; also log progress info every
 * 100 nodes.
 */
static int CPXPUBLIC
logcallback (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle)
{
   int status = 0;

   LOGINFOptr info = (LOGINFOptr) cbhandle;
   int        hasincumbent = 0;
   int        newincumbent = 0;
   double     dettime;
   double     objval;
   double     bound;
   double     *x = NULL;

   status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                CPX_CALLBACK_INFO_MIP_FEAS, &hasincumbent);
   if ( status )  goto TERMINATE;

   if ( hasincumbent ) {
      status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                   CPX_CALLBACK_INFO_BEST_INTEGER, &objval);
      if ( status )  goto TERMINATE;

      if ( fabs(info->lastincumbent - objval) > 1e-5*(1.0 + fabs(objval)) ) {
         newincumbent = 1;
         info->lastincumbent = objval;
      }
   }

   status = CPXXgetdettime (env, &dettime);
   if ( status )  goto TERMINATE;

   if ( dettime >= info->lastdettime + 1000.0  ||  newincumbent ) {
      double walltime;

      status = CPXXgetcallbackinfo (env, cbdata, wherefrom,
                                   CPX_CALLBACK_INFO_BEST_REMAINING, &bound);
      if ( status )  goto TERMINATE;

      if ( !newincumbent )  info->lastdettime = dettime;

      status = CPXXgettime (env, &walltime);
      if ( status )  goto TERMINATE;

      printf ("Time = %.2f  Dettime = %.2f  Best objective = %g",
              walltime - info->timestart, dettime - info->dettimestart, bound);
      if ( hasincumbent )  printf ("  Incumbent objective = %g\n", objval);
      else                 printf ("\n");
   }

   if ( newincumbent ) {
      int j;
      CPXDIM numcols = info->numcols;

      x = malloc (numcols*sizeof(*x));
      if ( x == NULL ) {
         status = CPXERR_NO_MEMORY;
         goto TERMINATE;
      }
      status = CPXXgetcallbackincumbent (env, cbdata, wherefrom,
                                        x, 0, numcols-1);
      if ( status )  goto TERMINATE;

      printf ("New incumbent values:\n");
      for (j = 0; j < numcols; j++) {
         if ( fabs(x[j]) > 1e-6 ) {
            printf ("  Column %d:  %g\n", j, x[j]);
         }
      }
   }

TERMINATE:

   free_and_null ((char **) &x);
   return (status);

} /* END logcallback */