[gnumeric] Solver: improve glpk constraint handling too.



commit f482248f9398aaeb4947a1516dcddcce23dfa5b1
Author: Morten Welinder <terra gnome org>
Date:   Tue May 5 21:46:19 2015 -0400

    Solver: improve glpk constraint handling too.

 plugins/glpk/glpk-write.c |   93 ++++++++++++++++-----------------------------
 1 files changed, 33 insertions(+), 60 deletions(-)
---
diff --git a/plugins/glpk/glpk-write.c b/plugins/glpk/glpk-write.c
index e227e3d..01a7a37 100644
--- a/plugins/glpk/glpk-write.c
+++ b/plugins/glpk/glpk-write.c
@@ -36,44 +36,6 @@
 #include <string.h>
 
 
-static gboolean
-gnm_solver_get_lp_coeff (GnmCell *target, GnmCell *cell,
-                        gnm_float *x, GError **err)
-{
-        gnm_float x0, x1;
-       gboolean res = FALSE;
-
-       gnm_cell_eval (target);
-       if (!VALUE_IS_NUMBER (target->value))
-               goto fail;
-       x0 = value_get_as_float (target->value);
-
-       gnm_cell_set_value (cell, value_new_float (1));
-       cell_queue_recalc (cell);
-       gnm_cell_eval (target);
-       if (!VALUE_IS_NUMBER (target->value))
-               goto fail;
-       x1 = value_get_as_float (target->value);
-
-       *x = x1 - x0;
-       res = TRUE;
-       goto out;
-
-fail:
-       g_set_error (err,
-                    go_error_invalid (),
-                    0,
-                    _("Target cell did not evaluate to a number."));
-       *x = 0;
-
-out:
-       gnm_cell_set_value (cell, value_new_int (0));
-       cell_queue_recalc (cell);
-       gnm_cell_eval (target);
-
-       return res;
-}
-
 static const char *
 glpk_var_name (GnmSubSolver *ssol, GnmCell const *cell)
 {
@@ -84,6 +46,7 @@ glpk_var_name (GnmSubSolver *ssol, GnmCell const *cell)
 
 static gboolean
 glpk_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
+                 gnm_float const *x1, gnm_float const *x2, guint8 const *pdisc,
                  gboolean zero_too,
                  gnm_float cst, GError **err)
 {
@@ -91,32 +54,30 @@ glpk_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
        unsigned ui;
        gboolean any = FALSE;
        gnm_float y;
-       GPtrArray *old_values;
        gboolean ok = TRUE;
        GPtrArray *input_cells = sol->input_cells;
+       gnm_float *cs;
 
        if (!target) {
                gnm_string_add_number (dst, cst);
                return TRUE;
        }
 
-       old_values = g_ptr_array_new ();
-       for (ui = 0; ui < input_cells->len; ui++) {
-               GnmCell *cell = g_ptr_array_index (input_cells, ui);
-               g_ptr_array_add (old_values, value_dup (cell->value));
-               gnm_cell_set_value (cell, value_new_int (0));
-               cell_queue_recalc (cell);
-       }
-
+       gnm_solver_set_vars (sol, x1);
        gnm_cell_eval (target);
        y = cst + value_get_as_float (target->value);
 
+       cs = gnm_solver_get_lp_coeffs (sol, target, x1, x2, pdisc, err);
+       if (!cs)
+               goto fail;
+
+       /* Adjust constant for choice of x1.  */
+       for (ui = 0; ui < input_cells->len; ui++)
+               y -= x1[ui] * cs[ui];
+
        for (ui = 0; ui < input_cells->len; ui++) {
                GnmCell *cell = g_ptr_array_index (input_cells, ui);
-               gnm_float x;
-               ok = gnm_solver_get_lp_coeff (target, cell, &x, err);
-               if (!ok)
-                       goto fail;
+               gnm_float x = cs[ui];
                if (x == 0 && !zero_too)
                        continue;
 
@@ -151,13 +112,7 @@ glpk_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
        }
 
 fail:
-       for (ui = 0; ui < input_cells->len; ui++) {
-               GnmCell *cell = g_ptr_array_index (input_cells, ui);
-               GnmValue *old = g_ptr_array_index (old_values, ui);
-               gnm_cell_set_value (cell, old);
-               cell_queue_recalc (cell);
-       }
-       g_ptr_array_free (old_values, TRUE);
+       g_free (cs);
 
        return ok;
 }
@@ -176,6 +131,9 @@ glpk_create_program (GnmSubSolver *ssol, GOIOContext *io_context, GError **err)
        GnmCell *target_cell = gnm_solver_param_get_target_cell (sp);
        GPtrArray *input_cells = sol->input_cells;
        gsize progress;
+       GPtrArray *old = NULL;
+       gnm_float *x1 = NULL, *x2 = NULL;
+       guint8 *pdisc = NULL;
 
        /* ---------------------------------------- */
 
@@ -202,7 +160,7 @@ glpk_create_program (GnmSubSolver *ssol, GOIOContext *io_context, GError **err)
 
        /* ---------------------------------------- */
 
-       progress = 2;
+       progress = 3;
        if (sp->options.assume_non_negative) progress++;
        if (sp->options.assume_discrete) progress++;
        progress += g_slist_length (sp->constraints);
@@ -211,6 +169,13 @@ glpk_create_program (GnmSubSolver *ssol, GOIOContext *io_context, GError **err)
 
        /* ---------------------------------------- */
 
+       old = gnm_solver_save_vars (sol);
+
+       gnm_solver_pick_lp_coords (sol, &x1, &x2, &pdisc);
+       go_io_count_progress_update (io_context, 1);
+
+       /* ---------------------------------------- */
+
        switch (sp->problem_type) {
        case GNM_SOLVER_MINIMIZE:
                g_string_append (objfunc, "Minimize\n");
@@ -224,7 +189,7 @@ glpk_create_program (GnmSubSolver *ssol, GOIOContext *io_context, GError **err)
        go_io_count_progress_update (io_context, 1);
 
        g_string_append (objfunc, " obj: ");
-       if (!glpk_affine_func (objfunc, target_cell, ssol,
+       if (!glpk_affine_func (objfunc, target_cell, ssol, x1, x2, pdisc,
                               TRUE, 0, err))
                goto fail;
        g_string_append (objfunc, "\n");
@@ -296,6 +261,7 @@ glpk_create_program (GnmSubSolver *ssol, GOIOContext *io_context, GError **err)
 
                                ok = glpk_affine_func
                                        (constraints, lhs, ssol,
+                                        x1, x2, pdisc,
                                         FALSE, cl, err);
                                if (!ok)
                                        goto fail;
@@ -306,6 +272,7 @@ glpk_create_program (GnmSubSolver *ssol, GOIOContext *io_context, GError **err)
 
                                ok = glpk_affine_func
                                        (constraints, rhs, ssol,
+                                        x1, x2, pdisc,
                                         FALSE, cr, err);
                                if (!ok)
                                        goto fail;
@@ -341,6 +308,12 @@ fail:
        g_string_free (constraints, TRUE);
        g_string_free (integers, TRUE);
        g_string_free (binaries, TRUE);
+       g_free (x1);
+       g_free (x2);
+       g_free (pdisc);
+
+       if (old)
+               gnm_solver_restore_vars (sol, old);
 
        return prg;
 }


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