classdef (Abstract) Lsqncommon < optim.options.MultiAlgorithm
%

%Lsqncommon Common base class for Lsqnonlin and Lsqcurvefit
%
%   OPTIM.OPTIONS.LSQNCOMMON is an abstract class containing the options
%   for Lsqnonlin and Lsqcurvefit. You cannot create instances of this class directly.  
%   You must create an instance of the derived classes, either
%   OPTIM.OPTIONS.LSQCURVEFIT or OPTIM.OPTIONS.LSQNONLIN.
%
%   See also OPTIM.OPTIONS.MULTIALGORITHM, OPTIM.OPTIONS.SOLVEROPTIONS
    
%   Copyright 2012-2023 The MathWorks, Inc.    
 


    properties (Dependent)

%CONSTRAINTTOLERANCE Termination tolerance on the constraint violation
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        ConstraintTolerance

%DISPLAY Level of display
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        Display
        
%FINITEDIFFERENCESTEPSIZE Scalar or vector step size factor
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        FiniteDifferenceStepSize
        
%FINITEDIFFERENCETYPE Finite difference type
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        FiniteDifferenceType

%FUNCTIONTOLERANCE Termination tolerance on the function value
%
%   For more information, type "doc linprog" and see the "Options" section
%   in the LINPROG documentation page.
        FunctionTolerance
        
%JACOBIANMULTIPLYFCN Handle to function that performs Jacobian-vector and
%                    Jacobian-matrix products
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)

        JacobianMultiplyFcn
        
%MAXFUNCTIONEVALUATIONS Maximum number of function evaluations allowed     
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        MaxFunctionEvaluations
        
%MAXITER Maximum number of iterations allowed 
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        MaxIterations      
 
%OPTIMALITYTOLERANCE Termination tolerance on the first-order optimality
%                    measure
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        OptimalityTolerance
        
%OUTPUTFCN Callbacks that are called at each iteration
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        OutputFcn

%PLOTFCN Plots various measures of progress while the algorithm executes
% 
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        PlotFcn        

%SPECIFYCONSTRAINTGRADIENT Gradient for the objective function defined 
%                         by the caller
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        SpecifyConstraintGradient

%SPECIFYOBJECTIVEGRADIENT Gradient for the objective function defined 
%                         by the caller
%
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        SpecifyObjectiveGradient        
        
%STEPTOLERANCE Termination tolerance on x
% 
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        StepTolerance        

%SUBPROBLEMALGORITHM Algorithm for solving a subproblem
% 
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        SubproblemAlgorithm
        
%TYPICALX Typical x values        
% 
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        TypicalX
        
        
%USEPARALLEL Option to use parallel finite difference calculation        
% 
%   For more information, see the "Options" section documentation page of
%   the solver you are using (either lsqnonlin or lsqcurvefit)
        UseParallel            

%BARRIERPARAMUPDATE Barrier Parameter Update
        BarrierParamUpdate

    end

%------------------------ Old hidden properties ---------------------------

    properties (Hidden, Dependent)

%CHECKGRADIENTS Compare user-supplied derivatives to finite-differencing
%                derivatives
        CheckGradients

%DERIVATIVECHECK Compare supplied derivatives to finite-differencing 
%                derivatives
        DerivativeCheck
        
%DIAGNOSTICS Display diagnostic information 
        Diagnostics
        
%DIFFMAXCHANGE Maximum change in variables for finite-difference gradients        
        DiffMaxChange
        
%DIFFMINCHANGE Minimum change in variables for finite-difference gradients        
        DiffMinChange
        
%FINDIFFRELSTEP Scalar or vector step size factor
        FinDiffRelStep
        
%FINDIFFTYPE Finite difference type
        FinDiffType

%FUNVALCHECK Check whether objective function and constraints values are
%            valid
        FunValCheck

%GRADCONSTR Gradient for nonlinear constraint functions defined by the user
%
        GradConstr
       
%INITDAMPING Initial Levenberg-Marquardt parameter
        InitDamping
        
%JACOBIAN Jacobian for the objective function defined by the caller
        Jacobian
        
%JACOBMULT Function handle for Jacobian multiply function        
        JacobMult
        
%JACOBPATTERN Sparsity pattern of the Jacobian for finite differencing        
        JacobPattern

%MAXFUNEVALS Maximum number of function evaluations allowed     
        MaxFunEvals
        
%MAXITER Maximum number of iterations allowed 
        MaxIter
        
%MAXPCGITER Maximum number of PCG (preconditioned conjugate gradient) 
%           iterations        
        MaxPCGIter      
        
