Commit 43196c09 authored by Morten Welinder's avatar Morten Welinder

Solver: code cleanup.

parent 5406d4b7
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -23,4 +23,4 @@
BOOLEAN:POINTER
BOOLEAN:OBJECT,POINTER
VOID:BOOLEAN,INT
VOID:VOID
BOOLEAN:VOID
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
......
......@@ -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,
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment