[gnumeric] Solver: adapt to glpk file format changes.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Solver: adapt to glpk file format changes.
- Date: Sun, 22 Jan 2017 18:16:17 +0000 (UTC)
commit 0b423b6138c402b8f098941ff2e7ff0f61ee46f6
Author: Morten Welinder <terra gnome org>
Date: Sun Jan 22 13:15:30 2017 -0500
Solver: adapt to glpk file format changes.
Glpk changed file format on or about version 4.58
NEWS | 1 +
plugins/glpk/ChangeLog | 8 ++
plugins/glpk/gnm-glpk.c | 183 +++++++++++++++++++++++++++++++++++++++++------
3 files changed, 171 insertions(+), 21 deletions(-)
---
diff --git a/NEWS b/NEWS
index 51d5939..1230c63 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ Morten:
* Bring documentation build into the 21 century.
* Non-linear solver improvements.
* Avoid atomizing style regions with conditional formats.
+ * Adapt to glpk file format changes.
--------------------------------------------------------------------------
Gnumeric 1.12.32
diff --git a/plugins/glpk/ChangeLog b/plugins/glpk/ChangeLog
index ef2e83e..becb1cb 100644
--- a/plugins/glpk/ChangeLog
+++ b/plugins/glpk/ChangeLog
@@ -1,3 +1,11 @@
+2017-01-22 Morten Welinder <terra gnome org>
+
+ * gnm-glpk.c (gnm_glpk_detect_version): New function.
+ (gnm_glpk_read_solution_457): Extract from gnm_glpk_read_solution.
+ (gnm_glpk_read_solution_458): New function.
+ (gnm_glpk_read_solution): Detect file format version and call
+ appropriate parser.
+
2016-08-20 Morten Welinder <terra gnome org>
* Release 1.12.32
diff --git a/plugins/glpk/gnm-glpk.c b/plugins/glpk/gnm-glpk.c
index 1ca7d8d..3f8bce6 100644
--- a/plugins/glpk/gnm-glpk.c
+++ b/plugins/glpk/gnm-glpk.c
@@ -101,22 +101,56 @@ parse_number (const char *s)
return g_ascii_strtod (s, NULL);
}
-static void
-gnm_glpk_read_solution (GnmGlpk *lp)
+typedef enum { GLPK_457, GLPK_458, GLPK_UNKNOWN } GlpkFileVersion;
+
+static GlpkFileVersion
+gnm_glpk_detect_version (GnmGlpk *lp,
+ GsfInputTextline *tl)
+{
+ GnmSubSolver *subsol = lp->parent;
+ gsf_off_t cur = gsf_input_tell (GSF_INPUT (tl));
+ GlpkFileVersion ver = GLPK_UNKNOWN;
+ const char *line;
+ unsigned cols, rows;
+
+ if ((line = gsf_input_textline_utf8_gets (tl)) == NULL)
+ goto out;
+ if (sscanf (line, "%u %u", &rows, &cols) == 2 &&
+ cols == g_hash_table_size (subsol->cell_from_name)) {
+ ver = GLPK_457;
+ if (gnm_solver_debug ())
+ g_printerr ("Detected version 4.57 file format\n");
+ goto out;
+ }
+
+ if ((line[0] == 'c' || line[0] == 's') && line[1] == ' ') {
+ ver = GLPK_458;
+ if (gnm_solver_debug ())
+ g_printerr ("Detected version 4.58 file format\n");
+ goto out;
+ }
+
+out:
+ // Extra seek due to gsf bug
+ gsf_input_seek (GSF_INPUT (tl), cur + 1, G_SEEK_SET);
+ gsf_input_seek (GSF_INPUT (tl), cur, G_SEEK_SET);
+ return ver;
+}
+
+static gboolean
+gnm_glpk_read_solution_457 (GnmGlpk *lp,
+ GsfInputTextline *tl,
+ GnmSolverResult *result,
+ GnmSolverSensitivity *sensitivity)
{
GnmSubSolver *subsol = lp->parent;
GnmSolver *sol = GNM_SOLVER (subsol);
- GsfInput *input;
- GsfInputTextline *tl = NULL;
const char *line;
- unsigned rows, cols, c, r;
- int pstat, dstat;
- gnm_float val;
- GnmSolverResult *result = NULL;
- GnmSolverSensitivity *sensitivity = NULL;
+ unsigned cols, rows, c, r;
gboolean has_integer;
GSList *l;
- enum { SEC_UNKNOWN, SEC_ROWS, SEC_COLUMNS } state;
+ int pstat, dstat;
+ gnm_float val;
/*
* glpsol's output format is different if there are any integer
@@ -129,17 +163,6 @@ gnm_glpk_read_solution (GnmGlpk *lp)
c->type == GNM_SOLVER_BOOLEAN);
}
- input = gsf_input_stdio_new (lp->result_filename, NULL);
- if (!input)
- goto fail;
- tl = GSF_INPUT_TEXTLINE (gsf_input_textline_new (input));
- g_object_unref (input);
-
- result = g_object_new (GNM_SOLVER_RESULT_TYPE, NULL);
- result->solution = g_new0 (gnm_float, sol->input_cells->len);
-
- sensitivity = gnm_solver_sensitivity_new (sol);
-
if ((line = gsf_input_textline_utf8_gets (tl)) == NULL)
goto fail;
if (sscanf (line, "%u %u", &rows, &cols) != 2 ||
@@ -209,6 +232,124 @@ gnm_glpk_read_solution (GnmGlpk *lp)
sensitivity->vars[idx].reduced_cost = dval;
}
+ // Success
+ return FALSE;
+
+fail:
+ return TRUE;
+}
+
+#define READ_LINE(tl,line) do { line = gsf_input_textline_utf8_gets (tl); if (!line) goto fail; } while
(line[0] == 'c' && (line[1] == 0 || line[1] == ' '))
+
+static gboolean
+gnm_glpk_read_solution_458 (GnmGlpk *lp,
+ GsfInputTextline *tl,
+ GnmSolverResult *result,
+ GnmSolverSensitivity *sensitivity)
+{
+ GnmSubSolver *subsol = lp->parent;
+ const char *line;
+ unsigned cols, rows, c, r;
+ gnm_float val;
+ char pstat, dstat;
+
+ READ_LINE (tl, line);
+
+ if (sscanf (line, "s %*s %u %u %c %c %" GNM_SCANF_g,
+ &rows, &cols, &pstat, &dstat, &val) != 5)
+ goto fail;
+ if (cols != g_hash_table_size (subsol->cell_from_name))
+ goto fail;
+
+ result->value = val;
+ switch (pstat) {
+ case 'f':
+ result->quality = GNM_SOLVER_RESULT_OPTIMAL;
+ break;
+ case 'u':
+ case 'i':
+ case 'n':
+ result->quality = GNM_SOLVER_RESULT_INFEASIBLE;
+ break;
+ default:
+ goto fail;
+ }
+
+ for (r = 0; r < rows; r++) {
+ gnm_float pval, dval;
+ char rstat;
+ unsigned r1, cidx = r;
+
+ READ_LINE (tl, line);
+
+ if (sscanf (line, "i %d %c %" GNM_SCANF_g " %" GNM_SCANF_g,
+ &r1, &rstat, &pval, &dval) != 4 ||
+ r1 != cidx + 1)
+ goto fail;
+ // rstat?
+
+ sensitivity->constraints[cidx].shadow_price = dval;
+ }
+
+ for (c = 0; c < cols; c++) {
+ gnm_float pval, dval;
+ char cstat;
+ unsigned c1, cidx = c;
+
+ READ_LINE (tl, line);
+
+ if (sscanf (line, "j %d %c %" GNM_SCANF_g " %" GNM_SCANF_g,
+ &c1, &cstat, &pval, &dval) != 4 ||
+ c1 != cidx + 1)
+ goto fail;
+ // cstat?
+
+ result->solution[cidx] = pval;
+ }
+
+ // Success
+ return FALSE;
+
+fail:
+ return TRUE;
+}
+
+static void
+gnm_glpk_read_solution (GnmGlpk *lp)
+{
+ GnmSubSolver *subsol = lp->parent;
+ GnmSolver *sol = GNM_SOLVER (subsol);
+ GsfInput *input;
+ GsfInputTextline *tl = NULL;
+ const char *line;
+ GnmSolverResult *result = NULL;
+ GnmSolverSensitivity *sensitivity = NULL;
+ enum { SEC_UNKNOWN, SEC_ROWS, SEC_COLUMNS } state;
+
+ input = gsf_input_stdio_new (lp->result_filename, NULL);
+ if (!input)
+ goto fail;
+ tl = GSF_INPUT_TEXTLINE (gsf_input_textline_new (input));
+ g_object_unref (input);
+
+ result = g_object_new (GNM_SOLVER_RESULT_TYPE, NULL);
+ result->solution = g_new0 (gnm_float, sol->input_cells->len);
+
+ sensitivity = gnm_solver_sensitivity_new (sol);
+
+ switch (gnm_glpk_detect_version (lp, tl)) {
+ case GLPK_457:
+ if (gnm_glpk_read_solution_457 (lp, tl, result, sensitivity))
+ goto fail;
+ break;
+ case GLPK_458:
+ if (gnm_glpk_read_solution_458 (lp, tl, result, sensitivity))
+ goto fail;
+ break;
+ default:
+ goto fail;
+ }
+
g_object_unref (tl);
tl = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]