%PLOTFCNS Plots various measures of progress while the algorithm executes
        PlotFcns
        
%PRECONDBANDWIDTH Upper bandwidth of preconditioner for PCG
        PrecondBandWidth        
        
%SCALEPROBLEM Determine whether all constraints and the objective function
%             are normalized
        ScaleProblem

%TOLCON Tolerance on the constraint violation
%
        TolCon

%TOLFUN Termination tolerance on the function value
        TolFun
        
%TOLPCG Termination tolerance on the PCG iteration
        TolPCG
        
%TOLX Termination tolerance on x
        TolX

%INITBARRIERPARAM Initial barrier value
        InitBarrierParam        
    end
    
    properties (Hidden, Access = protected)
%OPTIONSSTORE Contains the option values and meta-data for the class
%         
        OptionsStore = createOptionsStore;
    end       
    
    properties(Hidden, GetAccess=public)
% Constant, globally visible metadata about this class.
% This data is used to spec the options in this class for internal clients
% such as: tab-complete, and the options validation
% Properties
        PropertyMetaInfo = genPropInfo();    
    end

    methods (Hidden)
        
        function obj = Lsqncommon(varargin)
%Lsqncommon Common base class for Lsqnonlin and Lsqcurvefit
%
%   OPTIM.OPTIONS.LSQNCOMMON is an abstract class containing the options
%   for Lsqnonlin and Lsqcurvefit. You cannot create instances of this class directly.  
%   You must create an instance of the derived classes, either
%   OPTIM.OPTIONS.LSQCURVEFIT or OPTIM.OPTIONS.LSQNONLIN.
%
%   See also OPTIM.OPTIONS.MULTIALGORITHM, OPTIM.OPTIONS.SOLVEROPTIONS

            % Call the superclass constructor
            obj = obj@optim.options.MultiAlgorithm(varargin{:});
               
            % Record the class version
            obj.Version = 2;
        end
               
        function obj = replaceSpecialStrings(obj)
            %replaceSpecialStrings Replace special string values 
            %
            %   obj = replaceSpecialStrings(obj) replaces special string
            %   option values with their equivalent numerical value. We
            %   currently only use this method to convert FinDiffRelStep.
            %   However, in the future we would like to move the special
            %   string replacement code from the solver files to the
            %   options classes.
           
            % Call a package function to replace string values in
            % FinDiffRelStep.
            obj.OptionsStore.Options.FinDiffRelStep = ...
                optim.options.replaceFinDiffRelStepString(obj.FinDiffRelStep);
        end
    end
    
    % Set/get methods
    methods

        % ---------------------- Set methods ------------------------------

        function obj = set.CheckGradients(obj, value)
            obj = setNewProperty(obj, 'CheckGradients', value);
        end                

        function obj = set.ConstraintTolerance(obj, value)
            obj = setAliasProperty(obj, 'ConstraintTolerance', 'TolCon', value);        
        end
        
        function obj = set.Diagnostics(obj, value)
            obj = setProperty(obj, 'Diagnostics', value);
        end
        
        function obj = set.DiffMaxChange(obj, value)
            obj = setProperty(obj, 'DiffMaxChange', value);
        end        

        function obj = set.Display(obj, value)
            if strcmpi(value, 'testing')
                % Set Display to the undocumented value, 'testing'.
                obj = setPropertyNoChecks(obj, 'Display', 'testing');
            else
                % Pass the possible values that the Display option can take
                % via the fourth input of setProperty.
                obj = setProperty(obj, 'Display', value);
            end
        end
        
        function obj = set.FiniteDifferenceStepSize(obj, value)
            obj = setAliasProperty(obj, 'FiniteDifferenceStepSize', 'FinDiffRelStep', value);
        end        
        
        function obj = set.FinDiffRelStep(obj, value)
            obj = setProperty(obj, 'FinDiffRelStep', value);
        end

        function obj = set.FunctionTolerance(obj, value)
            obj = setAliasProperty(obj, 'FunctionTolerance', 'TolFunValue', value);        
        end

        function obj = set.GradConstr(obj,value)
            obj = setProperty(obj, 'GradConstr', value);
        end
        
        function obj = set.Jacobian(obj, value)
            obj = setProperty(obj, 'Jacobian', value);
        end        

        function obj = set.JacobMult(obj, value)
            obj = setProperty(obj, 'JacobMult', value);
        end
        
        function obj = set.JacobianMultiplyFcn(obj, value)
            obj = setAliasProperty(obj, 'JacobianMultiplyFcn', 'JacobMult', value);
        end        
        
        function obj = set.JacobPattern(obj, value)
            obj = setProperty(obj, 'JacobPattern', value);
        end

        function obj = set.MaxFunctionEvaluations(obj, value)
            obj = setAliasProperty(obj, 'MaxFunctionEvaluations', 'MaxFunEvals', value); 
        end                
        
        function obj = set.MaxFunEvals(obj, value)
            obj = setProperty(obj, 'MaxFunEvals', value);
        end        
        
        function obj = set.OutputFcn(obj, value)
            obj = setProperty(obj, 'OutputFcn', value);
        end        
        
        function obj = set.PlotFcn(obj, value)
            obj = setAliasProperty(obj, 'PlotFcn', 'PlotFcns', value); 
        end                
        
        function obj = set.PlotFcns(obj, value)
            obj = setAliasProperty(obj, 'PlotFcn', 'PlotFcns', value); 
        end        
        
        function obj = set.ScaleProblem(obj, value)
            % Pass the possible values that the ScaleProblem option can
            % take via the fourth input of setProperty.            
            obj = setProperty(obj, 'ScaleProblem', value);
        end        
        
        function obj = set.SpecifyConstraintGradient(obj, value)
            obj = setNewProperty(obj, 'SpecifyConstraintGradient', value);
        end                

        function obj = set.SpecifyObjectiveGradient(obj, value)
            obj = setNewProperty(obj, 'SpecifyObjectiveGradient', value);
        end                
        
        function obj = set.DiffMinChange(obj, value)
            obj = setProperty(obj, 'DiffMinChange', value);
        end        

        function obj = set.DerivativeCheck(obj, value)
            obj = setProperty(obj, 'DerivativeCheck', value);
        end        

        function obj = set.FiniteDifferenceType(obj, value)
            obj = setAliasProperty(obj, 'FiniteDifferenceType', 'FinDiffType', value);  
            % If we get here, the property set has been succesful and we
            % can update the OptionsStore
            if ~obj.OptionsStore.SetByUser.FinDiffRelStep
                obj.OptionsStore.Options.FinDiffRelStep = ...
                    optim.options.getDefaultFinDiffRelStep(...
                    obj.OptionsStore.Options.FinDiffType);
            end
        end
        
        function obj = set.FinDiffType(obj, value)
            obj = setProperty(obj, 'FinDiffType', value);
            % If we get here, the property set has been succesful and we
            % can update the OptionsStore
            if ~obj.OptionsStore.SetByUser.FinDiffRelStep
                obj.OptionsStore.Options.FinDiffRelStep = ...
                    optim.options.getDefaultFinDiffRelStep(...
                    obj.OptionsStore.Options.FinDiffType);
            end
        end

        function obj = set.FunValCheck(obj, value)
            obj = setProperty(obj, 'FunValCheck', value);
        end

        function obj = set.InitDamping(obj, value)
            obj = setProperty(obj, 'InitDamping', value);
        end
        
        function obj = set.MaxIterations(obj, value)
             obj = setAliasProperty(obj, 'MaxIterations', 'MaxIter', value);      
        end
       
        function obj = set.MaxIter(obj, value)
            obj = setProperty(obj, 'MaxIter', value);
        end
        
        function obj = set.MaxPCGIter(obj, value)
            obj = setProperty(obj, 'MaxPCGIter', value);
        end

        function obj = set.OptimalityTolerance(obj, value)
            obj = setAliasProperty(obj, 'OptimalityTolerance', 'TolFun', value);        
        end          
        
        function obj = set.StepTolerance(obj, value)
            obj = setAliasProperty(obj, 'StepTolerance', 'TolX', value);        
        end                
        
        function obj = set.SubproblemAlgorithm(obj, value)
            obj = setNewProperty(obj, 'SubproblemAlgorithm', value);
        end
        
        function obj = set.PrecondBandWidth(obj, value)
            obj = setProperty(obj, 'PrecondBandWidth', value);
        end

        function obj = set.TolCon(obj,value)
            obj = setProperty(obj,'TolCon',value);
        end

        function obj = set.TolFun(obj, value)
            % TolFun maps to FunctionTolerance for levenberg-marquardt and
            % to OptimalityTolerance for every other algorithm
            if strcmp(obj.Algorithm, 'levenberg-marquardt')
                obj = setAliasProperty(obj, 'TolFun', 'TolFunValue', value);
            else
                obj = setNewProperty(obj, 'TolFun', value);
            end
        end
        
        function obj = set.TolPCG(obj, value)
            obj = setProperty(obj, 'TolPCG', value);
        end

        function obj = set.TolX(obj, value)
            obj = setProperty(obj, 'TolX', value);
        end
        
        function obj = set.TypicalX(obj, value)
            obj = setProperty(obj, 'TypicalX', value);
        end
        
        function obj = set.UseParallel(obj, value)
            obj = setProperty(obj, 'UseParallel', value);
        end

        function obj = set.BarrierParamUpdate(obj, value)
            obj = setProperty(obj, 'BarrierParamUpdate', value);
        end

        function obj = set.InitBarrierParam(obj, value)
            obj = setProperty(obj, 'InitBarrierParam', value);
        end        
                
        % ---------------------- Get methods ------------------------------

        function value = get.ConstraintTolerance(obj)
            value = obj.OptionsStore.Options.TolCon;
        end  

        function value = get.CheckGradients(obj)
            value = optim.options.OptionAliasStore.convertToLogical( ...
                obj.OptionsStore.Options.DerivativeCheck, 'on');
        end
       
        function value = get.DerivativeCheck(obj)
            value = obj.OptionsStore.Options.DerivativeCheck;
        end
        
        function value = get.Diagnostics(obj)
            value = obj.OptionsStore.Options.Diagnostics;
        end
        
        function value = get.DiffMaxChange(obj)
            value = obj.OptionsStore.Options.DiffMaxChange;
        end        

        function value = get.DiffMinChange(obj)
            value = obj.OptionsStore.Options.DiffMinChange;
        end        
        
        function value = get.Display(obj)
            value = obj.OptionsStore.Options.Display;
        end

        function value = get.FiniteDifferenceType(obj)
            value = obj.OptionsStore.Options.FinDiffType;
        end        
        
        function value = get.FinDiffType(obj)
            value = obj.OptionsStore.Options.FinDiffType;
        end        
        
        function value = get.FiniteDifferenceStepSize(obj)
            value = obj.OptionsStore.Options.FinDiffRelStep;
        end                
        
        function value = get.FinDiffRelStep(obj)
            value = obj.OptionsStore.Options.FinDiffRelStep;
        end

        function value = get.FunctionTolerance(obj)
            value = obj.OptionsStore.Options.TolFunValue;
        end  

        function value = get.FunValCheck(obj)
            value = obj.OptionsStore.Options.FunValCheck;
        end

        function value = get.GradConstr(obj)
            value = obj.OptionsStore.Options.GradConstr;
        end

        function value = get.InitDamping(obj)
            value = obj.OptionsStore.Options.InitDamping;
        end
                
        function value = get.Jacobian(obj)
            value = obj.OptionsStore.Options.Jacobian;
        end

        function value = get.JacobianMultiplyFcn(obj)
            value = obj.OptionsStore.Options.JacobMult;
        end         
        
        function value = get.JacobMult(obj)
            value = obj.OptionsStore.Options.JacobMult;
        end        

        function value = get.JacobPattern(obj)
            value = obj.OptionsStore.Options.JacobPattern;
        end        
        
        function value = get.MaxFunctionEvaluations(obj)
            value = obj.OptionsStore.Options.MaxFunEvals;
        end         
        
        function value = get.MaxFunEvals(obj)
            value = obj.OptionsStore.Options.MaxFunEvals;
        end        
                
        function value = get.MaxIterations(obj)
            value = obj.OptionsStore.Options.MaxIter;
        end                
        
        function value = get.MaxIter(obj)
            value = obj.OptionsStore.Options.MaxIter;
        end
        
        function value = get.MaxPCGIter(obj)
            value = obj.OptionsStore.Options.MaxPCGIter;
        end

        function value = get.OptimalityTolerance(obj)
            value = obj.OptionsStore.Options.TolFun;
        end  
        
        function value = get.OutputFcn(obj)
            value = obj.OptionsStore.Options.OutputFcn;
        end
         
        function value = get.PlotFcn(obj)
            value = obj.OptionsStore.Options.PlotFcns;
        end        
        
        function value = get.PlotFcns(obj)
            value = obj.OptionsStore.Options.PlotFcns;
        end                
        
        function value = get.PrecondBandWidth(obj)
            value = obj.OptionsStore.Options.PrecondBandWidth;
        end

        function value = get.ScaleProblem(obj)
            value = obj.OptionsStore.Options.ScaleProblem;
        end

        function value = get.SpecifyConstraintGradient(obj)
            value = optim.options.OptionAliasStore.convertToLogical( ...
                        obj.OptionsStore.Options.GradConstr, 'on');
        end       

        function value = get.SpecifyObjectiveGradient(obj)
            value = optim.options.OptionAliasStore.convertToLogical( ...
                        obj.OptionsStore.Options.Jacobian, 'on');
        end       
                
        function value = get.SubproblemAlgorithm(obj)
            value = optim.options.OptionAliasStore.mapOptionFromStore(...
                'SubproblemAlgorithm', obj.OptionsStore.Options);
        end                        
        
        function value = get.StepTolerance(obj)
            value = obj.OptionsStore.Options.TolX;
        end  
        
        function value = get.TolCon(obj)
            value = obj.OptionsStore.Options.TolCon;
        end

        function value = get.TolFun(obj)
            value = obj.OptionsStore.Options.TolFun;
        end
        
        function value = get.TolPCG(obj)
            value = obj.OptionsStore.Options.TolPCG;
        end        
        
        function value = get.TolX(obj)
            value = obj.OptionsStore.Options.TolX;
        end
        
        function value = get.TypicalX(obj)
            value = obj.OptionsStore.Options.TypicalX;
        end

        function value = get.UseParallel(obj)
            value = obj.OptionsStore.Options.UseParallel;
        end

        function value = get.InitBarrierParam(obj)
            value = obj.OptionsStore.Options.InitBarrierParam;
        end

        function value = get.BarrierParamUpdate(obj)
            value = obj.OptionsStore.Options.BarrierParamUpdate;
        end
  
    end
    
        % Hidden utility methods
    methods (Hidden)
        
        function OptionsStruct = mapOptionsForSolver(~, OptionsStruct)
