function mamdani1()
% ======================================================================= %
% Fuzzy-Methoden Matlab-Uebungen
% ----------------------------------------------------------------------- %
% Aufgabenstellung:
%   siehe Uebungsblatt Aufgabe 5
% ======================================================================= %

% schliessen aller offenen 'figures'
close all

% ======================================================================= %
% Festlegung der Funktionen fuer Aggregation, Implikation, Akkumulatin und
% Defuzzifizierung
%
% Die Funktionen sind als 'subfunctions' im unteren Teil dieser Datei
% definiert
% ----------------------------------------------------------------------- %

% t-Normen:     - @t_min -> Minimum
%               - @t_alg -> algebraisches Produkt
% s-Normen:     - @s_max -> Maximum
%               - @s_alg -> algebraische Summe

% Aggregation
aggregation = @t_alg;

% Implikation:
implication = @t_alg;

% Akkumulation:
accumulation = @s_alg;

% Defuzzifizierung:
%   - @mom -> Mean-of-Maximum Methode
%   - @cog -> Schwerpunktsmethode
defuzz = @cog;

% ======================================================================= %
% Datenpunkte
% ----------------------------------------------------------------------- %

% x- und y-Koordinaten werden zum erzeugen des Kennfelds verwendet, d.h. an
% jedem Punkt [x(i), y(j)] fuer i,j = 1, ..., N wird der defuzzifizierte
% Ausgang z berechnet. N beeinflusst also die Aufloesung des Kennfelds.
% Beachten Sie, dass N^2 Punkte berechnet werden muessen!
N = 41;
x = linspace(-2, 2, N)';
y = linspace(-2, 2, N)';

% die z-Werte werden zum numerischen Bestimmen der Implikation verwendet
% und habe damit Einfluss auf die Genauigkeit von Akkumulation und
% Defuzzifizierung.
z = linspace(-4, 4, 101)';

% ======================================================================= %
% Plot der Zugehoerigkeitsfunktionen
% ----------------------------------------------------------------------- %
fig_count = 1; % Zaehlervariable fuer 'figure windows'
h = figure(fig_count);
set(h, 'Name', 'Fuzzy-Mengen');

% Fuzzy-Mengen A_i
% ----------------------------------------------------------------------- %
subplot(3,1,1, 'replace');
plot(x, mu_A1(x), x, mu_A2(x), x, mu_A3(x));
legend('A_1', 'A_2', 'A_3', 'Location', 'NorthEastOutside')
xlabel('x'), ylabel('\mu')
title('Fuzzy-Mengen A_i fuer Eingang x')
% ----------------------------------------------------------------------- %

% Fuzzy-Mengen B_i
% ----------------------------------------------------------------------- %
subplot(3,1,2, 'replace');
plot(y, mu_B1(y), y, mu_B2(y), y, mu_B3(y));
legend('B_1', 'B_2', 'B_3', 'Location', 'NorthEastOutside')
xlabel('y'), ylabel('\mu')
title('Fuzzy-Mengen B_i fuer Eingang y')
% ----------------------------------------------------------------------- %

% Fuzzy-Mengen C_i
% ----------------------------------------------------------------------- %
subplot(3,1,3, 'replace');
plot(z, mu_C1(z), z, mu_C2(z), z, mu_C3(z));
legend('C_1', 'C_2', 'C_3', 'Location', 'NorthEastOutside')
xlabel('z'), ylabel('\mu')
title('Fuzzy-Mengen C_i fuer Ausgang z')
% ----------------------------------------------------------------------- %

% ======================================================================= %
% Arrays der 'function_handles' zu den Zugehoerigkeitsfunktionen fuer
% Eingaenge und Ausgang
% ----------------------------------------------------------------------- %

x_fh = {@mu_A1, @mu_A2, @mu_A3};
y_fh = {@mu_B1, @mu_B2, @mu_B3};
z_fh = {@mu_C1, @mu_C2, @mu_C3};

