classdef gaussianOrthoGlobalModel < globalModel
    % GAUSSIANORTHOGLOBALMODEL class generates a global model consisting of orthogonal
    % Gaussians.
    %
    % GAUSSIANORTHOGLOBALMODEL  delivers all global properties of the local
    % models and the methods, that are needed to calculate the output model
    % and to plot the model, the partition and the membership function
    % values. Therefore some hidden methods are required, like the
    % calcualtion of the validity function value or the parallel simulation
    % for dynamic processes.
    %
    %
    % PROPERTIES:
    %
    % leafModels        (1 x M) logical vector, true for active models,
    %                           false for inactive models (default: []).
    %
    % history           (class) history class stores information concerning
    %                           the training algorithmn (default: []).
    %
    % kStepPrediction   (1 x 1) decribes which which kind of calculation
    %                           has to be done for getting the correct
    %                           model output  (default: 0).
    %
    % localModels       (1 x M)	cell array of all local models objects
    %                           (default: []).
    %
    % numberOfInputs 	(1 x 1)	number of all physical inputs (default:
    %                           []).
    %
    % numberOfOutputs 	(1 x 1)	number of all physical outputs (default:
    %                           []).
    %
    % smoothness        (1 x 1)	'fuddle'-parameter for defining the global
    %                           behaviour of the Gaussians (a factor that
    %                           change their steepness) (default: 1).
    %
    %
    % EXPLANATIONS:
    %
    %   "leafModels":
    %   This logical vector contains the information, which local models
    %   are the leaf one, i.e. they are the ones, that in super position
    %   result in the global model net.
    %
    %   "history":
    %   This property contains a history object, that stores all relevant
    %   information about the net structure and its evolution. Every
    %   iteration is kept inside this object.
    %
    %   "kStepPrediction":
    %   This property differs between a static model, a dynamic model with
    %   one-step-ahead prediction or a dynamic model simulation. For the
    %   first two cases, a simple prediction is performed, because all
    %   relevant data is existent. To simulate the output model for
    %   each time step, each step has to be calculated
    %   separately.
    %
    %   "localModels":
    %   This property contains all local model objects of the global model
    %   object. Each object stores all relevant infomation about the
    %   local model.
    %
    %   "numberOfInputs"/"numberOfOutputs":
    %   This property stores the number of inputs/outputs of the data set, which
    %   were used to train the global model object. If another data set is
    %   used for validation or testing, the quantities must fit.
    %
    %   "smoothness":
    %   This property defines the global behaviour of all Gaussians. Its a
    %   factor that changes the steepness of the Gaussians over the whole
    %   global model object. Therefore its a 'fuddle'-parameter that can be
    %   choosen by the operator to get a more or less smooth sureface. The
    %   default value is set to '1', which in most instances leads to a
    %   sufficient solution.
    %
    %
    % SYMBOLS AND ABBREVIATIONS:
    %
    % LM:  Local model
    %
    % p:   Number of inputs (physical inputs)
    % q:   Number of outputs
    % N:   Number of data samples
    % M:   Number of LMs
    % nx:  Number of regressors (x)
    % nz:  Number of regressors (z)
    %
    %
    % LMNtool - Local Model Network Toolbox
    % Tobias Ebert, 16-November-2011
    % Institute of Mechanics & Automatic Control, University of Siegen, Germany
    % Copyright (c) 2012 by Prof. Dr.-Ing. Oliver Nelles
    
    % 18.11.11  help updated (TE)
    % 09.03.12  set and get method for the property 'smoothness' updated (JB) 

    
    properties
    end
    
    properties(Dependent)
        smoothness                  % 1 x 1     'fuddle'-parameter for defining the global behaviour of the Gaussians (a factor that change their steepness)
    end
    
    properties(Access=private,Hidden=true)
        savedSmoothness = 1;        % 1 x 1     see property: smoothness;
    end
    
    
    methods
        [outputModel, MSFValue, validityFunctionValue] = calculateModelOutput(obj,input,output)
        [outputModel, MSFValue, validityFunctionValue] = calculateModelOutputCentered(obj,input,output)
        plotMSFValue(obj,dimToPlot)
    end
    
    methods(Hidden)
        [outputModel,MSFValue,validityFunctionValue] = simulateParallel(obj,xRegressor,zRegressor)
    end
    
    methods(Static)
        validityFunctionValue = calculateVFV(MSFValue)
    end

    
    methods
        %% Constructor
        function LM = gaussianOrthoGlobalModel
            
        end
        
        %% SET and GET methods, to prevent errors later
        function smoothness = get.smoothness(obj)
            smoothness  = obj.savedSmoothness;
        end
        function obj = set.smoothness(obj,value)
            if isscalar(value)
                obj.savedSmoothness = value;
                
                % check if there are existing local models
                if ~isempty(obj.localModels)
                    % update standardDeviations of local models
                    for localModel=1:size(obj.localModels,2)
                        [obj.localModels(1,localModel).center,obj.localModels(1,localModel).standardDeviation] = ...
                            obj.localModels(1,localModel).corner2Center(obj.localModels(1,localModel).lowerLeftCorner,obj.localModels(1,localModel).upperRightCorner,value);
                    end
                    
                    % update MSFValues
                    obj.MSFValue = arrayfun(@(loc) loc.calculateMSF(obj.zRegressor),obj.localModels,'UniformOutput',false);
                    
                    % update local model parameter
                    localModel = 1;
                    leafModelsTmp   = obj.leafModels;
                    for iteration=1:size(obj.history.leafModelIter,2)
                        % set number of iteration
                        obj.leafModels = obj.history.leafModelIter{1,iteration};
                        
                        % get all active gaussians and normalize them
                        validityFunctionValue = obj.calculateVFV(obj.MSFValue(obj.leafModels));
                        
                        % estimate parameters of the LM
                        if localModel == 1
                            % for the first iteration only one (global)
                            % model exists
                            obj.localModels(localModel).parameter = ...
                                estimateParametersLocal(obj,obj.xRegressor, obj.output, validityFunctionValue{end}, [], obj.dataWeighting);
                            localModel = localModel + 1;
                        else
                            obj.localModels(localModel).parameter = ...
                                estimateParametersLocal(obj,obj.xRegressor, obj.output, validityFunctionValue{end-1}, [], obj.dataWeighting);
                            localModel = localModel + 1;
                            obj.localModels(localModel).parameter = ...
                                estimateParametersLocal(obj,obj.xRegressor, obj.output, validityFunctionValue{end}, [], obj.dataWeighting);
                            localModel = localModel + 1;
                        end
                    end
                    obj.leafModels = leafModelsTmp;
                end
                
            else
                error('localModel:set:smoothness','smoothness must be a scalar')
            end
            
        end
        
        %         function obj = set.leafModels(obj,value)
        %             if islogical(value)
        %                 obj.leafModels = value;
        %             else
        %                 error('localModel:set:leafModels','leafModels must be a logical array')
        %             end
        %         end
    end
    
    
end

