int main (int argc, char *argv[]) { int status = 0; /* Declare and allocate space for the variables and arrays where we will store the optimization results, including the status, objective value, and variable values */ int solstat; double objval; double *x = NULL; CPXENVptr env = NULL; CPXLPptr lp = NULL; int j; int cur_numcols; CPXFILEptr logfile = NULL; int wantorig = 1; int nameind = 1; /* Check the command line arguments */ if ( argc != 2 ) { if ( argc != 3 || argv[1][0] != '-' || argv[1][1] != 'r' ) { usage (argv[0]); goto TERMINATE; } wantorig = 0; nameind = 2; } /* Initialize the CPLEX environment */ env = 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 parameter 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 != 0 ) { fprintf (stderr, "Failure to turn on screen indicator, error %d.\n", status); goto TERMINATE; } /* Set MIP parameters */ status = CPXsetintparam (env, CPXPARAM_MIP_Limits_Nodes, 10000); if ( status ) goto TERMINATE; /* Open a logfile */ logfile = CPXfopen ("admipex3.log", "a"); if ( logfile == NULL ) goto TERMINATE; status = CPXsetlogfile (env, logfile); if ( status ) goto TERMINATE; /* Create the problem, using the filename as the problem name */ lp = CPXcreateprob (env, &status, argv[nameind]); /* A returned pointer of NULL may mean that not enough memory was available or there was some other problem. In the case of failure, an error message will have been written to the error channel from inside CPLEX. In this example, the setting of the parameter CPXPARAM_ScreenOutput causes the error message to appear on stdout. Note that most CPLEX routines return an error code to indicate the reason for failure */ if ( lp == NULL ) { fprintf (stderr, "Failed to create LP.\n"); goto TERMINATE; } /* Now read the file, and copy the data into the created lp */ status = CPXreadcopyprob (env, lp, argv[nameind], NULL); if ( status ) { fprintf (stderr, "Failed to read and copy the problem data.\n"); goto TERMINATE; } /* Set up to use MIP callbacks */ status = CPXsetbranchcallbackfunc (env, usersetbranch, NULL); if ( status ) goto TERMINATE; if ( wantorig ) { /* Assure linear mappings between the presolved and original models */ status = CPXsetintparam (env, CPXPARAM_Preprocessing_Linear, 0); if ( status ) goto TERMINATE; /* Let MIP callbacks work on the original model */ status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_CallbackReducedLP, CPX_OFF); if ( status ) goto TERMINATE; } /* Turn on traditional search for use with control callbacks */ status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_Search, CPX_MIPSEARCH_TRADITIONAL); if ( status ) goto TERMINATE; /* Optimize the problem and obtain solution */ status = CPXmipopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize MIP.\n"); goto TERMINATE; } solstat = CPXgetstat (env, lp); printf ("Solution status %d.\n", solstat); status = CPXgetobjval (env, lp, &objval); if ( status ) { fprintf (stderr,"Failed to obtain objective value.\n"); goto TERMINATE; } printf ("Objective value %.10g\n", objval); cur_numcols = CPXgetnumcols (env, lp); /* Allocate space for solution */ x = (double *) malloc (cur_numcols * sizeof (double)); if ( x == NULL ) { fprintf (stderr, "No memory for solution values.\n"); goto TERMINATE; } status = CPXgetx (env, lp, x, 0, cur_numcols-1); if ( status ) { fprintf (stderr, "Failed to obtain solution.\n"); goto TERMINATE; } /* Write out the solution */ for (j = 0; j < cur_numcols; j++) { if ( fabs (x[j]) > 1e-10 ) { printf ( "Column %d: Value = %17.10g\n", j, x[j]); } } TERMINATE: /* Free the solution vector */ free_and_null ((char **) &x); /* Free the problem as allocated by CPXcreateprob and CPXreadcopyprob, if necessary */ if ( lp != NULL ) { status = CPXfreeprob (env, &lp); if ( status ) { fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status); } } /* Free 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 parameter 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); } } if ( logfile != NULL ) CPXfclose (logfile); return (status); } /* END main */
int main (void) { /* Declare variables and arrays where we will store the optimization results including the status, objective value, and variable values. */ int solstat; double objval; double x[2*NUMEDGES]; /* One flow variable and one fixed charge indicator for each edge */ CPXENVptr env = NULL; CPXLPptr lp = NULL; int status; int j; /* 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. */ lp = CPXcreateprob (env, &status, "fixnet"); /* A returned pointer of NULL may mean that not enough memory was available or there was some other problem. In the case of failure, an error message will have been written to the error channel from inside CPLEX. In this example, the setting of the parameter CPXPARAM_ScreenOutput causes the error message to appear on stdout. */ if ( lp == NULL ) { fprintf (stderr, "Failed to create LP.\n"); goto TERMINATE; } /* Build the fixed-charge network flow model using indicator constraints. */ status = buildnetwork (env, lp); if ( status ) { fprintf (stderr, "Failed to build network.\n"); goto TERMINATE; } /* Optimize the problem and obtain solution. */ status = CPXmipopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize MIP.\n"); goto TERMINATE; } solstat = CPXgetstat (env, lp); /* Write solution status and objective to the screen. */ printf ("\nSolution status = %d\n", solstat); status = CPXgetobjval (env, lp, &objval); if ( status ) { fprintf (stderr, "No MIP objective value available. Exiting...\n"); goto TERMINATE; } printf ("Solution value = %f\n", objval); printf ("Solution vector:\n"); dumpx (env, lp); status = CPXgetx (env, lp, x, 0, 2*NUMEDGES-1); if ( status ) { fprintf (stderr, "Failed to get optimal integer x.\n"); goto TERMINATE; } /* Make sure flow satisfies fixed-charge constraints */ for (j = 0; j < NUMEDGES; j++) { if ( x[j] > 0.0001 && x[NUMEDGES+j] < 0.9999 ) { printf ("WARNING : Edge from %d to %d has non-zero flow %.3f\n", orig[j], dest[j], x[j]); printf (" : fixed-charge indicator has value %.6f.\n", x[NUMEDGES+j]); } } printf("\n"); /* Finally, write a copy of the problem to a file. */ status = CPXwriteprob (env, lp, "fixnet.lp", NULL); if ( status ) { fprintf (stderr, "Failed to write LP to disk.\n"); goto TERMINATE; } /* Free problem */ status = CPXfreeprob (env, &lp); if ( status ) { fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status); goto TERMINATE; } TERMINATE: /* Free up the problem as allocated by CPXcreateprob, 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 */
int main (int argc, char *argv[]) { /* Declare and allocate space for the variables and arrays where we will store the optimization results including the status, objective value, maximum bound violation, variable values, and basis. */ int solnstat, solnmethod, solntype; double objval, maxviol; double *x = NULL; CPXENVptr env = NULL; CPXLPptr lp = NULL; int status = 0; int j; int cur_numrows, cur_numcols; /* Check the command line arguments */ if (( argc != 2 )) { usage (argv[0]); goto TERMINATE; } /* 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, argv[1]); /* A returned pointer of NULL may mean that not enough memory was available or there was some other problem. In the case of failure, an error message will have been written to the error channel from inside CPLEX. In this example, the setting of the parameter CPXPARAM_ScreenOutput causes the error message to appear on stdout. Note that most CPLEX routines return an error code to indicate the reason for failure. */ if ( lp == NULL ) { fprintf (stderr, "Failed to create LP.\n"); goto TERMINATE; } /* Now read the file, and copy the data into the created lp */ status = CPXreadcopyprob (env, lp, argv[1], NULL); if ( status ) { fprintf (stderr, "Failed to read and copy the problem data.\n"); goto TERMINATE; } if ( CPXgetprobtype (env, lp) != CPXPROB_MIQP ) { fprintf (stderr, "Input file is not a MIQP. Exiting.\n"); goto TERMINATE; } /* Optimize the problem and obtain solution. */ status = CPXsetintparam (env, CPXPARAM_SolutionTarget, CPX_SOLUTIONTARGET_OPTIMALGLOBAL); if ( status ) goto TERMINATE; status = CPXmipopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize nonconvex MIQP.\n"); goto TERMINATE; } solnstat = CPXgetstat (env, lp); if ( solnstat == CPXMIP_UNBOUNDED || solnstat == CPX_STAT_UNBOUNDED ) { printf ("Model is unbounded\n"); goto TERMINATE; } else if ( solnstat == CPXMIP_INFEASIBLE || solnstat == CPX_STAT_INFEASIBLE ) { printf ("Model is infeasible\n"); goto TERMINATE; } else if ( solnstat == CPX_STAT_INForUNBD ) { printf ("Model is infeasible or unbounded\n"); goto TERMINATE; } status = CPXsolninfo (env, lp, &solnmethod, &solntype, NULL, NULL); if ( status ) { fprintf (stderr, "Failed to obtain solution info.\n"); goto TERMINATE; } printf ("Solution status %d, solution method %d\n", solnstat, solnmethod); if ( solntype == CPX_NO_SOLN ) { fprintf (stderr, "Solution not available.\n"); goto TERMINATE; } status = CPXgetobjval (env, lp, &objval); if ( status ) { fprintf (stderr, "Failed to obtain objective value.\n"); goto TERMINATE; } printf ("Objective value %.10g.\n", objval); /* The size of the problem should be obtained by asking CPLEX what the actual size is. cur_numrows and cur_numcols store the current number of rows and columns, respectively. */ cur_numcols = CPXgetnumcols (env, lp); cur_numrows = CPXgetnumrows (env, lp); /* Retrieve solution vector */ x = (double *) malloc (cur_numcols*sizeof(double)); if ( x == NULL ) { fprintf (stderr, "No memory for solution.\n"); goto TERMINATE; } status = CPXgetx (env, lp, x, 0, cur_numcols-1); if ( status ) { fprintf (stderr, "Failed to obtain primal solution.\n"); goto TERMINATE; } /* Write out the solution */ for (j = 0; j < cur_numcols; j++) { printf ( "Column %d: Value = %17.10g", j, x[j]); printf ("\n"); } /* Display the maximum bound violation. */ status = CPXgetdblquality (env, lp, &maxviol, CPX_MAX_PRIMAL_INFEAS); if ( status ) { fprintf (stderr, "Failed to obtain bound violation.\n"); goto TERMINATE; } printf ("Maximum bound violation = %17.10g\n", maxviol); TERMINATE: /* Free up the basis and solution */ free_and_null ((char **) &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 */
int main (void) { /* Declare pointers for the variables and arrays that will contain the data which define the LP problem. The setproblemdata() routine allocates space for the problem data. */ char *probname = NULL; int numcols; int numrows; int objsen; double *obj = NULL; double *rhs = NULL; char *sense = NULL; int *matbeg = NULL; int *matcnt = NULL; int *matind = NULL; double *matval = NULL; double *lb = NULL; double *ub = NULL; char *ctype = NULL; /* Declare and allocate space for the variables and arrays where we will store the optimization results including the status, objective value, variable values, and row slacks. */ int solstat; double objval; double x[NUMCOLS]; double slack[NUMROWS]; CPXENVptr env = NULL; CPXLPptr lp = NULL; int status; int i, j; int cur_numrows, cur_numcols; /* 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; } /* Fill in the data for the problem. */ status = setproblemdata (&probname, &numcols, &numrows, &objsen, &obj, &rhs, &sense, &matbeg, &matcnt, &matind, &matval, &lb, &ub, &ctype); if ( status ) { fprintf (stderr, "Failed to build problem data arrays.\n"); goto TERMINATE; } /* Create the problem. */ lp = CPXcreateprob (env, &status, probname); /* A returned pointer of NULL may mean that not enough memory was available or there was some other problem. In the case of failure, an error message will have been written to the error channel from inside CPLEX. In this example, the setting of the parameter CPXPARAM_ScreenOutput causes the error message to appear on stdout. */ if ( lp == NULL ) { fprintf (stderr, "Failed to create LP.\n"); goto TERMINATE; } /* Now copy the problem data into the lp */ status = CPXcopylp (env, lp, numcols, numrows, objsen, obj, rhs, sense, matbeg, matcnt, matind, matval, lb, ub, NULL); if ( status ) { fprintf (stderr, "Failed to copy problem data.\n"); goto TERMINATE; } /* Now copy the ctype array */ status = CPXcopyctype (env, lp, ctype); if ( status ) { fprintf (stderr, "Failed to copy ctype\n"); goto TERMINATE; } /* Optimize the problem and obtain solution. */ status = CPXmipopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize MIP.\n"); goto TERMINATE; } solstat = CPXgetstat (env, lp); /* Write the output to the screen. */ printf ("\nSolution status = %d\n", solstat); status = CPXgetobjval (env, lp, &objval); if ( status ) { fprintf (stderr,"No MIP objective value available. Exiting...\n"); goto TERMINATE; } printf ("Solution value = %f\n\n", objval); /* The size of the problem should be obtained by asking CPLEX what the actual size is, rather than using what was passed to CPXcopylp. cur_numrows and cur_numcols store the current number of rows and columns, respectively. */ cur_numrows = CPXgetnumrows (env, lp); cur_numcols = CPXgetnumcols (env, lp); status = CPXgetx (env, lp, x, 0, cur_numcols-1); if ( status ) { fprintf (stderr, "Failed to get optimal integer x.\n"); goto TERMINATE; } status = CPXgetslack (env, lp, slack, 0, cur_numrows-1); if ( status ) { fprintf (stderr, "Failed to get optimal slack values.\n"); goto TERMINATE; } for (i = 0; i < cur_numrows; i++) { printf ("Row %d: Slack = %10f\n", i, slack[i]); } for (j = 0; j < cur_numcols; j++) { printf ("Column %d: Value = %10f\n", j, x[j]); } /* Finally, write a copy of the problem to a file. */ status = CPXwriteprob (env, lp, "mipex1.lp", NULL); if ( status ) { fprintf (stderr, "Failed to write LP to disk.\n"); goto TERMINATE; } TERMINATE: /* Free up the problem as allocated by CPXcreateprob, 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); } } /* Free up the problem data arrays, if necessary. */ free_and_null ((char **) &probname); free_and_null ((char **) &obj); free_and_null ((char **) &rhs); free_and_null ((char **) &sense); free_and_null ((char **) &matbeg); free_and_null ((char **) &matcnt); free_and_null ((char **) &matind); free_and_null ((char **) &matval); free_and_null ((char **) &lb); free_and_null ((char **) &ub); free_and_null ((char **) &ctype); return (status); } /* END main */
int main (int argc, char *argv[]) { /* Declare and allocate space for the variables and arrays where we will store the optimization results including the status, objective value, maximum bound violation, variable values, and basis. */ time_t start, end; /* returns elapsed time in sec */ // clock_t start, end; /* for elapsed CPU time */ double total_time; start = clock(); int solnstat, solnmethod, solntype; double objval, maxviol; double *x = NULL; int *cstat = NULL; int *rstat = NULL; CPXENVptr env = NULL; CPXLPptr lp = NULL; int status = 0; int j; int cur_numrows, cur_numcols; int method; char *basismsg; /* Check the command line arguments */ if (( argc != 4 ) || ( strchr ("podhbnsc", argv[2][0]) == NULL ) ) { usage (argv[0]); goto TERMINATE; } /* 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 CPX_PARAM_SCRIND 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, CPX_PARAM_SCRIND, 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, argv[1]); /* A returned pointer of NULL may mean that not enough memory was available or there was some other problem. In the case of failure, an error message will have been written to the error channel from inside CPLEX. In this example, the setting of the parameter CPX_PARAM_SCRIND 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, argv[1], NULL); if ( status ) { fprintf (stderr, "Failed to read and copy the problem data.\n"); goto TERMINATE; } /* Optimize the problem and obtain solution. */ switch (argv[2][0]) { case 'o': method = CPX_ALG_AUTOMATIC; break; case 'p': method = CPX_ALG_PRIMAL; break; case 'd': method = CPX_ALG_DUAL; break; case 'n': method = CPX_ALG_NET; break; case 'h': method = CPX_ALG_BARRIER; break; case 'b': method = CPX_ALG_BARRIER; status = CPXsetintparam (env, CPX_PARAM_BARCROSSALG, CPX_ALG_NONE); if ( status ) { fprintf (stderr, "Failed to set the crossover method, error %d.\n", status); goto TERMINATE; } break; case 's': method = CPX_ALG_SIFTING; break; case 'c': method = CPX_ALG_CONCURRENT; break; default: method = CPX_ALG_NONE; break; } status = CPXsetintparam (env, CPX_PARAM_LPMETHOD, method); if ( status ) { fprintf (stderr, "Failed to set the optimization method, error %d.\n", status); goto TERMINATE; } status = CPXlpopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize LP.\n"); goto TERMINATE; } solnstat = CPXgetstat (env, lp); if ( solnstat == CPX_STAT_UNBOUNDED ) { printf ("Model is unbounded\n"); goto TERMINATE; } else if ( solnstat == CPX_STAT_INFEASIBLE ) { printf ("Model is infeasible\n"); goto TERMINATE; } else if ( solnstat == CPX_STAT_INForUNBD ) { printf ("Model is infeasible or unbounded\n"); goto TERMINATE; } status = CPXsolninfo (env, lp, &solnmethod, &solntype, NULL, NULL); if ( status ) { fprintf (stderr, "Failed to obtain solution info.\n"); goto TERMINATE; } printf ("Solution status %d, solution method %d\n", solnstat, solnmethod); if ( solntype == CPX_NO_SOLN ) { fprintf (stderr, "Solution not available.\n"); goto TERMINATE; } status = CPXgetobjval (env, lp, &objval); if ( status ) { fprintf (stderr, "Failed to obtain objective value.\n"); goto TERMINATE; } printf ("Objective value %.10g.\n", objval); /* The size of the problem should be obtained by asking CPLEX what the actual size is. cur_numrows and cur_numcols store the current number of rows and columns, respectively. */ cur_numcols = CPXgetnumcols (env, lp); cur_numrows = CPXgetnumrows (env, lp); /* Retrieve basis, if one is available */ if ( solntype == CPX_BASIC_SOLN ) { cstat = (int *) malloc (cur_numcols*sizeof(int)); rstat = (int *) malloc (cur_numrows*sizeof(int)); if ( cstat == NULL || rstat == NULL ) { fprintf (stderr, "No memory for basis statuses.\n"); goto TERMINATE; } status = CPXgetbase (env, lp, cstat, rstat); if ( status ) { fprintf (stderr, "Failed to get basis; error %d.\n", status); goto TERMINATE; } } else { printf ("No basis available\n"); } /* Retrieve solution vector */ x = (double *) malloc (cur_numcols*sizeof(double)); if ( x == NULL ) { fprintf (stderr, "No memory for solution.\n"); goto TERMINATE; } status = CPXgetx (env, lp, x, 0, cur_numcols-1); if ( status ) { fprintf (stderr, "Failed to obtain primal solution.\n"); goto TERMINATE; } status = CPXsolwrite(env,lp,argv[3]); /* Write out the solution for (j = 0; j < cur_numcols; j++) { printf ( "Column %d: Value = %17.10g", j, x[j]); if ( cstat != NULL ) { switch (cstat[j]) { case CPX_AT_LOWER: basismsg = "Nonbasic at lower bound"; break; case CPX_BASIC: basismsg = "Basic"; break; case CPX_AT_UPPER: basismsg = "Nonbasic at upper bound"; break; case CPX_FREE_SUPER: basismsg = "Superbasic, or free variable at zero"; break; default: basismsg = "Bad basis status"; break; } printf (" %s",basismsg); } printf ("\n"); } */ /* Display the maximum bound violation. */ status = CPXgetdblquality (env, lp, &maxviol, CPX_MAX_PRIMAL_INFEAS); if ( status ) { fprintf (stderr, "Failed to obtain bound violation.\n"); goto TERMINATE; } printf ("Maximum bound violation = %17.10g\n", maxviol); TERMINATE: /* Free up the basis and solution */ free_and_null ((char **) &cstat); free_and_null ((char **) &rstat); free_and_null ((char **) &x); /* Free up the problem, if necessary */ if ( lp != NULL ) { status = 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 CPX_PARAM_SCRIND 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); } } end = clock(); total_time = (double)( end - start )/(double)CLOCKS_PER_SEC ; printf( "\nElapsed time : %0.3f \n", total_time ); return (status); } /* END main */
int main(int argc, char **argv) { char ejes[100]; char labels[100]; char test[100]; archivoInput = argv[1]; randomness = argv[2]; porcentajeParticiones = atof(argv[3]); algoritmo = argv[4]; epsilonClique = atof(argv[5]); epsilonAgujero = atof(argv[6]); numeroDeModelo = atoi(argv[7]); RECORRIDO_ARBOL = atoi(argv[8]); VARIABLE_CORTE = atoi(argv[9]); semilla = atoi(argv[10]); srand(semilla); if(not freopen(archivoInput.c_str(), "r", stdin)){ cout << "No pude abrir archivo: " << archivoInput << endl; return 1; } sprintf(ejes, "ejes.out"); sprintf(labels, "labels.out"); if(randomness == "notrandom") { sprintf(test, "%s%s", argv[1], argv[2]); } else if (randomness == "random") { sprintf(test, "%s%s", argv[1], argv[3]); } else{ cout << "Paramtros mal introducidos" << endl; return 0; } read(randomness); // cada elemento de la particion conformado por un unico nodo // Le paso por parametro el algoritmo a implementar: bb = branch and bound, cb = cut and branch if(algoritmo != "bb" && algoritmo != "cb") { cout << "Error introduciendo parametro de algoritmo a ser aplicado " << endl; return 0; } // ============================================================================================== // Genero el problema de cplex. int status; // Creo el entorno. CPXENVptr env = CPXopenCPLEX(&status); // Puntero al entorno. CPXLPptr lp; // Puntero al LP if (env == NULL) { cerr << "Error creando el entorno" << endl; exit(1); } ///Iniciio el reloj CPXgettime(env, &inittime); // Creo el LP. lp = CPXcreateprob(env, &status, "instancia coloreo de grafo particionado"); if (lp == NULL) { cerr << "Error creando el LP" << endl; exit(1); } // Definimos las variables. En total, son P + N*P variables ( las W[j] y las X[i][j] ) int cantVariables = P + N*P; double *ub, *lb, *objfun; // Cota superior, cota inferior, coeficiente de la funcion objetivo. char *xctype, **colnames; // tipo de la variable , string con el nombre de la variable. ub = new double[cantVariables]; lb = new double[cantVariables]; objfun = new double[cantVariables]; xctype = new char[cantVariables]; colnames = new char*[cantVariables]; for (int i = 0; i < cantVariables; i++) { ub[i] = 1.0; // seteo upper y lower bounds de cada variable lb[i] = 0.0; if(i < P) { // agrego el costo en la funcion objetivo de cada variables objfun[i] = 1; // busco minimizar Sum(W_j) para j=0..P (la cantidad de colores utilizados). } else { objfun[i] = 0; // los X[i][j] no contribuyen a la funcion objetivo } xctype[i] = 'B'; // 'C' es continua, 'B' binaria, 'I' Entera. colnames[i] = new char[10]; } /* Defino el tipo de variable BoolVarMatrix, que sera utilizado en la resolucion * recordar: X_v_j = 1 sii el color j es asignado al vertice v * recordar: W_j = 1 si X_v_j = 1 para al menos un vertice v */ for(int j=0; j<P; j++) { sprintf(colnames[j], "W_%d", j); // cout << colnames[j] << endl; } for(int i=0; i<N; i++) { for(int j=0; j<P; j++) { sprintf(colnames[xijIndice(i,j)], "X_%d_%d", i, j); // cout << colnames[xijIndice(i,j)] << endl; } } // ========================== Agrego las columnas. =========================== // if(algoritmo == "cb"){ // si quiero resolver la relajacion, agregar los cortes y despues resolver el MIP, no agrego xctype status = CPXnewcols(env, lp, cantVariables, objfun, lb, ub, NULL, colnames); } else if (algoritmo == "bb"){ // si quiero hacer MIP, directamente, con brancha and bound, agrego xctype status = CPXnewcols(env, lp, cantVariables, objfun, lb, ub, xctype, colnames); } else { cout << "Error: parametro de algoritmo bb/cb mal introducido" << endl; return 0; } if (status) { cerr << "Problema agregando las variables CPXnewcols" << endl; exit(1); } // Libero las estructuras. for (int i = 0; i < cantVariables; i++) { delete[] colnames[i]; } delete[] ub; delete[] lb; delete[] objfun; delete[] xctype; delete[] colnames; // CPLEX por defecto minimiza. Le cambiamos el sentido a la funcion objetivo si se quiere maximizar. // CPXchgobjsen(env, lp, CPX_MAX); // ================================================================================================ // // ===================================== Restricciones ============================================ // // i) Asigno exactamente un color a exactamente un vertice de cada particion ( P restricciones ) // ii) Dos vertices adyacentes no pueden tener el mismo color ( E restricciones ) // iii) Los W_j estan bien armados, en funcion de X_v_j ( 2*P restricciones ) // ccnt = numero nuevo de columnas en las restricciones. // rcnt = cuantas restricciones se estan agregando. // nzcnt = # de coeficientes != 0 a ser agregados a la matriz. Solo se pasan los valores que no son cero. int ccnt = 0; int rcnt; if(numeroDeModelo == 0){ rcnt = P + (E*P)/2 + 2*P; // Cota maxima a la cantidad de restricciones } else{ rcnt = P + (E*P)/2 + N*P; } // (E/2 porque en la entrada se supone que en la entrada me pasan 2 veces cada eje) int nzcnt = 0; // al ppio es cero (para cada valor q agrego, lo voy a incrementar en 1) char sense[rcnt]; // Sentido de la desigualdad. 'G' es mayor o igual y 'E' para igualdad, 'L' menor o igual double *rhs = new double[rcnt]; // Termino independiente de las restricciones. int *matbeg = new int[rcnt]; //Posicion en la que comienza cada restriccion en matind y matval. int *matind = new int[rcnt*cantVariables]; // Array con los indices de las variables con coeficientes != 0 en la desigualdad. double *matval = new double[rcnt*cantVariables]; // Array que en la posicion i tiene coeficiente ( != 0) de la variable matind[i] en la restriccion. // CPLEX va a leer hasta la cantidad nzcnt que le pasemos. int cantRestricciones = 0; // r = numero de restriccion // i) P restricciones - exactamente un color a cada vertice (una restriccion por cada particion) for(int particion = 0; particion < P; particion++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 1; sense[cantRestricciones] = 'E'; for(int e = 0; e < S[particion].size(); e++) { for(int color = 0; color < P; color++) { matind[nzcnt] = xijIndice(S[particion][e], color); matval[nzcnt] = 1; nzcnt++; } } cantRestricciones++; } // ii) Cota superior de (E*P)/2 restricciones mas // Una para cada par de vecinos i j, para cada color pero solo cuando i < j, y estan en distinta particion for(int i = 0; i < N; i++) { for(int j = i + 1; j < N; j++) { if(M[i][j] == 1 and dameParticion(i) != dameParticion(j)){ for(int color = 0; color < P; color++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 1; sense[cantRestricciones] = 'L'; matind[nzcnt] = xijIndice(i,color); matval[nzcnt] = 1; nzcnt++; matind[nzcnt] = xijIndice(j,color); matval[nzcnt] = 1; nzcnt++; cantRestricciones++; } } } } if(numeroDeModelo == 0){ // iii) 2*P restricciones mas // - P * wj + sigma xij <= 0 for(int k=0; k<P; k++) { // para cada color matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 0; sense[cantRestricciones] = 'L'; matind[nzcnt] = k; matval[nzcnt] = -1 * P; nzcnt++; for(int i=0; i<N; i++) { matind[nzcnt] = xijIndice(i,k); matval[nzcnt] = 1; nzcnt++; } cantRestricciones++; } // - wj + sigma xij >= 0 for(int k=0; k<P; k++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 0; sense[cantRestricciones] = 'G'; matind[nzcnt] = k; matval[nzcnt] = -1; nzcnt++; for(int i=0; i<N; i++) { matind[nzcnt] = xijIndice(i,k); matval[nzcnt] = 1; nzcnt++; } cantRestricciones++; } } else{ // iii) N*P restricciones mas // -wj + xij <= 0 for(int color = 0; color < P; color++) { for(int i = 0; i < N; i++) { matbeg[cantRestricciones] = nzcnt; rhs[cantRestricciones] = 0; sense[cantRestricciones] = 'L'; matind[nzcnt] = color; matval[nzcnt] = -1; nzcnt++; matind[nzcnt] = xijIndice(i, color); matval[nzcnt] = 1; nzcnt++; cantRestricciones++; } } } //Actualizo rcnt. rcnt = cantRestricciones; // =================================================================================================== // Agregamos las restricciones al lp. status = CPXaddrows(env, lp, ccnt, rcnt, nzcnt, rhs, sense, matbeg, matind, matval, NULL, NULL); if (status) { cerr << "Problema agregando restricciones." << endl; exit(1); } delete[] rhs; delete[] matbeg; delete[] matind; delete[] matval; // ============================================================================================== // // ================================== Optimizamos el problema. ================================== // // Seteo de algunos parametros. // Para desactivar la salida poner CPX_OFF. status = CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_ON); if (status) { cerr << "Problema seteando SCRIND" << endl; exit(1); } // Setea el tiempo limite de ejecucion. status = CPXsetdblparam(env, CPX_PARAM_TILIM, TIEMPO_LIMITE); // setear limite de tiempo en 3600 !!!!!!! if (status) { cerr << "Problema seteando el tiempo limite" << endl; exit(1); } // Escribimos el problema a un archivo .lp. // status = CPXwriteprob(env, lp, "test.lp", NULL); if (status) { cerr << "Problema escribiendo modelo" << endl; exit(1); } // Seteamos algunos parametros para resolver con branch and bound CPXsetintparam(env, CPX_PARAM_MIPSEARCH, CPX_MIPSEARCH_TRADITIONAL); // Para facilitar la comparación evitamos paralelismo: CPXsetintparam(env, CPX_PARAM_THREADS, 1); //Para que no se adicionen planos de corte: CPXsetintparam(env,CPX_PARAM_EACHCUTLIM, 0); CPXsetintparam(env, CPX_PARAM_FRACCUTS, -1); CPXsetintparam(env, CPX_PARAM_LANDPCUTS, -1); // Para que no haga preprocesamientos CPXsetintparam(env, CPX_PARAM_PRESLVND, -1); CPXsetintparam(env, CPX_PARAM_REPEATPRESOLVE, 0); CPXsetintparam(env, CPX_PARAM_RELAXPREIND, 0); CPXsetintparam(env, CPX_PARAM_REDUCE, 0); // Recorrido del arbol CPXsetintparam(env, CPX_PARAM_NODESEL, RECORRIDO_ARBOL); // Seleccion de variable CPXsetintparam(env, CPX_PARAM_VARSEL, VARIABLE_CORTE); CPXgettime(env, &endtime); tiempoPreparar = endtime - inittime; inittime = endtime; // ========================================================================================================= // resuelvo con cut and branch (con los cortes definidos por nosotros) o con branch and bound (y sin cortes) // ========================================================================================================= if(algoritmo == "cb") { // while (algo) ... resolver el lp, chequear si la restr inducida por la clique actual es violada. Seguir //cout << "antes" << endl; for(int ciclocb=0; ciclocb<CANT_CICLOS_CB; ciclocb++) { status = CPXlpopt(env, lp); //cout << "despues" << endl; double objval; status = CPXgetobjval(env, lp, &objval); // Aca, deberia agregar los cortes requeridos, en funcion de "cliques" y "objval" // mostrameValores(env, lp); double *sol = new double[cantVariables]; CPXgetx(env, lp, sol, 0, cantVariables - 1); //CPXwriteprob (env, lp, "antesDeClique.lp", "LP"); // BUSCAR Y AGREGAR CLIQUE vector < vector<int> > agregados; for(int color=0; color<P; color++) { for(int i=0; i<CANT_RESTR_CLIQUES; i++) { bool iteracionRandom = (i!=0); vector<int> clique = dameClique(sol, color, iteracionRandom); sort(clique.begin(), clique.end()); bool incluido = find(agregados.begin(), agregados.end(), clique) != agregados.end(); if (not incluido and not clique.empty()) { agregados.push_back(clique); agregarRestriccionClique(env, lp, clique); cantidadCortesClique++; // cout << "AGREGO RESTRICCION DE CLIQUE de random " << iteracionRandom << " y de color #"<< color << ": "; // for(int j=0; j<clique.size(); j++) { // cout << clique[j] << " "; // } // cout << endl; } } } // BUSCAR Y AGREGAR AGUJERO agregados.clear(); for(int color=0; color<P; color++) { for(int i=0; i<CANT_RESTR_AGUJEROS; i++) { vector<int> agujero = dameAgujero(sol, color); bool incluido = find(agregados.begin(), agregados.end(), agujero) != agregados.end(); if (not incluido and not agujero.empty()) { agregados.push_back(agujero); agregarRestriccionAgujero(env, lp, agujero); cantidadCortesAgujero++; // cout << "AGREGO RESTRICCION DE AGUJERO de color #"<< color << ": "; // for(int j=0; j<agujero.size(); j++) { // cout << agujero[j] << " "; // } // cout << endl; } } } delete [] sol; } // CPXwriteprob (env, lp, "lpCB.lp", "LP"); ///Cuando salimos, pasamos a binaria y corremos un branch and bound char *ctype = new char[cantVariables]; for (int i = 0; i < cantVariables; i++) { ctype[i] = 'B'; } // cout << "Antes cambiar tipo" << endl; status = CPXcopyctype (env, lp, ctype); // cout << "Despues cambiar tipo" << endl; delete[] ctype; CPXgettime(env, &endtime); tiempoCutAndBranch = endtime - inittime; inittime = endtime; } ///Corremos el BB, ya sea porque esto es lo que queriamos originalemente, o porque terminamos con los planos de corte // cout << "ANTES" << endl; //CPXwriteprob (env, lp, "antesDeMip.lp", "LP"); CPXmipopt(env,lp); // cout << "DESPUES" << endl; CPXgettime(env, &endtime); tiempoBranchAndBound = endtime - inittime; // inittime = endtime; status = CPXgettime(env, &endtime); if (status) { cerr << "Problema optimizando CPLEX" << endl; exit(1); } // Chequeamos el estado de la solucion. int solstat; char statstring[510]; CPXCHARptr p; solstat = CPXgetstat(env, lp); p = CPXgetstatstring(env, solstat, statstring); string statstr(statstring); cout << endl << "Resultado de la optimizacion: " << statstring << endl; if(solstat!=CPXMIP_OPTIMAL && solstat!=CPXMIP_OPTIMAL_TOL && solstat!=CPXMIP_NODE_LIM_FEAS && solstat!=CPXMIP_TIME_LIM_FEAS){ cout << "No hay solucion" << endl; } else{ double objval; status = CPXgetobjval(env, lp, &objval); if (status) { cerr << "Problema obteniendo valor de mejor solucion." << endl; exit(1); } cout << "Datos de la resolucion: " << "\t" << objval << "\t" << tiempoPreparar + tiempoCutAndBranch + tiempoBranchAndBound << endl; cout << "Tiempo en preparar: " << "\t" << tiempoPreparar << endl; cout << "Tiempo en CB: " << "\t" << tiempoCutAndBranch << endl; cout << "Tiempo en BB: " << "\t" << tiempoBranchAndBound << endl; // Tomamos los valores de todas las variables. Estan numeradas de 0 a n-1. double *sol = new double[cantVariables]; status = CPXgetx(env, lp, sol, 0, cantVariables - 1); if (status) { cerr << "Problema obteniendo la solucion del LP." << endl; exit(1); } impresionModelo(env, lp); // Solo escribimos las variables distintas de cero (tolerancia, 1E-05). //solfile << "Status de la solucion: " << statstr << endl; // for(int j=0; j<P; j++) { // if(sol[j] > TOL) { // cout << "W_" << j << " = " << sol[j] << endl; // } // } // for(int i=0; i<N; i++) { // for(int j=0; j<P; j++) { // if(sol[P + P*i + j] > TOL) { // cout << "X_" << i << "_" << j << " = " << sol[P+P*i+j] << endl; // } // } // } //solfile.close(); // ==================== Devuelvo el grafo resultante coloreado, para graficar! ====================== // // ofstream streamEjes, streamLabels; //ofstream streamParticiones; // Tomamos los valores de la solucion y los escribimos a un archivo. // streamEjes.open(ejes); // for(int v1=0; v1<N; v1++) { // for(int v2=v1+1; v2<N; v2++) { // if (M[v1][v2] == 1) { // streamEjes << v1+1 << " " << v2+1 << endl; // } // } // } streamEjes.close(); // cout << ejes << endl; // streamLabels.open(labels); // bool estaColoreado; // for(int v=0; v<N; v++){ // estaColoreado = false; // for(int j=0; j<P; j++){ // if (sol[P + P*v + j] == 1) { // streamLabels << v+1 << " " << j+1 << endl; // estaColoreado = true; // } // } // if(not estaColoreado) { // streamLabels << v+1 << " " << 0 << endl; // } // } // streamLabels.close(); // delete [] sol; } return 0; }
int main (void) { /* Declare variables and arrays where we will store the optimization results including the status, objective value, and variable values. */ int solstat; double objval; int colcnt = 0; double *x = NULL; CPXENVptr env = NULL; CPXLPptr lp = NULL; int status; int m, p; /* 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; } /* Formulate and solve the problem */ lp = CPXcreateprob (env, &status, "food manufacturing"); /* A returned pointer of NULL may mean that not enough memory was available or there was some other problem. In the case of failure, an error message will have been written to the error channel from inside CPLEX. In this example, the setting of the parameter CPXPARAM_ScreenOutput causes the error message to appear on stdout. */ if ( lp == NULL ) { fprintf (stderr, "Failed to create LP.\n"); goto TERMINATE; } /* Build the model */ status = buildmodel (env, lp); if ( status ) { fprintf (stderr, "Failed to build model.\n"); goto TERMINATE; } /* Write a copy of the problem to a file. */ status = CPXwriteprob (env, lp, "foodmanu.lp", NULL); if ( status ) { fprintf (stderr, "Failed to write LP to disk.\n"); goto TERMINATE; } /* Optimize the problem and obtain solution. */ status = CPXmipopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize MIP.\n"); goto TERMINATE; } solstat = CPXgetstat (env, lp); /* Write solution status, objective and solution vector to the screen. */ printf ("\nSolution status = %d\n", solstat); status = CPXgetobjval (env, lp, &objval); if ( status ) { fprintf (stderr,"No MIP objective value available. Exiting...\n"); goto TERMINATE; } printf ("Solution value (maximum profit) = %f\n\n", objval); colcnt = NUMVARS*NUMMONTHS*NUMPRODUCTS; x = (double *) malloc (colcnt * sizeof(double)); if ( x == NULL ) { status = CPXERR_NO_MEMORY; fprintf (stderr, "Could not allocate memory for solution.\n"); goto TERMINATE; } status = CPXgetx (env, lp, x, 0, colcnt - 1); if ( status ) { fprintf (stderr, "Failed to get optimal integer x.\n"); goto TERMINATE; } for (m = 0; m < NUMMONTHS; m++) { printf ("Month %d \n", m); printf (" . buy "); for (p = 0; p < NUMPRODUCTS; p++) printf ("%f\t", x[varindex(m, p, BUY)]); printf ("\n"); printf (" . use "); for (p = 0; p < NUMPRODUCTS; p++) printf ("%f\t", x[varindex (m, p, USE)]); printf ("\n"); printf (" . store "); for (p = 0; p < NUMPRODUCTS; p++) printf ("%f\t", x[varindex (m, p, STORE)]); printf ("\n"); } /* Free problem */ status = CPXfreeprob (env, &lp); if ( status ) { fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status); goto TERMINATE; } TERMINATE: free_and_null ((char **) &x); /* Free up the problem as allocated by CPXcreateprob, 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 */