% ======================================================================= %
% reduzierte Regelmatrix
% ----------------------------------------------------------------------- %
R = [3, 2, 1;
     3, 1, 2;
     1, 3, 2];
% ----------------------------------------------------------------------- %


%% Berechnung des Kennfelds
% ======================================================================= %

% Initialisierung des Arrays der defuzzifizierten Ausgangswerte
z_out = zeros(length(x), length(y));

% Schleife ueber alle Kombinationen der Datenpunkte (xy-Gitter)
for ix = 1:length(x)
    for iy = 1:length(y)
        
        % Initialisierung der akkumilierten Ausgangszugehoerigkeitswerte
        % (muss in jedem Schritt zu Null reinitialisiert werden, da sonst
        % falsche Ergebnisse im Akkumulationsschritt entstehen)
        mu_Cout = zeros(size(z));
        
        % Schleife ueber Regelkombinationen (Regelmatrix)
        for i = 1:length(x_fh)
            for j = 1:length(y_fh)
                % Zugehoerigkeitswerte der aktuellen x- und y-Werte
                mu_x = x_fh{i}(x(ix));
                mu_y = y_fh{j}(y(iy));
                
                % Aggregation
                nu = aggregation(mu_x, mu_y);
                
                % Implikation
                mu_Cout_ij = implication(nu, z_fh{R(i,j)}(z));
                
                % Akkumulation
                mu_Cout = accumulation(mu_Cout, mu_Cout_ij);
                
            end
        end
        
        % Defuzzifizierung
        z_out(ix,iy) = defuzz(z, mu_Cout);
        
    end
end

% ======================================================================= %
% Plot der Aggregation
% ----------------------------------------------------------------------- %

[X, Y] = meshgrid(x, y);    % Erzeugen der Gitterpunkte
fig_count = fig_count + 1;
h = figure(fig_count);
set(h, 'Name', 'Aggregation, Wahrheitswerte')
for i = 1:length(x_fh)
    for j = 1:length(y_fh)
        mu_x = x_fh{i}(Y);
        mu_y = y_fh{j}(X);

        % Aggregation
        N = aggregation(mu_x, mu_y);
        
        % Plot nu_(i,j)
        subplot(length(x_fh), length(y_fh), ...
            length(y_fh)*(i-1) + j, 'replace');
        meshz(X,Y,N);
        xlabel('x'), ylabel('y'), zlabel('\nu');
        title(['\nu_{' num2str(i) ',' num2str(j) '} = A_' ...
            num2str(i) ' und B_' num2str(j) ])
    end
end

% ======================================================================= %
% Plot der Implikation und Defuzzifikation an einem Punkt (x_i, y_j)
% ----------------------------------------------------------------------- %

fig_count = fig_count + 1;
h = figure(fig_count);
set(h, 'Name', 'Implikation, Akkumulation und Defuzzifikation (Beispiel)');
% Initialisierung der akkumilierten Ausgangszugehoerigkeitswerte
mu_Cout = zeros(size(z));

% x-,y-Koordinate zur beispielhaften Auswertung
x_i = 1;
y_j = 0.5;


% Schleife ueber Regelkombinationen (Regelmatrix)
for i = 1:length(x_fh)
    for j = 1:length(y_fh)
        % Zugehoerigkeitswerte der x- und y-Werte
        mu_x = x_fh{i}(x_i);
        mu_y = y_fh{j}(y_j);
        % Aggregation
        nu = aggregation(mu_x, mu_y);
        % Implikation
        mu_Cout_ij = implication(nu, z_fh{R(i,j)}(z));
        subplot(length(x_fh)+1, length(y_fh), ...
            length(y_fh)*(i-1) + j, 'replace');
        plot(z, mu_Cout_ij)
        xlabel('z'), ylabel('\mu');
        title(['Implikation \mu_{C_{' num2str(i) ',' num2str(j) ...
            '}}(x=' num2str(x_i) ', y=' num2str(y_j) ')']);
        % Akkumulation
        mu_Cout = accumulation(mu_Cout, mu_Cout_ij);
    end
