Exemple #1
0
static int
populatebycolumn (CPXENVptr env, CPXLPptr lp)
{
   int      status    = 0;
   double   obj[NUMCOLS];
   double   lb[NUMCOLS];
   double   ub[NUMCOLS];
   char     *colname[NUMCOLS];
   int      matbeg[NUMCOLS];
   int      matind[NUMNZ];
   double   matval[NUMNZ];
   double   rhs[NUMROWS];
   char     sense[NUMROWS];
   char     *rowname[NUMROWS];

   /* To build the problem by column, create the rows, and then 
      add the columns. */

   status = CPXchgobjsen (env, lp, CPX_MAX);  /* Problem is maximization */
   if ( status )  goto TERMINATE;

   /* Now create the new rows.  First, populate the arrays. */

   rowname[0] = "c1";
   sense[0]   = 'L';
   rhs[0]     = 20.0;

   rowname[1] = "c2";
   sense[1]   = 'L';
   rhs[1]     = 30.0;

   status = CPXnewrows (env, lp, NUMROWS, rhs, sense, NULL, rowname);
   if ( status )   goto TERMINATE;

   /* Now add the new columns.  First, populate the arrays. */

       obj[0] = 1.0;      obj[1] = 2.0;           obj[2] = 3.0;

    matbeg[0] = 0;     matbeg[1] = 2;          matbeg[2] = 4;
      
    matind[0] = 0;     matind[2] = 0;          matind[4] = 0;
    matval[0] = -1.0;  matval[2] = 1.0;        matval[4] = 1.0;
 
    matind[1] = 1;     matind[3] = 1;          matind[5] = 1;
    matval[1] = 1.0;   matval[3] = -3.0;       matval[5] = 1.0;

        lb[0] = 0.0;       lb[1] = 0.0;           lb[2]  = 0.0;
        ub[0] = 40.0;      ub[1] = CPX_INFBOUND;  ub[2]  = CPX_INFBOUND;

   colname[0] = "x1"; colname[1] = "x2";      colname[2] = "x3";

   status = CPXaddcols (env, lp, NUMCOLS, NUMNZ, obj, matbeg, matind,
                        matval, lb, ub, colname);
   if ( status )  goto TERMINATE;

TERMINATE:

   return (status);

}  /* END populatebycolumn */
Exemple #2
0
void CplexSolver::run() {
	CPXchgobjsen(_env, _prob, _is_minimize ? CPX_MIN : CPX_MAX);
	if (_is_mip) {
		CPXsetintparam(_env, CPX_PARAM_SOLUTIONTARGET, CPX_SOLUTIONTARGET_OPTIMALGLOBAL);
		CPXmipopt(_env, _prob);
	} else
		CPXlpopt(_env, _prob);
}
Exemple #3
0
//*******************************************************************
CPXLPptr CSolver::LoadProblem(bool bMip) {


   m_lp = CPXcreateprob (m_env, &m_status, m_pszProbname);

   CPXchgobjsen (m_env, m_lp, m_nObjSense );

   if ( m_status != 0 ) {
        CPXgeterrorstring(m_env, m_status, m_error );
        return 0;
   }


   if ( m_status != 0 ) {
        CPXgeterrorstring(m_env, m_status, m_error );
        return 0;
   }

   m_status = CPXnewrows( m_env, m_lp, m_nRhsItems, m_pRhs,
                          m_pRhsSense, 0, m_rname);

   if ( m_status != 0 ) {
        CPXgeterrorstring(m_env, m_status, m_error );
        return 0;
   }

   if (!bMip)
     m_status = CPXnewcols( m_env, m_lp, m_nObjItems, m_pObj,
                            m_pBdl, m_pBdu, NULL, m_cname);
   else
     m_status = CPXnewcols( m_env, m_lp, m_nObjItems, m_pObj,
                            m_pBdl, m_pBdu, m_pCtype, m_cname);

   if ( m_status != 0 ) {
        CPXgeterrorstring(m_env, m_status, m_error );
        return 0;
   }

   m_status = CPXchgcoeflist(m_env, m_lp, m_nCoefItems,
                             m_pRowNdx, m_pColNdx, m_pCoef);
   if ( m_status != 0 ) {
        CPXgeterrorstring(m_env, m_status, m_error );
        return 0;
   }

   FreeMemory();

   return m_lp;

}
Exemple #4
0
// Starts the CPLEX environment
CPLEX cplex_start() {
  int status;
  CPXENVptr env = CPXopenCPLEX(&status);
  
  // disable screen solution and data consistency checking for speed
  CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_OFF);
  CPXsetintparam(env, CPX_PARAM_DATACHECK, CPX_OFF);
  
  CPXLPptr lp = CPXcreateprob(env, &status, "tsp");
  CPXchgprobtype(env, lp, CPXPROB_MILP); // mixed integer problem
  CPXchgobjsen(env, lp, CPX_MIN); // objective is minimization
  
  //CPXwriteprob(env, lp, "problem.lp", "LP");
  
  CPLEX cplex = {env, lp, &status};
  
  return cplex;
}
Exemple #5
0
void CplexSolver::write(std::string const & fileName) const {
	CPXchgobjsen(_env, _prob, _is_minimize ? CPX_MIN : CPX_MAX);
	CPXwriteprob(_env, _prob, fileName.c_str(), "LP");
}
Exemple #6
0
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;
}
Exemple #7
0
 int main(int argc, char **argv)
 {
    int status = 0;
    CPXENVptr env = NULL;
    CPXLPptr lp = NULL;

    double obj[NUMCOLS];
    double lb[NUMCOLS];
    double ub[NUMCOLS];
    double x[NUMCOLS];
    int rmatbeg[NUMROWS];
    int rmatind[NUMNZ];
    double rmatval[NUMNZ];
    double rhs[NUMROWS];
    char sense[NUMROWS];
    char ctype[NUMCOLS];

    int solstat;
    double objval;

    env = CPXopenCPLEX (&status);


    CPXsetintparam(env, CPX_PARAM_MIPCBREDLP, CPX_OFF);
    CPXsetintparam(env, CPX_PARAM_PRELINEAR, CPX_OFF);
    /* Turn on traditional search for use with control callbacks */

    // status = CPXsetintparam (env, CPXPARAM_MIP_Strategy_Search,
    //                        CPX_MIPSEARCH_TRADITIONAL);


    lp = CPXcreateprob(env, &status, "lpex1");
    //CPXchgprobtype(env, lp, CPXPROB_MILP);

    CPXchgobjsen (env, lp, CPX_MAX);

    status = CPXsetlazyconstraintcallbackfunc (env, callback,
                                      NULL);


    lb[0] = 0.0;
    ub[0] = 40.0;

    lb[1] = 0.0;
    ub[1] = CPX_INFBOUND;

    lb[2] = 0.0;
    ub[2] = CPX_INFBOUND;

    obj[0] = 1.0;
    obj[1] = 2.0;
    obj[2] = 3.0;

    status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, NULL);

    rmatbeg[0] = 0;
    rmatind[0] = 0;     rmatind[1] = 1;     rmatind[2] = 2;
    rmatval[0] = -1.0;  rmatval[1] = 1.0;   rmatval[2] = 1.0;   sense[0] = 'L';     rhs[0] = 20.0;

    rmatbeg[1] = 3;
    rmatind[3] = 0;     rmatind[4] = 1;     rmatind[5] = 2;
    rmatval[3] = 1.0;   rmatval[4] = -3.0;  rmatval[5] = 1.0;   sense[1] = 'L';     rhs[1] = 30.0;

    ctype[0] = 'I'; ctype[1] = 'C'; ctype[2] = 'I';

    // status = CPXaddusercuts (env, lp, cutcnt, cutnzcnt, cutrhs,
    //                      cutsense, cutbeg, cutind, cutval, NULL);
    //status = CPXaddusercuts(env, lp, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL );

    status = CPXaddrows (env, lp, 0, NUMROWS, NUMNZ, rhs, sense, rmatbeg, rmatind, rmatval, NULL, NULL);
    status = CPXcopyctype (env, lp, ctype);

    // cuts
    int cmatbeg[1] = {0};
    int cmatind[3] = {0,1,2};
    double cmatval[3] = {1,0,0};
    char csense[1] = {'L'};
    double crhs[1] = {20};

    //CPXaddusercuts doesnt work for some f*****g reason

    //status = CPXaddlazyconstraints(env, lp, 1, 3, crhs, csense, cmatbeg, cmatind, cmatval, NULL );
    if ( status ) {
      fprintf (stderr, "Some f*****g error, status = %d.\n", status);
   }



    status = CPXmipopt (env, lp);



   /* Write the output to the screen. */
    // solstat = CPXgetstat (env, lp);
    // printf ("\nSolution status = %d\n", solstat);
    // status = CPXgetobjval (env, lp, &objval);
    // printf ("Solution value  = %f\n\n", objval);

    status = CPXsolution (env, lp, &solstat, &objval, x, NULL, NULL, NULL);
    printf ("\nSolution status = %d\n", solstat);
    printf ("Solution value = %f\n", objval);
    printf ("Solution= [%f, %f, %f]\n\n", x[0], x[1], x[2]);

    printf("This is great stuff\n");


    return 0;
 }
