function fis = genfis(Xin,Xout,varargin)
%GENFIS - Generates a fuzzy inference system (FIS) using the specified
%partition/clustering method in order to provide initial conditions for
%ANFIS training.
%
%  FIS = GENFIS(XIN,XOUT) generates a single-output Sugeno-type FIS using a
%  grid partition on the input data XIN and output data XOUT. XIN is a
%  matrix with N columns, which contain data for each FIS input, and XOUT
%  is a column vector, which contains the output data. GENFIS uses the
%  default grid partition option values returned by GENFISOPTIONS function.
%
%  FIS = GENFIS(XIN,XOUT,OPTIONS) creates an FIS using the specified
%  OPTIONS returned by GENFISOPTIONS function. You can specify three
%  different sets of option values using GENFISOPTIONS function as follows:
%
%    OPTIONS = GENFISOPTIONS('GRIDPARTITION',NAME1,VALUE1,...) creates
%    options for grid partition using the specified parameter NAME/VALUE
%    pairs.
%
%    OPTIONS = GENFISOPTIONS('SUBTRACTIVECLUSTERING',NAME1,VALUE1,...)
%    creates options for subtractive clustering method with the specified
%    parameter NAME/VALUE pairs.
%
%    OPTIONS = GENFISOPTIONS('FCMCLUSTERING',NAME1,VALUE1,...) creates
%    options for FCM clustering method with the specified parameter
%    NAME/VALUE pairs.
%
%    For more information on creating option sets, see GENFISOPTIONS
%    function.
%    
%  For subtractive and FCM clustering, the matrices XIN and XOUT have one
%  column per FIS  input and output, respectively. A Sugeno-type FIS is
%  generated by extracting a set of rules that models the input and output
%  data behavior. The rule extraction method uses SUBCLUST/FCM function to
%  determine the number of rules and membership functions for the
%  antecedents and consequents.
%
%  Example:
%    Xin = [rand(10,1) 10*rand(10,1)-5];
%    Xout = rand(10,1);
%    options = genfisOptions('SubtractiveClustering');
%    options.Verbose = true;
%    fis = genfis(Xin,Xout,options);
%
%    See also genfisOptions, subclust, fcm, anfis
 
% Copyright 2016 The MathWorks, Inc.

validateXin(Xin);
validateXout(Xout,size(Xin,1));

if isempty(varargin)
    option = genfisOptions('GridPartition');
else
    option = varargin{1};
end

if isa(option,'fuzzy.genfis.GridPartitionOptions')
    warningState = warning('off','fuzzy:general:warnGenfis1_Deprecation');
    restoreWarning = onCleanup(@()warning(warningState));
    fis = genfis1([Xin Xout],option.NumMembershipFunctions, ...
        option.InputMembershipFunctionType, ...
        option.OutputMembershipFunctionType);
elseif isa(option,'fuzzy.genfis.SubtractiveClusteringOptions')
    warningState = warning('off','fuzzy:general:warnGenfis2_Deprecation');
    restoreWarning = onCleanup(@()warning(warningState));
    dataScale = option.DataScale;
    if strcmp(option.DataScale,'auto')
        dataScale = [];
    end
    args = {option.ClusterInfluenceRange,dataScale, ...
        [option.SquashFactor,option.AcceptRatio, ...
        option.RejectRatio,option.Verbose]};
    if ~isempty(option.CustomClusterCenters)
        args = [args option.CustomClusterCenters];
    end
    fis = genfis2(Xin,Xout,args{:});
elseif isa(option,'fuzzy.genfis.FCMClusteringOptions')
    warningState = warning('off','fuzzy:general:warnGenfis3_Deprecation');
    restoreWarning = onCleanup(@()warning(warningState));
    fis = genfis3(Xin,Xout,option.FISType,option.NumClusters, ...
        [option.Exponent option.MaxNumIteration ...
        option.MinImprovement option.Verbose]);
else
    error(message('fuzzy:general:errGenfisOptions_InvalidType'));
end
end
%% Helper functions -------------------------------------------------------
function validateXin(value)
validateattributes(value, ...
    {'numeric'}, ...
    {'nonempty','2d','real','finite'}, ...
    '', ...
    'Xin');
end

function validateXout(value,numRows)
validateattributes(value, ...
    {'numeric'}, ...
    {'nonempty','2d','real','nrows',numRows,'finite'}, ...
    '', ...
    'Xout');
end