[gnumeric] Solver: code cleanup.



commit 43196c099a9a22695476ba07a4df0df9c115b4da
Author: Morten Welinder <terra gnome org>
Date:   Sat Apr 25 12:57:33 2015 -0400

    Solver: code cleanup.

 plugins/glpk/glpk-write.c       |   52 ++++++++++++++-----------------
 plugins/lpsolve/lpsolve-write.c |   45 +++++++++++++--------------
 plugins/nlsolve/gnm-nlsolve.c   |   53 ++++++--------------------------
 src/gnm-marshalers.list         |    2 +-
 src/tools/ChangeLog             |    5 +++
 src/tools/gnm-solver.c          |   64 ++++++++++++++++++++++----------------
 src/tools/gnm-solver.h          |    4 +-
 7 files changed, 100 insertions(+), 125 deletions(-)
---
diff --git a/plugins/glpk/glpk-write.c b/plugins/glpk/glpk-write.c
index f3892ae..a9b9a73 100644
--- a/plugins/glpk/glpk-write.c
+++ b/plugins/glpk/glpk-write.c
@@ -85,12 +85,12 @@ glpk_var_name (GnmSubSolver *ssol, GnmCell const *cell)
 static gboolean
 glpk_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
                  gboolean zero_too,
-                 gnm_float cst, GSList *input_cells, GError **err)
+                 gnm_float cst, GPtrArray *input_cells, GError **err)
 {
-       GSList *l, *ol;
+       unsigned ui;
        gboolean any = FALSE;
        gnm_float y;
-       GSList *old_values = NULL;
+       GPtrArray *old_values;
        gboolean ok = TRUE;
 
        if (!target) {
@@ -98,20 +98,19 @@ glpk_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
                return TRUE;
        }
 
-       for (l = input_cells; l; l = l->next) {
-               GnmCell *cell = l->data;
-               old_values = g_slist_prepend (old_values,
-                                             value_dup (cell->value));
+       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);
        }
-       old_values = g_slist_reverse (old_values);
 
        gnm_cell_eval (target);
        y = cst + value_get_as_float (target->value);
 
-       for (l = input_cells; l; l = l->next) {
-               GnmCell *cell = l->data;
+       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)
@@ -150,15 +149,13 @@ glpk_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
        }
 
 fail:
-       for (l = input_cells, ol = old_values;
-            l;
-            l = l->next, ol = ol->next) {
-               GnmCell *cell = l->data;
-               GnmValue *old = ol->data;
+       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_slist_free (old_values);
+       g_ptr_array_free (old_values, TRUE);
 
        return ok;
 }
