Files
matlab/RBM/UFLDL/common/minFunc_2012/minFunc/ArmijoBacktrack.m
T
jens 7b34529b24 imported RBM
git-svn-id: http://moon:8086/svn/matlab/trunk@91 801c6759-fa7c-4059-a304-17956f83a07c
2016-07-12 11:24:12 +00:00

140 lines
4.4 KiB
Matlab

function [t,x_new,f_new,g_new,funEvals,H] = ArmijoBacktrack(...
x,t,d,f,fr,g,gtd,c1,LS_interp,LS_multi,progTol,debug,doPlot,saveHessianComp,funObj,varargin)
% [t,x_new,f_new,g_new,funEvals,H] = ArmijoBacktrack(...
% x,t,d,f,fr,g,gtd,c1,LS_interp,LS_multi,progTol,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_interp: type of interpolation
% progTol: 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)
%
% recet change: LS changed to LS_interp and LS_multi
% Evaluate the Objective and Gradient at the Initial Step
if nargout == 6
[f_new,g_new,H] = funObj(x + t*d,varargin{:});
else
[f_new,g_new] = funObj(x+t*d,varargin{:});
end
funEvals = 1;
while f_new > fr + c1*t*gtd || ~isLegal(f_new)
temp = t;
if LS_interp == 0 || ~isLegal(f_new)
% Ignore value of new point
if debug
fprintf('Fixed BT\n');
end
t = 0.5*t;
elseif LS_interp == 1 || ~isLegal(g_new)
% Use function value at new point, but not its derivative
if funEvals < 2 || LS_multi == 0 || ~isLegal(f_prev)
% Backtracking w/ quadratic interpolation based on two points
if debug
fprintf('Quad BT\n');
end
t = polyinterp([0 f gtd; t f_new sqrt(-1)],doPlot,0,t);
else
% Backtracking w/ cubic interpolation based on three 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,0,t);
end
else
% Use function value and derivative at new point
if funEvals < 2 || LS_multi == 0 || ~isLegal(f_prev)
% 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,0,t);
elseif ~isLegal(g_prev)
% Backtracking w/ quartic interpolation 3 points and derivative
% of two
if debug
fprintf('Grad-Quartic BT\n');
end
t = polyinterp([0 f gtd; t f_new g_new'*d; t_prev f_prev sqrt(-1)],doPlot,0,t);
else
% Backtracking w/ quintic interpolation of 3 points and derivative
% of two
if debug
fprintf('Grad-Quintic BT\n');
end
t = polyinterp([0 f gtd; t f_new g_new'*d; t_prev f_prev g_prev'*d],doPlot,0,t);
end
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
% Store old point if doing three-point interpolation
if LS_multi
f_prev = f_new;
t_prev = temp;
if LS_interp == 2
g_prev = g_new;
end
end
if ~saveHessianComp && nargout == 6
[f_new,g_new,H] = funObj(x + t*d,varargin{:});
else
[f_new,g_new] = funObj(x + t*d,varargin{:});
end
funEvals = funEvals+1;
% Check whether step size has become too small
if max(abs(t*d)) <= progTol
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] = funObj(x + t*d,varargin{:});
funEvals = funEvals+1;
end
x_new = x + t*d;
end