%mapOptionsForSolver Map structure to an optimset one
%
%   OptionsStruct = mapOptionsForSolver(obj, OptionsStruct) maps the
%   specified structure so it can be used in the solver functions and in
%   OPTIMTOOL.            
            % If MaxFunEvals is at its default (a string), set to empty
            if isfield(OptionsStruct, 'MaxFunEvals') && ...
                    ischar(OptionsStruct.MaxFunEvals)
                OptionsStruct.MaxFunEvals = [];
            end
        end
    end
    
    methods (Hidden, Access = protected)
        
        % Common method to allow child classes to upgrade
        % Levenberg-Marquardt and FinDiffRelStep to the R2013b state during
        % object loading.
        function obj = upgradeLMandFinDiffTo13b(obj)
            
            % Add the Levenberg-Marquardt parameter. Also, update
            % FinDiffRelStep default that was upgraded in R2013b.
            
            % Add the InitDamping option to the OptionsStore
            obj.OptionsStore.AlgorithmDefaults{2}.InitDamping = 0.01;
            obj.OptionsStore.SetByUser.InitDamping = false;
            obj.OptionsStore.IsConstantDefault.InitDamping = true;
            obj.OptionsStore.Options.InitDamping = 0.01;
            
            % Upgrade FinDiffRelStep default
            obj.OptionsStore.AlgorithmDefaults{1}.FinDiffRelStep = 'sqrt(eps)';
            obj.OptionsStore.AlgorithmDefaults{2}.FinDiffRelStep = 'sqrt(eps)';
            if ~isSetByUser(obj, 'FinDiffRelStep')
                obj.OptionsStore.Options.FinDiffRelStep = 'sqrt(eps)';
            end
            
        end
        
        % Common method to allow child classes to upgrade to the R2016a
        % state during object loading.
        function obj = upgradeTo16a(obj, defaultOptionsStore)
            
            % Add UseParallel property.
            obj.OptionsStore.AlgorithmDefaults{2}.UseParallel = false;
            obj.OptionsStore.AlgorithmDefaults{1}.UseParallel = false;
            obj.OptionsStore.SetByUser.UseParallel = false;
            obj.OptionsStore.IsConstantDefault.UseParallel = true;
            obj.OptionsStore.Options.UseParallel = false;            
            
            % Add the TolFunValue option to the OptionsStore
            obj.OptionsStore.AlgorithmDefaults{1}.TolFunValue = 1e-6;
            obj.OptionsStore.AlgorithmDefaults{2}.TolFunValue = 1e-6;
            obj.OptionsStore.IsConstantDefault.TolFunValue = true;
            
            % Set TolFunValue to whatever of TolFun was saved, but only if the selected algorithm has
            % "FunctionTolerance". Otherwise, set to its default value
            % for another algorithm
            if isfield(obj.OptionsStore.AlgorithmDefaults{obj.OptionsStore.AlgorithmIndex},'TolFunValue') && obj.OptionsStore.SetByUser.TolFun
                obj.OptionsStore.SetByUser.TolFunValue = obj.OptionsStore.SetByUser.TolFun;
                obj.OptionsStore.Options.TolFunValue = obj.OptionsStore.Options.TolFun;
            else
                obj.OptionsStore.SetByUser.TolFunValue = false;
                obj.OptionsStore.Options.TolFunValue = obj.OptionsStore.AlgorithmDefaults{1}.TolFunValue;
            end
            
            % Remove TolFun field for Levenberg-Marquardt
            obj.OptionsStore.AlgorithmDefaults{2} = ...
                rmfield(obj.OptionsStore.AlgorithmDefaults{2}, 'TolFun');
        end

        % Common method to allow child classes to upgrade to the R2022b
        % state during object loading.
        function obj = upgradeTo23a(obj,defaultOptionsStore)
            obj.OptionsStore.AlgorithmNames{3} = 'interior-point';
            obj.OptionsStore.AlgorithmDefaults{3} = defaultOptionsStore.AlgorithmDefaults{3};
            obj.OptionsStore.AlgorithmIndex(3) = false;

            obj.OptionsStore.IsConstantDefault.MaxIter = false;
            obj.OptionsStore.IsConstantDefault.TolCon = true;
            obj.OptionsStore.IsConstantDefault.GradConstr = true;
            obj.OptionsStore.IsConstantDefault.TolX = false;
            obj.OptionsStore.IsConstantDefault.BarrierParamUpdate = true;
            obj.OptionsStore.IsConstantDefault.InitBarrierParam = true;
            obj.OptionsStore.IsConstantDefault.SubproblemAlgorithm = true;

            obj.OptionsStore.NonConstantDefaultFields{2,1} = 'MaxIter';
            obj.OptionsStore.NonConstantDefaultFields{3,1} = 'TolX';
            obj.OptionsStore.NonConstantDefaults.MaxFunEvals{3} = 3000;
            obj.OptionsStore.NonConstantDefaults.MaxIter = {400, 400, 1000};
            obj.OptionsStore.NonConstantDefaults.TolX = {1e-6, 1e-6, 1e-10};

            obj.OptionsStore.Options.TolCon = 1e-6;
            obj.OptionsStore.SetByUser.TolCon = false;

            obj.OptionsStore.Options.GradConstr = 'off';
            obj.OptionsStore.SetByUser.GradConstr = false;

            obj.OptionsStore.Options.BarrierParamUpdate = 'monotone';
            obj.OptionsStore.SetByUser.BarrierParamUpdate = false;

            obj.OptionsStore.Options.InitBarrierParam = 0.1;
            obj.OptionsStore.SetByUser.InitBarrierParam = false;

            obj.OptionsStore.Options.SubproblemAlgorithm = 'ldl-factorization';
            obj.OptionsStore.SetByUser.SubproblemAlgorithm = false;

            % Add NumDisplayOptions and DisplayOptions fields
            obj.OptionsStore = optim.options.getDisplayOptionFieldsFor16a(...
                obj.OptionsStore, defaultOptionsStore);
        end
        
    end

