function [p,pBp] = cgsteihaug(fnhess,fngrad,fn,gradold,xold) % usage: [p,pBp] = cgsteihaug(fnhess,fngrad,fn,gradold,xold) % description: solves the local trust-region problem % min m(p) = fk + gradfk'*p+0.5*p'*B*p % with CG-Steihaug algorithm and returns step change p and % p'*B*p, where B is the Hessian at xold. Input parameters: % fnhess: function hessian name % fngrad: function grad name % fn: function name % xold: starting point % global variables: global parms; % local variables: % ii: iteration variable deltacurr = parms.deltacurr; cgeps = parms.cgeps; maxcgiter = parms.maxcgiter; tau = [0 0]'; p = zeros(size(xold)); r = feval(fngrad,xold); d = -r; B = feval(fnhess,xold); for ii = (1:maxcgiter); if (norm(r) <= cgeps); pBp = p'*B*p; return; end dBd = d'*B*d; if (dBd <= 0) % if so, find p+tau*d that minimizes m in trust region % we won't check for zero d'*d, but let's do safe quadratics a = d'*d; b = (p'*d)/a; c = (p'*p-deltacurr^2)/a; if (b >= 0) tau(1) = (-b - sqrt(b^2 - c)); else tau(1) = (-b + sqrt(b^2 - c)); end tau(2) = c/tau(1); % now find minimum value of m dBp = d'*B*p; val = dBp*tau + dBd/2*tau.^2; minval = min(val); taumin = tau(find(val == minval)); p = p + taumin(1)*d; pBp = p'*B*p; return; else alpha = r'*r/dBd; pnew = p + alpha*d; if (norm(pnew)>=deltacurr) % if so, find p+tau*d, tau >0, on bdy of trust region % we won't check for zero d'*d, but let's do safe quadratics a = d'*d; b = (p'*d)/a; c = (p'*p-deltacurr^2)/a; if (b >= 0) tau(1) = (-b - sqrt(b^2 - c)); else tau(1) = (-b + sqrt(b^2 - c)); end tau(2) = c/tau(1); % one has to be positive taumin = max(tau); p = p + taumin(1)*d; pBp = p'*B*p; return; else p = pnew; rnew = r+alpha*B*d; d = -rnew + (rnew'*rnew/(r'*r))*d; r = rnew; end end end pBp = p'*B*p;