[gnumeric] Solver: move some code around.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Solver: move some code around.
- Date: Wed, 29 Apr 2015 15:00:35 +0000 (UTC)
commit ba86400f3f311b6e5978196651d92c05bfcf87a4
Author: Morten Welinder <terra gnome org>
Date: Wed Apr 29 11:00:13 2015 -0400
Solver: move some code around.
plugins/nlsolve/gnm-nlsolve.c | 36 ++---------
src/tools/gnm-solver.c | 145 ++++++++++++++++++++++++-----------------
src/tools/gnm-solver.h | 6 +-
3 files changed, 94 insertions(+), 93 deletions(-)
---
diff --git a/plugins/nlsolve/gnm-nlsolve.c b/plugins/nlsolve/gnm-nlsolve.c
index 022d3bf..ee05b6d 100644
--- a/plugins/nlsolve/gnm-nlsolve.c
+++ b/plugins/nlsolve/gnm-nlsolve.c
@@ -111,8 +111,8 @@ set_vector (GnmNlsolve *nl, const gnm_float *xs)
static gnm_float
get_value (GnmNlsolve *nl)
{
- /* nl->isol has been taught to flip sign if needed. */
- return gnm_iter_solver_get_target_value (nl->isol);
+ /* nl->sol has been taught to flip sign if needed. */
+ return gnm_solver_get_target_value (nl->sol);
}
static void
@@ -157,34 +157,7 @@ gnm_nlsolve_prepare (GnmSolver *sol, WorkbookControl *wbc, GError **err,
static gnm_float *
compute_gradient (GnmNlsolve *nl, const gnm_float *xs)
{
- gnm_float *g;
- gnm_float y0;
- const int n = nl->n;
- int i;
-
- set_vector (nl, xs);
- y0 = get_value (nl);
-
- g = g_new (gnm_float, n);
- for (i = 0; i < n; i++) {
- gnm_float x0 = xs[i];
- gnm_float dx;
- gnm_float y1;
- gnm_float eps = gnm_pow2 (-25);
-
- if (x0 == 0)
- dx = eps;
- else
- dx = gnm_abs (x0) * eps;
-
- set_value (nl, i, x0 + dx);
- y1 = get_value (nl);
- g[i] = (y1 - y0) / dx;
-
- set_value (nl, i, x0);
- }
-
- return g;
+ return gnm_solver_compute_gradient (nl->sol, xs);
}
static gnm_float **
@@ -590,7 +563,8 @@ nlsolve_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params)
gnm_solver_iterator_compound_add (citer, gnm_solver_iterator_new_polish (isol), 0);
- isol->iterator = GNM_SOLVER_ITERATOR (citer);
+ gnm_iter_solver_set_iterator (isol, GNM_SOLVER_ITERATOR (citer));
+ g_object_unref (citer);
nl->sol = sol;
nl->isol = isol;
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index c0f3f34..e32836f 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -5,6 +5,7 @@
#include "expr.h"
#include "sheet.h"
#include "workbook.h"
+#include "rangefunc.h"
#include "ranges.h"
#include "gutils.h"
#include "gnm-solver.h"
@@ -781,7 +782,8 @@ enum {
SOL_PROP_PARAMS,
SOL_PROP_RESULT,
SOL_PROP_STARTTIME,
- SOL_PROP_ENDTIME
+ SOL_PROP_ENDTIME,
+ SOL_PROP_FLIP_SIGN
};
static GObjectClass *gnm_solver_parent_class;
@@ -875,6 +877,10 @@ gnm_solver_get_property (GObject *object, guint property_id,
g_value_set_double (value, sol->endtime);
break;
+ case SOL_PROP_FLIP_SIGN:
+ g_value_set_boolean (value, sol->flip_sign);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -914,6 +920,10 @@ gnm_solver_set_property (GObject *object, guint property_id,
sol->endtime = g_value_get_double (value);
break;
+ case SOL_PROP_FLIP_SIGN:
+ sol->flip_sign = g_value_get_boolean (value);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -1665,6 +1675,13 @@ gnm_solver_create_report (GnmSolver *solver, const char *name)
#undef ADD_HEADER
#undef MARK_BAD
+/**
+ * gnm_solver_get_target_value:
+ * @isol: solver
+ *
+ * Returns: the current value of the target cell, possibly with the sign
+ * flipped.
+ */
gnm_float
gnm_solver_get_target_value (GnmSolver *solver)
{
@@ -1673,9 +1690,10 @@ gnm_solver_get_target_value (GnmSolver *solver)
gnm_cell_eval (solver->target);
v = solver->target->value;
- if (VALUE_IS_NUMBER (v) || VALUE_IS_EMPTY (v))
- return value_get_as_float (v);
- else
+ if (VALUE_IS_NUMBER (v) || VALUE_IS_EMPTY (v)) {
+ gnm_float y = value_get_as_float (v);
+ return solver->flip_sign ? 0 - y : y;
+ } else
return gnm_nan;
}
@@ -1703,6 +1721,49 @@ gnm_solver_set_vars (GnmSolver *sol, gnm_float const *xs)
gnm_solver_set_var (sol, i, xs[i]);
}
+/**
+ * gnm_solver_compute_gradient:
+ * @sol: Solver
+ * @xs: Point to compute gradient at
+ *
+ * Returns: (transfer full): A vector containing the gradient. This
+ * function takes the flip_sign into account. Note, that this is a
+ * numerical approximation.
+ */
+gnm_float *
+gnm_solver_compute_gradient (GnmSolver *sol, gnm_float const *xs)
+{
+ gnm_float *g;
+ gnm_float y0;
+ const int n = sol->input_cells->len;
+ int i;
+
+ gnm_solver_set_vars (sol, xs);
+ y0 = gnm_solver_get_target_value (sol);
+
+ g = g_new (gnm_float, n);
+ for (i = 0; i < n; i++) {
+ gnm_float x0 = xs[i];
+ gnm_float dx;
+ gnm_float y1;
+ gnm_float eps = gnm_pow2 (-25);
+
+ if (x0 == 0)
+ dx = eps;
+ else
+ dx = gnm_abs (x0) * eps;
+
+ gnm_solver_set_var (sol, i, x0 + dx);
+ y1 = gnm_solver_get_target_value (sol);
+ g[i] = (y1 - y0) / dx;
+
+ gnm_solver_set_var (sol, i, x0);
+ }
+
+ return g;
+}
+
+
static void
gnm_solver_class_init (GObjectClass *object_class)
{
@@ -1763,6 +1824,13 @@ gnm_solver_class_init (GObjectClass *object_class)
GSF_PARAM_STATIC |
G_PARAM_READWRITE));
+ g_object_class_install_property (object_class, SOL_PROP_FLIP_SIGN,
+ g_param_spec_boolean ("flip-sign",
+ P_("Flip Sign"),
+ P_("Flip sign of target value"),
+ FALSE,
+ GSF_PARAM_STATIC | G_PARAM_READWRITE));
+
solver_signals[SOL_SIG_PREPARE] =
g_signal_new ("prepare",
G_OBJECT_CLASS_TYPE (object_class),
@@ -2257,7 +2325,7 @@ cb_polish_iter (GnmSolverIterator *iter, GnmIterSolver *isol)
if (x[c] == xc)
break;
gnm_solver_set_vars (sol, x);
- y = gnm_iter_solver_get_target_value (isol);
+ y = gnm_solver_get_target_value (sol);
if (y < isol->yk && gnm_solver_check_constraints (sol)) {
/* Success! */
@@ -2422,17 +2490,17 @@ GSF_CLASS (GnmSolverIteratorCompound, gnm_solver_iterator_compound,
static GObjectClass *gnm_iter_solver_parent_class;
-enum {
- ISOL_PROP_0,
- ISOL_PROP_FLIP_SIGN
-};
-
-gnm_float
-gnm_iter_solver_get_target_value (GnmIterSolver *isol)
+void
+gnm_iter_solver_set_iterator (GnmIterSolver *isol, GnmSolverIterator *iterator)
{
- GnmSolver *sol = GNM_SOLVER (isol);
- gnm_float y = gnm_solver_get_target_value (sol);
- return isol->flip_sign ? 0 - y : y;
+ GnmSolverIterator *old_iterator;
+
+ g_return_if_fail (GNM_IS_ITER_SOLVER (isol));
+
+ old_iterator = isol->iterator;
+ isol->iterator = iterator ? g_object_ref (iterator) : NULL;
+ if (old_iterator)
+ g_object_unref (old_iterator);
}
gboolean
@@ -2458,7 +2526,7 @@ got_it:
GnmCell *cell = g_ptr_array_index (sol->input_cells, i);
isol->xk[i] = value_get_as_float (cell->value);
}
- isol->yk = gnm_iter_solver_get_target_value (isol);
+ isol->yk = gnm_solver_get_target_value (sol);
gnm_iter_solver_set_solution (isol);
@@ -2474,7 +2542,7 @@ gnm_iter_solver_set_solution (GnmIterSolver *isol)
int i;
result->quality = GNM_SOLVER_RESULT_FEASIBLE;
- result->value = isol->flip_sign ? 0 - isol->yk : isol->yk;
+ result->value = sol->flip_sign ? 0 - isol->yk : isol->yk;
result->solution = value_new_array_empty (sol->input_width,
sol->input_height);
for (i = 0; i < n; i++) {
@@ -2535,40 +2603,6 @@ gnm_iter_solver_init (GnmIterSolver *isol)
{
}
-static void
-gnm_iter_solver_get_property (GObject *object, guint property_id,
- GValue *value, GParamSpec *pspec)
-{
- GnmIterSolver *isol = (GnmIterSolver *)object;
-
- switch (property_id) {
- case ISOL_PROP_FLIP_SIGN:
- g_value_set_boolean (value, isol->flip_sign);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gnm_iter_solver_set_property (GObject *object, guint property_id,
- GValue const *value, GParamSpec *pspec)
-{
- GnmIterSolver *isol = (GnmIterSolver *)object;
-
- switch (property_id) {
- case ISOL_PROP_FLIP_SIGN:
- isol->flip_sign = g_value_get_boolean (value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
static gint
gnm_iter_solver_idle (gpointer data)
{
@@ -2634,17 +2668,8 @@ gnm_iter_solver_class_init (GObjectClass *object_class)
object_class->dispose = gnm_iter_solver_dispose;
object_class->finalize = gnm_iter_solver_finalize;
object_class->constructed = gnm_iter_solver_constructed;
- object_class->set_property = gnm_iter_solver_set_property;
- object_class->get_property = gnm_iter_solver_get_property;
sclass->start = gnm_iter_solver_start;
sclass->stop = gnm_iter_solver_stop;
-
- g_object_class_install_property (object_class, ISOL_PROP_FLIP_SIGN,
- g_param_spec_boolean ("flip-sign",
- P_("Flip Sign"),
- P_("Flip sign of target value"),
- FALSE,
- GSF_PARAM_STATIC | G_PARAM_READWRITE));
}
GSF_CLASS (GnmIterSolver, gnm_iter_solver,
diff --git a/src/tools/gnm-solver.h b/src/tools/gnm-solver.h
index f457c70..564f693 100644
--- a/src/tools/gnm-solver.h
+++ b/src/tools/gnm-solver.h
@@ -200,6 +200,7 @@ typedef struct {
GnmSolverParameters *params;
GnmSolverResult *result;
double starttime, endtime;
+ gboolean flip_sign;
/* Derived information */
GnmCell *target;
@@ -255,6 +256,8 @@ gnm_float gnm_solver_get_target_value (GnmSolver *solver);
void gnm_solver_set_var (GnmSolver *sol, int i, gnm_float x);
void gnm_solver_set_vars (GnmSolver *sol, gnm_float const *xs);
+gnm_float *gnm_solver_compute_gradient (GnmSolver *sol, gnm_float const *xs);
+
/* ------------------------------------------------------------------------- */
/* Solver subclass for subprocesses. */
@@ -378,7 +381,6 @@ struct GnmIterSolver_ {
/* Current point */
gnm_float *xk, yk;
- gboolean flip_sign;
GnmSolverIterator *iterator;
@@ -394,7 +396,7 @@ typedef struct {
GType gnm_iter_solver_get_type (void);
-gnm_float gnm_iter_solver_get_target_value (GnmIterSolver *isol);
+void gnm_iter_solver_set_iterator (GnmIterSolver *isol, GnmSolverIterator *iterator);
gboolean gnm_iter_solver_get_initial_solution (GnmIterSolver *isol, GError **err);
void gnm_iter_solver_set_solution (GnmIterSolver *isol);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]