end

function OS = createOptionsStore
%CREATEOPTIONSSTORE Create the OptionsStore
%
%   OS = createOptionsStore creates the OptionsStore structure. This
%   structure contains the options and meta-data for option display, e.g.
%   data determining whether an option has been set by the user. This
%   function is only called when the class is first instantiated to create
%   the OptionsStore structure in its default state. Subsequent
%   instatntiations of this class pick up the default OptionsStore from the
%   MCOS class definition.
%
%   Class authors must create a structure containing the following fields:-
%
%   AlgorithmNames   : Cell array of algorithm names for the solver
%   DefaultAlgorithm : String containing the name of the default algorithm
%   AlgorithmDefaults: Cell array of structures. AlgorithmDefaults{i}
%                      holds a structure containing the defaults for 
%                      AlgorithmNames{i}.
%
%   This structure must then be passed to the
%   optim.options.generateMultiAlgorithmOptionsStore function to create
%   the full OptionsStore. See below for an example.

% Define the algorithm names
OS.AlgorithmNames = {'trust-region-reflective', 'levenberg-marquardt', 'interior-point'};

% Define the default algorithm
OS.DefaultAlgorithm = 'trust-region-reflective';

% Define the defaults for each algorithm
% trust-region-reflective
OS.AlgorithmDefaults{1}.DerivativeCheck = 'off';
OS.AlgorithmDefaults{1}.Diagnostics = 'off';
OS.AlgorithmDefaults{1}.DiffMaxChange = Inf;
OS.AlgorithmDefaults{1}.DiffMinChange = 0;
OS.AlgorithmDefaults{1}.Display = 'final';
OS.AlgorithmDefaults{1}.FinDiffRelStep = 'sqrt(eps)';
OS.AlgorithmDefaults{1}.FinDiffType = 'forward';
OS.AlgorithmDefaults{1}.FunValCheck = 'off';
OS.AlgorithmDefaults{1}.Jacobian = 'off';
OS.AlgorithmDefaults{1}.MaxFunEvals = '100*numberOfVariables';
OS.AlgorithmDefaults{1}.MaxIter = 400;
OS.AlgorithmDefaults{1}.OutputFcn = [];
OS.AlgorithmDefaults{1}.PlotFcns = [];
OS.AlgorithmDefaults{1}.TolFunValue = 1e-6;
OS.AlgorithmDefaults{1}.TolFun = 1e-6;
OS.AlgorithmDefaults{1}.TolX = 1e-6;
OS.AlgorithmDefaults{1}.TypicalX = 'ones(numberOfVariables,1)';
OS.AlgorithmDefaults{1}.JacobMult = [];
OS.AlgorithmDefaults{1}.JacobPattern = 'sparse(ones(Jrows,Jcols))';
OS.AlgorithmDefaults{1}.MaxPCGIter = 'max(1,floor(numberOfVariables/2))';
OS.AlgorithmDefaults{1}.PrecondBandWidth = Inf;
OS.AlgorithmDefaults{1}.TolPCG = 0.1;
OS.AlgorithmDefaults{1}.UseParallel = false;

