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 */
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 */
//========================================================================== 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; }
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; }
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 */
/* * 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; }