function solverState = lbfgsState(NameValueArgs)
%lbfgsState   State for L-BFGS updates
%
%   solverState = lbfgsState creates an empty state object for L-BFGS
%   updates. By default, the state has a history size of 10 and an inverse
%   Hessian factor of 1. Use lbfgsState objects with lbfgsupdate function
%   to iteratively update learnable parameters during network training.
%
%   solverState = lbfgsState(Name=Value) specifies additional options
%   using one or more name-value arguments:
%       HistorySize           - Number of steps to store, specified as a
%                               positive integer. Values between 3 and 20
%                               suit most tasks. The default is 10.
%       InitialInverseHessianFactor
%                             - Value to approximate the inverse Hessian
%                               when applying the first L-BFGS update step,
%                               specified as a positive scalar.
%                               The default is 1.
%
%   Example:
%       % Create an L-BFGS solver state with a maximum history size of 3
%       % and an initial inverse Hessian factor with value 1.1.
%
%       solverState = lbfgsState(HistorySize=3, InitialInverseHessianFactor=1.1);
%
%   See also deep.LBFGSState, lbfgsupdate.

%   Copyright 2022 The MathWorks, Inc.

arguments
    NameValueArgs.HistorySize(1,1)          {mustBeNumeric, mustBeInteger, mustBePositive} = 10
    NameValueArgs.InitialInverseHessianFactor(1,1) {mustBeNumeric, mustBeReal, mustBePositive, mustBeFinite} = 1
end

% Convert arguments to canonical form.
NameValueArgs = iConvertToCanonicalForm(NameValueArgs);

% Construct external solver state.
solverState = deep.LBFGSState( ...
    NameValueArgs.HistorySize, ...
    NameValueArgs.InitialInverseHessianFactor);
end

function inputArguments = iConvertToCanonicalForm(params)
% Make sure values are converted to double
inputArguments = struct;
inputArguments.HistorySize = double(params.HistorySize);
inputArguments.InitialInverseHessianFactor = double(params.InitialInverseHessianFactor);
end