% levenberg-marquardt
OS.AlgorithmDefaults{2}.DerivativeCheck = 'off';
OS.AlgorithmDefaults{2}.Diagnostics = 'off';
OS.AlgorithmDefaults{2}.DiffMaxChange = Inf;
OS.AlgorithmDefaults{2}.DiffMinChange = 0;
OS.AlgorithmDefaults{2}.Display = 'final';
OS.AlgorithmDefaults{2}.FinDiffRelStep = 'sqrt(eps)';
OS.AlgorithmDefaults{2}.FinDiffType = 'forward';
OS.AlgorithmDefaults{2}.FunValCheck = 'off';
OS.AlgorithmDefaults{2}.Jacobian = 'off';
OS.AlgorithmDefaults{2}.InitDamping = 0.01;
OS.AlgorithmDefaults{2}.MaxFunEvals = '200*numberOfVariables';
OS.AlgorithmDefaults{2}.MaxIter = 400;
OS.AlgorithmDefaults{2}.OutputFcn = [];
OS.AlgorithmDefaults{2}.PlotFcns = [];
OS.AlgorithmDefaults{2}.TolFunValue = 1e-6;
OS.AlgorithmDefaults{2}.TolX = 1e-6;
OS.AlgorithmDefaults{2}.TypicalX = 'ones(numberOfVariables,1)';
OS.AlgorithmDefaults{2}.ScaleProblem = 'none';
OS.AlgorithmDefaults{2}.UseParallel = false;

% interior-point
OS.AlgorithmDefaults{3}.Display = 'final';
OS.AlgorithmDefaults{3}.OutputFcn = [];
OS.AlgorithmDefaults{3}.PlotFcns = [];
OS.AlgorithmDefaults{3}.Diagnostics = 'off';
OS.AlgorithmDefaults{3}.FinDiffType = 'forward';
OS.AlgorithmDefaults{3}.FinDiffRelStep = 'sqrt(eps)';
OS.AlgorithmDefaults{3}.DiffMaxChange= Inf;
OS.AlgorithmDefaults{3}.DiffMinChange= 0;
OS.AlgorithmDefaults{3}.DerivativeCheck = 'off';
OS.AlgorithmDefaults{3}.TypicalX = 'ones(numberOfVariables,1)';
OS.AlgorithmDefaults{3}.ScaleProblem = 'none';
OS.AlgorithmDefaults{3}.InitBarrierParam = 0.1000;
OS.AlgorithmDefaults{3}.SubproblemAlgorithm = 'ldl-factorization';
OS.AlgorithmDefaults{3}.BarrierParamUpdate = 'monotone';
OS.AlgorithmDefaults{3}.GradConstr = 'off';
OS.AlgorithmDefaults{3}.Jacobian = 'off';
OS.AlgorithmDefaults{3}.FunValCheck= 'off';
OS.AlgorithmDefaults{3}.MaxFunEvals = 3000;
OS.AlgorithmDefaults{3}.MaxIter = 1000;
OS.AlgorithmDefaults{3}.TolCon = 1e-6;
OS.AlgorithmDefaults{3}.TolFun = 1e-6;
OS.AlgorithmDefaults{3}.TolX = 1e-10;
OS.AlgorithmDefaults{3}.UseParallel = false;

