Closed jkiviluo closed 2 years ago
We only have the raw (computer-readable) and pretty (human-readable) formats at present, but it's not too much trouble to write out in a different format.
I can guess what some of the above refers to, but where is this MathProg format defined?
I have not found a reference documentation, but the GLPK / GNU Mathprog source code has a file that does the output. I'm attaching it here.
This would give a pathway to start using HiGHS with GLPK / Mathprog model files that typically use GLPSOL as the solver. I believe there are quite a lot of those models lying around.
/* prsol.c (write basic solution in printable format) */
/***********************************************************************
* This code is part of GLPK (GNU Linear Programming Kit).
* Copyright (C) 2009-2016 Free Software Foundation, Inc.
* Written by Andrew Makhorin <mao@gnu.org>.
*
* GLPK is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPK is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GLPK. If not, see <http://www.gnu.org/licenses/>.
***********************************************************************/
#include "env.h"
#include "prob.h"
#define xfprintf glp_format
int glp_print_sol(glp_prob *P, const char *fname)
{ /* write basic solution in printable format */
glp_file *fp;
GLPROW *row;
GLPCOL *col;
int i, j, t, ae_ind, re_ind, ret;
double ae_max, re_max;
xprintf("Writing basic solution to '%s'...\n", fname);
fp = glp_open(fname, "w");
if (fp == NULL)
{ xprintf("Unable to create '%s' - %s\n", fname, get_err_msg());
ret = 1;
goto done;
}
xfprintf(fp, "%-12s%s\n", "Problem:",
P->name == NULL ? "" : P->name);
xfprintf(fp, "%-12s%d\n", "Rows:", P->m);
xfprintf(fp, "%-12s%d\n", "Columns:", P->n);
xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz);
t = glp_get_status(P);
xfprintf(fp, "%-12s%s\n", "Status:",
t == GLP_OPT ? "OPTIMAL" :
t == GLP_FEAS ? "FEASIBLE" :
t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" :
t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" :
t == GLP_UNBND ? "UNBOUNDED" :
t == GLP_UNDEF ? "UNDEFINED" : "???");
xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:",
P->obj == NULL ? "" : P->obj,
P->obj == NULL ? "" : " = ", P->obj_val,
P->dir == GLP_MIN ? "MINimum" :
P->dir == GLP_MAX ? "MAXimum" : "???");
xfprintf(fp, "\n");
xfprintf(fp, " No. Row name St Activity Lower bound "
" Upper bound Marginal\n");
xfprintf(fp, "------ ------------ -- ------------- ------------- "
"------------- -------------\n");
for (i = 1; i <= P->m; i++)
{ row = P->row[i];
xfprintf(fp, "%6d ", i);
if (row->name == NULL || strlen(row->name) <= 12)
xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name);
else
xfprintf(fp, "%s\n%20s", row->name, "");
xfprintf(fp, "%s ",
row->stat == GLP_BS ? "B " :
row->stat == GLP_NL ? "NL" :
row->stat == GLP_NU ? "NU" :
row->stat == GLP_NF ? "NF" :
row->stat == GLP_NS ? "NS" : "??");
xfprintf(fp, "%13.6g ",
fabs(row->prim) <= 1e-9 ? 0.0 : row->prim);
if (row->type == GLP_LO || row->type == GLP_DB ||
row->type == GLP_FX)
xfprintf(fp, "%13.6g ", row->lb);
else
xfprintf(fp, "%13s ", "");
if (row->type == GLP_UP || row->type == GLP_DB)
xfprintf(fp, "%13.6g ", row->ub);
else
xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : "");
if (row->stat != GLP_BS)
{ if (fabs(row->dual) <= 1e-9)
xfprintf(fp, "%13s", "< eps");
else
xfprintf(fp, "%13.6g ", row->dual);
}
xfprintf(fp, "\n");
}
xfprintf(fp, "\n");
xfprintf(fp, " No. Column name St Activity Lower bound "
" Upper bound Marginal\n");
xfprintf(fp, "------ ------------ -- ------------- ------------- "
"------------- -------------\n");
for (j = 1; j <= P->n; j++)
{ col = P->col[j];
xfprintf(fp, "%6d ", j);
if (col->name == NULL || strlen(col->name) <= 12)
xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name);
else
xfprintf(fp, "%s\n%20s", col->name, "");
xfprintf(fp, "%s ",
col->stat == GLP_BS ? "B " :
col->stat == GLP_NL ? "NL" :
col->stat == GLP_NU ? "NU" :
col->stat == GLP_NF ? "NF" :
col->stat == GLP_NS ? "NS" : "??");
xfprintf(fp, "%13.6g ",
fabs(col->prim) <= 1e-9 ? 0.0 : col->prim);
if (col->type == GLP_LO || col->type == GLP_DB ||
col->type == GLP_FX)
xfprintf(fp, "%13.6g ", col->lb);
else
xfprintf(fp, "%13s ", "");
if (col->type == GLP_UP || col->type == GLP_DB)
xfprintf(fp, "%13.6g ", col->ub);
else
xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : "");
if (col->stat != GLP_BS)
{ if (fabs(col->dual) <= 1e-9)
xfprintf(fp, "%13s", "< eps");
else
xfprintf(fp, "%13.6g ", col->dual);
}
xfprintf(fp, "\n");
}
xfprintf(fp, "\n");
xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n");
xfprintf(fp, "\n");
glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max,
&re_ind);
xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n",
ae_max, ae_ind);
xfprintf(fp, " max.rel.err = %.2e on row %d\n",
re_max, re_ind);
xfprintf(fp, "%8s%s\n", "",
re_max <= 1e-9 ? "High quality" :
re_max <= 1e-6 ? "Medium quality" :
re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG");
xfprintf(fp, "\n");
glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max,
&re_ind);
xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n",
ae_max, ae_ind <= P->m ? "row" : "column",
ae_ind <= P->m ? ae_ind : ae_ind - P->m);
xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
re_max, re_ind <= P->m ? "row" : "column",
re_ind <= P->m ? re_ind : re_ind - P->m);
xfprintf(fp, "%8s%s\n", "",
re_max <= 1e-9 ? "High quality" :
re_max <= 1e-6 ? "Medium quality" :
re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL"
"E");
xfprintf(fp, "\n");
glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max,
&re_ind);
xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n",
ae_max, ae_ind == 0 ? 0 : ae_ind - P->m);
xfprintf(fp, " max.rel.err = %.2e on column %d\n",
re_max, re_ind == 0 ? 0 : re_ind - P->m);
xfprintf(fp, "%8s%s\n", "",
re_max <= 1e-9 ? "High quality" :
re_max <= 1e-6 ? "Medium quality" :
re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG");
xfprintf(fp, "\n");
glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max,
&re_ind);
xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n",
ae_max, ae_ind <= P->m ? "row" : "column",
ae_ind <= P->m ? ae_ind : ae_ind - P->m);
xfprintf(fp, " max.rel.err = %.2e on %s %d\n",
re_max, re_ind <= P->m ? "row" : "column",
re_ind <= P->m ? re_ind : re_ind - P->m);
xfprintf(fp, "%8s%s\n", "",
re_max <= 1e-9 ? "High quality" :
re_max <= 1e-6 ? "Medium quality" :
re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE")
;
xfprintf(fp, "\n");
xfprintf(fp, "End of output\n");
#if 0 /* FIXME */
xfflush(fp);
#endif
if (glp_ioerr(fp))
{ xprintf("Write error on '%s' - %s\n", fname, get_err_msg());
ret = 1;
goto done;
}
ret = 0;
done: if (fp != NULL) glp_close(fp);
return ret;
}
/* eof */
Thanks. This helps me work out the format of the solution file, but it sounds as if this system involves an input file format (see [http://manpages.ubuntu.com/manpages/trusty/man1/glpsol.1.html]) that we can't read
This should probably be a discussion topic rather than an issue, but I'd like to know if there are other solution file formats available or planned?
For my part, I'd like to read the solution to MathProg in order to use the code that writes out results, but the solution file format in MathProg is different:
s bas 17169 14089 f f 1.06684e+11 i 1 b 1.06684e+11 0
i 2 s 947.477 1579.87 i 3 s 864.792 1579.87 i 4 s 814.937 1579.87 ...