%% extend_nary1.m 

%% This function uses Zadeh's Extension Principle (Section 7.2 in the 
%% book Uncertain Rule-Based Fuzzy Logic Systems: Introduction and 
%% New Directions, by Jerry M. Mendel, and published by Prentice-Hall, 
%% 2000.) to extend an "n"-ary operation "op_n" to "n" type-1 fuzzy sets. 

%% Written by Nilesh N. Karnik - July 22,1998
%% For use with MATLAB 5.1 or higher.

%% NOTE : This program is fast, but it uses a HUGE amount of memory 
%% (matrices having dimensions "m^n" are used - see below for the 
%% meaning of "m" and "n"); and hence, it is practical to use this 
%% program only for very small values of "m" and "n". If "m" and "n"
%% are not very small, use "extend_nary2.m".

%% Outputs : "out" and "mem" (column vectors) are, respectively, 
%% the domain and the memberships of the result of the extended 
%% "op_n" operation. 
 
%% Inputs : "X" is an "n x m" matrix, containing the domain elements 
%% of the "n" type-1 sets (the domain of each set is assumed to 
%% contain "m" elements). "Y" has the same size as "X" and contains
%% the memberships of the points in "X". "op_n" is a string (entered 
%% in inverted commas, as " 'op_n' ") containing the name of the 
%% function which defines the  n-ary operation to be extended (the 
%% function should be stored in the file "op_n.m"). If "tnorm" < 0 
%% (scalar), minimum t-norm is used, otherwise product t-norm is used. 
%% "step" (scalar) is an optional parameter. If it is not provided, the 
%% "n" type-1 sets are assumed to have discrete domains and the output 
%% is presented just by sorting the result of the extended "op_n" 
%% operation. If "step" is provided, it is assumed that the "n" type-1 
%% sets actually have continuous domains and are discretized for 
%% computing purposes. The resulting type-1 set, in this case, has 
%% equispaced domain points : "[minx : step : maxx]", where "minx" and 
%% "maxx" are, respectively, the minimum and the maximum of the results 
%% of the "op_n" operation between domain elements of the participating 
%% type-1 sets. 
 
%% Note 1 : The t-conorm used is maximum.
%% Note 2 : If "op_n" is a built-in function, you may have to use the 
%% MATLAB function "builtin" rather than "feval".
%% Note 3 : The function "op_n" should be written so that it can work 
%% with matrices, and perform the n-ary operation on each column of the 
%% matrix, similar to the MATLAB functions "min(X)" or "prod(X)", where 
%% "X" is a matrix. As an example, see the function "wt_avg_op.m".
 
%% Uses function "trimvec.m" .


function[out,mem] = extend_nary1(X,Y,op_n,tnorm,step)

[n,m] = size(X) ;

lm = m^n ; 
comb_out = zeros(n,lm) ;
comb_mem = zeros(n,lm) ;

     % Creating all different "n"-tuples.
vec = [1 : m]' ;

for i3 = 1 : n,
    o1 = ones(1,m^(i3-1)) ;
    vec1 = vec*o1 ;
    vec2 = vec1(1,:) ;
    for i4 = 2 : m,
       vec2 = [vec2 vec1(i4,:)] ;
    end %% for i4
    vec3 = vec2 ; 
    for i5 = 1 : n-i3,
        vtemp = vec3 ;
        for i6 = 1 : m-1,
            vec3 = [vec3 vtemp] ;
        end   %% for i6
    end %% for i5
 
   comb_out(i3,:) = X(i3,vec3) ;
   comb_mem(i3,:) = Y(i3,vec3) ;

end   %% for i3

xout = feval(op_n,comb_out) ; 

if tnorm < 0,
   memout = min(comb_mem) ;
else 
   memout = prod(comb_mem) ;
end   %%% if tnorm 


if nargin == 4,

    [out,mem] = trimvec(xout,memout) ;

else 
    
    minx = min(xout) ;
    maxx = max(xout) ;    
   
    eps = step/2 ;
    i2 = 1 ;
    for k = minx : step : maxx,
        out(i2) = k ;
        in1 = find(abs(xout-k) <= eps) ;

        if ~isempty(in1),
            mem(i2) = max(memout(in1)) ;
        else 
            mem(i2) = mem(i2-1) ;
        end   %%% if 
        
        i2 = i2 + 1;
    end   %% for k
    if k ~= maxx,
        out(i2) = maxx ;
        in1 = find(abs(xout-maxx) <= eps) ;

        if ~isempty(in1),
            mem(i2) = max(memout(in1)) ;
        else 
            mem(i2) = mem(i2-1) ;
        end   %%% if ~isempty
    end   % if k      


end % if nargin

return ; 