% Call the package function to generate the OptionsStore
OS = optim.options.generateMultiAlgorithmOptionsStore(OS, 'optim.options.Lsqncommon');

end

function propInfo = genPropInfo()
% Helper function to generate constant property metadata for the Lsqncommon
% options class.

import optim.options.meta.Factory
import optim.options.meta.label
import optim.options.meta.category

% For some hidden options, we don't require labels, etc.
% Because of that, we can initialize a few "empty" type handles that can be
% re-used for all options that need a validator of similar type.
emptyToleranceType = Factory.toleranceType('');
emptyResourceLimitType = Factory.resourceLimitType('');
onOffType = Factory.onOffType();
emptyPosDoubleScalarType = Factory.positiveRealType('','');

propInfo.Algorithm = Factory.algorithmType({'trust-region-reflective','levenberg-marquardt','interior-point'});
propInfo.ConstraintTolerance = Factory.constraintToleranceType;
propInfo.Display = Factory.displayType({'none','off','iter','iter-detailed','final','final-detailed'});
propInfo.FiniteDifferenceStepSize = Factory.finiteDifferenceStepSizeType;
propInfo.FiniteDifferenceType = Factory.finiteDifferenceType;
propInfo.FunctionTolerance = Factory.functionToleranceType;
propInfo.JacobianMultiplyFcn = Factory.fcnType(label('JacobMult'),category('Derivatives'));
propInfo.MaxFunctionEvaluations = Factory.maxFunEvalsType;
propInfo.MaxIterations = Factory.maxIterType;
propInfo.OptimalityTolerance = Factory.optimalityToleranceType;
propInfo.OutputFcn = Factory.outputFcnType;
propInfo.PlotFcn = Factory.plotFcnType({'optimplotx','optimplotfunccount','optimplotresnorm','optimplotfval','optimplotstepsize','optimplotfirstorderopt'});
propInfo.SpecifyObjectiveGradient = Factory.specifyObjectiveGradientType;
propInfo.StepTolerance = Factory.stepToleranceType;
propInfo.SpecifyConstraintGradient = Factory.specifyConstraintGradientType;
propInfo.SubproblemAlgorithm = Factory.enumType({'cg','factorization','ldl-factorization'},label('SubprobAlg'),category('Algorithm'));
propInfo.TypicalX = Factory.typicalXType;
propInfo.UseParallel = Factory.useParallelType;
propInfo.BarrierParamUpdate = Factory.enumType({'monotone','predictor-corrector'},label('BarrierParamUpdate'),category('Algorithm'));