inline int
populatebynonzero (CPXENVptr env, CPXLPptr lp, int m, int n, int timeout,
		sched_nodeinfo_t *node_array, solver_job_list_t *job_array)
{
	int NUMCOLS = n * (2 * m + 2);
	int NUMROWS = n * 3 + m * 2 + m * n * 2;
	int NUMNZ = 2 * n * (4 * m + 1); 
	int NZc = 0; /* nonzero counter */
	
	int status = 0;
	double *obj = NULL;
	obj = (double*)malloc(NUMCOLS * sizeof(double));
	double *lb = (double*)malloc(NUMCOLS * sizeof(double));
	double *ub = (double*)malloc(NUMCOLS * sizeof(double));
	double *rhs = (double*)malloc(NUMROWS * sizeof(double));
	char *sense = (char*)malloc(NUMROWS * sizeof(char));
	/*
	char **colname = (char**)malloc(NUMCOLS * sizeof(char*));
	char **rowname = (char**)malloc(NUMROWS * sizeof(char[10]));
	char str[10];
	*/
	int *rowlist = (int*)malloc(NUMNZ * sizeof(int));
	int *collist = (int*)malloc(NUMNZ * sizeof(int));
	double *vallist = (double*)malloc(NUMNZ * sizeof(double));
	int i, j, d;
	/*int rc = 0, cc = 0;*/

	CPXchgobjsen (env, lp, CPX_MAX);  /* Problem is maximization */

	/* row definitions */
	
	for (j = 0; j < n; j++) {
		sense[j] = 'E';
		rhs[j] = 0.0;
		/*debug3("cpueq row counter: %d, no: %d",rc++, j);*/
		/*sprintf(str,"CPUeq_%d",j+1);
		rowname[j] = str;*/
	}
	for (i = 0; i < m; i++) {
		sense[n + i] = 'L';
		rhs[n + i] = (double)(node_array[i].rem_cpus);
		/*sprintf(str,"NODEeq_%d",i+1);
		rowname[n + i] = str;*/
		/*debug3("nodeeq row counter: %d, no: %d",rc++, n+i);*/

		sense[n + m + i] = 'L';
		rhs[n + m + i] = (double)(node_array[i].rem_gpus);
		/*debug3("gpueq row counter: %d, no: %d",rc++, n+m+i);*/
		/*sprintf(str,"GPUeq_%d",i+1);
		rowname[n + m + i] = str;*/
	}

	for (j = 0; j < n; j++) {
		for (i = 0; i < m; i++) {
			d = n + 2 * m + j * m * 2 + i * 2;
			sense[d] = 'L';
			rhs[d] = 0.0;
			/*debug3("t_i_j_le row counter: %d, no: %d",rc++,d);*/
			/*sprintf(rowname[d],"t_%d_%d_LE",j+1,i+1);
			rowname[d] = str;*/
			sense[d + 1] = 'G';
			rhs[d + 1] = 0.0;
			/*debug3("t_i_j_ge row counter: %d, no: %d",rc++,d+1);*/
			/*sprintf(rowname[d+1],"t_%d_%d_GE",j+1,i+1);
			rowname[d+1] = str;*/
		}
	}

	for (j = 0; j < n; j++) {
		sense[n + 2 * m + n * m * 2 + j * 2] = 'L';
		rhs[n + 2 * m + n * m * 2 + j * 2] = 0.0;
		/*debug3("minmax row counter: %d, no: %d",rc++,n + 2 * m + n * m * 2 + j * 2);*/
		sense[n + 2 * m + n * m * 2 + j * 2 + 1] = 'G';
		rhs[n + 2 * m + n * m * 2 + j * 2 + 1] = 0.0;
		/*debug3("minmax row counter: %d, no: %d",rc++,n + 2 * m + n * m * 2 + j * 2 + 1);*/
		/*sprintf(str,"minmax_%d",j+1);
		rowname[n + 4 * m + n * m * 2 + j] = str;*/
	}

	status = CPXnewrows (env, lp, NUMROWS, rhs, sense, NULL, NULL);
	if ( status ) goto TERMINATE;

	/*debug3("ROWS: %d, column def starting",NUMROWS);*/
	/* column definitions */	
	for (j = 0; j < n; j++) {
		/*sprintf(str, "s_%d",j+1);
		colname[j] = str;*/
		lb[j] = 0.0;
		ub[j] = 1.0;
		/*debug3("s_j col counter: %d, no: %d",cc++,j);*/
	}

	/*debug3("defined s_j");*/
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			/*sprintf(str, "x_%d_%d",i+1,j+1);
			colname[(i + 1) * n + j] = str;*/
			lb[(i + 1) * n + j] = 0.0;
			ub[(i + 1) * n + j] = CPX_INFBOUND;
			/*debug3("x_i_j col counter: %d, no: %d",cc++,(i+1)*n+j);*/
		}
	}
	/*debug3("defined x_i_j");*/

	for (j = 0; j < n; j++) {
		/*sprintf(str, "c_%d",j+1);
		colname[n * (m + 1) + j] = str;*/
		/* min_nodes_j <= c_j <= max_nodes_j */
		lb[n * (m + 1) + j] = (m + 1) * (job_array[j].min_nodes);
		ub[n * (m + 1) + j] = (m + 1) * (job_array[j].max_nodes);
		/*debug3("c_j col counter: %d, no: %d",cc++,n*(m+1)+j);*/
	}
	/*debug3("defined c_j");*/

	for (j = 0; j < n; j++) {
		for (i = 0; i < m; i++) {
			/*sprintf(str, "t_%d_%d",j+1,i+1);
			colname[n * (m + 2) + j * m + i] = str;*/
			lb[n * (m + 2) + j * m + i] = 0.0;
			ub[n * (m + 2) + j * m + i] = 1.0;
			/*debug3("t_i_j col counter: %d, no: %d",cc++,n*(m+2)+j*m+i);*/
		}
	}
	/*debug3("defined t_i_j");*/
	
	for (j = 0; j < NUMCOLS; j++) {
		obj[j] = 0;
	}
	for (j = 0; j < n; j++) {
		obj[j] = (job_array[j].priority);
		obj[n * (m + 1) + j] = (-1.0)*(job_array[j].priority);
	}

	status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, NULL);
	if ( status )  goto TERMINATE;

	/*debug3("constraint coefficients");*/
	/* constraints */
	/* sum over nodes should be equal to job's required cpu */
	/* sum_i(x_ij) = r_j * s_j */
	for (j = 0; j < n; j++) {
		for (i = 0; i < m; i++) {
			rowlist[NZc] = j;			
			vallist[NZc] = 1.0;
			collist[NZc++] = (i + 1) * n + j;
			/*debug3("con1 collist %d",(i + 1) * n + j);*/
		}
		rowlist[NZc] = j;
		vallist[NZc] = (int)(-job_array[j].min_cpus);
		collist[NZc++] = j;
		/*debug3("con1 collist %d",j);*/
	}	
	/* nzc = m*n+n */

	/* sum over jobs for cpu should be available on nodes */
	/* sum_j(x_ij) <= R_i */
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			/*debug3("con2 collist %d",(i + 1) * n + j);*/
			rowlist[NZc] = n + i;
			vallist[NZc] = 1.0;
			collist[NZc++] = (i + 1) * n + j;
		}
	}
	/* nzc = 2*m*n+n */

	/* sum over jobs for gpu should be available on nodes */
	/* sum_j(t_ji * g_j) <= G_i */
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			rowlist[NZc] = n + m + i;
			vallist[NZc] = job_array[j].gpu;
			collist[NZc++] = n * (m + 2) + j * m + i;
			/*debug3("con3 collist %d",n * (m + 2) + j * m + i);*/
		}
	}
	/* nzc = 3*m*n+n */

	status = CPXchgcoeflist (env, lp, NZc, rowlist, collist, vallist);   
	if ( status )  goto TERMINATE;

