Beispiel #1
0
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;
}
Beispiel #2
0
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;
    int      *qmatbeg = NULL;
    int      *qmatcnt = NULL;
    int      *qmatind = NULL;
    double   *qmatval = NULL;

    /* Declare pointers for the variables that will contain the data
       for the constraint that cuts off certain local optima. */

    int      numrows_extra;
    int      numnnz_extra;
    double   *rhs_extra = NULL;
    char     *sense_extra = NULL;
    int      *rmatbeg = NULL;
    int      *rmatind = NULL;
    double   *rmatval = NULL;
    int      rowind[1];

    /* Declare and allocate space for the variables and arrays where we
       will store the optimization results including the status, objective
       value, variable values, dual values, row slacks and variable
       reduced costs. */

    int      solstat;
    double   objval;

    CPXENVptr     env = NULL;
    CPXLPptr      lp = NULL;
    int           status;

    /* 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, &qmatbeg, &qmatcnt,
                             &qmatind, &qmatval,
                             &numrows_extra, &numnnz_extra,
                             &rhs_extra, &sense_extra,
                             &rmatbeg, &rmatind, &rmatval);
    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 problem.\n");
        goto TERMINATE;
    }

    /* Now copy the LP part of 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;
    }

    status = CPXcopyquad (env, lp, qmatbeg, qmatcnt, qmatind, qmatval);
    if ( status ) {
        fprintf (stderr, "Failed to copy quadratic matrix.\n");
        goto TERMINATE;
    }


    /* When a non-convex objective function is present, CPLEX will
       return error CPXERR_Q_NOT_POS_DEF unless the parameter
       CPXPARAM_OptimalityTarget is set to accept first-order optimal
       solutions.  */
    status = CPXsetintparam (env, CPXPARAM_OptimalityTarget,
                             CPX_OPTIMALITYTARGET_FIRSTORDER);
    if ( status ) goto TERMINATE;

    /* Optimize the problem and obtain solution. */

    status = optimize_and_report(env, lp, &solstat, &objval);
    if ( status ) goto TERMINATE;


    /* Add a constraint to cut off the solution at (-1, 1) */

    status = CPXaddrows (env, lp, 0, numrows_extra, numnnz_extra,
                         rhs_extra, sense_extra,
                         rmatbeg, rmatind, rmatval,
                         NULL, NULL);
    if ( status ) goto TERMINATE;

    status = optimize_and_report(env, lp, &solstat, &objval);
    if ( status ) goto TERMINATE;


    /* Reverse the sense of the new constraint to cut off the solution at (1, 1) */

    rowind[0] = CPXgetnumrows (env, lp) - 1;
    status    = CPXchgsense (env, lp, 1, rowind, "L");
    if ( status ) goto TERMINATE;

    status = optimize_and_report(env, lp, &solstat, &objval);
    if ( status ) goto TERMINATE;

    /* Finally, write a copy of the problem to a file. */

    status = CPXwriteprob (env, lp, "indefqpex1.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 **) &qmatbeg);
    free_and_null ((char **) &qmatcnt);
    free_and_null ((char **) &qmatind);
    free_and_null ((char **) &qmatval);
    free_and_null ((char **) &rhs_extra);
    free_and_null ((char **) &sense_extra);
    free_and_null ((char **) &rmatbeg);
    free_and_null ((char **) &rmatind);
    free_and_null ((char **) &rmatval);

    return (status);

}  /* END main */