Mercurial > octave
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