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 */
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); }
//******************************************************************* 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; }
// 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; }
void CplexSolver::write(std::string const & fileName) const { CPXchgobjsen(_env, _prob, _is_minimize ? CPX_MIN : CPX_MAX); CPXwriteprob(_env, _prob, fileName.c_str(), "LP"); }
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; }
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 */
// initialize the objective function int cplex_solver::begin_objectives(void) { // Set Problem as a minimization problem CPXchgobjsen (env, lp, CPX_MIN); return 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; }
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; }
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); }
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 */