[gnumeric] Solver: create gradient decent iterator.



commit f51f6b4a54376efff7339c9514261898f5864f0b
Author: Morten Welinder <terra gnome org>
Date:   Mon May 11 08:12:06 2015 -0400

    Solver: create gradient decent iterator.

 src/tools/gnm-solver.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/tools/gnm-solver.h |    1 +
 2 files changed, 47 insertions(+), 1 deletions(-)
---
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index 1311ac9..ba0dfca 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -2651,7 +2651,7 @@ cb_polish_iter (GnmSolverIterator *iter, GnmIterSolver *isol)
                                            s0, sm, 0.0, &y);
                dir[c] = 0;
 
-               if (gnm_finite (s)) {
+               if (gnm_finite (s) && s != 0) {
                        isol->xk[c] += s;
                        isol->yk = y;
                        progress = TRUE;
@@ -2679,6 +2679,51 @@ gnm_solver_iterator_new_polish (GnmIterSolver *isol)
 }
 
 
+static gboolean
+cb_gradient_iter (GnmSolverIterator *iter, GnmIterSolver *isol)
+{
+       GnmSolver *sol = GNM_SOLVER (isol);
+       const int n = sol->input_cells->len;
+       gboolean progress = FALSE;
+       gnm_float s, y;
+       gnm_float *g;
+       int i;
+
+       /* Search in opposite direction of gradient.  */
+       g = gnm_solver_compute_gradient (sol, isol->xk);
+       for (i = 0; i < n; i++)
+               g[i] = -g[i];
+
+       s = gnm_solver_line_search (sol, isol->xk, g, FALSE,
+                                   1, gnm_pinf, 0.0, &y);
+       if (s > 0) {
+               for (i = 0; i < n; i++)
+                       isol->xk[i] += s * g[i];
+               isol->yk = y;
+               progress = TRUE;
+       }
+
+       g_free (g);
+
+       if (progress)
+               gnm_iter_solver_set_solution (isol);
+
+       return progress;
+}
+
+/**
+ * gnm_solver_iterator_new_gradient:
+ * @isol: the solver to operate on
+ *
+ * Returns: (transfer full): an iterator object that can be used to perform
+ * a gradient decent step.
+ */
+GnmSolverIterator *
+gnm_solver_iterator_new_gradient (GnmIterSolver *isol)
+{
+       return gnm_solver_iterator_new_func (G_CALLBACK (cb_gradient_iter), isol);
+}
+
 GSF_CLASS (GnmSolverIterator, gnm_solver_iterator,
           gnm_solver_iterator_class_init, NULL, G_TYPE_OBJECT)
 
diff --git a/src/tools/gnm-solver.h b/src/tools/gnm-solver.h
index 1f584d5..26345db 100644
--- a/src/tools/gnm-solver.h
+++ b/src/tools/gnm-solver.h
@@ -360,6 +360,7 @@ GType gnm_solver_iterator_get_type (void);
 
 GnmSolverIterator *gnm_solver_iterator_new_func (GCallback iterate, gpointer user);
 GnmSolverIterator *gnm_solver_iterator_new_polish (GnmIterSolver *isol);
+GnmSolverIterator *gnm_solver_iterator_new_gradient (GnmIterSolver *isol);
 
 gboolean gnm_solver_iterator_iterate (GnmSolverIterator *iter);
 


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