function [varargout] = fitrkernel(X,Y,varargin)
%FITRKERNEL Fit a kernel regression model by explicit feature expansion. 
%   MODEL=FITRKERNEL(TBL,Y) returns a kernel regression model MODEL by
%   explicitly mapping the predictors in the table TBL to a high
%   dimensional space. Y can be one of the following:
%      1. A column vector of floating point numbers.
%      2. The name of a variable in TBL. This variable is used as the
%         response Y, and the remaining variables in TBL are used as
%         predictors.
%      3. A formula string such as 'y ~ x1 + x2 + x3' specifying that the
%         variable y is used as the response, and the other variables in 
%         the formula are predictors. Any table variables not listed in
%         the formula are not used.
% 
%   First, non-numeric predictors in TBL are changed to dummy numeric
%   variables. Then, FITRKERNEL sets a random transformation T() such that
%   dot(T(X(i,:)),T(X(j,:))) approximates the Gaussian kernel. X is the set
%   of original numeric predictors and dummy predictors. Once X is
%   transformed, FITRKERNEL implements a LBFGS (low-memory BFGS) solver
%   with ridge (L2) regularization to fit a linear model over the
%   transformed data.
%
%   MODEL=fitrkernel(X,Y) is an alternative syntax that accepts X as an
%   N-by-P matrix of predictors with one row per observation and one column
%   per predictor. Y is the response vector.
%
%   [MODEL,FITINFO]=FITRKERNEL(...) also returns a struct containing fit
%   information FITINFO.
%  
%   [MODEL,FITINFO,HYPERPARAMETEROPTIMIZATIONRESULTS]=FITRKERNEL(...) also
%   returns an object describing the results of hyperparameter
%   optimization, if 'OptimizeHyperparameters' was passed.
%  
%   [...]=FITRKERNEL(...,'PARAM1',val1,'PARAM2',val2,...) specifies optional
%   name-value parameter pairs:
%       'BetaTolerance'      - Relative tolerance on linear coefficients and
%                              bias term. A non-negative scalar. Default is 1e-4.
%       'BlockSize'          - A positive scalar specifying the maximum amount of 
%                              memory that can be allocated in megabytes(MB). If 
%                              FITRKERNEL requires more memory than this parameter
%                              to hold the transformed data, the internal
%                              algorithms will automatically switch to a 
%                              block-wise strategy. Default is 4e3, i.e. 4GB.
%       'BoxConstraint'      - Positive scalar specifying the box constraint. 
%                              Valid only for SVM learner and when Lambda is not 
%                              given. Default is 1.
%       'CrossVal'           - If 'on', performs 10-fold cross-validation. You
%                              use 'KFold', 'Holdout', 'Leaveout' and 'CVPartition' 
%                              parameters for alternate cross-validation options. 
%                              Default: 'off'
%       'CVPartition'        - A partition created with CVPARTITION to use
%                              for cross-validation.
%       'Epsilon'            - Either 'auto' or a non-negative scalar specifying  
%                              half the width of the epsilon-insensitive band.
%                              If 'auto', epsilon is set to iqr(Y)/13.49 or 0.1 if 
%                              iqr(Y) equals 0. Default is 'auto'.
%       'GradientTolerance'  - Absolute gradient tolerance. A non-negative scalar. 
%                              Default is 1e-6;
%       'HessianHistorySize' - Size of history buffer for Hessian approximation. 
%                              A positive integer. Default is 15.
%       'Holdout'            - Holdout validation uses the specified fraction
%                              of the data for test, and uses the rest of the
%                              data for training. Specify a numeric scalar
%                              between 0 and 1.
%       'IterationLimit'     - Maximal number of optimization iterations. A
%                              positive integer. Default is 1000 if the transformed
%                              data fits in memory (see BlockSize) or 100
%                              if FITRKERNEL switches to a block-wise strategy.
%       'KernelScale'        - Either string 'auto' or positive scalar specifying
%                              the value for the scale parameter. If you pass  
%                              'auto', FITRKERNEL selects an appropriate scale 
%                              using a heuristic procedure. Default is 1. 
%       'KFold'              - K-fold cross-validation. Specify K as a positive 
%                              integer.
%       'Lambda'             - Either 'auto' or a non-negative scalar values
%                              specifying the strength of the regularization term.
%                              If 'auto', the regularization parameter is set to 
%                              1/N, where N is the number of observations in X. 
%                              Default is 'auto'.
%       'Learner'            - String, either 'svm' for support vector machine or
%                              'leastsquares' for least-squares regression.
%                              Default is 'svm'.
%       'Leaveout'           - Set to 'on' for leave-one-out cross-validation.
%       'NumExpansionDimensions' - Number of dimensions in the expanded space.
%                              Either 'auto' or a positive integer. If you pass 
%                              'auto', FITRKERNEL selects an appropriate number 
%                              using a heuristic procedure.  Default is 'auto'.
%       'OptimizeHyperparameters' - Hyperparameters to optimize. Either 'none',
%                              'auto', 'all', a cell array of eligible
%                              hyperparameter names, or a vector of
%                              optimizableVariable objects, such as that
%                              returned by the 'hyperparameters' function.
%                              To control other aspects of the
%                              optimization, use the
%                              HyperparameterOptimizationOptions name-value
%                              pair. 'auto' is equivalent to
%                              {'KernelScale', 'Lambda', 'Epsilon'}. 'all'
%                              is equivalent to {'Learner', 'KernelScale',
%                              'Lambda', 'NumExpansionDimensions', 'Epsilon'}.
%                              Default: 'none'.
%       'RandomStream'       - A random number stream to control reproducibility 
%                              of the random basis functions used for
%                              transforming X to a high dimensional space.
%       'Verbose'            - Verbosity level, a non-negative integer:
%                               * 0  - FITRKERNEL does not display any
%                                      diagnostic messages. (default)
%                               * 1  - FITRKERNEL periodically displays the
%                                      value of the objective function,
%                                      gradient magnitude, and other
%                                      diagnostic info.
%       'Weights'            - Vector of observation weights, one weight per
%                              observation. FITRKERNEL normalizes the weights to
%                              add up to one. Default is equal weights.
%       'Standardize'        - Logical scalar. If true, standardize X by centering
%                              and dividing columns by their standard deviations.
%                              Default: false
%
%   Refer to the MATLAB documentation for info on parameters for
%       <a href="matlab:helpview('stats', 'fitrkernelHyperparameterOptimizationOptions')">Hyperparameter Optimization</a>
%
%   See also fitrlinear.
        