TERMINATE:
	free_and_null ((char **) &obj);
	free_and_null ((char **) &lb);
	free_and_null ((char **) &ub);
	free_and_null ((char **) &rhs);
	free_and_null ((char **) &sense);
	return (status);
} 
static int
populatebynonzero (CPXENVptr env, CPXLPptr lp)
{
   int      status    = 0;
   double   obj[NUMCOLS];
   double   lb[NUMCOLS];
   double   ub[NUMCOLS];
   char     *colname[NUMCOLS];
   double   rhs[NUMROWS];
   char     sense[NUMROWS];
   char     *rowname[NUMROWS];
   int      rowlist[NUMNZ];
   int      collist[NUMNZ];
   double   vallist[NUMNZ];

   status = CPXchgobjsen (env, lp, CPX_MAX);  /* Problem is maximization */
   if ( status )  goto TERMINATE;

   /* Now create the new rows.  First, populate the arrays. */

   rowname[0] = "c1";
   sense[0]   = 'L';
   rhs[0]     = 20.0;

   rowname[1] = "c2";
   sense[1]   = 'L';
   rhs[1]     = 30.0;

   status = CPXnewrows (env, lp, NUMROWS, rhs, sense, NULL, rowname);
   if ( status )   goto TERMINATE;

   /* Now add the new columns.  First, populate the arrays. */

       obj[0] = 1.0;      obj[1] = 2.0;           obj[2] = 3.0;

        lb[0] = 0.0;       lb[1] = 0.0;           lb[2]  = 0.0;
        ub[0] = 40.0;      ub[1] = CPX_INFBOUND;  ub[2]  = CPX_INFBOUND;

   colname[0] = "x1"; colname[1] = "x2";      colname[2] = "x3";

   status = CPXnewcols (env, lp, NUMCOLS, obj, lb, ub, NULL, colname);
   if ( status )  goto TERMINATE;

   /* Now create the list of coefficients */

   rowlist[0] = 0;   collist[0] = 0;   vallist[0] = -1.0;
   rowlist[1] = 0;   collist[1] = 1;   vallist[1] = 1.0;
   rowlist[2] = 0;   collist[2] = 2;   vallist[2] = 1.0;
   rowlist[3] = 1;   collist[3] = 0;   vallist[3] = 1.0;
   rowlist[4] = 1;   collist[4] = 1;   vallist[4] = -3.0;
   rowlist[5] = 1;   collist[5] = 2;   vallist[5] = 1.0;

   status = CPXchgcoeflist (env, lp, 6, rowlist, collist, vallist);
   
   if ( status )  goto TERMINATE;

TERMINATE:

   return (status);

}  /* END populatebynonzero */
Exemple #10
0
// initialize the objective function
int cplex_solver::begin_objectives(void) { 
	// Set Problem as a minimization problem
	CPXchgobjsen (env, lp, CPX_MIN);
	return 0;
}
Exemple #11
0
/* This function creates the following model:
 *   Minimize
 *    obj: x1 + x2 + x3 + x4 + x5 + x6
 *   Subject To
 *    c1: x1 + x2      + x5      = 8
 *    c2:           x3 + x5 + x6 = 10
 *    q1: [ -x1^2 + x2^2 + x3^2 ] <= 0
 *    q2: [ -x4^2 + x5^2 ] <= 0
 *   Bounds
 *    x2 Free
 *    x3 Free
 *    x5 Free
 *   End
 * which is a second order cone program in standard form.
 * The function returns a true value on success and false on error.
 * The function also sets up *cone_p as follows:
 * (*cone_p)[j] >= 0              Column j is contained in a cone constraint
 *                                and is the cone head variable of that
 *                                constraint. The index of the respective
 *                                quadratic constraint is given by (*cone_p)[j].
 * (*cone_p)[j] = NOT_CONE_HEAD   Column j is contained in a cone constraint
 *                                but is not the cone head variable of that
 *                                constraint.
 * (*cone_p)[j] = NOT_IN_CONE     Column j is not contained in any cone
 *                                constraint.
 */
