[gnumeric] glpk: fix handling of integer and mixed-integer problems.



commit d5d5c96952e6439143099d10c700436815b19aeb
Author: Morten Welinder <terra gnome org>
Date:   Fri May 26 19:22:28 2017 -0400

    glpk: fix handling of integer and mixed-integer problems.
    
    The new format also has a variant when integer variables are present.

 NEWS                    |    1 +
 plugins/glpk/ChangeLog  |    5 +++
 plugins/glpk/gnm-glpk.c |   77 ++++++++++++++++++++++++++++++----------------
 3 files changed, 56 insertions(+), 27 deletions(-)
---
diff --git a/NEWS b/NEWS
index 586a712..68b5398 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Morten:
        * Test suite improvements.
        * Improve relative accuracy of BESSELJ and BESSELY.
        * New function REDUCEPI.
+       * Fix further fallout from glpk format change.  [#783077]
 
 --------------------------------------------------------------------------
 Gnumeric 1.12.34
diff --git a/plugins/glpk/ChangeLog b/plugins/glpk/ChangeLog
index 3bab4c8..7f2e677 100644
--- a/plugins/glpk/ChangeLog
+++ b/plugins/glpk/ChangeLog
@@ -1,3 +1,8 @@
+2017-05-26  Morten Welinder  <terra gnome org>
+
+       * gnm-glpk.c (gnm_glpk_read_solution_458): Format is different
+       when integer variables are present.  *Sigh*
+
 2017-03-20  Morten Welinder <terra gnome org>
 
        * Release 1.12.34
diff --git a/plugins/glpk/gnm-glpk.c b/plugins/glpk/gnm-glpk.c
index 3f8bce6..c85c86d 100644
--- a/plugins/glpk/gnm-glpk.c
+++ b/plugins/glpk/gnm-glpk.c
@@ -141,28 +141,15 @@ static gboolean
 gnm_glpk_read_solution_457 (GnmGlpk *lp,
                            GsfInputTextline *tl,
                            GnmSolverResult *result,
-                           GnmSolverSensitivity *sensitivity)
+                           GnmSolverSensitivity *sensitivity,
+                           gboolean has_integer)
 {
        GnmSubSolver *subsol = lp->parent;
-       GnmSolver *sol = GNM_SOLVER (subsol);
        const char *line;
        unsigned cols, rows, c, r;
-       gboolean has_integer;
-       GSList *l;
        int pstat, dstat;
        gnm_float val;
 
-       /*
-        * glpsol's output format is different if there are any integer
-        * constraint.  Go figure.
-        */
-       has_integer = sol->params->options.assume_discrete;
-       for (l = sol->params->constraints; !has_integer && l; l = l->next) {
-               GnmSolverConstraint *c = l->data;
-               has_integer = (c->type == GNM_SOLVER_INTEGER ||
-                              c->type == GNM_SOLVER_BOOLEAN);
-       }
-
        if ((line = gsf_input_textline_utf8_gets (tl)) == NULL)
                goto fail;
        if (sscanf (line, "%u %u", &rows, &cols) != 2 ||
@@ -239,13 +226,19 @@ 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] == ' '))
+#define READ_LINE(tl,line) do {                                        \
+       line = gsf_input_textline_utf8_gets (tl);               \
+        if (!line) goto fail;                                  \
+       if (gnm_solver_debug ())                                \
+               g_printerr ("%s\n", line);                      \
+} while (line[0] == 'c' && (line[1] == 0 || line[1] == ' '))
 
 static gboolean
 gnm_glpk_read_solution_458 (GnmGlpk *lp,
                            GsfInputTextline *tl,
                            GnmSolverResult *result,
-                           GnmSolverSensitivity *sensitivity)
+                           GnmSolverSensitivity *sensitivity,
+                           gboolean has_integer)
 {
        GnmSubSolver *subsol = lp->parent;
        const char *line;
@@ -255,17 +248,26 @@ gnm_glpk_read_solution_458 (GnmGlpk *lp,
 
        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 (has_integer) {
+               if (sscanf (line, "s %*s %u %u %c %" GNM_SCANF_g,
+                           &rows, &cols, &pstat, &val) != 4)
+                       goto fail;
+       } else {
+               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':
+       case 'o':
                result->quality = GNM_SOLVER_RESULT_OPTIMAL;
                break;
+       case 'f':
+               result->quality = GNM_SOLVER_RESULT_FEASIBLE;
+               break;
        case 'u':
        case 'i':
        case 'n':
@@ -282,8 +284,11 @@ gnm_glpk_read_solution_458 (GnmGlpk *lp,
 
                READ_LINE (tl, line);
 
-               if (sscanf (line, "i %d %c %" GNM_SCANF_g " %" GNM_SCANF_g,
-                           &r1, &rstat, &pval, &dval) != 4 ||
+               if ((has_integer
+                    ? sscanf (line, "i %d %" GNM_SCANF_g,
+                              &r1, &dval) != 2
+                    : sscanf (line, "i %d %c %" GNM_SCANF_g " %" GNM_SCANF_g,
+                              &r1, &rstat, &pval, &dval) != 4) ||
                    r1 != cidx + 1)
                        goto fail;
                // rstat?
@@ -298,8 +303,11 @@ gnm_glpk_read_solution_458 (GnmGlpk *lp,
 
                READ_LINE (tl, line);
 
-               if (sscanf (line, "j %d %c %" GNM_SCANF_g " %" GNM_SCANF_g,
-                           &c1, &cstat, &pval, &dval) != 4 ||
+               if ((has_integer
+                    ? sscanf (line, "j %d %" GNM_SCANF_g,
+                              &c1, &pval) != 2
+                    : sscanf (line, "j %d %c %" GNM_SCANF_g " %" GNM_SCANF_g,
+                              &c1, &cstat, &pval, &dval) != 4) ||
                    c1 != cidx + 1)
                        goto fail;
                // cstat?
@@ -325,6 +333,8 @@ gnm_glpk_read_solution (GnmGlpk *lp)
        GnmSolverResult *result = NULL;
        GnmSolverSensitivity *sensitivity = NULL;
        enum { SEC_UNKNOWN, SEC_ROWS, SEC_COLUMNS } state;
+       gboolean has_integer;
+       GSList *l;
 
        input = gsf_input_stdio_new (lp->result_filename, NULL);
        if (!input)
@@ -337,13 +347,26 @@ gnm_glpk_read_solution (GnmGlpk *lp)
 
        sensitivity = gnm_solver_sensitivity_new (sol);
 
+       /*
+        * glpsol's output format is different if there are any integer
+        * constraint.  Go figure.
+        */
+       has_integer = sol->params->options.assume_discrete;
+       for (l = sol->params->constraints; !has_integer && l; l = l->next) {
+               GnmSolverConstraint *c = l->data;
+               has_integer = (c->type == GNM_SOLVER_INTEGER ||
+                              c->type == GNM_SOLVER_BOOLEAN);
+       }
+
        switch (gnm_glpk_detect_version (lp, tl)) {
        case GLPK_457:
-               if (gnm_glpk_read_solution_457 (lp, tl, result, sensitivity))
+               if (gnm_glpk_read_solution_457 (lp, tl, result, sensitivity,
+                                               has_integer))
                        goto fail;
                break;
        case GLPK_458:
-               if (gnm_glpk_read_solution_458 (lp, tl, result, sensitivity))
+               if (gnm_glpk_read_solution_458 (lp, tl, result, sensitivity,
+                                               has_integer))
                        goto fail;
                break;
        default:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]