@@ -175,7 +172,7 @@ glpk_create_program (Sheet *sheet, GOIOContext *io_context,
        GString *objfunc = g_string_new (NULL);
        GSList *l;
        GnmCell *target_cell = gnm_solver_param_get_target_cell (sp);
-       GSList *input_cells = gnm_solver_param_get_input_cells (sp);
+       GPtrArray *input_cells = gnm_solver_param_get_input_cells (sp);
        gsize progress;
 
        /* ---------------------------------------- */
@@ -192,11 +189,10 @@ glpk_create_program (Sheet *sheet, GOIOContext *io_context,
 
        if (ssol) {
                unsigned ui;
-               GSList *l;
 
-               for (ui = 1, l = input_cells; l; ui++, l = l->next) {
-                       GnmCell *cell = l->data;
-                       char *name = g_strdup_printf ("X_%u", ui);
+               for (ui = 0; ui < input_cells->len; ui++) {
+                       GnmCell *cell = g_ptr_array_index (input_cells, ui);
+                       char *name = g_strdup_printf ("X_%u", ui + 1);
                        gnm_sub_solver_name_cell (ssol, cell, name);
                        g_free (name);
                }
@@ -235,9 +231,9 @@ glpk_create_program (Sheet *sheet, GOIOContext *io_context,
        /* ---------------------------------------- */
 
        if (sp->options.assume_non_negative) {
-               GSList *l;
-               for (l = input_cells; l; l = l->next) {
-                       GnmCell *cell = l->data;
+               unsigned ui;
+               for (ui = 0; ui < input_cells->len; ui++) {
+                       GnmCell *cell = g_ptr_array_index (input_cells, ui);
                        g_string_append_printf (constraints, " %s >= 0\n",
                                                glpk_var_name (ssol, cell));
                }
@@ -245,9 +241,9 @@ glpk_create_program (Sheet *sheet, GOIOContext *io_context,
        }
 
        if (sp->options.assume_discrete) {
-               GSList *l;
-               for (l = input_cells; l; l = l->next) {
-                       GnmCell *cell = l->data;
+               unsigned ui;
+               for (ui = 0; ui < input_cells->len; ui++) {
+                       GnmCell *cell = g_ptr_array_index (input_cells, ui);
                        g_string_append_printf (integers, " %s\n",
                                                glpk_var_name (ssol, cell));
                }
@@ -343,7 +339,7 @@ fail:
        g_string_free (constraints, TRUE);
        g_string_free (integers, TRUE);
        g_string_free (binaries, TRUE);
-       g_slist_free (input_cells);
+       g_ptr_array_free (input_cells, TRUE);
 
        return prg;
 }
diff --git a/plugins/lpsolve/lpsolve-write.c b/plugins/lpsolve/lpsolve-write.c
index 863d34c..cb9cee9 100644
--- a/plugins/lpsolve/lpsolve-write.c
+++ b/plugins/lpsolve/lpsolve-write.c
@@ -88,12 +88,12 @@ lpsolve_var_name (GnmSubSolver *ssol, GnmCell const *cell)
 
 static gboolean
 lpsolve_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
-                    gnm_float cst, GSList *input_cells, GError **err)
+                    gnm_float cst, GPtrArray *input_cells, GError **err)
 {
-       GSList *l, *ol;
+       unsigned ui;
        gboolean any = FALSE;
        gnm_float y;
-       GSList *old_values = NULL;
+       GPtrArray *old_values;
        gboolean ok = TRUE;
 
        if (!target) {
@@ -101,20 +101,19 @@ lpsolve_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
                return TRUE;
        }
 
-       for (l = input_cells; l; l = l->next) {
-               GnmCell *cell = l->data;
-               old_values = g_slist_prepend (old_values,
-                                             value_dup (cell->value));
+       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);
        }
-       old_values = g_slist_reverse (old_values);
 
        gnm_cell_eval (target);
        y = cst + value_get_as_float (target->value);
 
-       for (l = input_cells; l; l = l->next) {
-               GnmCell *cell = l->data;
+       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)
@@ -153,15 +152,13 @@ lpsolve_affine_func (GString *dst, GnmCell *target, GnmSubSolver *ssol,
        }
 
 fail:
-       for (l = input_cells, ol = old_values;
-            l;
-            l = l->next, ol = ol->next) {
-               GnmCell *cell = l->data;
-               GnmValue *old = ol->data;
+       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_slist_free (old_values);
+       g_ptr_array_free (old_values, TRUE);
 
        return ok;
 }
@@ -177,7 +174,7 @@ lpsolve_create_program (Sheet *sheet, GOIOContext *io_context,
        GString *objfunc = g_string_new (NULL);
        GSList *l;
        GnmCell *target_cell = gnm_solver_param_get_target_cell (sp);
-       GSList *input_cells = gnm_solver_param_get_input_cells (sp);
+       GPtrArray *input_cells = gnm_solver_param_get_input_cells (sp);
        gsize progress;
 
        /* ---------------------------------------- */
@@ -222,9 +219,9 @@ lpsolve_create_program (Sheet *sheet, GOIOContext *io_context,
        /* ---------------------------------------- */
 
        if (sp->options.assume_non_negative) {
-               GSList *l;
-               for (l = input_cells; l; l = l->next) {
-                       GnmCell *cell = l->data;
+               unsigned ui;
+               for (ui = 0; ui < input_cells->len; ui++) {
+                       GnmCell *cell = g_ptr_array_index (input_cells, ui);
                        g_string_append (constraints,
                                         lpsolve_var_name (ssol, cell));
                        g_string_append (constraints, " >= 0;\n");
@@ -233,9 +230,9 @@ lpsolve_create_program (Sheet *sheet, GOIOContext *io_context,
        }
 
        if (sp->options.assume_discrete) {
-               GSList *l;
-               for (l = input_cells; l; l = l->next) {
-                       GnmCell *cell = l->data;
+               unsigned ui;
+               for (ui = 0; ui < input_cells->len; ui++) {
+                       GnmCell *cell = g_ptr_array_index (input_cells, ui);
                        g_string_append (declarations, "int ");
                        g_string_append (declarations,
                                         lpsolve_var_name (ssol, cell));
@@ -326,7 +323,7 @@ fail:
        g_string_free (objfunc, TRUE);
        g_string_free (constraints, TRUE);
        g_string_free (declarations, TRUE);
-       g_slist_free (input_cells);
+       g_ptr_array_free (input_cells, TRUE);
 
        return prg;
 }
diff --git a/plugins/nlsolve/gnm-nlsolve.c b/plugins/nlsolve/gnm-nlsolve.c
index ff7401d..046d4f4 100644
--- a/plugins/nlsolve/gnm-nlsolve.c
+++ b/plugins/nlsolve/gnm-nlsolve.c
@@ -7,7 +7,6 @@
 #include "regression.h"
 #include "rangefunc.h"
 #include "workbook.h"
-#include "application.h"
 #include <gsf/gsf-impl-utils.h>
 #include <glib/gi18n-lib.h>
 #include <string.h>
@@ -64,17 +63,19 @@ typedef struct {
 
        /* Parameters: */
        gboolean debug;
-       guint64 max_iter;
        gnm_float min_factor;
 } GnmNlsolve;
 
 static void free_matrix (gnm_float **m, int n);
+static void rosenbrock_tentative_end (GnmNlsolve *nl, gboolean accept);
 
 static void
 gnm_nlsolve_final (GnmNlsolve *nl)
 {
        const int n = nl->vars->len;
 
+       rosenbrock_tentative_end (nl, FALSE);
+
        if (nl->vars)
                g_ptr_array_free (nl->vars, TRUE);
        g_free (nl->xk);
@@ -620,17 +621,6 @@ rosenbrock_iter (GnmNlsolve *nl)
        return any_at_all;
 }
 
-static void
-rosenbrock_shutdown (GnmNlsolve *nl)
-{
-       const int n = nl->vars->len;
-
-       rosenbrock_tentative_end (nl, FALSE);
-
-       free_matrix (nl->xi, n);
-       nl->xi = NULL;
-}
-
 static gboolean
 polish_iter (GnmNlsolve *nl)
 {
@@ -679,13 +669,11 @@ polish_iter (GnmNlsolve *nl)
        return any_at_all;
 }
 
-static void
+static gboolean
 gnm_nlsolve_iterate (GnmIterSolver *isol, GnmNlsolve *nl)
 {
-       GnmSolver *sol = GNM_SOLVER (isol);
        const int n = nl->vars->len;
-       gboolean ok;
-       gboolean call_again = TRUE;
+       gboolean progress;
 
        if (isol->iterations == 0)
                rosenbrock_init (nl);
@@ -696,28 +684,13 @@ gnm_nlsolve_iterate (GnmIterSolver *isol, GnmNlsolve *nl)
                print_vector ("Current point", nl->xk, n);
        }
 
-       ok = rosenbrock_iter (nl);
-
-       if (!ok && !nl->tentative) {
-               ok = polish_iter (nl);
-       }
+       progress = rosenbrock_iter (nl);
 
-       if (!ok) {
-               gnm_solver_set_status (sol, GNM_SOLVER_STATUS_DONE);
-               call_again = FALSE;
+       if (!progress && !nl->tentative) {
+               progress = polish_iter (nl);
        }
 
-       if (call_again && isol->iterations >= nl->max_iter) {
-               gnm_solver_set_status (sol, GNM_SOLVER_STATUS_DONE);
-               call_again = FALSE;
-       }
-
-       if (!call_again) {
-               set_vector (nl, nl->x0);
-               gnm_app_recalc ();
-
-               rosenbrock_shutdown (nl);
-       }
+       return progress;
 }
 
 gboolean
@@ -740,7 +713,6 @@ nlsolve_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params)
                                           "params", params,
                                           NULL);
        GnmNlsolve *nl = g_new0 (GnmNlsolve, 1);
-       GSList *input_cells, *l;
        int n;
        GnmValue const *vinput = gnm_solver_param_get_input (params);
        GnmEvalPos ep;
@@ -760,16 +732,11 @@ nlsolve_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params)
        }
 
        nl->debug = gnm_solver_debug ();
-       nl->max_iter = params->options.max_iter;
        nl->min_factor = 1e-10;
 
        nl->target = gnm_solver_param_get_target_cell (params);
 
-       nl->vars = g_ptr_array_new ();
-       input_cells = gnm_solver_param_get_input_cells (params);
-       for (l = input_cells; l; l = l->next)
-               g_ptr_array_add (nl->vars, l->data);
-       g_slist_free (input_cells);
+       nl->vars = gnm_solver_param_get_input_cells (params);
        n = nl->vars->len;
 
        nl->x0 = g_new (gnm_float, n);
diff --git a/src/gnm-marshalers.list b/src/gnm-marshalers.list
index 8961862..7b01393 100644
--- a/src/gnm-marshalers.list
+++ b/src/gnm-marshalers.list
@@ -23,4 +23,4 @@
 BOOLEAN:POINTER
 BOOLEAN:OBJECT,POINTER
 VOID:BOOLEAN,INT
-VOID:VOID
+BOOLEAN:VOID
diff --git a/src/tools/ChangeLog b/src/tools/ChangeLog
index 385d9ad..c10f211 100644
--- a/src/tools/ChangeLog
+++ b/src/tools/ChangeLog
@@ -1,3 +1,8 @@
+2015-04-25  Morten Welinder  <terra gnome org>
+
+       * gnm-solver.c (gnm_solver_param_get_input_cells): Return result
+       as a GPtrArray for random access.  All callers changed.
+
 2015-04-24  Morten Welinder  <terra gnome org>
 
        * gnm-solver.c (gnm_solver_get_current_values): Delete unused
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index d0279f1..6c9abce 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -10,6 +10,7 @@
 #include "gnm-solver.h"
 #include "workbook-view.h"
 #include "workbook-control.h"
+#include "application.h"
 #include "gnm-marshalers.h"
 #include "dao.h"
 #include "gui-util.h"
@@ -507,31 +508,31 @@ gnm_solver_param_set_input (GnmSolverParameters *sp, GnmValue *v)
 static GnmValue *
 cb_grab_cells (GnmCellIter const *iter, gpointer user)
 {
-       GSList **the_list = user;
+       GPtrArray *input_cells = user;
        GnmCell *cell;
 
        if (NULL == (cell = iter->cell))
                cell = sheet_cell_create (iter->pp.sheet,
                        iter->pp.eval.col, iter->pp.eval.row);
-       *the_list = g_slist_prepend (*the_list, cell);
+       g_ptr_array_add (input_cells, cell);
        return NULL;
 }
 
-GSList *
+GPtrArray *
 gnm_solver_param_get_input_cells (GnmSolverParameters const *sp)
 {
        GnmValue const *vr = gnm_solver_param_get_input (sp);
-       GSList *input_cells = NULL;
-       GnmEvalPos ep;
+       GPtrArray *input_cells = g_ptr_array_new ();
 
-       if (!vr)
-               return NULL;
+       if (vr) {
+               GnmEvalPos ep;
+               eval_pos_init_sheet (&ep, sp->sheet);
+               workbook_foreach_cell_in_range (&ep, vr, CELL_ITER_ALL,
+                                               cb_grab_cells,
+                                               input_cells);
+       }
 
-       eval_pos_init_sheet (&ep, sp->sheet);
-       workbook_foreach_cell_in_range (&ep, vr, CELL_ITER_ALL,
-                                       cb_grab_cells,
-                                       &input_cells);
-       return g_slist_reverse (input_cells);
+       return input_cells;
 }
 
 void
@@ -584,7 +585,8 @@ gnm_solver_param_valid (GnmSolverParameters const *sp, GError **err)
        GSList *l;
        int i;
        GnmCell *target_cell;
-       GSList *input_cells;
+       GPtrArray *input_cells;
+       unsigned ui;
 
        target_cell = gnm_solver_param_get_target_cell (sp);
        if (!target_cell) {
@@ -617,8 +619,8 @@ gnm_solver_param_valid (GnmSolverParameters const *sp, GError **err)
                return FALSE;
        }
        input_cells = gnm_solver_param_get_input_cells (sp);
-       for (l = input_cells; l; l = l->next) {
-               GnmCell *cell = l->data;
+       for (ui = 0; ui < input_cells->len; ui++) {
+               GnmCell *cell = g_ptr_array_index (input_cells, ui);
                if (gnm_cell_has_expr (cell)) {
                        char *cname = gnm_solver_cell_name (cell, sp->sheet);
                        g_set_error (err,
@@ -627,11 +629,11 @@ gnm_solver_param_valid (GnmSolverParameters const *sp, GError **err)
                                     _("Input cell %s contains a formula"),
                                     cname);
                        g_free (cname);
-                       g_slist_free (input_cells);
+                       g_ptr_array_free (input_cells, TRUE);
                        return FALSE;
                }
        }
-       g_slist_free (input_cells);
+       g_ptr_array_free (input_cells, TRUE);
 
        for (i = 1, l = sp->constraints; l; i++, l = l->next) {
                GnmSolverConstraint *c = l->data;
@@ -1136,12 +1138,12 @@ gnm_solver_check_constraints (GnmSolver *solver)
 
        if (sp->options.assume_non_negative ||
            sp->options.assume_discrete) {
-               GSList *input_cells = gnm_solver_param_get_input_cells (sp);
-               GSList *l;
+               GPtrArray *input_cells = gnm_solver_param_get_input_cells (sp);
+               unsigned ui;
                gboolean bad;
 
-               for (l = input_cells; l; l = l->next) {
-                       GnmCell *cell = l->data;
+               for (ui = 0; ui < input_cells->len; ui++) {
+                       GnmCell *cell = g_ptr_array_index (input_cells, ui);
                        gnm_float val;
 
                        gnm_cell_eval (cell);
@@ -1152,8 +1154,8 @@ gnm_solver_check_constraints (GnmSolver *solver)
                            val != gnm_floor (val))
                                break;
                }
-               bad = (l != NULL);
-               g_slist_free (input_cells);
+               bad = (ui < input_cells->len);
+               g_ptr_array_free (input_cells, TRUE);
 
                if (bad)
                        return FALSE;
@@ -2169,13 +2171,21 @@ gnm_iter_solver_idle (gpointer data)
 {
        GnmIterSolver *isol = data;
        GnmSolver *sol = &isol->parent;
+       GnmSolverParameters *params = sol->params;
+       gboolean progress;
 
-       g_signal_emit (isol, iter_solver_signals[ITER_SOL_SIG_ITERATE], 0);
-
+       g_signal_emit (isol, iter_solver_signals[ITER_SOL_SIG_ITERATE], 0, &progress);
        isol->iterations++;
 
+       if (!gnm_solver_finished (sol) &&
+           (!progress || isol->iterations >= params->options.max_iter))
+               gnm_solver_set_status (sol, GNM_SOLVER_STATUS_DONE);
+
        if (gnm_solver_finished (sol)) {
                isol->idle_tag = 0;
+
+               gnm_app_recalc ();
+
                return FALSE;
        } else {
                /* Call again.  */
@@ -2227,8 +2237,8 @@ gnm_iter_solver_class_init (GObjectClass *object_class)
                              G_SIGNAL_RUN_LAST,
                              G_STRUCT_OFFSET (GnmIterSolverClass, iterate),
                              NULL, NULL,
-                             gnm__VOID__VOID,
-                             G_TYPE_NONE, 0);
+                             gnm__BOOLEAN__VOID,
+                             G_TYPE_BOOLEAN, 0);
 }
 
 GSF_CLASS (GnmIterSolver, gnm_iter_solver,
diff --git a/src/tools/gnm-solver.h b/src/tools/gnm-solver.h
index ca9a9b2..5711837 100644
--- a/src/tools/gnm-solver.h
+++ b/src/tools/gnm-solver.h
@@ -103,7 +103,7 @@ char *gnm_solver_constraint_as_str (GnmSolverConstraint const *c, Sheet *sheet);
 
 typedef struct {
        int                 max_time_sec;
-       int                 max_iter;
+       unsigned            max_iter;
        GnmSolverFactory   *algorithm;
        GnmSolverModelType  model_type;
        gboolean            assume_non_negative;
@@ -149,7 +149,7 @@ gboolean gnm_solver_param_equal (GnmSolverParameters const *a,
 
 GnmValue const *gnm_solver_param_get_input (GnmSolverParameters const *sp);
 void gnm_solver_param_set_input (GnmSolverParameters *sp, GnmValue *v);
-GSList *gnm_solver_param_get_input_cells (GnmSolverParameters const *sp);
+GPtrArray *gnm_solver_param_get_input_cells (GnmSolverParameters const *sp);
 
 const GnmCellRef *gnm_solver_param_get_target (GnmSolverParameters const *sp);
 void gnm_solver_param_set_target (GnmSolverParameters *sp,


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