echo off;

% klasyfikator Hamminga
% ciekawostka: tej sieci sie nie uczy, tylko oblicza sie jej wagi... A ona, wredna, i tak dziala ;)

% tytulem wstepu: macierz znakow wejsciowych
% sa to cyfry 0 do 7 zakodowane na matrycy 3x5 pikseli - tutaj cala matryca zapisywana jest w pojedynczym wierszu
% dla wiekszej przejrzystosci pooddzielane przecinkami

 znaki(1,:) =  [1 1 1, 1 0 1, 1 0 1, 1 0 1, 1 1 1];
 znaki(2,:) =  [0 1 0, 0 1 0, 0 1 0, 0 1 0, 0 1 0];
 znaki(3,:) =  [1 1 1, 0 0 1, 1 1 1, 1 0 0, 1 1 1];
 znaki(4,:) =  [1 1 1, 0 0 1, 0 1 1, 0 0 1, 1 1 1];
 znaki(5,:) =  [1 0 1, 1 0 1, 1 1 1, 0 0 1, 0 0 1];
 znaki(6,:) =  [1 1 1, 1 0 0, 1 1 1, 0 0 1, 1 1 1];
 znaki(7,:) =  [1 1 1, 1 0 0, 1 1 1, 1 0 1, 1 1 1];
 znaki(8,:) =  [1 1 1, 0 0 1, 0 0 1, 0 0 1, 0 0 1];

 il_znakow = 8;

% normalizacja znakow
znakinorm = normr(znaki);
 
 
% dzialanie: w pierwszym takcie "ladujemy" siec, a potem pozwalamy sie jej samej wysterowac

% struktura sieci:
% wejsc jest 15...
% warstwa wejsciowa to po prostu 8 neuronow, kazdy polaczony tylko z jednym neuronem kolejnej warstwy
% macierz wag wejsciowych 15x8 - waga = pobudzenie... U nas po prostu transponowana, podzielona przez 2 macierz znakow
wagi_pierwsza = (znakinorm');

% warstwa wyjsciowa: 8 neuronow sprzezonych "kazdy z kazdym"
% mamy 8 wzorcow, wiec wagi sprzezen miedzy neuronami = -0,125
sprzezenia = -1 / 8;

% macierz wag neuronow warstwy wyjsciowej... kazdy neuron ma 16 pobudzen, czyli macierz bedzie 16x8
% wejscie odpowiadajace numerowi to autosprzezenie, w dolnej polowie macierzy wejscie o numerze danego neuronu +8 to wejscie z pierwszej warstwy
wagi_druga = ones(8,8) * sprzezenia;

for i=1:8,
    wagi_druga(i,i) = 1;
end

wagi_druga = [wagi_druga; eye(8)];
wagi_druga = normr(wagi_druga);

% przydadza sie nam jeszcze wyjscia
wyjscia_pierwsza = zeros(1,8);
wyjscia_druga = zeros(1,8);

% testujemy kolejne znaki
ilosc_powtorzen = 15; % calkowicie arbitralna, ale zapewnia zbieznosc

for znak = 1:il_znakow,
    wyjscia_pierwsza = znakinorm(znak,:)*wagi_pierwsza;

    wyjscia_druga = satlin( ([wyjscia_druga, wyjscia_pierwsza] *wagi_druga) );
    wyjscia_pierwsza = zeros(1,8);

    for licznik = 1:ilosc_powtorzen,
        wyjscia_druga = satlin(( [wyjscia_druga, wyjscia_pierwsza] *wagi_druga));
        wyjscia_druga = normr(wyjscia_druga);
    end;

    hardlim(wyjscia_druga-0.01)
    wyjscia_druga = zeros(1,8);

end;

% a skoro dziala tak ladnie, to potestujmy jak sprawdza sie z zaszumionymi znakami :D

% najpierw stworzymy zaszumiona tablice znakow
% powiedzmy, ze bedzie w niej eta bledow
eta = 100;
for kolejny_blad = 1:eta,
    pozycja_x = int8(rand*8+1);
    pozycja_y = int8(rand*15+1);
    
    znaki(pozycja_x, pozycja_y) = abs(znaki(pozycja_x, pozycja_y) - rand);
end;

% wyswietlamy tablice "popsutych" znakow
znaki
znakinorm = normr(znaki);

% no i zobaczymy, jak sobie siec radzi z tym zadaniem

for znak = 1:il_znakow,
    wyjscia_pierwsza = znakinorm(znak,:)*wagi_pierwsza;

    wyjscia_druga = satlin( ([wyjscia_druga, wyjscia_pierwsza] *wagi_druga) );
    wyjscia_pierwsza = zeros(1,8);

    for licznik = 1:ilosc_powtorzen,
        wyjscia_druga = satlin(( [wyjscia_druga, wyjscia_pierwsza] *wagi_druga));
        wyjscia_druga = normr(wyjscia_druga);
    end;

    hardlim(wyjscia_druga-0.01)
    wyjscia_druga = zeros(1,8);

end;
% 