classdef VariableSpecification
    % One instance represents all the variables.

    %   Copyright 2016-2022 The MathWorks, Inc.

    properties
        Names           % cellstr
        LBs             % vector
        UBs             % vector
        Categories      % cell array of categorical arrays
    end

    properties(SetAccess = private)
        Types           % cellstr
        Transforms      % cellstr
        isReal          % A logical vector used for efficiency
        isInt           % A logical vector used for efficiency
        isCat           % A logical vector used for efficiency
        isLog           % A logical vector used for efficiency
    end

    properties(Dependent)
        NumVars
        % Transformed lower and upper bounds
        LBTrans     	% vector
        UBTrans      	% vector
    end

    methods
        function this = VariableSpecification(Names, Types, Transforms)
            this.Names = Names;
            % Set types
            this.Types = Types;
            this.isReal = ismember(this.Types, 'real');
            this.isInt = ismember(this.Types, 'integer');
            this.isCat = ismember(this.Types, 'categorical');
            % Set transforms
            this.Transforms = Transforms;
            this.isLog = ismember(this.Transforms, 'log');
        end

        function N = get.NumVars(this)
            N = length(this.Names);
        end

        function LBT = get.LBTrans(this)
            LBT = this.LBs;
            LBT(this.isLog & this.LBs~=0) = log(LBT(this.isLog & this.LBs~=0));
            % Log variables with LB=0 are transformed with log1p
            LBT(this.isLog & this.LBs==0) = log1p(LBT(this.isLog & this.LBs==0));
        end

        function UBT = get.UBTrans(this)
            UBT = this.UBs;
            UBT(this.isLog & this.LBs~=0) = log(UBT(this.isLog & this.LBs~=0));
            % Log variables with LB=0 are transformed with log1p
            UBT(this.isLog & this.LBs==0) = log1p(UBT(this.isLog & this.LBs==0));
        end
    end

    methods(Static)
        function obj = loadobj(s)
            % s may be a struct or an object. Either way, call the
            % constructor and then copy in the 3 remaining properties.
            obj = bayesoptim.VariableSpecification(s.Names, s.Types, s.Transforms);
            obj.LBs = s.LBs;
            obj.UBs = s.UBs;
            obj.Categories = s.Categories;
        end
    end
end
