function [ModelOutput] = ModelUse(Data,Model,OutputType,DesiredOutput)
%*******************************************************************************%
% File : ModelUse.m
% Last update: 15/10/98
% Author : SIEMENS\Dominique PASSAQUAY
% Subject: Calculate the estimated outputs 
%*******************************************************************************%
% [ModelOutput] = ModelUse(Data,Model,type,Output)
%   Data is an input vector
%
%   Model is a fuzzy model with the following structure:
%    NbInput                  ... number of inputs
%    NbOutput                 ... number of outputs
%    NbRule                   ... number of fuzzy rules
%    m                        ... fuzziness exponent
%    ScaleFactor              ... scale factors of inputs and outputs (vector[NbInput+NbOutput])
%    Range                    ... Inputs and outputs ranges (vector[NbInput+NbOutput])
%    MembershipFunctionCenter ... memberships function centers (matrix[NbRule,NbInput+NbOutput])
%    LocalLinearModel         ... local linear model (matrix[NbRule,NbInput+1,NbOutput])
%    NbData                   ... number of datas used to build the fuzzy model
%    Thresold                 ... Thresold used to build the fuzzy model
%    ErrorCriteria            ... Error criteria used to build the fuzzy model
%
%   Type is an optional parameter (default=1)
%    1 - Calculate the estimated output
%    2 - Calculate the local linear model
%    3 - Calculate the membership activation degrees
%   Output is an optional parameter to define the desired output (vector[2] Default=[1..NbOutput])
%
%   ModelOutput represents either the estimated output
%                          either the local linear model coefficients (vector[NbInput+1])
%                          either the membership activation degrees (vector[NbRule])

 if nargin<2, error('Incorrect number of inputs.'); end
 if nargin<3, OutputType=1; end
 if nargin<4, DesiredOutput=[1:Model.NbOutput]; end
 
 MembershipDegree=zeros(1,Model.NbRule);
 
 %Membership degree calculation
 x1=MembershipDegree;
 x2=0;
 for Rule=1:Model.NbRule
  MembershipFunctionCenter=Model.MembershipFunctionCenter(Rule,1:Model.NbInput);
  SquareDistance=sum(((Data(1:Model.NbInput)-MembershipFunctionCenter).*Model.ScaleFactor(1:Model.NbInput)).^2,2);
  x1(Rule)=SquareDistance^(1/(Model.m-1));
  if not(SquareDistance)
   %No division by zero
   SquareDistance=1;
  end   
  x2=x2+1/(SquareDistance^(1/(Model.m-1)));
 end
 if all(x1)
  MembershipDegree=ones(1,Model.NbRule)./(x1.*repmat(x2,1,Model.NbRule));
 else %NormalisedData is equal to a membership function center
  MembershipDegree=not(x1);
  MembershipDegree=MembershipDegree/sum(MembershipDegree);
 end
 
 %Output calculation
 if OutputType==1
  ModelOutput=zeros(1,Model.NbOutput);
  for Output=1:Model.NbOutput
   ModelOutput(Output)=sum((MembershipDegree*Model.LocalLinearModel(:,:,Output)).*[Data(1:Model.NbInput) 1],2);
  end
  ModelOutput=ModelOutput(DesiredOutput);
 elseif OutputType==2 %Local linear coefficients
  ModelOutput=zeros(Model.NbInput+1,Model.NbOutput);
  for Output=1:Model.NbOutput
   ModelOutput(1:Model.NbInput+1,Output)=...
    (MembershipDegree*Model.LocalLinearModel(:,:,Output))';
  end
  ModelOutput=ModelOutput(:,DesiredOutput);
 else %Membership activation degrees
  ModelOutput=MembershipDegree;
 end
%*******************************************************************************%
 