static int
createmodel (CPXENVptr env, CPXLPptr lp, int **cone_p)
{
   /* Column data. */
   static double const obj[]        = {  1.0,  1.0,  1.0,  1.0,  1.0,  1.0 };
   static double const lb[]         = {  0.0, -INF, -INF,  0.0, -INF,  0.0 };
   static double const ub[]         = {  INF,  INF,  INF,  INF,  INF,  INF };
   static char const *const cname[] = { "x1", "x2", "x3", "x4", "x5", "x6" };

   /* Row data. */
   static double const rval[]       = { 1.0, 1.0, 1.0,    1.0, 1.0, 1.0 };
   static int const rind[]          = {   0,   1,   4,      2,   4,   5 };
   static int const rbeg[]          = {   0,                3           };
   static double const rhs[]        = { 8.0,             10.0           };
   static char const sense[]        = { 'E',              'E'           };
   static char const *const rname[] = { "c1",             "c2"          };

   /* Data for second order cone constraints. */
   static double const qval[]  = { -1.0, 1.0, 1.0 }; /* Same for all Q cons. */
   static double const qrhs    = 0.0;                /* Same for all Q cons. */
   static char const qsense    = 'L';                /* Same for all Q cons. */
   static int const qind1[] = { 0, 1, 2 };
   static int const qind2[] = { 3, 4 };

   int status;
   int ok = 0;
   int *cone = NULL;

   CPXCHANNELptr errc;

   /* Get the channel for printing error messages. */
   if ( (status = CPXgetchannels (env, NULL, NULL, &errc, NULL)) != 0 )
      goto TERMINATE;

   cone = malloc ((sizeof (obj) / sizeof (obj[0])) * sizeof (*cone));
   if ( cone == NULL ) {
      CPXmsg (errc, "Out of memory!\n");
      goto TERMINATE;
   }

   status = CPXchgobjsen (env, lp, CPX_MIN);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXnewcols (env, lp, sizeof (obj) / sizeof (obj[0]),
                        obj, lb, ub, NULL, (char **)cname);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXaddrows (env, lp, 0, sizeof (rhs) / sizeof (rhs[0]),
                        sizeof (rval) / sizeof (rval[0]), rhs, sense,
                        rbeg, rind, rval, NULL, (char **)rname);
   if ( status != 0 )
      goto TERMINATE;

   status = CPXaddqconstr (env, lp, 0, sizeof (qind1) / sizeof (qind1[0]),
                           qrhs, qsense, NULL, NULL,
                           qind1, qind1, qval, "q1");
   if ( status != 0 )
      goto TERMINATE;
   cone[0] = 0;
   cone[1] = NOT_CONE_HEAD;
   cone[2] = NOT_CONE_HEAD;
   status = CPXaddqconstr (env, lp, 0, sizeof (qind2) / sizeof (qind2[0]),
                           qrhs, qsense, NULL, NULL,
                           qind2, qind2, qval, "q2");
   if ( status != 0 )
      goto TERMINATE;
   cone[3] = 1;
   cone[4] = NOT_CONE_HEAD;

   cone[5] = NOT_IN_CONE;

   ok = 1;
 TERMINATE:
   if ( !ok )
      free (cone);

   *cone_p = cone;

   return ok;
}
Exemple #12
0
long GenModelCplex::CreateModel()
{
    if(!binit)
        return ThrowError("CreateModel() not available : Problem not initialized yet");
    CplexData* d = (CplexData*)solverdata;
    int status = 0;
    d->nc = nc;
    d->nc = nc;
    d->onc = nc;
    d->onr = nr;

    if(boolParam.count("maximize") > 0 && boolParam["maximize"])
        CPXchgobjsen (d->env, d->lp, CPX_MAX);
    else
        CPXchgobjsen (d->env, d->lp, CPX_MIN);
    d->lrhs = new double[nr];
    d->urhs = new double[nr];
    d->sense = new char[nr];
    d->ub = new double[nc];
    d->lb = new double[nc];
    d->obj = new double[nc];
    d->type = new char[nc];
    d->mat_r = new int[nz];
    d->mat_c = new int[nz];
    d->mat_v = new double[nz];
    d->cname = new char*[nc];
    d->rname = new char*[nr];


    nz=0;
    for(unsigned long i = 0; i < nr; i++)
    {
        d->rname[i] = new char[consts[i].name.length()+1];
        snprintf(d->rname[i], consts[i].name.length()+1, "%s", consts[i].name.c_str());
        //printf("%ld %s: ", i, consts[i].name.c_str());
        for(unsigned long j = 0; j < consts[i].nz; j++)
        {
            d->mat_r[nz] = i;
            d->mat_c[nz] = consts[i].cols[j];
            d->mat_v[nz] = consts[i].coefs[j];
            //if(i >= 198)
                //printf("(%ld,%ld(%s),%f) ", d->mat_r[nz], d->mat_c[nz], vars.name[d->mat_c[nz]].c_str(), d->mat_v[nz]);
            nz++;
        }

        if(consts[i].lrhs == numeric_limits<double>::infinity())
            d->lrhs[i] = CPX_INFBOUND;
        else if(consts[i].lrhs == -numeric_limits<double>::infinity())
            d->lrhs[i] = -CPX_INFBOUND;
        else
            d->lrhs[i] = consts[i].lrhs;
        if(consts[i].urhs == numeric_limits<double>::infinity())
            d->urhs[i] = CPX_INFBOUND;
        else if(consts[i].urhs == -numeric_limits<double>::infinity())
            d->urhs[i] = -CPX_INFBOUND;
        else
            d->urhs[i] = consts[i].urhs-consts[i].lrhs;
        d->sense[i] = consts[i].sense;
    //	printf("%ld/%ld -> %c\n", i, nr, d->sense[i]);
    }
    for(unsigned long i = 0; i < nc; i++)
    {
        d->cname[i] = new char[vars.name[i].length()+1];
        snprintf(d->cname[i], vars.name[i].length()+1, "%s", vars.name[i].c_str());
        d->obj[i] = vars.obj[i];
        if(vars.ub[i] == numeric_limits<double>::infinity())
            d->ub[i] = CPX_INFBOUND;
        else if(vars.ub[i] == -numeric_limits<double>::infinity())
            d->ub[i] = -CPX_INFBOUND;
        else
            d->ub[i] = vars.ub[i];
        if(vars.lb[i] == numeric_limits<double>::infinity())
            d->lb[i] = CPX_INFBOUND;
        else if(vars.lb[i] == -numeric_limits<double>::infinity())
            d->lb[i] = -CPX_INFBOUND;
        else
            d->lb[i] = vars.lb[i];
        d->type[i] = vars.type[i];

        //printf("%ld (%s) -> %f %f %f %c\n", i, vars.name[i].c_str(), d->obj[i], d->lb[i], d->ub[i], d->type[i]);
    }
    status = CPXnewrows (d->env, d->lp, nr, d->lrhs, d->sense, d->urhs, d->rname);
    if ( status )
    {
        char  errmsg[1024];
        fprintf (stderr, "Could not create new rows.\n");
        CPXgeterrorstring (d->env, status, errmsg);
        fprintf (stderr, "%s", errmsg);
        return 1;
    }
    //else
        //printf("Row added!\n");

    if(boolParam.count("mip") > 0 && boolParam["mip"])
        status = CPXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, d->type, d->cname);
    else
        status = CPXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, NULL, NULL);
    if ( status )
    {
        char  errmsg[1024];
        fprintf (stderr, "Could not create new cols.\n");
        CPXgeterrorstring (d->env, status, errmsg);
        fprintf (stderr, "%s", errmsg);
        return 1;
    }
    //status = CPXnewcols (env, lp, nc, obj, lb, ub, NULL, colname);
    if ( status )
        return 1;
    //else
        //printf("Col added!\n");
    status = CPXchgcoeflist (d->env, d->lp, nz, d->mat_r, d->mat_c, d->mat_v);
    if ( status )
        return 1;

    vector<long>::iterator iti;
    vector<long>::iterator itj = vars.qj.begin();
    vector<double>::iterator itv = vars.qobj.begin();

    vector<vector<pair<int,double> > > qptemp;
    qptemp.resize(nc);
    int* qpbeg = NULL;
    int* qpnum = NULL;
    int* qpind = NULL;
    double* qpv = NULL;
    int qpnz = 0;

    if(!vars.qi.empty())
    {
        boolParam["qp"] = true;
        qpbeg = new int[nc];
        qpnum = new int[nc];
    }
    if(boolParam.count("qp_mat") == 0 || boolParam["qp_mat"])
    {
        for(iti = vars.qi.begin(); iti != vars.qi.end(); iti++, itj++, itv++)
        {
            qptemp[*iti].push_back(pair<int, double>(*itj,*itv));
            qpnz++;
            if(*iti != *itj)
            {
                qptemp[*itj].push_back(pair<int, double>(*iti,*itv));
                qpnz++;
            }
        }
        if(!vars.qi.empty())
        {
            qpv = new double[qpnz];
            qpind = new int[qpnz];
            
            qpnz=0;
            for(int i = 0; i < int(nc); i++)
            {
                qpbeg[i] = qpnz;
                qpnum[i] = int(qptemp[i].size());
                for(int j = 0; j < int(qptemp[i].size()); j++)
                {
                    qpind[qpnz] = qptemp[i][j].first;
                    qpv[qpnz] = 2.0*qptemp[i][j].second;
                    qpnz++;
                }
            }
            status = CPXcopyquad(d->env, d->lp, qpbeg, qpnum, qpind, qpv);
            delete[] qpbeg;
            delete[] qpnum;
            delete[] qpind;
            delete[] qpv;
        }
        if ( status )
        {
            printf("QP problem!\n");
            return 1;
        }
    }
    //else
        //printf("Coefs added!\n");
    bcreated = true;

    return 0;
}
Exemple #13
0
int cg_solver(int m, MyRow* rows)
{
   CPXENVptr     env = NULL;
   CPXLPptr      model = NULL;
   int           status = 0;
   int           error = 0;
   int           i, j;
   int           cur_numrows, cur_numcols;
   int           n_cuts, cut;

   int       solstat;
   double    objval;
   double   *x;
   double   *z;
   int      *cstat;
 
   int      n0 = rows[0].n;      
   int      n1 = rows[0].n+m-1;  /// One slack variable for constraint
   int      h = (m-1)*n0 + m-1;  /// Number of nonzeros

   double   obj[n1];

   double   rhs[m-1];    /// The first row is for the cost vector
   char     sense[m-1];

   int      jnd[h];
   int      ind[h];
   double   val[h];

   int      idx = 0;

   int*     rmatbeg;
   int*     rmatind;
   double*  rmatval;
   double*  b_bar;
   char*    gc_sense;
   double*  gc_rhs;

   /// Create environment
   env = CPXopenCPLEX (&status);
   if ( env == NULL ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      fprintf (stderr, "Could not open CPLEX environment. Status: %d\n", status);
      CPXgeterrorstring (env, status, errmsg);
      fprintf (stderr, "%s", errmsg);
      goto QUIT;
   }

   /// Disable presolve
   POST_CMD( CPXsetintparam (env, CPX_PARAM_PREIND, CPX_OFF) );
   
   /// Create problem
   model = CPXcreateprob (env, &error, "gomory");
   if (error) goto QUIT;

   /// Minimization problem
   POST_CMD( CPXchgobjsen (env, model, CPX_MIN) );
   
   /// Add rows (remember first row is cost vector)
   for ( i = 0; i < m-1; ++i ) {
      sense[i]='E';
      rhs[i] = rows[i+1].rhs;
   }
   POST_CMD( CPXnewrows(env, model, m-1, rhs, sense, NULL, NULL) );
   
   /// Add problem variables 
   for ( j = 0; j < n0; ++j ) 
      obj[j] = rows[0].lhs[j];
   /// Add slack variables 
   for ( j = n0; j < n1; ++j ) 
      obj[j] = 0;
   POST_CMD( CPXnewcols(env, model, n1, obj, NULL, NULL, NULL, NULL) );

   /// Write the full matrix A into the LP (WARNING: should use only nonzeros entries)
   for ( i = 1; i < m; ++i ) {
      for ( j = 0; j < n0; ++j ) {
         jnd[idx] = i-1;
         ind[idx] = rows[i].ind[j];
         val[idx] = rows[i].lhs[j];
         idx++;
      }
      /// Add a slack variable per constraint
      jnd[idx] = i-1;
      ind[idx] = n0+i-1;
      val[idx] = 1.0;
      idx++;
   }
   POST_CMD( CPXchgcoeflist(env, model, idx, jnd, ind, val) );

   /// Optimize the problem
   POST_CMD( CPXlpopt(env, model) );

   /// Check the results
   cur_numrows = CPXgetnumrows (env, model);
   cur_numcols = CPXgetnumcols (env, model);

   x =  (double *) malloc (cur_numcols * sizeof(double));
   z =  (double *) malloc (cur_numcols * sizeof(double));
   cstat = (int *) malloc (cur_numcols * sizeof(int));

   b_bar = (double *) malloc (cur_numrows * sizeof(double));

   POST_CMD( CPXsolution (env, model, &solstat, &objval, x, NULL, NULL, NULL) );
   if ( solstat != 1 ) {
      printf("The solver did not find an optimal solution\nSolver status code: %d\n",solstat);
      exit(0);
   }

   /// Write the output to the screen 
   printf ("\nSolution status = %d\t\t", solstat);
   printf ("Solution value  = %f\n\n", objval);

   /// If the solution is integer, is the optimum -> exit the loop
   if ( isInteger(cur_numcols, x) ) {
      fprintf(stdout,"The solution is already integer!\n");
      goto QUIT;
   }

   /// Dump the problem model to 'gomory.lp' for debbuging
   POST_CMD( CPXwriteprob(env, model, "gomory.lp", NULL) );

   /// Get the base statuses
   POST_CMD( CPXgetbase(env, model, cstat, NULL) );

   print_solution(cur_numcols, x, cstat);

   printf("\nOptimal base inverted matrix:\n");
   for ( i = 0; i < cur_numrows; ++i ) {
      b_bar[i] = 0;
      POST_CMD( CPXbinvrow(env, model, i, z) );
      for ( j = 0; j < cur_numrows; ++j ) {
         printf("%.1f ", z[j]);
         b_bar[i] += z[j]*rhs[j];
      }
      printf("\n");
   }

   printf("\nOptimal solution (non basic variables are equal to zero):\n");
   idx = 0;     /// Compute the nonzeros
   n_cuts = 0;  /// Number of fractional variables (cuts to be generated)
   for ( i = 0; i < m-1; ++i ) {
      POST_CMD( CPXbinvarow(env, model, i, z) );
      for ( j = 0; j < n1; ++j ) {
         if ( z[j] >= 0 )
            printf("+");
         printf("%.1f x%d ", z[j], j+1);
         if ( floor(z[j]+0.5) != 0 )
            idx++;
      }
      printf("= %.1f\n", b_bar[i]);
      /// Count the number of cuts to be generated
      if ( floor(b_bar[i]) != b_bar[i] ) 
         n_cuts++;
   }

   /// Allocate memory for the new data structure
   gc_sense = (char*)   malloc ( n_cuts * sizeof(char) ); 
   gc_rhs   = (double*) malloc ( n_cuts * sizeof(double) ); 
   rmatbeg  = (int*)    malloc ( n_cuts * sizeof(int) ); 
   rmatind  = (int*)    malloc (    idx * sizeof(int) ); 
   rmatval  = (double*) malloc (    idx * sizeof(double) ); 

   printf("\nGenerate Gomory cuts:\n");
   idx = 0;
   cut = 0;  /// Index of cut to be added
   for ( i = 0; i < m-1; ++i ) 
      if ( floor(b_bar[i]) != b_bar[i] ) {
         printf("Row %d gives cut ->   ", i+1);
         POST_CMD( CPXbinvarow(env, model, i, z) );
         rmatbeg[cut] = idx;
         for ( j = 0; j < n1; ++j ) {
            z[j] = floor(z[j]); /// DANGER!
            if ( z[j] != 0 ) {
               rmatind[idx] = j;
               rmatval[idx] = z[j];
               idx++;
            }
            /// Print the cut
            if ( z[j] >= 0 )
               printf("+");
            printf("%.1f x%d ", z[j], j+1);
         }
         gc_rhs[cut] = floor(b_bar[i]); /// DANGER!
         gc_sense[cut] = 'L';
         printf("<= %.1f\n", gc_rhs[cut]);
         cut++;
      }

   /// Add the new cuts
   POST_CMD( CPXaddrows (env, model, 0, 
            n_cuts, idx, gc_rhs, gc_sense, 
            rmatbeg, rmatind, rmatval, 
            NULL, NULL) );

   /// Solve the new LP
   POST_CMD( CPXlpopt(env, model) );

   /// Check the results
   cur_numrows = CPXgetnumrows (env, model);
   cur_numcols = CPXgetnumcols (env, model);

   POST_CMD( CPXsolution (env, model, &solstat, &objval, x, NULL, NULL, NULL) );

   if ( solstat != 1 ) {
      printf("The solver did not find an optimal solution\nSolver status code: %d\n",solstat);
      exit(0);
   }
   /// Write the output to the screen 
   printf ("\nSolution status = %d\n", solstat);
   printf ("Solution value = %f\n\n", objval);

   POST_CMD( CPXgetbase(env, model, cstat, NULL) );

   print_solution(cur_numcols, x, cstat);

   free_and_null ((char **) &x);
   free_and_null ((char **) &z);
   free_and_null ((char **) &cstat);
   free_and_null ((char **) &rmatbeg);
   free_and_null ((char **) &rmatind);
   free_and_null ((char **) &rmatval);

QUIT:
   free_and_null ((char **) &x);
   free_and_null ((char **) &z);
   free_and_null ((char **) &cstat);

   if ( error ) {
      char  errmsg[CPXMESSAGEBUFSIZE];
      CPXgeterrorstring (env, error, errmsg);
      fprintf (stderr, "%s", errmsg);
   }

   /* Free up the problem as allocated by CPXcreateprob, if necessary */
   if ( model != NULL ) {
      status = CPXfreeprob (env, &model);
      if ( status ) {
         fprintf (stderr, "CPXfreeprob failed, error code %d.\n", status);
      }
   }

   /* Free up the CPLEX environment, if necessary */
   if ( env != NULL ) {
      status = CPXcloseCPLEX (&env);

      if ( error ) {
         char  errmsg[CPXMESSAGEBUFSIZE];
         fprintf (stderr, "Could not close CPLEX environment.\n");
         CPXgeterrorstring (env, status, errmsg);
         fprintf (stderr, "%s", errmsg);
      }
   }

   return (status);
}
Exemple #14
0
static int
buildmodel (CPXENVptr env, CPXLPptr lp)
{

   int    colcnt = NUMVARS*NUMMONTHS*NUMPRODUCTS;

   double *obj     = NULL;
   double *lb      = NULL;
   double *ub      = NULL;
   char   *ctype   = NULL;
   int    *rmatind = NULL;
   double *rmatval = NULL;

   int    indicator;
   int    rmatbeg[1];
   double rhs[1];
   char   sense[1];

   int    m, p;
   int    status = 0;

   status = CPXchgobjsen (env, lp, CPX_MAX); /* Maximization problem */
   if ( status ) {
      fprintf (stderr, "Could not change objective sense.\n");
      goto TERMINATE;
   }

   rmatbeg[0] = 0;

   /* Allocate colcnt-sized arrays */

   obj     = (double *) malloc (colcnt * sizeof(double));
   lb      = (double *) malloc (colcnt * sizeof(double));
   ub      = (double *) malloc (colcnt * sizeof(double));
   ctype   = (char *)   malloc (colcnt * sizeof(char));
   rmatind = (int * )   malloc (colcnt * sizeof(int));
   rmatval = (double *) malloc (colcnt * sizeof(double));

   if ( obj     == NULL ||
        lb      == NULL ||
        ub      == NULL ||
        ctype   == NULL ||
        rmatind == NULL ||
        rmatval == NULL   ) {
      fprintf (stderr, "Could not allocate colcnt arrays\n");
      status = CPXERR_NO_MEMORY;
      goto TERMINATE;
   }

   /* Create variables. For each month and each product, we have 3
      variables corresponding to the quantity used (semi-continuous),
      stored (continuous) and bought (continuous) and one binary
      variable indicating whether or not the product is used during
      this month. */

   for (m = 0; m < NUMMONTHS; m++) {
      for (p = 0; p < NUMPRODUCTS; p++) {

         /* The quantity bought is a continuous variable. It has a cost */

         obj[varindex(m, p, BUY)]    = -cost[m*NUMPRODUCTS + p];
         lb[varindex (m, p, BUY)]    = 0.0;
         ub[varindex (m, p, BUY)]    = CPX_INFBOUND;
         ctype[varindex (m, p, BUY)] = 'C';

         /* When an oil is used, the quantity must be at least 20
            tons. This is modeled as a semi-continuous variable. */

         obj[varindex (m, p, USE)]   = 0.0;
         lb[varindex (m, p, USE)]    = 20.0;
         ub[varindex (m, p, USE)]    = CPX_INFBOUND;
         ctype[varindex (m, p, USE)] = 'S';

         /* It is possible to store up to 1000 tons of each
            product. There are storage costs. */

         obj[varindex (m, p, STORE)]   = -5.0;
         lb[varindex (m, p, STORE)]    = 0.0;
         ub[varindex (m, p, STORE)]    = 1000.0;
         ctype[varindex (m, p, STORE)] = 'C';

         /* At the end, we must have exactly 500 tons of each
            product in storage. */

         if ( m == NUMMONTHS - 1 ) {
            lb[varindex (m, p, STORE)] = 500.0;
            ub[varindex (m, p, STORE)] = 500.0;
         }

         /* The variable indicating whether or not a product is
            used during a month is a binary variable. */

         obj[varindex (m, p, IS_USED)]   = 0.0;
         lb[varindex (m, p, IS_USED)]    = 0.0;
         ub[varindex (m, p, IS_USED)]    = 1.0;
         ctype[varindex (m, p, IS_USED)] = 'B';
      }
   }

   status = CPXnewcols (env, lp, colcnt, obj, lb, ub, ctype, NULL);
   if ( status ) {
      fprintf (stderr, "Could not add new columns.\n");
      goto TERMINATE;
   }

   /* Constraints for each month */

   for (m = 0; m < NUMMONTHS; m++) {
      int totalindex;

      /* For each product, create an indicator constraint linking the
         quantity used and the binary variable indicating whether or
         not the product is used */

      for (p = 0; p < NUMPRODUCTS; p++) {
         indicator  = varindex (m, p, IS_USED);
         rmatind[0] = varindex (m, p, USE);
         rmatval[0] = 1.0;
         status = CPXaddindconstr (env, lp, indicator, 1, 1, 0.0, 'L',
                                   rmatind, rmatval, NULL);
         if ( status ) {
            fprintf (stderr, "Could not add new indicator constraint.\n");
            goto TERMINATE;
         }
      }

      /* Not more than 200 tons of vegetable oil can be refined */

      rmatind[0] = varindex (m, VEGOIL1, USE);
      rmatind[1] = varindex (m, VEGOIL2, USE);
      rmatval[0] = 1.0;
      rmatval[1] = 1.0;
      rhs[0]     = 200.0;
      sense[0]   = 'L';
      status = CPXaddrows (env, lp, 0, 1, 2, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);

      /* Not more than 250 tons of non-vegetable oil can be refined */

      rmatind[0] = varindex (m, OIL1, USE);
      rmatind[1] = varindex (m, OIL2, USE);
      rmatind[2] = varindex (m, OIL3, USE);
      rmatval[0] = 1.0;
      rmatval[1] = 1.0;
      rmatval[2] = 1.0;
      rhs[0]     = 250.0;
      sense[0]   = 'L';
      status = CPXaddrows (env, lp, 0, 1, 3, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* Constraint on food composition */

      /* Add a variable corresponding to total quantity produced
         in a month */

      obj[0]   = 150.0;
      lb[0]    = 0.0;
      ub[0]    = CPX_INFBOUND;
      ctype[0] = 'C';

      status = CPXnewcols (env, lp, 1, obj, lb, ub, ctype, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new columns.\n");
         goto TERMINATE;
      }
      totalindex = CPXgetnumcols (env, lp) - 1;

      /* Total quantity = sum (quantities) */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, USE);
         rmatval[p] = 1.0;
      }
      rmatind[NUMPRODUCTS] = totalindex;
      rmatval[NUMPRODUCTS] = -1.0;
      rhs[0]               =  0.0;
      sense[0]             = 'E';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* Hardness constraints
          sum (quantity * hardness) >= 3 * total quantity
          sum (quantity * hardness) <= 6 * total quantity
      */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, USE);
         rmatval[p] = hardness[p];
      }
      rmatind[NUMPRODUCTS] = totalindex;
      rmatval[NUMPRODUCTS] = -3.0;
      rhs[0]               =  0.0;
      sense[0]             = 'G';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      rmatval[NUMPRODUCTS] = -6.0;
      sense[0]             = 'L';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS + 1, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* The food may never be made up of more than three oils */

      for (p = 0; p < NUMPRODUCTS; p++) {
         rmatind[p] = varindex (m, p, IS_USED);
         rmatval[p] = 1.0;
      }
      rhs[0]   = 3.0;
      sense[0] = 'L';
      status = CPXaddrows (env, lp, 0, 1, NUMPRODUCTS, rhs,
                           sense, rmatbeg, rmatind, rmatval,
                           NULL, NULL);
      if ( status ) {
         fprintf (stderr, "Could not add new rows.\n");
         goto TERMINATE;
      }

      /* If product veg 1 or veg 2 is used then oil 3 must be used */

      indicator  = varindex (m, VEGOIL1, IS_USED);
      rmatind[0] = varindex (m, OIL3, USE);
      rmatval[0] = 1.0;
      status = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      indicator = varindex (m, VEGOIL2, IS_USED);
      status = CPXaddindconstr (env, lp, indicator, 0, 1, 20.0, 'G',
                                rmatind, rmatval, NULL);

      if ( status ) {
         fprintf (stderr, "Could not add new indicator constraint.\n");
         goto TERMINATE;
      }

      /* We can store each product from one month to the next,
         starting with a stock of 500 tons */

      for (p = 0; p < NUMPRODUCTS; p++) {
         int n = 0;
         if ( m != 0 ) {
            rmatind[n]   = varindex (m-1, p, STORE); /* stored last month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, BUY);     /* bought this month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, USE);     /* used this month */
            rmatval[n++] = -1.0;
            rmatind[n]   = varindex (m, p, STORE);   /* stored this month */
            rmatval[n++] = -1.0;
            rhs[0]       = 0.0;
            sense[0]     = 'E';
         }
         else {
            rmatind[n]   = varindex (m, p, BUY);   /* bought this month */
            rmatval[n++] = 1.0;
            rmatind[n]   = varindex (m, p, USE);   /* used this month */
            rmatval[n++] = -1.0;
            rmatind[n]   = varindex (m, p, STORE); /* stored this month */
            rmatval[n++] = -1.0;
            rhs[0]       = -500.0;
            sense[0]     = 'E';
         }
         status = CPXaddrows (env, lp, 0, 1, n, rhs,
                              sense, rmatbeg, rmatind, rmatval,
                              NULL, NULL);
         if ( status ) {
            fprintf (stderr, "Could not add new rows.\n");
            goto TERMINATE;
         }
      }
   }

 TERMINATE:

   free_and_null ((char **)&obj);
   free_and_null ((char **)&lb);
   free_and_null ((char **)&ub);
   free_and_null ((char **)&ctype);
   free_and_null ((char **)&rmatind);
   free_and_null ((char **)&rmatval);

   return (status);

}  /* END buildmodel */