/* Name: api.c ** Author: Leo Liberti ** Purpose: api for CPLEX callable library avoiding use of ** problematic matbeg/matind/matval interface in row addition ** Source: C ** History: 060220 work started */ // standard include files #include #include #include #include #include #include // maximum length of variable/constraint names #define MAXNAME 64 void AddConstraint(CPXENVptr env, CPXLPptr lp, int nz, double* coeffs, int* ind, char sense, double rhs) { int status = 0; // add constraints in row-wise sparse format int rmatbeg[2]; // nonzeroes stored in rmatval starting at position: rmatbeg[0] = 0; // nonzeroes stored in rmatval ending at position: rmatbeg[1] = nz-1; // create the constraints status = CPXaddrows(env, lp, 0, 1, nz, &rhs, &sense, rmatbeg, ind, coeffs, NULL, NULL); if (status != 0) { fprintf(stderr, "api: could not create constraints, error %d\n", status); exit(3); } } int main(int argc, char** argv) { // return code int ret = 0; // status code returned by cplex callable library functions int status = 0; // number of rows (constraints) int m = 0; // number of columns (variables) int n = 0; // cplex environment to pass to/from cplex callable library CPXENVptr env = NULL; // cplex linear program to pass to/from cplex callable library CPXLPptr lp = NULL; // use for storing error messages returned by CPLEX char errmsg[1024]; // counters int i, j; // try to initialize the CPLEX environment env = CPXopenCPLEX(&status); if (env == NULL) { fprintf(stderr, "%s: could not open CPLEX environment\n", argv[0]); CPXgeterrorstring (env, status, errmsg); fprintf (stderr, "%s", errmsg); exit(2); } // turn on output to screen status = CPXsetintparam(env, CPX_PARAM_SCRIND, CPX_ON); status = CPXsetintparam (env, CPX_PARAM_SIMDISPLAY, 2); if (status != 0) { fprintf(stderr, "%s: could not turn on screen indicator, error %d\n", argv[0], status); exit(3); } // create the problem max{x1+x2 | x1+2x2<=2, 2x1+x2<=2, x>= 0} lp = CPXcreateprob(env, &status, "simple"); if (lp == NULL) { fprintf(stderr, "%s: failed to create problem\n"); exit(4); } // two variables n = 2; // two constraints m = 2; // objective function coefficients double *c = (double*) malloc(n * sizeof(double)); c[0] = -1.0; c[1] = -1.0; // variable lower bounds double *xL = (double*) malloc(n * sizeof(double)); xL[0] = 0.0; xL[1] = 0.0; // variable upper bounds double *xU = (double*) malloc(n * sizeof(double)); xU[0] = CPX_INFBOUND; xU[1] = CPX_INFBOUND; // variable names char** xn = (char**) malloc(n * sizeof(char*)); for(j = 0; j < n; j++) { xn[j] = (char*) malloc(MAXNAME * sizeof(char)); } strncpy(xn[0], "x1", MAXNAME); strncpy(xn[1], "x2", MAXNAME); // create the variables status = CPXnewcols(env, lp, n, c, xL, xU, NULL, xn); if (status != 0) { fprintf(stderr, "%s: could not create variables, error %d\n", argv[0], status); exit(3); } // add constraints double* thecoeffs = (double*) malloc(n * sizeof(double)); int* theind = (int*) malloc(n * sizeof(int)); char thesense; double therhs; int thenz = 0; // constraint 1 thenz = 2; thecoeffs[0] = 1.0; thecoeffs[1] = 2.0; theind[0] = 0; theind[1] = 1; thesense = 'L'; therhs = 2.0; AddConstraint(env, lp, thenz, thecoeffs, theind, thesense, therhs); // constraint 2 thenz = 2; thecoeffs[0] = 2.0; thecoeffs[1] = 1.0; theind[0] = 0; theind[1] = 1; thesense = 'L'; therhs = 2.0; AddConstraint(env, lp, thenz, thecoeffs, theind, thesense, therhs); // select the optimization algorithm status = CPXsetintparam(env, CPX_PARAM_LPMETHOD, CPX_ALG_AUTOMATIC); if (status != 0) { fprintf(stderr, "%s: could not select optimization algorithm, error %d\n", argv[0], status); exit(3); } // optimize status = CPXlpopt(env, lp); if (status != 0) { fprintf(stderr, "%s: failed to call optimization algorithm\n", argv[0]); exit(10); } // get solution information // value of the objective function double objval = 0; // values of the primal problem variables double *x = (double*) malloc(n * sizeof(double)); for(j = 0; j < n; j++) { x[j] = 0.0; } // values of the dual problem variables double *y = (double*) malloc(m * sizeof(double)); for(i = 0; i < m; i++) { y[i] = 0.0; } // values of the slack variables double *s = (double*) malloc(m * sizeof(double)); for(i = 0; i < m; i++) { s[i] = 0.0; } // reduced costs double *rc = (double*) malloc(n * sizeof(double)); for(j = 0; j < n; j++) { rc[j] = 0.0; } CPXsolution(env, lp, &status, &objval, x, y, s, rc); // print solution printf("%s: solution of problem \"simple\":\n", argv[0]); printf(" solver return status = %d\n", status); printf(" optimal objective function value = %f\n", objval); printf(" optimal primal variables:\n ( "); for(j = 0; j < n; j++) { printf("%f ", x[j]); } printf(")\n"); printf(" optimal dual variables:\n ( "); for(i = 0; i < m; i++) { printf("%f ", y[i]); } printf(")\n"); printf(" optimal slack variables:\n ( "); for(i = 0; i < m; i++) { printf("%f ", y[i]); } printf(")\n"); // free storage CPXfreeprob(env, &lp); free(rc); free(s); free(y); free(x); free(thecoeffs); free(theind); for(j = n - 1; j >= 0; j--) { free(xn[j]); } free(xn); free(xU); free(xL); free(c); return ret; }