Exemple #1
0
int
main (int argc, char *argv[])
{
   CPXENVptr env = NULL;
   CPXLPptr  lp = NULL;
   int       status = 0;
   int       j;
   int       numcols;
   double    totinv; 

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

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

   int       *indices = NULL;
   double    *values = NULL;
   char      *namestore = NULL;
   char      **nameptr = NULL;
   int       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 = CPXopenCPLEX (&status);

   /* If an error occurs, the status value indicates the reason for
      failure.  A call to CPXgeterrorstring will produce the text of
      the error message.  Note that CPXopenCPLEX produces no output,
      so the only way to see the cause of the error is to use
      CPXgeterrorstring.  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");
      CPXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto TERMINATE;
   }

   /* Turn on output to the screen */

   status = CPXsetintparam (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 = CPXcreateprob (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 = CPXreadcopyprob (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 = CPXsetintparam (env, CPXPARAM_Preprocessing_Reduce, 1);
   if ( status ) {
      fprintf (stderr, "Failed to set CPXPARAM_Preprocessing_Reduce: %d\n", status);
      goto TERMINATE;
   }
   status = CPXsetintparam (env, CPXPARAM_Simplex_Display, 0);
   if ( status ) {
      fprintf (stderr, "Failed to set CPXPARAM_Simplex_Display: %d\n", status);
      goto TERMINATE;
   } 

   if ( status ) {
      fprintf (stderr, "Failure to set parameters\n");
      goto TERMINATE;
   } 


   /* Optimize the problem and obtain solution. */

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

   solstat = CPXgetstat (env, lp);
   status  = CPXgetobjval (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 = CPXgetnumcols (env, lp);
   if ( !numcols ) {
      fprintf (stderr, "No columns in problem\n");
      goto TERMINATE;
   }

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

   namestore = (char *) malloc (storespace * sizeof(char));
   nameptr   = (char **) malloc (numcols * sizeof(char *));
   if ( namestore == NULL  ||  nameptr == NULL ) {
      fprintf (stderr, "No memory for column names\n");
      goto TERMINATE;
   }
 
   status = CPXgetcolname (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 = (double *) malloc (numcols * sizeof(double));

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

   status = CPXgetx (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 = (int *)    malloc (numcols * sizeof (int));
   values  = (double *) malloc (numcols * sizeof (double));

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

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

   status = CPXgetobj (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 = CPXpreaddrows (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 = CPXprechgobj (env, lp, numcols, indices, values);

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

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

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

   printf("Solution status %d.\n", solstat);
   printf ("Inventory level after optimization is %g\n", -objval);


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

   printf("Found solution");

   /* Write out the solution */

   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 = CPXfreeprob (env, &lp);
      if ( status ) {
         fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
      }
   }

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

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

      /* Note that CPXcloseCPLEX produces no output,
         so the only way to see the cause of the error is to use
         CPXgeterrorstring.  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");
         CPXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }
     
   return (status);

}  /* END main */
Exemple #2
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 = CPXgetcallbacklp (env, cbdata, wherefrom, &lp);
   if ( status ) {
      fprintf (stdout, "Can't get lp pointer.");
      goto TERMINATE;
   }

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

   status = CPXgetcallbacknodeintfeas (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 */
Exemple #3
0
//==========================================================================
int
main (int argc, char * argv[])
{
    // Temporary variables
    struct stat filestat;

    char astring[DDSIP_ln_fname];

    int status = 0, cont, boundstat, comb, i;

    // guarantee minimal stacksize limit
    const rlim_t kStackSize = 128 * 1024 * 1024;   // min stack size = 128 MB
    struct rlimit rl;
    int result;
    unsigned long cur_limit;

    result = getrlimit(RLIMIT_STACK, &rl);
    if (result == 0)
    {
        cur_limit = rl.rlim_cur;
        printf ("original stacksize limit %lu\n", cur_limit);
        if (rl.rlim_cur < kStackSize)
        {
            rl.rlim_cur = kStackSize;
            result = setrlimit(RLIMIT_STACK, &rl);
            if (result != 0)
            {
                fprintf(stderr, "setrlimit returned result = %d\n", result);
            }
            result = getrlimit(RLIMIT_STACK, &rl);
            if (result == 0)
            {
                cur_limit = rl.rlim_cur;
                printf ("changed  stacksize limit %lu\n", cur_limit);
            }
        }
    }

    i = argc;
    //

    // Welcome
    printf ("#######################################################################################\n");
    printf ("#########  D D S I P -- Dual Decomposition In Stochastic Integer Programming  #########\n");
    printf ("#########  %-66s #########\n", DDSIP_version);
    printf ("For copyright, license agreements, help, comments, requests, ... ");
    printf ("see\n\thttp://www.uni-duisburg-essen.de/~hn215go/ddsip.shtml\n");
    printf ("\thttp://www.www.github.com/RalfGollmer/ddsip\n");
    /*    printf ("  Copyright (C) to University of Duisburg-Essen \n\n"); */
    /*    printf("  This program is free software; you can redistribute it and/or\n"); */
    /*    printf ("  modify it under the terms of the GNU General Public License\n"); */
    /*    printf("  as published by the Free Software Foundation; either version 2\n"); */
    /*    printf ("  of the License, or (at your option) any later version.\n\n"); */
    /*    printf ("  This program is distributed in the hope that it will be useful,\n"); */
    /*    printf("  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); */
    /*    printf ("  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"); */
    /*    printf ("  GNU General Public License for more details.\n\n"); */
    /*    printf ("  You should have received a copy of the GNU General Public License\n"); */
    /*    printf("  along with this program; if not, write to the Free Software\n"); */
    /*    printf ("  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n"); */
    /*    printf ("==============================================================================\n\n"); */

    // These four structures shall carry the whole problem data
    DDSIP_param = NULL;
    DDSIP_bb = NULL;
    DDSIP_data = NULL;
    DDSIP_node = NULL;

    // In DDSIP some signals are handled seperatly
    DDSIP_RegisterSignalHandlers ();

    // Create output directory if it doesn't already exist
    if (stat (DDSIP_outdir, &filestat) == -1)
    {
        sprintf (astring, "mkdir %s\n", DDSIP_outdir);
        i = system (astring);
        printf ("Creating subdirectory %s ...\n", DDSIP_outdir);
    }
    // remove possibly existing output file
    sprintf (astring, "rm -f %s\n", DDSIP_outfname);
    i = system (astring);
    // Open output file
    if ((DDSIP_outfile = fopen (DDSIP_outfname, "a")) == NULL)
    {
        fprintf (stderr, "ERROR: Cannot open '%s'. \n", DDSIP_outfname);
        status = 107;
        goto TERMINATE;
    }

    setbuf (DDSIP_outfile, 0);
    fprintf (DDSIP_outfile, "%s\n", argv[0]);
    fprintf (DDSIP_outfile, "-----------------------------------------------------------\n");
    fprintf (DDSIP_outfile, "current system time: ");
    fflush (DDSIP_outfile);
#ifndef _WIN32
    i = system ("date");
    // Print time to output file
    sprintf (astring, "date >> %s\n", DDSIP_outfname);
    i = system (astring);
    fprintf (DDSIP_outfile, "host            : ");
    sprintf (astring, "hostname >> %s; cat /proc/cpuinfo | sed '/processor.*: 0/,/^$/!d' |grep -E 'vendor|cpu |model|stepping|MHz|cache |cores' >> %s\n", DDSIP_outfname, DDSIP_outfname);
    for (i = 0; i < 100; i++)
        exp(1.11*(-i-2));
    i = system (astring);
#else
    sprintf (astring, "date /T >> %s & time /T >> %s\n", DDSIP_outfname,DDSIP_outfname);
    i = system (astring);
#endif

    fprintf (DDSIP_outfile, "\nDDSIP  %s\n", DDSIP_version);
    fprintf (DDSIP_outfile, "-----------------------------------------------------------\n");

    // Open cplex environment
    DDSIP_env = CPXopenCPLEX (&status);
    if (DDSIP_env == NULL)
    {
        fprintf (stderr, "ERROR: Failed to open cplex environment, CPLEX error code %d.\n",status);
        fprintf (DDSIP_outfile, "ERROR: Failed to open cplex environment, CPLEX error code %d.\n",status);
        return status;
    }
    sprintf (astring, "%s", CPXversion (DDSIP_env));
    printf ("CPLEX version is %s\n", astring);
    fprintf (DDSIP_outfile, "CPLEX version is %s\n\n", astring);

    // Allocate the structures to hold the information on the problem
    DDSIP_param = (para_t *) DDSIP_Alloc (sizeof (para_t), 1, "param(Main)");
    DDSIP_bb    = (bb_t *)   DDSIP_Alloc (sizeof (bb_t),   1, "bb(Main)");
    DDSIP_data  = (data_t *) DDSIP_Alloc (sizeof (data_t), 1, "data(Main)");

    // Read model (lp) file
    if ((status = DDSIP_ReadModel ()))
        goto TERMINATE;

    // Read specification file
    if ((status = DDSIP_ReadSpec ()))
        goto TERMINATE;

    // Set specified CPLEX parameters
    if ((status = DDSIP_InitCpxPara ()))
        goto TERMINATE;

    // if a Benders annotation file is given, read it
    if (DDSIP_param->annotationFile)
    {
        status = CPXreadcopyannotations (DDSIP_env, DDSIP_lp, DDSIP_param->annotationFile);
        if ( status ) {
           fprintf (stderr, "ERROR: Failed to read and copy the annotation data from file %s.\n", DDSIP_param->annotationFile);
           fprintf (DDSIP_outfile, "ERROR: Failed to read and copy the annotation data from file %s.\n", DDSIP_param->annotationFile);
           goto TERMINATE;
        }
    }

    // data->cost contains: stoch. costs for all scenarios, followed by the original costs
    DDSIP_data->cost =
        (double *) DDSIP_Alloc (sizeof (double),
                                DDSIP_param->scenarios * DDSIP_param->stoccost + DDSIP_data->novar, "cost (ReadData)");
    // Store original objective coefficients
    status = CPXgetobj (DDSIP_env, DDSIP_lp, DDSIP_data->cost + DDSIP_param->scenarios * DDSIP_param->stoccost, 0, DDSIP_data->novar - 1);
    if (status)
    {
        fprintf (stderr, "ERROR: Failed to get objective coefficients\n");
        fprintf (DDSIP_outfile, "ERROR: Failed to get objective coefficients\n");
        goto TERMINATE;
    }

    DDSIP_bb->moreoutfile = NULL;
    if (DDSIP_param->outlev)
    {
        // Open debug output file
        if ((DDSIP_bb->moreoutfile = fopen (DDSIP_moreoutfname, "a")) == NULL)
        {
            fprintf (stderr, "ERROR: Cannot open '%s'. \n", DDSIP_moreoutfname);
            fprintf (DDSIP_outfile, "ERROR: Cannot open '%s'. \n", DDSIP_moreoutfname);
            status = 109;
            goto TERMINATE;
        }
        if (DDSIP_param->outlev > 10)
        {
            // Buffer size = 0
            setbuf (stdout, 0);
            if (DDSIP_param->outlev > 20)
                setbuf (DDSIP_bb->moreoutfile, 0);
        }
#ifndef _WIN32
        // Print time to output file
        sprintf (astring, "date > %s\n", DDSIP_moreoutfname);
        i = system (astring);
#else
        sprintf (astring, "date /T > %s & time /T >> %s\n", DDSIP_moreoutfname,DDSIP_moreoutfname);
        i = system (astring);
#endif
        fprintf (DDSIP_bb->moreoutfile, "--------------------------------------------------------------");
        fprintf (DDSIP_bb->moreoutfile, "---------\nThis is an additional output file of DDSIP. The ");
        fprintf (DDSIP_bb->moreoutfile, "actual amount of output\nis controlled by the parameter ");
        fprintf (DDSIP_bb->moreoutfile, "OUTLEV in the specification file.\n---------");
        fprintf (DDSIP_bb->moreoutfile, "--------------------------------------------------------------\n\n");
    }

    DDSIP_node = (node_t **) DDSIP_Alloc (sizeof (node_t *), DDSIP_param->nodelim + 3, "node(Main)");
    DDSIP_node[0] = (node_t *) DDSIP_Alloc (sizeof (node_t), 1, "node[0](Main)");
    DDSIP_node[0]->first_sol = (double **) DDSIP_Alloc (sizeof (double *), DDSIP_param->scenarios, "node[0]->first_sol(Main)");
    DDSIP_node[0]->cursubsol = (double *) DDSIP_Alloc (sizeof (double), DDSIP_param->scenarios, "node[0]->cursubsol(Main)");
    DDSIP_node[0]->subbound = (double *) DDSIP_Alloc (sizeof (double), DDSIP_param->scenarios, "node[0]->subbound(Main)");
    if (DDSIP_param->cb)
    {
        DDSIP_node[0]->scenBoundsNoLag = (double *) DDSIP_Alloc (sizeof (double), DDSIP_param->scenarios, "node[0]->scenBoundsNoLag(Main)");
        DDSIP_node[0]->BoundNoLag = -DDSIP_infty;

    }
    DDSIP_node[0]->mipstatus = (int *) DDSIP_Alloc (sizeof (int), DDSIP_param->scenarios, "node[0]->mipstatus(Main)");
    DDSIP_node[0]->ref_scenobj = (double *) DDSIP_Alloc (sizeof (double), DDSIP_param->scenarios, "node[0]->ref_scenobj(Main)");

    // Prepare first and second stage variables
    if ((status = DDSIP_InitStages ()))
    {
        fprintf (stderr, "ERROR: Failed to initialize stages\n");
        fprintf (DDSIP_outfile, "ERROR: Failed to initialize stages\n");
        goto TERMINATE;
    }

    // Read data file(s)
    if ((status = DDSIP_ReadData ()))
        goto TERMINATE;

    // Read order file if specified
    if (DDSIP_param->cpxorder)
    {
        status = CPXsetintparam (DDSIP_env, CPX_PARAM_MIPORDIND, 1);
        if (status)
        {
            fprintf (stderr, "ERROR: Failed to set cplex parameter CPX_PARAM_MIPORDIND.\n");
            return status;
        }
        if (DDSIP_ReadCPLEXOrder ())
            goto TERMINATE;
    }

    // Detect first and second stage constraints
    if ((status = DDSIP_DetectStageRows ()))
    {
        fprintf (stderr, "ERROR: Failed detection of row stages (BbInit)\n");
        fprintf (DDSIP_outfile, "ERROR: Failed detection of row stages (BbInit)\n");
        goto TERMINATE;
    }

    DDSIP_bb->DDSIP_step =  solve;

#ifdef CONIC_BUNDLE
    if (DDSIP_param->cb)
    {
        status = DDSIP_NonAnt ();
        if (status)
            goto TERMINATE;
    }
#endif

    if (DDSIP_param->outlev)
    {
        printf ("\t Total initialization time: %4.2f seconds.\n", DDSIP_GetCpuTime ());
        fprintf (DDSIP_bb->moreoutfile, " Total initialization time: %4.2f seconds.\n", DDSIP_GetCpuTime ());
    }
#ifndef _WIN32
    sprintf (astring, "grep 'MHz' /proc/cpuinfo|sort -r|head -1 >> %s\n", DDSIP_outfname);
    i = system (astring);
#endif

    // at the start there is no solution
    status = CPXsetintparam (DDSIP_env, CPX_PARAM_ADVIND, 0);
    if (status)
    {
        fprintf (stderr, "ERROR: Failed to set cplex parameter CPX_PARAM_ADVIND.\n");
        fprintf (DDSIP_outfile, "ERROR: Failed to set cplex parameter CPX_PARAM_ADVIND.\n");
        return status;
    }

#ifndef NEOS
    // Write deterministic equivalent (only expectation-based cases)
    if (DDSIP_param->write_detequ)
        DDSIP_DetEqu ();
#endif
    if (DDSIP_param->riskmod < 0)
    {
        fprintf (stderr, " pure risk models are disabled for now, exiting.\n");
        fprintf (DDSIP_outfile, " pure risk models are disabled for now, exiting.\n");
        goto TERMINATE;
    }
    if (DDSIP_param->stoccost && DDSIP_param->riskmod)
    {
        fprintf (DDSIP_outfile, "XXX Error: Risk optimization not implemented for stochastic cost coefficients.\n");
        fprintf (stderr, "XXX Error: Risk optimization not implemented for stochastic cost coefficients.\n");
        goto TERMINATE;
    }

    // Read advanced starting info
    if (DDSIP_param->advstart)
    {
        DDSIP_node[DDSIP_bb->curnode]->step = DDSIP_bb->DDSIP_step = adv;

        if ((status = DDSIP_AdvStart ()))
            goto TERMINATE;

        // Solution provided?
        if (DDSIP_param->advstart == 2)
        {
            DDSIP_bb->curnode = 0;
            DDSIP_bb->sug[DDSIP_param->nodelim + 2] = (struct sug_l *)DDSIP_Alloc (sizeof (sug_t), 1, "sug[0](Advanced start solution)");
            (DDSIP_bb->sug[DDSIP_param->nodelim + 2])->firstval =
                (double *) DDSIP_Alloc (sizeof (double), DDSIP_bb->firstvar, "sug[0]->firstval(adv start)");
            for (i = 0; i < (DDSIP_bb->firstvar); i++)
                (DDSIP_bb->sug[DDSIP_param->nodelim + 2]->firstval)[i] = DDSIP_bb->adv_sol[i];
            (DDSIP_bb->sug[DDSIP_param->nodelim + 2])->next = NULL;
            if ((status = DDSIP_UpperBound (DDSIP_param->scenarios, 0)) && status < 100000)
                goto TERMINATE;
        }
        // Only weak consistency check:
        if ((DDSIP_node[0]->bound) > DDSIP_bb->bestvalue)
        {
            status = 121;
            goto TERMINATE;
        }
        fprintf (DDSIP_outfile, "-----------------------------------------------------------\n\n");
    }
    // Solve EV and EEV if specified
    if (DDSIP_param->expected)
    {
        DDSIP_node[DDSIP_bb->curnode]->step = DDSIP_bb->DDSIP_step = eev;

        // status = 1 -> ExpValProb infeasible
        if ((status = DDSIP_ExpValProb ()) == 1)
        {
            if (DDSIP_param->outlev)
                fprintf (DDSIP_bb->moreoutfile, "    exp. val. prob: INFEASIBLE\n");
            fprintf (DDSIP_outfile, "    exp. val. prob: INFEASIBLE\n");
        }

        if (!status)
        {
            DDSIP_bb->curnode = 0;
            DDSIP_bb->sug[DDSIP_param->nodelim + 2] = (struct sug_l *)DDSIP_Alloc (sizeof (sug_t), 1, "sug[0](Advanced start solution)");
            DDSIP_bb->sug[DDSIP_param->nodelim + 2]->firstval =
                (double *) DDSIP_Alloc (sizeof (double), DDSIP_bb->firstvar, "sug[i]->firstval(Heuristic)");
            for (i = 0; i < DDSIP_bb->firstvar; i++)
                (DDSIP_bb->sug[DDSIP_param->nodelim + 2]->firstval)[i] = DDSIP_bb->adv_sol[i];
            DDSIP_bb->sug[DDSIP_param->nodelim + 2]->next = NULL;
            if ((status = DDSIP_UpperBound (DDSIP_param->scenarios, 0)) && status < 100000)
                goto TERMINATE;
        }

        if (fabs (DDSIP_bb->expbest) < DDSIP_infty)
        {
            if (DDSIP_param->outlev)
                printf ("\t\t EEV:  %13.7f\n", DDSIP_bb->expbest);
            fprintf (DDSIP_outfile, "-EEV:     %13.7f\n", DDSIP_bb->expbest);
        }
        else
        {
            if (DDSIP_param->outlev)
                printf ("\t\t EEV:  No solution found.\n");
            fprintf (DDSIP_outfile, "-EEV:     No solution found.\n");
        }
    }				// END if (EV)
    // stop here if NODELIM is zero
     if (!(DDSIP_param->nodelim))
         goto TERMINATE;
    // Print cplex log to debugfile
    if (DDSIP_param->outlev > 51)
    {
#ifdef CPLEX_12_8
       if ((status = CPXsetlogfilename (DDSIP_env, DDSIP_moreoutfname, "a")))
           goto TERMINATE;
#else
       if ((status = CPXsetlogfile (DDSIP_env, DDSIP_bb->moreoutfile)))
           goto TERMINATE;
#endif
    }

    // No of DDSIP iterations
    DDSIP_bb->noiter = 0;
    // cont = 1 if no stop criteria is fullfilled
    cont = 1;
    // comb tells in case of a combined heuristic, which one to apply (3 = RoundNear)
    comb = 3;

    if (DDSIP_param->outlev)
        printf ("Starting branch-and-bound algorithm.\n");
    fprintf (DDSIP_outfile, "----------------------------------------------------------------------------------------\n");

    while (cont)
    {
        // the cuts from the root node are contained in every following node model, there is no need to check their violation
        // for the scenario solutions. But the rounding heuristics could violate a cut, so keep them.
#ifdef CONIC_BUNDLE
#ifdef DEBUG
////////////////////////////////////////////
if (DDSIP_bb->curnode && DDSIP_param->outlev)
{ 
if((DDSIP_node[DDSIP_bb->curnode-1])->step == dual)
  fprintf(DDSIP_bb->moreoutfile, "######## last node %d step=dual, leaf= %d,  dualdescitcnt = %d, DDSIP_bb->cutoff= %d\n",DDSIP_bb->curnode-1,(DDSIP_node[DDSIP_bb->curnode-1])->leaf,DDSIP_bb->dualdescitcnt,DDSIP_bb->cutoff);
}
////////////////////////////////////////////
#endif

        if (DDSIP_param->outlev > 20 && DDSIP_bb->curnode && DDSIP_node[DDSIP_node[DDSIP_bb->curnode]->father]->cbReturn32)
            fprintf (DDSIP_bb->moreoutfile, "########## DDSIP_node[%d >father]->cbReturn32 = 1\n", DDSIP_bb->curnode);
        // Dual method
        if ((!DDSIP_bb->curnode || !DDSIP_node[DDSIP_node[DDSIP_bb->curnode]->father]->cbReturn32) &&
            ((DDSIP_param->cb > 0 && (!(DDSIP_bb->noiter % abs(DDSIP_param->cb))) && (abs(DDSIP_param->riskmod) != 4 || DDSIP_bb->noiter)) ||
             (DDSIP_param->cb < 0 && (((DDSIP_node[DDSIP_bb->curnode]->depth <= DDSIP_param->cb_depth) && abs(DDSIP_param->riskmod) != 4) ||
                                      (abs(DDSIP_param->riskmod) == 5 && DDSIP_node[DDSIP_bb->curnode]->depth == 8) ||
                                      (DDSIP_bb->noiter > DDSIP_param->cbBreakIters && 
                                        ((!(DDSIP_bb->noiter % abs(DDSIP_param->cb))) ||
                                         (!((DDSIP_bb->noiter+1) % -DDSIP_param->cb)) ||
                                         (DDSIP_bb->noiter%200 > 199 - DDSIP_param->cbContinuous) ||
                                         (DDSIP_bb->noiter < DDSIP_param->cbContinuous + DDSIP_param->cbBreakIters) ||
                                         ((DDSIP_bb->noiter  >= 2*DDSIP_param->cbBreakIters) && (DDSIP_bb->noiter < DDSIP_param->cbContinuous + 2*DDSIP_param->cbBreakIters)) ||
                                         ((DDSIP_bb->cutoff > 6) &&
                                             (((DDSIP_bb->no_reduced_front < 51) && (DDSIP_bb->noiter % -DDSIP_param->cb) < DDSIP_param->cbContinuous)
                                             || (((DDSIP_node[DDSIP_bb->curnode-1])->step == dual) && (DDSIP_node[DDSIP_bb->curnode-1])->leaf /*&& (DDSIP_bb->dualdescitcnt < 11)*/)
                                             )
                                         )
                                       )
                                     ) ||
                                     (abs(DDSIP_param->riskmod) != 5 && DDSIP_bb->noiter <= DDSIP_param->cbBreakIters && DDSIP_bb->noiter > DDSIP_param->cbBreakIters*.5 &&
                                          (CBFORALL || (DDSIP_node[DDSIP_bb->curnode]->numInheritedSols > (DDSIP_Imin(DDSIP_param->scenarios/20,2)+(DDSIP_param->scenarios+1)/2))))
                                   )
                )
            )
           )
        {
            DDSIP_bb->DDSIP_step = DDSIP_node[DDSIP_bb->curnode]->step = dual;
            if ((status = DDSIP_DualOpt ()))
            {
                if (!DDSIP_bb->curnode)
                    goto TERMINATE;
                else
                {
                    DDSIP_bb->skip = 1;
                    DDSIP_node[DDSIP_bb->curnode]->bound = DDSIP_infty;
                }
            }
        }
        else
        {
            DDSIP_node[DDSIP_bb->curnode]->step = DDSIP_bb->DDSIP_step = solve;
            // status=1 means there was no solution found to a scenario problem
            if ((status = DDSIP_LowerBound ()))
                goto TERMINATE;
        }
#else
        DDSIP_node[DDSIP_bb->curnode]->step = DDSIP_bb->DDSIP_step = solve;
        // status=1 means there was no solution found to a subproblem
        if ((status = LowerBound ()))
            goto TERMINATE;
#endif

        if (!DDSIP_bb->skip || DDSIP_bb->skip == -1)
        {
            double old_bound;
            int cntr, maxCntr;

            DDSIP_bb->cutAdded = 0;
            DDSIP_EvaluateScenarioSolutions (&comb);
            cntr = 0;
            if (DDSIP_node[DDSIP_bb->curnode]->step != dual)
                maxCntr = DDSIP_param->numberReinits;
            else
                maxCntr = 0;
            old_bound = DDSIP_node[DDSIP_bb->curnode]->bound;
            boundstat = DDSIP_Bound ();
            if (!DDSIP_bb->curnode)
            {
                int cnt, j;
                double lhs;
                cutpool_t *currentCut;
                DDSIP_PrintState (DDSIP_bb->noiter);
                if (DDSIP_bb->cutAdded && DDSIP_param->outlev)
                {
                    fprintf (DDSIP_outfile, " %6d%101d cuts\n", DDSIP_bb->curnode, DDSIP_bb->cutAdded);
                }
                while ((DDSIP_bb->cutAdded || DDSIP_node[0]->step == dual) && cntr < maxCntr)
                {
                    old_bound = DDSIP_node[0]->bound;
                    // Free the solutions from former LowerBound
                    for (i = 0; i < DDSIP_param->scenarios; i++)
                    {
                        if (((DDSIP_node[0])->first_sol)[i])
                        {
                            if (DDSIP_node[0]->step == solve)
                            {
                                currentCut = DDSIP_bb->cutpool;
                                while (currentCut)
                                {
                                    lhs = 0.;
                                    for (j = 0; j < DDSIP_bb->firstvar; j++)
                                    {
                                        lhs += (DDSIP_node[0])->first_sol[i][j] * currentCut->matval[j];
                                    }
                                    if (lhs < currentCut->rhs - 1.e-7)
                                    {
#ifdef DEBUG
                                        if (DDSIP_param->outlev > 50)
                                            fprintf (DDSIP_bb->moreoutfile, "scen %d solution violates cut %d.\n", i+1, currentCut->number);
#endif
                                        if ((cnt = (int) ((((DDSIP_node[0])->first_sol)[i])[DDSIP_bb->firstvar] - 0.9)))
                                        for (j = i + 1; cnt && j < DDSIP_param->scenarios; j++)
                                        {
                                            {
                                                if (((DDSIP_node[0])->first_sol)[j]
                                                  && ((DDSIP_node[0])->first_sol)[i] == ((DDSIP_node[0])->first_sol)[j])
                                                {
                                                    ((DDSIP_node[0])->first_sol)[j] = NULL;
                                                    cnt--;
                                                }
                                            }
                                        }
                                        DDSIP_Free ((void **) &(((DDSIP_node[0])->first_sol)[i]));
                                        break;
                                    }
                                    currentCut = currentCut->prev;
                                }
                            }
                            else
                            {
                               if ((cnt = (int) ((((DDSIP_node[0])->first_sol)[i])[DDSIP_bb->firstvar] - 0.9)))
                               for (j = i + 1; cnt && j < DDSIP_param->scenarios; j++)
                               {
                                   {
                                       if (((DDSIP_node[0])->first_sol)[j]
                                         && ((DDSIP_node[0])->first_sol)[i] == ((DDSIP_node[0])->first_sol)[j])
                                       {
                                           ((DDSIP_node[0])->first_sol)[j] = NULL;
                                           cnt--;
                                       }
                                   }
                               }
                               DDSIP_Free ((void **) &(((DDSIP_node[0])->first_sol)[i]));
                            }
                        }
                    }
                    DDSIP_node[0]->step = DDSIP_bb->DDSIP_step = solve;
                    // status=1 means there was no solution found to a scenario problem
                    if ((status = DDSIP_LowerBound ()))
                        goto TERMINATE;
                    DDSIP_bb->cutAdded = 0;
                    DDSIP_EvaluateScenarioSolutions (&comb);
                    cntr++;
                    DDSIP_bb->bestbound = DDSIP_node[0]->bound;
                    DDSIP_bb->noiter++;
                    DDSIP_PrintState (1);
                    if (DDSIP_bb->cutAdded && DDSIP_param->outlev)
                    {
                        fprintf (DDSIP_outfile, " %6d %82d. reinit: %8d cuts\n", 0, cntr, DDSIP_bb->cutAdded);
                    }
                    if ((DDSIP_node[0]->bound - old_bound)/(fabs(old_bound) + 1e-16) < 1.e-7 ||
                        (DDSIP_bb->bestvalue - DDSIP_node[0]->bound)/(fabs(DDSIP_bb->bestvalue) + 1e-16) < 0.5*DDSIP_param->relgap)
                        break;
                }
                if (DDSIP_param->deleteRedundantCuts)
                    DDSIP_CheckRedundancy(1);
            }
            else
            {
                // Print a line of output at the first, the last and each `ith' node
                if (!DDSIP_bb->noiter || (!((DDSIP_bb->noiter + 1) % DDSIP_param->logfreq)) || (DDSIP_param->outlev && (DDSIP_node[DDSIP_bb->curnode])->step == dual))
                        DDSIP_PrintState (DDSIP_bb->noiter);
                if (DDSIP_bb->cutAdded && DDSIP_param->outlev > 1)
                {
                    fprintf (DDSIP_outfile, " %6d%101d cuts\n", DDSIP_bb->curnode, DDSIP_bb->cutAdded);
                }
            }
        }
        else
        {
            boundstat = DDSIP_Bound ();
            // Print a line of output at the first, the last and each `ith' node
            if (!DDSIP_bb->noiter || (!((DDSIP_bb->noiter + 1) % DDSIP_param->logfreq)) || (DDSIP_param->outlev && (DDSIP_node[DDSIP_bb->curnode])->step == dual))
                DDSIP_PrintState (DDSIP_bb->noiter);
        }
        if (!DDSIP_bb->curnode)
             DDSIP_bb->cutCntr0 = DDSIP_bb->cutNumber;
        else if (DDSIP_param->alwaysBendersCuts)
        {
            if (DDSIP_bb->curnode == 24)
            {
                if (DDSIP_bb->cutCntr0 == DDSIP_bb->cutNumber)
                {
                    if (DDSIP_param->outlev > 20)
                        fprintf (DDSIP_bb->moreoutfile, "### setting alwaysBendersCuts to 0\n");
                    DDSIP_param->alwaysBendersCuts = 0;
                }
                else
                    DDSIP_bb->cutCntr0 = DDSIP_bb->cutNumber;
            }
            else if (DDSIP_bb->curnode == 49)
            {
                if (DDSIP_bb->cutCntr0 == DDSIP_bb->cutNumber)
                {
                    if (DDSIP_param->outlev > 20)
                        fprintf (DDSIP_bb->moreoutfile, "### setting alwaysBendersCuts to 0\n");
                    DDSIP_param->alwaysBendersCuts = 0;
                }
                else
                    DDSIP_bb->cutCntr0 = DDSIP_bb->cutNumber;
            }
            else if (DDSIP_bb->curnode == 99)
            {
                if (DDSIP_bb->cutCntr0 == DDSIP_bb->cutNumber)
                {
                    if (DDSIP_param->outlev > 20)
                        fprintf (DDSIP_bb->moreoutfile, "### setting alwaysBendersCuts to 0\n");
                    DDSIP_param->alwaysBendersCuts = 0;
                }
            }
        }

        // DDSIP_bb->skip > 0 indicates that UpperBound calls have been skipped
        // DDSIP_bb->heurval contains the objective value of the heuristic solution
        // Reset to initial values
        DDSIP_bb->heurval = DDSIP_infty;
        DDSIP_bb->skip = 0;

        cont = DDSIP_Continue (&DDSIP_bb->noiter, &boundstat);
        if (!cont)
        {
            status = boundstat;
            goto TERMINATE;
        }

        if ((status = DDSIP_Branch ()))
            goto TERMINATE;

        if (DDSIP_param->deleteRedundantCuts && !(DDSIP_bb->curnode % 10))
            DDSIP_CheckRedundancy(1);
    }

    // Termination
TERMINATE:


    DDSIP_PrintErrorMsg (status);

    printf ("\nOutput files in directory `%s'.\n", DDSIP_outdir);

    // Free up problem as allocated above
    //
    if (DDSIP_node != NULL)
    {
        DDSIP_FreeFrontNodes ();
        for (i = 0; i < DDSIP_bb->nonode; i++)
            DDSIP_Free ((void **) &(DDSIP_node[i]));
        DDSIP_Free ((void **) &(DDSIP_node));
    }

    if (DDSIP_data != NULL)
    {
        DDSIP_FreeData ();
        DDSIP_Free ((void **) &(DDSIP_data));
    }

    // Free up the problem as allocated by CPXcreateprob, if necessary
    if (DDSIP_lp != NULL)
    {
        status = CPXfreeprob (DDSIP_env, &DDSIP_lp);
        if (status)
            fprintf (stderr, "ERROR: CPXfreeprob failed, error code %d\n", status);
    }
    // Free up the CPLEX environment
    if (DDSIP_env != NULL)
    {
        status = CPXcloseCPLEX (&DDSIP_env);
        if (status)
        {
            char errmsg[1024];
            fprintf (stderr, "ERROR: Failed to close CPLEX environment.\n");
            CPXgeterrorstring (DDSIP_env, status, errmsg);
            fprintf (stderr, "%s\n", errmsg);
        }
    }

    if (DDSIP_bb != NULL)
    {
        DDSIP_FreeBb ();
        DDSIP_Free ((void **) &(DDSIP_bb));
    }

    if (DDSIP_param->outlev)
        printf ("Terminating DDSIP.\n");

    if (DDSIP_param != NULL)
    {
        DDSIP_FreeParam ();
        DDSIP_Free ((void **) &(DDSIP_param));
    }

    fprintf (DDSIP_outfile, "Current system time: ");
#ifndef _WIN32
    i = system ("date");
    // Print time to output file
    sprintf (astring, "date >> %s\n", DDSIP_outfname);
    i = system (astring);
#else
    sprintf (astring, "date /T >> %s & time /T >> %s\n", DDSIP_outfname,DDSIP_outfname);
    i = system (astring);
#endif

    if (DDSIP_outfile != NULL)
        fclose (DDSIP_outfile);

    return 0;
}
Exemple #4
0
void
DDSIP_DetEqu ()
{
    CPXLPptr det_equ;

    int status, scen, i, j, k;
    char probname[] = "sipout/det_equ.lp.gz";
    double *obj_coef;
    double *scaled_obj_coef;
    char *sense;
    char **scen_spec_rowname;
    char **scen_spec_colname;
    char **rowname, *rownamestore;
    char **colname, *colnamestore;
    int rowstorespace, rowsurplus_p;
    int colstorespace, colsurplus_p;
    char *string1, *string2;
    double coef;
    double *lb, *lb_sorted;
    double *ub, *ub_sorted;
    char *vartype, *vartype_sorted;
    int *colindex_sorted, *colindex_revers, *matcol_sorted;
    double *value;
    double *det_equ_rhs = NULL;
    double *non_stoc_rhs = NULL;
    if (DDSIP_param->seccon)
        det_equ_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_param->seccon,"det_equ_rhs(DetEqu)");
    else
    {
        fprintf (stderr,"XXX ERROR: no second stage contraints, got DDSIP_param->seccon=%d.\n",DDSIP_param->seccon);
        exit (1);
    }
    if (DDSIP_param->seccon - DDSIP_param->stocrhs>0)
        non_stoc_rhs = (double *) DDSIP_Alloc(sizeof(double),DDSIP_param->seccon - DDSIP_param->stocrhs,"non_stoc_rhs(DetEqu)");

    fprintf (stderr,
             "\nBuilding deterministic equivalent. This may take some time.\nWorks only for expectation-based model so far.\n");

    if (!(sense = (char *) calloc (DDSIP_param->seccon, sizeof (char))))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        return;
    }

    if (!(obj_coef = (double *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (double))) ||
            !(scaled_obj_coef = (double *) calloc (DDSIP_bb->secvar, sizeof (double))))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        return;
    }


    det_equ = CPXcloneprob (DDSIP_env, DDSIP_lp, &status);
    CPXchgprobname (DDSIP_env, det_equ, probname);

    if (!(rowname = (char **) calloc (DDSIP_param->seccon, sizeof (char *)))
            || !(scen_spec_rowname = (char **) calloc (DDSIP_param->seccon, sizeof (char *)))
            || !(rownamestore = (char *) calloc (DDSIP_param->seccon * 255, sizeof (char))))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        return;
    }
    rowstorespace = DDSIP_param->seccon * 255;
    status = CPXgetrowname (DDSIP_env, DDSIP_lp, rowname, rownamestore,
                            rowstorespace, &rowsurplus_p, DDSIP_param->firstcon, DDSIP_param->firstcon + DDSIP_param->seccon - 1);


    if (!(colname = (char **) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (char *)))
            || !(scen_spec_colname = (char **) calloc (DDSIP_param->secvar, sizeof (char *)))
            || !(colnamestore = (char *) calloc (DDSIP_param->secvar * 255, sizeof (char))))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        return;
    }
    colstorespace = (DDSIP_param->firstvar + DDSIP_param->secvar) * 255;
    status = CPXgetcolname (DDSIP_env, DDSIP_lp, colname, colnamestore,
                            colstorespace, &colsurplus_p, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1);

    /*____________________________________________________________________________________*/
    status = CPXgetsense (DDSIP_env, DDSIP_lp, sense, DDSIP_param->firstcon, DDSIP_param->firstcon + DDSIP_param->seccon - 1);
    /*____________________________________________________________________________________*/
    status = CPXgetrhs (DDSIP_env, DDSIP_lp, non_stoc_rhs, DDSIP_param->firstcon + DDSIP_param->stocrhs, DDSIP_param->firstcon + DDSIP_param->seccon - 1);
    /*____________________________________________________________________________________*/
    status = CPXgetobj (DDSIP_env, DDSIP_lp, obj_coef, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1);
    /*____________________________________________________________________________________*/
    //copy rownames scenario many times, append scenario index
    //and enter sense and rhs
    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        for (j = 0; j < DDSIP_param->seccon; j++)
        {
            if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
            {
                fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                return;
            }
            string1 = rowname[j];
            sprintf (string2, "%sSC%.3d", string1, scen);
            scen_spec_rowname[j] = string2;

            if (j < DDSIP_param->stocrhs)
                det_equ_rhs[j] = DDSIP_data->rhs[DDSIP_param->stocrhs * scen + j];
            else
                det_equ_rhs[j] = non_stoc_rhs[j - DDSIP_param->stocrhs];
        }
        status = CPXnewrows (DDSIP_env, det_equ, DDSIP_param->seccon, det_equ_rhs, sense, NULL, scen_spec_rowname);
        for (j = 0; j < DDSIP_param->seccon; j++)
            DDSIP_Free ((void **) &(scen_spec_rowname[j]));
    }

    //copy colnames scenario many times, append scenario index
    //and enter into constraint matrix
    if (!(lb = (double *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (double)))
            || !(lb_sorted = (double *) calloc (DDSIP_param->secvar, sizeof (double)))
            || !(ub = (double *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (double)))
            || !(ub_sorted = (double *) calloc (DDSIP_param->secvar, sizeof (double)))
            || !(vartype = (char *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (char)))
            || !(vartype_sorted = (char *) calloc (DDSIP_param->secvar, sizeof (double)))
            || !(colindex_revers = (int *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (int)))
            || !(colindex_sorted = (int *) calloc (DDSIP_param->firstvar + DDSIP_param->secvar, sizeof (int))))
    {
        fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
        return;
    }

    status = CPXgetlb (DDSIP_env, det_equ, lb, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1);
    status = CPXgetub (DDSIP_env, det_equ, ub, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1);
    status = CPXgetctype (DDSIP_env, det_equ, vartype, 0, DDSIP_param->firstvar + DDSIP_param->secvar - 1);
    for (j = 0; j < DDSIP_param->secvar; j++)
    {
        vartype_sorted[j] = vartype[DDSIP_bb->secondindex[j]];
        lb_sorted[j] = lb[DDSIP_bb->secondindex[j]];
        ub_sorted[j] = ub[DDSIP_bb->secondindex[j]];
    }


    for (scen = 0; scen < DDSIP_param->scenarios; scen++)
    {
        for (j = 0; j < DDSIP_param->secvar; j++)
        {
            if (!(string2 = (char *) calloc (1, 255 * sizeof (char))))
            {
                fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
                return;
            }
            string1 = colname[DDSIP_bb->secondindex[j]];
            sprintf (string2, "%sSC%.3d", string1, scen);
            scen_spec_colname[j] = string2;
            scaled_obj_coef[j] = DDSIP_data->prob[scen] * obj_coef[DDSIP_bb->secondindex[j]];
        }

        status =
            CPXnewcols (DDSIP_env, det_equ, DDSIP_param->secvar, scaled_obj_coef,
                        lb_sorted, ub_sorted, vartype_sorted, scen_spec_colname);
        for (j = 0; j < DDSIP_param->secvar; j++)
            DDSIP_Free ((void **) &(scen_spec_colname[j]));

    }

    /////////////////////////////////////////////////
    for (j = 0; j < DDSIP_param->firstvar; j++)
    {
        colindex_sorted[j] = DDSIP_bb->firstindex[j];
    }
    for (j = 0; j < DDSIP_param->secvar; j++)
    {
        colindex_sorted[DDSIP_param->firstvar + j] = DDSIP_bb->secondindex[j];
    }
    for (j = 0; j < DDSIP_param->firstvar + DDSIP_param->secvar; j++)
    {
        colindex_revers[colindex_sorted[j]] = j;
    }

    k = DDSIP_param->seccon / 60;
    printf ("\n0%%                                                         100%%\n");
    for (i = 0; i < DDSIP_param->seccon; i++)
    {
        for (j = 0; j < DDSIP_param->firstvar; j++)
        {
            if ((status = CPXgetcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + i, colindex_sorted[j], &coef)))
            {
                fprintf (stderr, " Build det. equivalent: Error retrieving coefficient of first-stage Variable %d.\n", j);
                exit (1);
            }
            if (coef)
            {
                for (scen = 0; scen < DDSIP_param->scenarios; scen++)
                {
                    status =
                        CPXchgcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + DDSIP_bb->seccon + scen * DDSIP_param->seccon + i, colindex_sorted[j], coef);
                    if (status)
                    {
                        fprintf (stderr, " Build det. equivalent: Error setting coefficient of first-stage Variable %d.\n", j);
                        exit (1);
                    }
                }
            }
        }
        for (j = DDSIP_param->firstvar; j < DDSIP_param->firstvar + DDSIP_param->secvar; j++)
        {
            if ((status = CPXgetcoef (DDSIP_env, det_equ, DDSIP_param->firstcon + i, colindex_sorted[j], &coef)))
            {
                fprintf (stderr,
                         " Build det. equivalent: Error retrieving coefficient of second-stage Variable %d.\n",
                         j - DDSIP_param->firstvar);
                exit (1);
            }
            if (coef)
            {
                for (scen = 0; scen < DDSIP_param->scenarios; scen++)
                {
                    status =
                        CPXchgcoef (DDSIP_env, det_equ,
                                    DDSIP_param->firstcon + DDSIP_bb->seccon + scen * DDSIP_param->seccon + i, (scen + 1) * DDSIP_param->secvar + j, coef);
                }
                if (status)
                {
                    fprintf (stderr,
                             " Build det. equivalent: Error setting coefficient of second-stage Variable %d.\n",
                             j - DDSIP_param->firstvar);
                    exit (1);
                }
            }
        }
        if (!k)
        {
            for (j = 0; j <= 60 / DDSIP_param->seccon; j++)
                printf ("#");
        }
        else if (i % k == k - 1)
            printf ("#");
    }
    printf ("\n\n");

    ///////delete original second stage rows & cols ////////////////////////////////////////////

    status = CPXdelrows (DDSIP_env, det_equ, DDSIP_param->firstcon, DDSIP_param->firstcon + DDSIP_bb->seccon - 1);
    j = 0;
    for (i = 0; i < DDSIP_param->secvar; i++)
    {
        status = CPXdelcols (DDSIP_env, det_equ, DDSIP_bb->secondindex[i] - j, DDSIP_bb->secondindex[i] - j);
        j++;
    }

    ///////enter stochastic matrix entries//////////////////////////////////////////////////////
    if (DDSIP_param->stocmat)
    {

        if (!(value = (double *) calloc (DDSIP_param->stocmat, sizeof (double)))
                || !(matcol_sorted = (int *) calloc (DDSIP_param->stocmat, sizeof (int))))
        {
            fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
            return;
        }
        for (j = 0; j < DDSIP_param->stocmat; j++)
        {
            matcol_sorted[j] = colindex_revers[DDSIP_data->matcol[j]];
        }
        for (scen = 0; scen < DDSIP_param->scenarios; scen++)
        {
            for (j = 0; j < DDSIP_param->stocmat; j++)
            {
                value[j] = DDSIP_data->matval[scen * DDSIP_param->stocmat + j];
            }
            status = CPXchgcoeflist (DDSIP_env, det_equ, DDSIP_param->stocmat, DDSIP_data->matrow, matcol_sorted, value);
            if (status)
            {
                char errmsg[1024];
                CPXgeterrorstring (DDSIP_env, status, errmsg);
                fprintf (stderr, "in DetEqu: %s\n", errmsg);
            }
            for (j = 0; j < DDSIP_param->stocmat; j++)
            {
                DDSIP_data->matrow[j] += DDSIP_param->seccon;
                if (matcol_sorted[j] >= DDSIP_param->firstvar)
                    matcol_sorted[j] += DDSIP_param->secvar;
            }
        }
        DDSIP_Free ((void **) &(value));
        DDSIP_Free ((void **) &(matcol_sorted));
        //set matrow to the old values
        for (j = 0; j < DDSIP_param->stocmat; j++)
        {
            DDSIP_data->matrow[j] -= DDSIP_param->scenarios * DDSIP_param->seccon;
        }

    }
    ///////enter stochastic cost coefficients //////////////////////////////////////////////////
    if (DDSIP_param->stoccost)
    {

        if (!(value = (double *) calloc (DDSIP_param->stoccost, sizeof (double)))
                || !(matcol_sorted = (int *) calloc (DDSIP_param->stoccost, sizeof (int))))
        {
            fprintf (stderr, "Not enough memory for building deterministic equivalent\n");
            return;
        }
        for (j = 0; j < DDSIP_param->stoccost; j++)
        {
            value[j] = 0.0;
            matcol_sorted[j] = colindex_revers[DDSIP_data->costind[j]];
        }
        for (scen = 0; scen < DDSIP_param->scenarios; scen++)
        {
            for (j = 0; j < DDSIP_param->stoccost; j++)
            {
                if (matcol_sorted[j] >= DDSIP_param->firstvar)
                    value[j] = DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j];
                else
                    value[j] += DDSIP_data->prob[scen] * DDSIP_data->cost[scen * DDSIP_param->stoccost + j];
            }
            status = CPXchgobj (DDSIP_env, det_equ, DDSIP_param->stoccost, matcol_sorted, value);
            if (status)
            {
                char errmsg[1024];
                CPXgeterrorstring (DDSIP_env, status, errmsg);
                fprintf (stderr, "in DetEqu: %s\n", errmsg);
            }
            for (j = 0; j < DDSIP_param->stoccost; j++)
            {
                if (matcol_sorted[j] >= DDSIP_param->firstvar)
                    matcol_sorted[j] += DDSIP_param->secvar;
            }
        }
        DDSIP_Free ((void **) &(value));
        DDSIP_Free ((void **) &(matcol_sorted));

    }
    ////////////////////////////////////////////////////////////////////////////////////////////

    status = CPXwriteprob (DDSIP_env, det_equ, probname, NULL);
    if (status)
        fprintf (DDSIP_outfile, " *** Deterministic equivalent not written successfully, status = %d\n", status);
    else
        fprintf (DDSIP_outfile, " *** Deterministic equivalent written successfully\n");
    status = CPXfreeprob (DDSIP_env, &det_equ);

    DDSIP_Free ((void **) &(sense));
    DDSIP_Free ((void **) &(vartype));
    DDSIP_Free ((void **) &(rowname));
    DDSIP_Free ((void **) &(rownamestore));
    DDSIP_Free ((void **) &(colname));
    DDSIP_Free ((void **) &(colnamestore));
    DDSIP_Free ((void **) &(det_equ_rhs));
    DDSIP_Free ((void **) &(non_stoc_rhs));
    DDSIP_Free ((void **) &(lb));
    DDSIP_Free ((void **) &(ub));
    DDSIP_Free ((void **) &(vartype_sorted));
    DDSIP_Free ((void **) &(lb_sorted));
    DDSIP_Free ((void **) &(ub_sorted));
    DDSIP_Free ((void **) &(obj_coef));
    DDSIP_Free ((void **) &(scaled_obj_coef));
    DDSIP_Free ((void **) &(colindex_sorted));
    DDSIP_Free ((void **) &(colindex_revers));
    DDSIP_Free ((void **) &(scen_spec_rowname));
    DDSIP_Free ((void **) &(scen_spec_colname));
    return;
}
Exemple #5
0
static int CPXPUBLIC
usersetbranch (CPXCENVptr   env,
               void         *cbdata,
               int          wherefrom,
               void         *cbhandle,
               int          brtype,
               int          sos,
               int          nodecnt,
               int          bdcnt,
               const int    *nodebeg,
               const int    *indices,
               const char   *lu,
               const double *bd,
               const double *nodeest,
               int          *useraction_p)   
{
   int status = 0;
 
   int      j, bestj = -1;
   int      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];
   int      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 = CPXgetcallbacklp (env, cbdata, wherefrom, &lp);
   if ( status ) {
      fprintf (stdout, "Can't get LP pointer.\n");
      goto TERMINATE;
   }
 
   cols = CPXgetnumcols (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    = (double *) malloc (cols * sizeof (double));
   obj  = (double *) malloc (cols * sizeof (double));
   feas = (int *)    malloc (cols * sizeof (int));
   if ( x     == NULL ||
        obj   == NULL ||
        feas  == NULL   ) {
      fprintf (stdout, "Out of memory.");
      status = CPXERR_CALLBACK;
      goto TERMINATE;
   }
 
   status = CPXgetcallbacknodex (env, cbdata, wherefrom, x, 0,
                                 cols-1);
   if ( status ) {
      fprintf (stdout, "Can't get node solution.");
      goto TERMINATE;
   }
 
   status = CPXgetcallbacknodeobjval (env, cbdata, wherefrom,
                                      &objval);
   if ( status ) {
      fprintf (stdout, "Can't get node objective value.");
      goto TERMINATE;
   }
 
   status = CPXgetobj (env, lp, obj, 0, cols-1);
   if ( status ) {
      fprintf (stdout, "Can't get obj.");
      goto TERMINATE;
   }
 
   status = CPXgetcallbacknodeintfeas (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 = CPXbranchcallbackbranchbds (env, cbdata, wherefrom,
                                        1, &bestj, varlu, varbd, objval,
                                        NULL, &seqnum1);
   if ( status )  goto TERMINATE;
 
   /* Down node */
 
   varlu[0] = 'U';
   varbd[0] = xj_lo;
 
   status = CPXbranchcallbackbranchbds (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 */
Exemple #6
0
/*
 * The function returns a true value if the tested KKT conditions are
 * satisfied and false otherwise.
 */
static int
checkkkt (CPXCENVptr env, CPXLPptr lp, int const *cone, double tol)
{
   int cols = CPXgetnumcols (env, lp);
   int rows = CPXgetnumrows (env, lp);
   int qcons = CPXgetnumqconstrs (env, lp);
   double *dslack = NULL, *pi = NULL, *socppi = NULL;
   double *val = NULL, *rhs = NULL;
   int *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;
   int i, j, q;

   qbuf_init (&qbuf);

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

   /* Fetch results and problem data that we need to check the KKT
    * conditions.
    */
   CPXmsg (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) )
   {
      CPXmsg (errc, "Out of memory!\n");
      goto TERMINATE;
   }

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

   /* Fetch solution information. */
   if ( (status = CPXgetx (env, lp, x, 0, cols - 1)) != 0 )
      goto TERMINATE;
   if ( (status = CPXgetpi (env, lp, pi, 0, rows - 1)) != 0 )
      goto TERMINATE;
   if ( (status = getsocpconstrmultipliers (env, lp, dslack, socppi)) != 0 )
      goto TERMINATE;
   if ( (status = CPXgetslack (env, lp, slack, 0, rows - 1)) != 0 )
      goto TERMINATE;
   if ( (status = CPXgetqconstrslack (env, lp, qslack, 0, qcons - 1)) != 0 )
      goto TERMINATE;
   CPXmsg (logc, "ok.\n");

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

   /* Test primal feasibility. */
   CPXmsg (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. */
   CPXmsg (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.
    */
   CPXmsg (logc, "Testing dual feasibility ... ");
   for (i = 0; i < rows; ++i) {
      switch (sense[i]) {
      case 'L':
         if ( pi[i] < -tol ) {
            CPXmsg (errc, "<= row %d has invalid dual multiplier %f.\n",
                    i, pi[i]);
            goto TERMINATE;
         }
         break;
      case 'G':
         if ( pi[i] > tol ) {
            CPXmsg (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 ) {
         CPXmsg (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 ) {
         CPXmsg (errc, "dslack value for column %d is invalid: %f\n", j, dslack[j]);
         goto TERMINATE;
      }
   }
   CPXmsg (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).
    */
   CPXmsg (logc, "Testing complementary slackness ... ");
   for (i = 0; i < rows; ++i) {
      if ( fabs (slack[i]) > tol && fabs (pi[i]) > tol ) {
         CPXmsg (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 ) {
         CPXmsg (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 ) {
            CPXmsg (errc, "Complementary slackness not satisfied for non-cone variable %f (%f, %f).\n",
                    j, x[j], dslack[j]);
            goto TERMINATE;
         }
      }
   }
   CPXmsg (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.
    */
   CPXmsg (logc, "Testing stationarity ... ");
   /* Initialize sum = c. */
   if ( (status = CPXgetobj (env, lp, sum, 0, cols - 1)) != 0 )
      goto TERMINATE;

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

      status = CPXgetrows (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;
      int 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 ) {
         CPXmsg (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 ) {
         CPXmsg (errc, "Stationarity not satisfied at index %d: %f\n",
                 j, sum[j]);
         goto TERMINATE;
      }
   }
   CPXmsg (logc, "ok.\n");

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

   ok = 1;
 TERMINATE:
   if ( !ok )
      CPXmsg (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;
}