4 * Copyright: (c) Universitaet Karlsruhe
5 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
12 #include "lpp_local.h"
21 #include "sp_matrix.h"
22 #include "ilcplex/cplex.h"
24 #define LOGFILE stdout
27 static char cpx_cst_encoding[4] = {'?', 'E', 'L', 'G'};
28 static char cpx_var_encoding[4] = {'?', '?', 'C', 'B'};
30 typedef struct _cpx_t {
38 static INLINE void chk_cpx_err(cpx_t *cpx) {
40 if (CPXgeterrorstring(cpx->env, cpx->status, cpx->buf))
43 printf("Unknown CPLEX error\n");
48 static cpx_t *new_cpx(lpp_t *lpp) {
49 cpx_t *cpx = xcalloc(1, sizeof(*cpx));
51 cpx->env = CPXopenCPLEX(&cpx->status);
53 cpx->prob = CPXcreateprob(cpx->env, &cpx->status, lpp->name);
55 CPXchgobjsen(cpx->env, cpx->prob, (lpp->opt_type == minimize)?1:-1);
57 if (CPXsetlogfile(cpx->env, LOGFILE))
58 assert(0 && "Could not set logfile");
62 static void free_cpx(cpx_t *cpx) {
63 CPXfreeprob(cpx->env, &cpx->prob);
64 CPXcloseCPLEX(&cpx->env);
68 static void cpx_construct(cpx_t *cpx) {
69 const matrix_elem_t *elem;
70 int i, o, sv_cnt, numcols, numrows, numentries, objsen, *matbeg, *matcnt, *matind, *indices;
71 double *obj, *rhs, *matval, *lb, *ub, *startv;
72 char *sense, *vartype, **colname;
73 lpp_t *lpp = cpx->lpp;
75 numcols = lpp->var_next-1;
76 numrows = lpp->cst_next-1;
77 numentries = matrix_get_entries(lpp->m);
78 objsen = lpp->opt_type == minimize ? 1 : -1;
80 obj = alloca(numcols * sizeof(*obj));
81 lb = alloca(numcols * sizeof(*lb));
82 ub = alloca(numcols * sizeof(*ub));
83 colname = alloca(numcols * sizeof(*colname));
84 vartype = alloca(numcols * sizeof(*vartype));
85 indices = alloca(numcols * sizeof(*indices));
86 startv = alloca(numcols * sizeof(*startv));
87 matbeg = alloca(numcols * sizeof(*matbeg));
88 matcnt = alloca(numcols * sizeof(*matcnt));
89 matind = alloca(numentries * sizeof(*matind));
90 matval = alloca(numentries * sizeof(*matval));
91 rhs = alloca(numrows * sizeof(*rhs));
92 sense = alloca(numrows * sizeof(*sense));
96 for(i=0; i<numcols; ++i) {
97 name_t *curr_var = lpp->vars[1+i];
98 obj[i] = matrix_get(lpp->m, 0, 1+i);
100 ub[i] = CPX_INFBOUND;
101 colname[i] = curr_var->name;
102 vartype[i] = cpx_var_encoding[curr_var->type.var_type];
103 if(curr_var->value_kind == value_start) {
105 startv[sv_cnt++] = curr_var->value;
109 matrix_foreach_in_col(lpp->m, 1+i, elem) {
112 matind[o] = elem->row-1;
113 matval[o] = elem->val;
119 for(i=0; i<numrows; ++i) {
120 rhs[i] = matrix_get(lpp->m, 1+i, 0);
121 sense[i] = cpx_cst_encoding[lpp->csts[1+i]->type.cst_type];
124 cpx->status = CPXcopylpwnames(cpx->env, cpx->prob,
125 numcols, numrows, objsen,
127 matbeg, matcnt, matind, matval,
131 cpx->status = CPXcopyctype(cpx->env, cpx->prob, vartype);
133 cpx->status = CPXcopymipstart(cpx->env, cpx->prob, sv_cnt, indices, startv);
137 static void cpx_solve(cpx_t *cpx) {
138 int i, CPX_state, numcols;
140 struct timeval tvb, tva;
142 lpp_t *lpp = cpx->lpp;
143 numcols = CPXgetnumcols(cpx->env, cpx->prob);
146 /* set performance parameters */
147 CPXsetintparam(cpx->env, CPX_PARAM_MIPSTART, CPX_ON);
148 CPXsetintparam(cpx->env, CPX_PARAM_MIPEMPHASIS, CPX_MIPEMPHASIS_BESTBOUND);
149 CPXsetintparam(cpx->env, CPX_PARAM_VARSEL, CPX_VARSEL_STRONG);
152 gettimeofday(&tvb, NULL);
153 cpx->status = CPXmipopt(cpx->env, cpx->prob);
154 gettimeofday(&tva, NULL);
157 /* get solution status */
158 CPX_state = CPXgetstat(cpx->env, cpx->prob);
160 case CPXMIP_INFEASIBLE:
161 case CPX_STAT_INFEASIBLE: lpp->sol_state = infeasible; break;
162 case CPXMIP_INForUNBD:
163 case CPX_STAT_INForUNBD: lpp->sol_state = inforunb; break;
164 case CPXMIP_UNBOUNDED:
165 case CPX_STAT_UNBOUNDED: lpp->sol_state = unbounded; break;
166 case CPXMIP_ABORT_FEAS:
167 case CPXMIP_FAIL_FEAS:
168 case CPXMIP_MEM_LIM_FEAS:
169 case CPXMIP_NODE_LIM_FEAS:
170 case CPXMIP_TIME_LIM_FEAS: lpp->sol_state = feasible; break;
172 case CPX_STAT_OPTIMAL: lpp->sol_state = optimal; break;
173 default: lpp->sol_state = unknown;
175 assert(lpp->sol_state == optimal);
177 /* get variable solution values */
178 values = alloca(numcols * sizeof(*values));
179 CPXgetmipx(cpx->env, cpx->prob, values, 0, numcols-1);
181 for(i=0; i<numcols; ++i) {
182 lpp->vars[1+i]->value = values[i];
183 lpp->vars[1+i]->value_kind = value_solution;
186 /* get some statistics */
187 lpp->sol_time = tva.tv_sec - tvb.tv_sec;
188 lpp->iterations = CPXgetmipitcnt(cpx->env, cpx->prob);
191 void lpp_solve_local(lpp_t *lpp) {
192 cpx_t *cpx = new_cpx(lpp);
200 void lpp_solve_local(lpp_t *lpp) {
201 fprintf(stderr, "CPLEX not available!\n");