end
% Defuzzifizierung
z_outij = defuzz(z, mu_Cout);
subplot(length(x_fh)+1, length(y_fh), length(x_fh)*length(y_fh) + 1 : ...
    length(y_fh)*(length(x_fh) + 1), 'replace');
plot(z, mu_Cout,[z_outij z_outij], [0,1])
xlabel('z'), ylabel('\mu');
title(['Implikation und Defuzzifikation fuer Ausgang z mit ' ...
    'Eingangsgroessen x = ' num2str(x_i) ' und y = ' num2str(y_j)]);
legend('\mu_{C*}', 'z*')


% ======================================================================= %
% Plot des Kennfelds
% ----------------------------------------------------------------------- %

[X, Y] = meshgrid(x, y);    % Erzeugen der Gitterpunkte
fig_count = fig_count + 1;
h = figure(fig_count);
set(h, 'Name', 'Kennfeld des Fuzzy-Systems');
meshz(X, Y, z_out);
xlabel('x'), ylabel('y'), zlabel('z');
title('Kennfeld des Fuzzy-Systems; Eingaenge x und y, Ausgang z');

end % Ende der Hauptfunktion
% ======================================================================= %
%% Subfunctions
% ----------------------------------------------------------------------- %
% Hier muessen die Funktionen fuer die Auswertung des Fuzzy-Systems 
% implementiert werden.
% ======================================================================= %
%% t- und s-Normen
% ======================================================================= %

% ----------------------------------------------------------------------- %
% Algebraisches Produkt
function mu_alg = t_alg(mu1, mu2)
    %#TODO
    mu_alg = [];
end
% Algebraische Summe
function mu_alg = s_alg(mu1, mu2)
    %#TODO
    mu_alg = [];
end
% ----------------------------------------------------------------------- %
% Minimum
function mu_min = t_min(mu1, mu2)
    %#TODO
    mu_min = [];
end
% Maximum
function mu_max = s_max(mu1, mu2)
    %#TODO
    mu_max = [];
end

%% Defuzzifizierung
% Implementierung der Defuzzifizierungsmethoden
% ======================================================================= %

% ----------------------------------------------------------------------- %
% Mean-of-Maxima Methode
function z_out = mom(z, mu_Cout)
    %#TODO
    z_out = [];
end
% ----------------------------------------------------------------------- %
% Schwerpunktsmethode (Center-of-Gravity)
function z_out = cog(z, mu_Cout)
    %#TODO
    z_out = [];
end

%% Fuzzy-Mengen
% Definition der Zugehoerigkeitsfunktionen
% ======================================================================= %
% Eingang x
% ----------------------------------------------------------------------- %
function mu = mu_A1(x)
    %#TODO
    mu = [];
end
% ----------------------------------------------------------------------- %
function mu = mu_A2(x)
    %#TODO
    mu = [];
end
% ----------------------------------------------------------------------- %
function mu = mu_A3(x)
    %#TODO
    mu = [];
end

% ======================================================================= %
% Eingang y
% ----------------------------------------------------------------------- %
function mu = mu_B1(y)
    %#TODO
    mu = [];
end
% ----------------------------------------------------------------------- %
function mu = mu_B2(y)
    %#TODO
    mu = [];
end
% ----------------------------------------------------------------------- %
function mu = mu_B3(y)
    %#TODO
    mu = [];
end

% ======================================================================= %
% Ausgang z
% ----------------------------------------------------------------------- %
function mu = mu_C1(z)
    %#TODO
    mu = [];
end
% ----------------------------------------------------------------------- %
function mu = mu_C2(z)
    %#TODO
    mu = [];
end
% ----------------------------------------------------------------------- %
function mu = mu_C3(z)
    %#TODO
    mu = [];
end
% ======================================================================= %