% Hidden options - no alias.
propInfo.CheckGradients = Factory.checkGradientsType;
propInfo.DerivativeCheck = onOffType; 
propInfo.Diagnostics = onOffType;
propInfo.DiffMaxChange = emptyToleranceType;
propInfo.DiffMinChange = emptyToleranceType;
propInfo.FunValCheck = onOffType;
propInfo.GradConstr = onOffType;
propInfo.InitDamping = emptyToleranceType;
propInfo.Jacobian = onOffType;
propInfo.JacobPattern = Factory.numericType('matrix',[-Inf Inf],[true true],'','');
propInfo.MaxPCGIter = emptyResourceLimitType;
propInfo.PrecondBandWidth = Factory.integerType([0 Inf],'','');
propInfo.ScaleProblem = Factory.enumType({'none','jacobian','obj-and-constr'},'','');
propInfo.TolPCG = emptyToleranceType;
propInfo.InitBarrierParam = emptyPosDoubleScalarType;

% Re-direct to new named option: grab handle to its meta type
propInfo.FinDiffRelStep = propInfo.FiniteDifferenceStepSize;
propInfo.FinDiffType = propInfo.FiniteDifferenceType;
propInfo.JacobMult = propInfo.JacobianMultiplyFcn;
propInfo.MaxIter = propInfo.MaxIterations;
propInfo.MaxFunEvals = propInfo.MaxFunctionEvaluations;
propInfo.PlotFcns = propInfo.PlotFcn;
propInfo.TolCon = propInfo.ConstraintTolerance;
propInfo.TolFun = propInfo.FunctionTolerance;
propInfo.TolX = propInfo.StepTolerance;
end
