changeset 26237:34cc6edf2041

sqp.m: Eliminate redundant objective function calls (patch #8073). Reduces calls to objective function by ~50% without change in functionality. * sqp.m: New variable have_grd to indicate whether a user-supplied gradient function was given. When using the built-in numerical gradient, call gradient function with an extra input containing the value of the objective function evaluated at x (which is already known). * sqp.m (fdgrd): Change prototype to accept additional input y0 (objective function evaluated at x). Delete calculation of y0 within function. * sqp.m (fd_ob_grd): Change prototype to accept additional input y0 (objective function evaluated at x).
author Ken Marek <gm.kmarek@gmail.com>
date Wed, 25 Mar 2015 13:04:54 -0500
parents 73512571d85a
children 71d618146e4c
files scripts/optimization/sqp.m
diffstat 1 files changed, 28 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/optimization/sqp.m	Fri Dec 14 10:00:04 2018 -0800
+++ b/scripts/optimization/sqp.m	Wed Mar 25 13:04:54 2015 -0500
@@ -202,26 +202,29 @@
     x0 = x0';
   endif
 
+  have_grd = 0;
   have_hess = 0;
   if (iscell (objf))
     switch (numel (objf))
       case 1
         obj_fun = objf{1};
-        obj_grd = @(x) fd_obj_grd (x, obj_fun);
+        obj_grd = @(x, obj) fd_obj_grd (x, obj, obj_fun);
       case 2
         obj_fun = objf{1};
         obj_grd = objf{2};
+        have_grd = 1;
       case 3
         obj_fun = objf{1};
         obj_grd = objf{2};
         obj_hess = objf{3};
+        have_grd = 1;
         have_hess = 1;
       otherwise
         error ("sqp: invalid objective function specification");
     endswitch
   else
     obj_fun = objf;   # No cell array, only obj_fun set
-    obj_grd = @(x) fd_obj_grd (x, obj_fun);
+    obj_grd = @(x, obj) fd_obj_grd (x, obj, obj_fun);
   endif
 
   ce_fun = @empty_cf;
@@ -351,7 +354,11 @@
   obj = feval (obj_fun, x0);
   globals.nfun = 1;
 
-  c = feval (obj_grd, x0);
+  if (have_grd)
+    c = feval (obj_grd, x0);
+  else
+    c = feval (obj_grd, x0, obj);
+  endif
 
   ## Choose an initial NxN symmetric positive definite Hessian approximation B.
   n = length (x0);
@@ -433,10 +440,22 @@
     ## merit function phi.
     [x_new, alpha, obj_new, globals] = ...
         linesearch_L1 (x, p, obj_fun, obj_grd, ce_fun, ci_fun, lambda, ...
-                       obj, globals);
+                       obj, c, globals);
+    
+    delx = x_new - x;
+
+    ## Check if step size has become too small (indicates lack of progress).
+    if (norm (delx) < tol * norm (x))
+      info = 104;
+      break;
+    endif
 
     ## Evaluate objective function, constraints, and gradients at x_new.
-    c_new = feval (obj_grd, x_new);
+    if (have_grd)
+      c_new = feval (obj_grd, x_new);
+    else
+      c_new = feval (obj_grd, x_new, obj_new);
+    endif
 
     ce_new = feval (ce_fun, x_new);
     F_new = feval (ce_grd, x_new);
@@ -458,14 +477,6 @@
       y -= t;
     endif
 
-    delx = x_new - x;
-
-    ## Check if step size has become too small (indicates lack of progress).
-    if (norm (delx) < tol * norm (x))
-      info = 104;
-      break;
-    endif
-
     if (have_hess)
 
       B = feval (obj_hess, x);
@@ -556,7 +567,7 @@
 
 
 function [x_new, alpha, obj, globals] = ...
-   linesearch_L1 (x, p, obj_fun, obj_grd, ce_fun, ci_fun, lambda, obj, globals)
+   linesearch_L1 (x, p, obj_fun, obj_grd, ce_fun, ci_fun, lambda, obj, c, globals)
 
   ## Choose parameters
   ##
@@ -576,7 +587,6 @@
 
   alpha = 1;
 
-  c = feval (obj_grd, x);
   ce = feval (ce_fun, x);
 
   [phi_x_mu, obj, globals] = phi_L1 (obj, obj_fun, ce_fun, ci_fun, x, ...
@@ -611,10 +621,9 @@
 endfunction
 
 
-function grd = fdgrd (f, x)
+function grd = fdgrd (f, x, y0)
 
   if (! isempty (f))
-    y0 = feval (f, x);
     nx = length (x);
     grd = zeros (nx, 1);
     deltax = sqrt (eps);
@@ -653,9 +662,9 @@
 endfunction
 
 
-function grd = fd_obj_grd (x, obj_fun)
+function grd = fd_obj_grd (x, obj, obj_fun)
 
-  grd = fdgrd (obj_fun, x);
+  grd = fdgrd (obj_fun, x, obj);
 
 endfunction