function [p,pBp] = dogleg(fnhess,fngrad,fn,gradold,xold) % usage: [p,pBp] = dogleg(fnhess,fngrad,fn,gradold,xold) % description: solves the local trust-region problem % min m(p) = fk + gradfk'*p+0.5*p'*B*p % using the dogleg algorithm. Returns p = xnew-xold and % pBp = p'*B*p, where B is Hessian matrix. % Input parameters: % fnhess: function hessian name % fngrad: function grad name % fn: function name % xold: starting point % delta: trust region radius % global variables: global parms; % local variables: % delta: current trust region radius % B: current Hessian % gBg: gradold'*B*gradold % normg: norm(gradold) % pU: steepest descent point % pB: Newton point % pQ: pB-pU % normpU,normpQ: norm(p*) % b,c: temporary coefs in a quadratic % t1, t2: roots of quadratic % taum1: tau - 1 of dogleg formula % initialize delta = parms.deltacurr; % compute the steepest descent point B = feval(fnhess,xold); gBg = gradold'*B*gradold; normg = norm(gradold); if (gBg <= 0) % if negative curvature revert to steepest descent if (normg == 0) p = gradold; else p = -delta*gradold/normg; % note we don't chech for div by 0 end else pU = -gradold'*gradold/gBg*gradold; normpU = norm(pU); if (normpU >= delta) % if so, don't need pB here p = delta*pU/normpU; else % ok, do need Newton point pB = -B\gradold; if (norm(pB) <= delta) % newton point in trust region? p = pB; else % no pQ = pB - pU; pUpQ = pU'*pQ; if (pUpQ <= 0) % indicates negative curvature, revert to steep descent p = pU; else normpQ = norm(pQ); % we won't check for zero normpQ, but let's do safe quadratics b = pUpQ/normpQ^2; c = (normpU^2-delta^2)/normpQ^2; t1 = (-pUpQ -sign(pUpQ)*sqrt(b^2 -c)); t2 = c/t1; taum1 = min(1,max(t1,t2)); % we want the positive root, should be <= 1 p = pU + taum1*pQ; end end end end pBp = p'*B*p;