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 #undef LOGFILE //stdout
25 #define TIME_LIMIT 5*60 /* in sec. 0 for none */
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);
58 if (CPXsetlogfile(cpx->env, LOGFILE))
59 assert(0 && "Could not set logfile");
64 static void free_cpx(cpx_t *cpx) {
65 CPXfreeprob(cpx->env, &cpx->prob);
66 CPXcloseCPLEX(&cpx->env);
70 static void cpx_construct(cpx_t *cpx) {
71 const matrix_elem_t *elem;
72 int i, o, sv_cnt, numcols, numrows, numentries, objsen, *matbeg, *matcnt, *matind, *indices;
73 double *obj, *rhs, *matval, *lb, *ub, *startv;
74 char *sense, *vartype, **colname;
75 lpp_t *lpp = cpx->lpp;
77 numcols = lpp->var_next-1;
78 numrows = lpp->cst_next-1;
79 numentries = matrix_get_entries(lpp->m);
80 objsen = lpp->opt_type == minimize ? 1 : -1;
82 obj = alloca(numcols * sizeof(*obj));
83 lb = alloca(numcols * sizeof(*lb));
84 ub = alloca(numcols * sizeof(*ub));
85 colname = alloca(numcols * sizeof(*colname));
86 vartype = alloca(numcols * sizeof(*vartype));
87 indices = alloca(numcols * sizeof(*indices));
88 startv = alloca(numcols * sizeof(*startv));
89 matbeg = alloca(numcols * sizeof(*matbeg));
90 matcnt = alloca(numcols * sizeof(*matcnt));
91 matind = alloca(numentries * sizeof(*matind));
92 matval = alloca(numentries * sizeof(*matval));
93 rhs = alloca(numrows * sizeof(*rhs));
94 sense = alloca(numrows * sizeof(*sense));
98 for(i=0; i<numcols; ++i) {
99 name_t *curr_var = lpp->vars[1+i];
100 obj[i] = matrix_get(lpp->m, 0, 1+i);
102 ub[i] = CPX_INFBOUND;
103 colname[i] = curr_var->name;
104 vartype[i] = cpx_var_encoding[curr_var->type.var_type];
105 if(curr_var->value_kind == value_start) {
107 startv[sv_cnt++] = curr_var->value;
111 matrix_foreach_in_col(lpp->m, 1+i, elem) {
114 matind[o] = elem->row-1;
115 matval[o] = elem->val;
121 for(i=0; i<numrows; ++i) {
122 rhs[i] = matrix_get(lpp->m, 1+i, 0);
123 sense[i] = cpx_cst_encoding[lpp->csts[1+i]->type.cst_type];
126 cpx->status = CPXcopylpwnames(cpx->env, cpx->prob,
127 numcols, numrows, objsen,
129 matbeg, matcnt, matind, matval,
133 cpx->status = CPXcopyctype(cpx->env, cpx->prob, vartype);
135 cpx->status = CPXcopymipstart(cpx->env, cpx->prob, sv_cnt, indices, startv);
139 static void cpx_solve(cpx_t *cpx) {
140 int i, CPX_state, numcols;
142 struct timeval tvb, tva;
144 lpp_t *lpp = cpx->lpp;
145 numcols = CPXgetnumcols(cpx->env, cpx->prob);
148 /* set performance parameters */
149 CPXsetintparam(cpx->env, CPX_PARAM_MIPSTART, CPX_ON);
150 CPXsetintparam(cpx->env, CPX_PARAM_MIPEMPHASIS, CPX_MIPEMPHASIS_BESTBOUND);
151 CPXsetintparam(cpx->env, CPX_PARAM_VARSEL, CPX_VARSEL_STRONG);
153 CPXsetdblparam(cpx->env, CPX_PARAM_TILIM, TIME_LIMIT);
156 gettimeofday(&tvb, NULL);
157 cpx->status = CPXmipopt(cpx->env, cpx->prob);
158 gettimeofday(&tva, NULL);
161 /* get solution status */
162 CPX_state = CPXgetstat(cpx->env, cpx->prob);
164 case CPXMIP_INFEASIBLE:
165 case CPX_STAT_INFEASIBLE: lpp->sol_state = infeasible; break;
166 case CPXMIP_INForUNBD:
167 case CPX_STAT_INForUNBD: lpp->sol_state = inforunb; break;
168 case CPXMIP_UNBOUNDED:
169 case CPX_STAT_UNBOUNDED: lpp->sol_state = unbounded; break;
170 case CPXMIP_ABORT_FEAS:
171 case CPXMIP_FAIL_FEAS:
172 case CPXMIP_MEM_LIM_FEAS:
173 case CPXMIP_NODE_LIM_FEAS:
174 case CPXMIP_TIME_LIM_FEAS: lpp->sol_state = feasible; break;
176 case CPX_STAT_OPTIMAL: lpp->sol_state = optimal; break;
177 default: lpp->sol_state = unknown;
179 assert(lpp->sol_state == optimal || lpp->sol_state == feasible);
181 /* get variable solution values */
182 values = alloca(numcols * sizeof(*values));
183 CPXgetmipx(cpx->env, cpx->prob, values, 0, numcols-1);
185 for(i=0; i<numcols; ++i) {
186 lpp->vars[1+i]->value = values[i];
187 lpp->vars[1+i]->value_kind = value_solution;
190 /* get some statistics */
191 lpp->sol_time = tva.tv_sec - tvb.tv_sec;
192 lpp->iterations = CPXgetmipitcnt(cpx->env, cpx->prob);
195 void lpp_solve_local(lpp_t *lpp) {
196 cpx_t *cpx = new_cpx(lpp);
204 void lpp_solve_local(lpp_t *lpp) {
205 fprintf(stderr, "CPLEX not available!\n");