%   Copyright 2017-2023 The MathWorks, Inc.

%   Undocumented warm start using ADMM:
%
%   FITRKERNEL can also refine the initial estimates of the parameters by
%   using a number of iterations of the ADMM algorithm (warm start). To control
%   the ADMM iterations the extra parameter name/value pairs are supported:
%
%       'ADMMIterationLimit' - Non-negative integer, defaults to 1.
%       'ADMMUpdateIterationLimit' - Positive integer, number of iterations for LBFGS 
%                           running inside the ADMM chunks. This value is applied to 
%                           all ADDM iterations unless WarmStartIterationLimit was also 
%                           specified, in such case ADMMUpdateIterationLimit is used for 
%                           all iterations after the first one. Default is 100.
%       'Consensus'      -  Strength of the ADMM penalty ensuring consensus across the 
%                           estimated parameters for different parts of the tall array. 
%                           A non-negative scalar, defaults to 0.1. Relevant only when
%                           ADMMIterationLimit>1
%       'WarmStartIterationLimit' - Positive integer. When FITRKERNEL switches to a 
%                           block-wise startegy (see BlockSize), FITRKERNEL first 
%                           refines the initial estimates of the parameters by 
%                           fitting the model locally to parts of the data and 
%                           combining the coefficients by averaging. 
%                           WarmStartIterationLimit sets the maximum number of 
%                           iterations for the local LBFGS. Default is 100.
%                           Tip: Increasing WarmStartIterationLimit may reduce the 
%                           fitting time of the main LBFGS algorithm executed after 
%                           the warm start.
%
%   TIPS:
%    - With larger values of the consensus penalty ADMM converges quicker,
%      with smaller vales of the consensus ADMM converges to lower values of
%      the objective function.
%    - Either 'IterationLimit' or 'ADMMIterationLimit' can be set to 0 to run only
%      ADMM iterations or distributed LBFGS iterations respectively.
%
%   Other undocummented parameter name/value pairs:
%
%         'ObservationsIn'  - only supports 'rows'
%         'Regularization'  - only supports 'ridge'
%         'Solver'          - only supports 'lbfgs'
%         'Beta'            - not supported, specifically forbiden
%         'Bias'            - not supported, specifically forbiden
%         'FitBias'         - only supports true
%         'Tranformation'   - either 'FastFood' or 'KitchenSinks'
%         'UseParallel'     - not supported
%         'InitialStepSize' - A real positive scalar specifying the approximate maximum 
%                             absolute value of the first step of the 'lbfgs' algorithm. 
%                             Suppose g0 is the maximum absolute value of the gradient at 
%                             the initial point. The initial Hessian approximation is 
%                             chosen as B0 =(g0/s0)*I where I is the identity matrix. 
%                             Default is 1.
%         'TallPassLimit'   - Maximum number of passes allowed. Defaults to intmax.
%                             TallPassLimit is most relevant when using tall data.
%

if nargin > 1
    Y = convertStringsToChars(Y);
end

if nargin > 2
    [varargin{:}] = convertStringsToChars(varargin{:});
end

[IsOptimizing, RemainingArgs] = classreg.learning.paramoptim.parseOptimizationArgs(varargin);
if IsOptimizing
    [varargout{1:nargout}] = classreg.learning.paramoptim.fitoptimizing('fitrkernel',X,Y,varargin{:});
else
    [varargout{1:nargout}] = RegressionKernel.fit(X,Y,RemainingArgs{:});
end
end
