> I am using GLPK in C++ programs like :
> glp_prob *lp = glp_create_prob();
> glp_tran *tran = glp_mpl_alloc_wksp();
>
> glp_mpl_read_model(tran, "..\\MyModel.mod", 1);
> glp_mpl_read_data(tran, "..\\MyModel.dat");
> glp_mpl_generate(tran, NULL);
> glp_mpl_build_prob(tran, lp);
> glp_simplex(lp, NULL);
> glp_mpl_postsolve(tran, lp, GLP_MIP);
>
> glp_create_index(lp);
> int index = glp_find_col(lp, "MyVariable");
> double optimalValue = glp_get_row_prim(lp, index);
>
> When using with big input data, the solving time becomes very important. So,
> I would like to use another solver like CLP. For example, in the above
> source, it would replace the ligne "glp_simplex(lp, NULL);" by the call of
> the new solver.
>
> I found references for Symphony or Osi but I did not find clear examples
> doing what I am looking for.
> Maybe, someone have met this problem or you could have valuable advices or
> suggestions that I could test...
AFAIK, both Coin and Symphony allow using the glpk model translator.
Another way is to output the mip data into a file, say, in free mps
format, call an external solver, and load the solution back into the
glpk problem object. To simplify the interface between glpk and the
external solver you may use api routines glp_write_prob, glp_read_mip,
and glp_write_mip described in the glpk reference manual.
If the external solver has its own api, you also may write an interface
module; see an example attached.
/* 3party.c */
#include "cplex.h"
#include "glpapi.h"
static void cplex_error(CPXENVptr env, const char *who, int status)
{ char buffer[511+1];
if (CPXgeterrorstring(env, status, buffer) == NULL)
xprintf("%s failed\nCPLEX Error %5d: Unknown error code.\n",
who, status);
else
xprintf("%s failed\n%s", who, buffer);
return;
}
int solve_mip(glp_prob *P, const glp_iocp *parm)
{ CPXENVptr env;
CPXLPptr prob = NULL;
CPXFILEptr logfile = NULL;
GLPROW *row;
GLPCOL *col;
GLPAIJ *aij;
int status, numrows, numcols, objsen, numnz, m, n;
int *matbeg, *matcnt, *matind, loc, i, j, k;
char *sense, *ctype;
int *ref = NULL, ret, *indices;
double *matval, *obj, *lb, *ub, *rhs, *rngval, *x, sum;
/* initialize CPLEX environment */
env = CPXopenCPLEX(&status);
if (env == NULL)
{ xprintf("CPXopenCPLEX failed; CPLEX Error %5d.\n", status);
ret = GLP_EFAIL;
goto done;
}
xprintf("CPLEX version is %s\n", CPXversion(env));
/* set CPLEX log file */
logfile = CPXfopen("CONOUT$", "w");
xassert(logfile != NULL);
status = CPXsetlogfile(env, logfile);
if (status)
{ cplex_error(env, "CPXsetlogfile", status);
ret = GLP_EFAIL;
goto done;
}
/* create CPLEX problem object */
prob = CPXcreateprob(env, &status, "MIP");
if (prob == NULL)
{ cplex_error(env, "CPXcreateprob", status);
ret = GLP_EFAIL;
goto done;
}
/* determine original number of rows and columns */
m = P->m, n = P->n;
/* build the row reference array;
ref[i], i = 1,...,m, is the number which i-th row would have
in the problem object after removing all free rows;
if i-th row is free, ref[i] is set to 0;
also count the number of rows and constraint coefficients in
CPLEX problem object */
ref = xcalloc(1+m, sizeof(int));
numrows = 0, numnz = 0;
for (i = 1; i <= m; i++)
{ row = P->row[i];
if (row->type == GLP_FR)
ref[i] = 0;
else
{ ref[i] = ++numrows;
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
numnz++;
}
}
/* the set of columns includes one additional column fixed at 1
to account the constant term of the objective function */
numcols = n+1;
/* allocate working arrays */
obj = xcalloc(numcols, sizeof(double));
sense = xcalloc(numrows, sizeof(char));
rhs = xcalloc(numrows, sizeof(double));
rngval = xcalloc(numrows, sizeof(double));
matbeg = xcalloc(numcols, sizeof(int));
matcnt = xcalloc(numcols, sizeof(int));
matind = xcalloc(numnz, sizeof(int));
matval = xcalloc(numnz, sizeof(double));
lb = xcalloc(numcols, sizeof(double));
ub = xcalloc(numcols, sizeof(double));
/* set objective sense */
if (P->dir == GLP_MIN)
objsen = CPX_MIN;
else if (P->dir == GLP_MAX)
objsen = CPX_MAX;
else
xassert(P != P);
/* set row attributes */
for (k = 1; k <= m; k++)
{ row = P->row[k];
i = ref[k];
if (i == 0) continue;
if (row->type == GLP_LO)
{ sense[i-1] = 'G';
rhs[i-1] = row->lb;
rngval[i-1] = 0.0;
}
else if (row->type == GLP_UP)
{ sense[i-1] = 'L';
rhs[i-1] = row->ub;
rngval[i-1] = 0.0;
}
else if (row->type == GLP_DB)
{ sense[i-1] = 'R';
rhs[i-1] = row->lb;
rngval[i-1] = row->ub - row->lb;
}
else if (row->type == GLP_FX)
{ sense[i-1] = 'E';
rhs[i-1] = row->lb;
rngval[i-1] = 0.0;
}
else
xassert(row != row);
}
/* set column attributes */
for (j = 1; j <= n; j++)
{ col = P->col[j];
obj[j-1] = col->coef;
if (col->type == GLP_FR)
{ lb[j-1] = -CPX_INFBOUND;
ub[j-1] = +CPX_INFBOUND;
}
else if (col->type == GLP_LO)
{ lb[j-1] = col->lb;
ub[j-1] = +CPX_INFBOUND;
}
else if (col->type == GLP_UP)
{ lb[j-1] = -CPX_INFBOUND;
ub[j-1] = col->ub;
}
else if (col->type == GLP_DB)
{ lb[j-1] = col->lb;
ub[j-1] = col->ub;
}
else if (col->type == GLP_FX)
lb[j-1] = ub[j-1] = col->lb;
else
xassert(col != col);
}
obj[numcols-1] = P->c0;
lb[numcols-1] = ub[numcols-1] = 1.0;
/* build the constraint matrix in column-wise format */
loc = 0;
for (j = 1; j <= n; j++)
{ col = P->col[j];
matbeg[j-1] = loc;
for (aij = col->ptr; aij != NULL; aij = aij->c_next)
{ i = ref[aij->row->i];
if (i != 0)
{ matind[loc] = i-1;
matval[loc] = aij->val;
loc++;
}
}
matcnt[j-1] = loc - matbeg[j-1];
}
matbeg[numcols-1] = loc;
matcnt[numcols-1] = 0;
xassert(loc == numnz);
/* copy problem data to CPLEX problem object */
status = CPXcopylp(env, prob, numcols, numrows, objsen, obj, rhs,
sense, matbeg, matcnt, matind, matval, lb, ub, rngval);
/* free working arrays */
xfree(obj);
xfree(sense);
xfree(rhs);
xfree(rngval);
xfree(matbeg);
xfree(matcnt);
xfree(matind);
xfree(matval);
xfree(lb);
xfree(ub);
/* check if copying problem data is successful */
if (status)
{ cplex_error(env, "CPXcopylp", status);
ret = GLP_EFAIL;
goto done;
}
/* change problem type to MIP */
status = CPXchgprobtype(env, prob, CPXPROB_MILP);
if (status)
{ cplex_error(env, "CPXchgprobtype", status);
ret = GLP_EFAIL;
goto done;
}
/* set column types */
indices = xcalloc(numcols+1, sizeof(int));
ctype = xcalloc(numcols+1, sizeof(char));
for (j = 1; j <= n; j++)
{ col = P->col[j];
indices[j-1] = j-1;
if (col->kind == GLP_CV)
ctype[j-1] = 'C';
else if (col->kind == GLP_IV)
ctype[j-1] = 'I';
else
xassert(col != col);
}
indices[numcols-1] = numcols-1;
ctype[numcols-1] = 'C';
status = CPXchgctype(env, prob, numcols, indices, ctype);
xfree(indices);
xfree(ctype);
if (status)
{ cplex_error(env, "CPXchgctype", status);
ret = GLP_EFAIL;
goto done;
}
/* set MIP node log display level */
status = CPXsetintparam(env, CPX_PARAM_MIPDISPLAY, 4);
if (status)
{ cplex_error(env, "CPXsetintparam(CPX_PARAM_MIPDISPLAY)",
status);
ret = GLP_EFAIL;
goto done;
}
/* set solution time limit */
if (parm->tm_lim < INT_MAX)
{ status = CPXsetdblparam(env, CPX_PARAM_TILIM,
(double)parm->tm_lim / 1000.0);
if (status)
{ cplex_error(env, "CPXsetdblparam(CPX_PARAM_TILIM)",
status);
ret = GLP_EFAIL;
goto done;
}
}
/* try to solve the problem */
status = CPXmipopt(env, prob);
if (status)
{ cplex_error(env, "CPXmipopt", status);
ret = GLP_EFAIL;
goto done;
}
/* determine solution status */
status = CPXgetstat(env, prob);
switch (status)
{ case CPXMIP_OPTIMAL:
case CPXMIP_OPTIMAL_TOL:
P->mip_stat = GLP_OPT;
break;
case CPXMIP_TIME_LIM_FEAS:
P->mip_stat = GLP_FEAS;
break;
case CPXMIP_TIME_LIM_INFEAS:
P->mip_stat = GLP_UNDEF;
ret = GLP_ETMLIM;
goto done;
default:
xprintf("CPXgetstat returned %d\n", status);
ret = GLP_EFAIL;
goto done;
}
/* obtain column values */
x = xcalloc(numcols, sizeof(double));
status = CPXgetmipx(env, prob, x, 0, numcols-1);
if (status)
{ cplex_error(env, "CPXgetmipx", status);
xfree(x);
P->mip_stat = GLP_UNDEF;
ret = GLP_EFAIL;
goto done;
}
for (j = 1; j <= n; j++)
{ double t;
col = P->col[j];
if (col->kind == GLP_IV)
{ t = floor(x[j-1] + 0.5);
xassert(fabs(x[j-1] - t) <= 1e-3);
x[j-1] = t;
}
col->mipx = x[j-1];
}
xfree(x);
/* calculate objective value */
sum = P->c0;
for (j = 1; j <= n; j++)
{ col = P->col[j];
sum += col->coef * col->mipx;
}
P->mip_obj = sum;
/* calculate row values */
for (i = 1; i <= m; i++)
{ row = P->row[i];
sum = 0.0;
for (aij = row->ptr; aij != NULL; aij = aij->r_next)
sum += aij->val * aij->col->mipx;
row->mipx = sum;
}
ret = 0;
done: if (ref != NULL)
xfree(ref);
if (prob != NULL)
CPXfreeprob(env, &prob);
if (logfile != NULL)
fclose(logfile);
if (env != NULL)
CPXcloseCPLEX(&env);
return ret;
}
/* eof */
_______________________________________________
Help-glpk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-glpk