//========================================================================== // Restore bounds and type of the first stage variables int DDSIP_RestoreBoundAndType (void) { int status = 0; if ((DDSIP_bb->DDSIP_step == neobj || DDSIP_bb->DDSIP_step == eev) && DDSIP_param->riskvar) DDSIP_UndeleteRiskObj (); // Restore original bounds status = CPXchgbds (DDSIP_env, DDSIP_lp, DDSIP_bb->firstvar, DDSIP_bb->firstindex, DDSIP_bb->lbident, DDSIP_bb->lborg); if (status) { fprintf (stderr, "ERROR: Failed to change lower bounds \n"); return status; } status = CPXchgbds (DDSIP_env, DDSIP_lp, DDSIP_bb->firstvar, DDSIP_bb->firstindex, DDSIP_bb->ubident, DDSIP_bb->uborg); if (status) { fprintf (stderr, "ERROR: Failed to change upper bounds \n"); return status; } // probtype=0 (LP) if (!CPXgetprobtype (DDSIP_env, DDSIP_lp)) { status = CPXchgprobtype (DDSIP_env, DDSIP_lp, CPXPROB_MILP); if (status) { fprintf (stderr, "ERROR: Failed to change problem type (Restore) \n"); return status; } status = CPXchgctype (DDSIP_env, DDSIP_lp, DDSIP_bb->secvar, DDSIP_bb->secondindex, DDSIP_bb->sectype); if (status) { fprintf (stderr, "ERROR: Failed to change types of second-stage variables (Restore) \n"); return status; } } //Restore ctypes if solving was processed with relaxed first stage if (DDSIP_bb->DDSIP_step == solve && DDSIP_param->relax == 1) { status = CPXchgctype (DDSIP_env, DDSIP_lp, DDSIP_bb->firstvar, DDSIP_bb->firstindex, DDSIP_bb->firsttype); if (status) { fprintf (stderr, "ERROR: Failed to change types of first stage variables (Restore) \n"); return status; } } return status; }
int main (int argc, char *argv[]) { /* Declare and allocate space for the variables and arrays where we will store the optimization results including the status, objective value, maximum bound violation, variable values, and basis. */ int solnstat, solnmethod, solntype; double objval, maxviol; double *x = NULL; int *cstat = NULL; int *rstat = NULL; CPXENVptr env = NULL; CPXLPptr lp = NULL; int status = 0; int j; int cur_numrows, cur_numcols; char *basismsg; /* Check the command line arguments */ if (( argc != 3 ) || ( strchr ("cfg", 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 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_QP ) { fprintf (stderr, "Input file is not a QP. Exiting.\n"); goto TERMINATE; } /* Optimize the problem and obtain solution. */ switch (argv[2][0]) { case 'c': status = CPXsetintparam (env, CPXPARAM_SolutionTarget, CPX_SOLUTIONTARGET_OPTIMALCONVEX); if ( status ) goto TERMINATE; status = CPXqpopt (env, lp); if ( status ) { if ( status == CPXERR_Q_NOT_POS_DEF ) printf ("Problem is not convex. Use argument f to get local optimum " "or g to get global optimum.\n"); else fprintf (stderr, "Failed to optimize QP.\n"); goto TERMINATE; } break; case 'f': status = CPXsetintparam (env, CPXPARAM_SolutionTarget, CPX_SOLUTIONTARGET_FIRSTORDER); if ( status ) goto TERMINATE; status = CPXqpopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize QP.\n"); goto TERMINATE; } break; case 'g': status = CPXsetintparam (env, CPXPARAM_SolutionTarget, CPX_SOLUTIONTARGET_OPTIMALGLOBAL); if ( status ) goto TERMINATE; status = CPXqpopt (env, lp); if ( status ) { fprintf (stderr, "Failed to optimize noncvonex QP.\n"); goto TERMINATE; } break; default: break; } 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 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; } /* 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 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 CPLEXAddConstraint(LinEquation* InEquation) { int Status = 0; if (InEquation->ConstraintType != QUADRATIC && InEquation->ConstraintType != LINEAR) { FErrorFile() << "This constraint type is not supported in CPLEX: " << InEquation->ConstraintType << endl; FlushErrorFile(); return FAIL; } //First I check the number of rows. If it's larger than the index, then this constraint already exists and is only being changed int NumberRows = CPXgetnumrows (CPLEXenv, CPLEXModel); if (NumberRows <= InEquation->Index) { char* Sense = new char[1]; if (InEquation->EqualityType == EQUAL) { if (InEquation->QuadOne.size() > 0) { delete [] Sense; FErrorFile() << "Quadratic constraints cannot be equivalent constraints in CPLEX." << endl; FlushErrorFile(); return FAIL; } else { Sense[0] = 'E'; } } else if (InEquation->EqualityType == LESS) { Sense[0] = 'L'; } else if (InEquation->EqualityType == GREATER) { Sense[0] = 'G'; } else { delete [] Sense; FErrorFile() << "Unrecognized constraint type: " << InEquation->ConstraintType << endl; FlushErrorFile(); return FAIL; } double* Rhs = new double[1]; Rhs[0] = InEquation->RightHandSide; int* ColInd = NULL; int* RowInd = NULL; double* Coeff = NULL; if (InEquation->Variables.size() > 0) { ColInd = new int[int(InEquation->Variables.size())]; RowInd = new int[int(InEquation->Variables.size())]; Coeff = new double[int(InEquation->Variables.size())]; for (int i=0; i < int(InEquation->Variables.size()); i++) { Coeff[i] = InEquation->Coefficient[i]; RowInd[i] = 0; ColInd[i] = InEquation->Variables[i]->Index; } } if (InEquation->QuadOne.size() > 0) { if (CPXgetprobtype(CPLEXenv, CPLEXModel) == CPXPROB_LP) { Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_QP); } else if (CPXgetprobtype(CPLEXenv, CPLEXModel) == CPXPROB_MILP) { Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_MIQP); } int *QuadCol = new int[int(InEquation->QuadOne.size())]; int *QuadRow = new int[int(InEquation->QuadTwo.size())]; double *QuadCoeff = new double[int(InEquation->QuadCoeff.size())]; for (int i=0; i < int(InEquation->QuadOne.size()); i++) { QuadCol[i] = InEquation->QuadOne[i]->Index; QuadRow[i] = InEquation->QuadTwo[i]->Index; QuadCoeff[i] = InEquation->QuadCoeff[i]; } Status = CPXaddqconstr(CPLEXenv, CPLEXModel, int(InEquation->Variables.size()), int(InEquation->QuadOne.size()), Rhs[0], int(Sense[0]), ColInd, Coeff, QuadRow, QuadCol, QuadCoeff, NULL); delete [] QuadCol; delete [] QuadRow; delete [] QuadCoeff; } else if (InEquation->Variables.size() > 0) { string StrName = GetConstraintName(InEquation); char** Name = new char*; Name[0] = new char[StrName.length()+1]; strcpy(Name[0],StrName.data()); if ((InEquation->ConstraintMeaning.compare("chemical potential constraint") == 0) && (InEquation->Loaded == false) && (GetParameter("Check potential constraints feasibility").compare("1") == 0)) { Rhs[0] = InEquation->LoadedRightHandSide; Sense[0] = 'L'; } else if ((InEquation->ConstraintMeaning.compare("chemical potential constraint") == 0) && (InEquation->Loaded == false) && (InEquation->RightHandSide > 0.9*FLAG)){ Rhs[0] = FLAG; Sense[0] = 'L'; } Status = CPXaddrows(CPLEXenv, CPLEXModel, 0, 1, int(InEquation->Variables.size()), Rhs, Sense, RowInd, ColInd, Coeff, NULL, Name); delete [] Name[0]; delete [] Name; delete [] ColInd; delete [] RowInd; delete [] Coeff; } delete [] Rhs; delete [] Sense; if (Status) { FErrorFile() << "Failed to add constraint: " << InEquation->Index << endl; FlushErrorFile(); return FAIL; } } else { if (InEquation->QuadOne.size() > 0) { FErrorFile() << "Cannot change a quadratic constraint." << endl; FlushErrorFile(); return FAIL; } else { int NumberOfColumns = CPXgetnumcols(CPLEXenv, CPLEXModel); //First I reset all of the coefficients to zero for (int i=0; i < NumberOfColumns; i++) { Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, i, 0); if (Status) { FErrorFile() << "Failed to change constraint: " << InEquation->Index << endl; FlushErrorFile(); return FAIL; } } //Next I set all of the nonzero coefficients according to the input equation for (int i=0; i < int(InEquation->Variables.size()); i++) { Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, InEquation->Variables[i]->Index, InEquation->Coefficient[i]); if (Status) { FErrorFile() << "Failed to change constraint: " << InEquation->Index << endl; FlushErrorFile(); return FAIL; } } char* Sense = new char[1]; if (InEquation->ConstraintMeaning.compare("chemical potential constraint") == 0 && InEquation->Loaded == false) { Sense[0] = 'L'; Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, -1, InEquation->LoadedRightHandSide); Status = CPXchgsense (CPLEXenv, CPLEXModel, 1, &(InEquation->Index), Sense); } else { //Now I change the RHS of the constraint Status = CPXchgcoef (CPLEXenv, CPLEXModel, InEquation->Index, -1, InEquation->RightHandSide); //Also change the sense of the constraint if nec if (InEquation->EqualityType == EQUAL) { if (InEquation->QuadOne.size() > 0) { delete [] Sense; FErrorFile() << "Quadratic constraints cannot be equivalent constraints in CPLEX." << endl; FlushErrorFile(); return FAIL; } else { Sense[0] = 'E'; } } else if (InEquation->EqualityType == LESS) { Sense[0] = 'L'; } else if (InEquation->EqualityType == GREATER) { Sense[0] = 'G'; } else { delete [] Sense; FErrorFile() << "Unrecognized constraint type: " << InEquation->ConstraintType << endl; FlushErrorFile(); return FAIL; } Status = CPXchgsense (CPLEXenv, CPLEXModel, 1, &(InEquation->Index), Sense); if (Status) { FErrorFile() << "Failed to change constraint: " << InEquation->Index << endl; FlushErrorFile(); return FAIL; } } } } return SUCCESS; }
int CPLEXLoadObjective(LinEquation* InEquation, bool Max) { int NumCols = CPXgetnumcols(CPLEXenv, CPLEXModel); int Status = 0; if (Max) { CPXchgobjsen (CPLEXenv, CPLEXModel, CPX_MAX); } else { CPXchgobjsen (CPLEXenv, CPLEXModel, CPX_MIN); } int* Indeces = new int[NumCols]; double* Coeffs = new double[NumCols]; for (int i=0; i < NumCols; i++) { Indeces[i] = i; Coeffs[i] = 0; } for (int i=0; i < int(InEquation->Variables.size()); i++) { Coeffs[InEquation->Variables[i]->Index] = InEquation->Coefficient[i]; } Status = CPXchgobj(CPLEXenv, CPLEXModel, NumCols, Indeces, Coeffs); delete [] Indeces; delete [] Coeffs; if (Status) { cout << "Failed to set objective coefficients. " << endl; return FAIL; } if (InEquation->QuadOne.size() > 0) { if (CPXgetprobtype(CPLEXenv, CPLEXModel) == CPXPROB_LP) { Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_QP); } else if (CPXgetprobtype(CPLEXenv, CPLEXModel) == CPXPROB_MILP) { Status = CPXchgprobtype(CPLEXenv, CPLEXModel, CPXPROB_MIQP); } if (Status) { FErrorFile() << "Failed to change problem type." << endl; FlushErrorFile(); return FAIL; } for (int i=0; i < NumCols; i++) { for (int j=0; j < NumCols; j++) { Status = CPXchgqpcoef(CPLEXenv, CPLEXModel, i, j, 0); if (Status) { FErrorFile() << "Failed to change quadratic coefficient." << endl; FlushErrorFile(); return FAIL; } } } for (int i=0; i < int(InEquation->QuadOne.size()); i++) { Status = CPXchgqpcoef(CPLEXenv, CPLEXModel, InEquation->QuadOne[i]->Index, InEquation->QuadTwo[i]->Index, InEquation->QuadCoeff[i]); if (Status) { FErrorFile() << "Failed to change quadratic coefficient." << endl; FlushErrorFile(); return FAIL; } } } return SUCCESS; }