changeset 5633:6286cb2940c0 octave-forge

Caching feval calls in order to prevent it from doing double calls with exactly the same parameters.
author tealev
date Wed, 13 May 2009 18:57:27 +0000
parents 1d4abec4ac9f
children dce2dd6e8720
files main/optim/src/__bfgsmin.cc
diffstat 1 files changed, 46 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/main/optim/src/__bfgsmin.cc	Wed May 13 18:45:19 2009 +0000
+++ b/main/optim/src/__bfgsmin.cc	Wed May 13 18:57:27 2009 +0000
@@ -29,6 +29,48 @@
 #include <float.h>
 #include "error.h"
 
+// the compares two octave_values (thanks to jwe)
+bool isequal (const octave_value& a, const octave_value& b,
+           bool nans_compare_equal = false)
+{
+    octave_value_list args;
+
+    args(2) = b;
+    args(1) = a;
+    args(0) = nans_compare_equal;
+
+    octave_value_list tmp = feval ("__isequal__", args, 1);
+
+    // We expect __isequal__ to always return a single logical scalar.
+    return tmp(0).bool_value ();
+}
+
+// this is cache on feval to prevent the extra evaluation of the
+// objective function when subsequent calls with exactly the same arguments would take place
+
+octave_value_list _feval( const std::string f, const octave_value_list f_args )
+{
+    static octave_value_list f_args_prev;
+    static octave_value_list ret;
+
+    // check if ( f_args_prev == f_args )
+    bool same = true;
+    for( int i=0; i < f_args.length(); i++)
+    {
+        if (!isequal( f_args(i),f_args_prev(i)))
+        {
+            same = false;
+            break;
+        }
+    }
+    if (same)
+        return ret;
+    
+    f_args_prev = f_args;
+    ret = feval( f, f_args );
+
+    return ret;
+}
 
 int __bfgsmin_obj(double &obj, const std::string f, const octave_value_list f_args, const ColumnVector theta, const int minarg)
 {
@@ -36,7 +78,7 @@
 	int success = 1;
 	f_args_new = f_args;
 	f_args_new(minarg - 1) = theta;
-	f_return = feval(f, f_args_new);
+	f_return = _feval(f, f_args_new);
 	obj = f_return(0).double_value();
 	// bullet-proof the objective function
 	if (error_state) {
@@ -89,12 +131,12 @@
 	Matrix check_gradient(k,1);
 	if (have_analytic_gradient) {
 		f_args(minarg - 1) = theta;
-		f_return = feval(f, f_args);
+		f_return = _feval(f, f_args);
 		g = f_return(1).column_vector_value();
 	}
 	else if (try_analytic_gradient) {
 		f_args(minarg - 1) = theta;
-		f_return = feval(f, f_args);
+		f_return = _feval(f, f_args);
 		if (f_return.length() > 1) {
 			if (f_return(1).is_real_matrix()) {
         			if ((f_return(1).rows() == k) & (f_return(1).columns() == 1)) {
@@ -278,7 +320,7 @@
 	warnings = 0;
 	if (verbosity == 3) warnings = 1;
 
-	// copy cell contents over to octave_value_list to use feval()
+	// copy cell contents over to octave_value_list to use _feval()
 	k = f_args_cell.length();
 	f_args(k); // resize only once
 	for (i = 0; i<k; i++) f_args(i) = f_args_cell(i);