--- a +++ b/combinedDeepLearningActiveContour/minFunc/ArmijoBacktrack.m @@ -0,0 +1,108 @@ +function [t,x_new,f_new,g_new,funEvals,H] = ArmijoBacktrack(... + x,t,d,f,fr,g,gtd,c1,LS,tolX,debug,doPlot,saveHessianComp,funObj,varargin) +% +% Backtracking linesearch to satisfy Armijo condition +% +% Inputs: +% x: starting location +% t: initial step size +% d: descent direction +% f: function value at starting location +% fr: reference function value (usually funObj(x)) +% gtd: directional derivative at starting location +% c1: sufficient decrease parameter +% debug: display debugging information +% LS: type of interpolation +% tolX: minimum allowable step length +% doPlot: do a graphical display of interpolation +% funObj: objective function +% varargin: parameters of objective function +% +% Outputs: +% t: step length +% f_new: function value at x+t*d +% g_new: gradient value at x+t*d +% funEvals: number function evaluations performed by line search +% H: Hessian at initial guess (only computed if requested + +% Evaluate the Objective and Gradient at the Initial Step +if nargout == 6 + [f_new,g_new,H] = feval(funObj, x + t*d, varargin{:}); +else + [f_new,g_new] = feval(funObj, x + t*d, varargin{:}); +end +funEvals = 1; + +while f_new > fr + c1*t*gtd || ~isLegal(f_new) + + temp = t; + if LS == 0 || ~isLegal(f_new) + % Backtrack w/ fixed backtracking rate + if debug + fprintf('Fixed BT\n'); + end + t = 0.5*t; + elseif LS == 2 && isLegal(g_new) + % Backtracking w/ cubic interpolation w/ derivative + if debug + fprintf('Grad-Cubic BT\n'); + end + t = polyinterp([0 f gtd; t f_new g_new'*d],doPlot); + elseif funEvals < 2 || ~isLegal(f_prev) + % Backtracking w/ quadratic interpolation (no derivative at new point) + if debug + fprintf('Quad BT\n'); + end + t = polyinterp([0 f gtd; t f_new sqrt(-1)],doPlot); + else%if LS == 1 + % Backtracking w/ cubic interpolation (no derivatives at new points) + if debug + fprintf('Cubic BT\n'); + end + t = polyinterp([0 f gtd; t f_new sqrt(-1); t_prev f_prev sqrt(-1)],doPlot); + end + + % Adjust if change in t is too small/large + + if t < temp*1e-3 + if debug + fprintf('Interpolated Value Too Small, Adjusting\n'); + end + t = temp*1e-3; + elseif t > temp*0.6 + if debug + fprintf('Interpolated Value Too Large, Adjusting\n'); + end + t = temp*0.6; + end + + f_prev = f_new; + t_prev = temp; + if ~saveHessianComp && nargout == 6 + [f_new,g_new,H] = feval(funObj, x + t*d, varargin{:}); + else + [f_new,g_new] = feval(funObj, x + t*d, varargin{:}); + end + funEvals = funEvals+1; + + % Check whether step size has become too small + if sum(abs(t*d)) <= tolX + if debug + fprintf('Backtracking Line Search Failed\n'); + end + t = 0; + f_new = f; + g_new = g; + break; + end +end + +% Evaluate Hessian at new point +if nargout == 6 && funEvals > 1 && saveHessianComp + [f_new,g_new,H] = feval(funObj, x + t*d, varargin{:}); + funEvals = funEvals+1; +end + +x_new = x + t*d; + +end