Második labor

Contents

Tesztfeladat a szkémaszámoláshoz

Súlyok 1, 10, 1, 10, ...

Értékek: 10, 1, 10, 1, ...

targyakszama=10;
sulyok=ones(1, targyakszama);
sulyok(2:2:end)=10;
ertekek=ones(1, targyakszama);
ertekek(1:2:end)=10;

generacio=30;
populaciomeret=10;
keresztezesvaloszinusege=0.9;
mutaciovaloszinusege=0.03;

kapacitas=targyakszama*2.5; % ekkor az optimális pakolás 5.2*n lesz, itt 52
tic
[populacio,maximumfitnesz,atlagfitnesz, szkemaszam]=hatizsakGenetikusSzkema...
    (sulyok,ertekek,kapacitas,keresztezesvaloszinusege, mutaciovaloszinusege, generacio, populaciomeret);
toc

subplot(2,1,1)
plot(1:generacio, szkemaszam)
ylabel('Illeszkedő szkémák száma')
xlabel('Generáció')
subplot(2,1,2)
plot(1:generacio, maximumfitnesz, 1:generacio, atlagfitnesz, 1:generacio, 52*ones(1,generacio))
ylabel('Fitnesz')
xlabel('Generáció')
Elapsed time is 6.111881 seconds.

Tesztelés és validáció

A tesztelés célja a paraméterek optimalizálása (ide értve a fitneszfüggvény is), a validáció célja annak eldöntése, hogy mennyire jó általános feladatra az általunk készített algoritmus. Azaz a tesztfeladaton egy előre ismert optimumú függvényt tesztelünk, minnél többet az optimális paraméterek/fitneszfüggvény meghatározása céljából. A validáció folyamán egy (vagy több) előre nem ismert feladattal próbáljuk eldönteni, hogy jó-e (igazából jól általánosítható-e) az algoritmusunk a majdani, már nem ismert optimumú feladatra.

Órai feladat

Gondoljuk meg, hogyan reprezentálnánk az alábbi kérdés pontenciális megoldásait. Milyen tesztet és validációt javasolnánk?

Szeretnénk 1-hibajavító kódot készítése 8 hosszú bitsorozaton. Mekkora lehet maximum a szavak száma? Akkor lesz a kódunk 1 hibajavító, ha bármely 2 kódszó Hamming-távolsága legalább 3. A Hamming-korlátból tudjuk, hogy a szavak maximális száma 28 ebben a konkrét esetben.

A szkémaszámoló kódja

function [populacio,maximumfitnesz,atlagfitnesz, szkemaszam]=hatizsakGenetikusSzkema(sulyvektor,...
  ertekvektor,sulykorlat,keresztezesval,mutacioval,generaciokszama,populaciomeret)

% Hátizsák-probléma: adott n db tárgy, s1,s2,..sn súlyúak, v1,v2,...,vn
% értékűek, és egy fix teherbírású hátizsák. A cél, hogy kiválasszunk néhány 
% tárgyat, hogy azok összsúlya a sulykorlatott ne haladja meg, és az összértékük maximális 
% legyen.

if length(sulyvektor)~=length(ertekvektor) || mutacioval<0 || mutacioval>1 ...
        || keresztezesval<0 || keresztezesval>1 || generaciokszama <0 ||...
        populaciomeret<0 || mod(populaciomeret,2)==1
     error('Rossz bemenő paraméterek'); 
end %A bemeneti paraméterek ellenőrzése

%A kezdeti populáció létrehozása
targyakszama=length(sulyvektor); 
populacio=ceil(rand(populaciomeret,targyakszama)-0.5);
%a populációt egy mátrixként kezeli a program a továbbiakban
atlagfitnesz=zeros(generaciokszama,1);
maximumfitnesz=zeros(generaciokszama,1);
szkemaszam=zeros(generaciokszama,1);
szkemak=szkemaepito(targyakszama);

for i=1:generaciokszama %A leállási feltétel: fix generáció fut le
    
    populaciofitnesz=fitneszfv(populacio,sulyvektor,ertekvektor,sulykorlat);
    
    atlagfitnesz(i)=sum(populaciofitnesz)/populaciomeret;
    maximumfitnesz(i)=max(populaciofitnesz);
    szkemaszam(i)=szkema(populacio,szkemak);
    
    populacio=kivalaszt_rulettkerek(populacio,populaciofitnesz);
    populacio=keresztez_egypontos(populacio,keresztezesval);
    populacio=mutacio_egybit(populacio,mutacioval);
    
    
end

%-----------------------------------------------------------------------

function populaciofitnesz=fitneszfv(populacio,sulyvektor,ertekvektor,sulykorlat)

populaciofitnesz=zeros(size(populacio,1),1); %!!!preallokálás

for i=1:size(populacio,1)
    if dot(populacio(i,:),sulyvektor)>sulykorlat
        populaciofitnesz(i)=dot(populacio(i,:),ertekvektor)...
            /(1+dot(populacio(i,:),sulyvektor)-sulykorlat);
    else
        populaciofitnesz(i)=dot(populacio(i,:),ertekvektor);
    end
end

%-------------------------------------------------------------------------

function szulok=kivalaszt_rulettkerek(populacio,populaciofitnesz)
%rullettkerék elven működik

eloszlas=populaciofitnesz/sum(populaciofitnesz);
osszegek=zeros(length(populaciofitnesz),1);
osszegek(1)=eloszlas(1);

for i=2:size(populaciofitnesz)
    osszegek(i)=osszegek(i-1)+eloszlas(i);
end
szulok=zeros(size(populacio,1),size(populacio,2));
for j=1:size(populacio,1)    
    p=rand;
    for i=1:size(osszegek)
        if osszegek(i)>p
            break;
        end
    end
    szulok(j,:)=populacio(i,:);
end
    
%-------------------------------------------------------------------------

function utod=keresztez_egypontos(populacio,keresztezesval)

utod=populacio;
n=size(populacio,2);%a kromoszómák hossza

for i=1:2:size(populacio,1)

    if rand<keresztezesval
    
        vagopont=ceil((n-1)*rand);
        utod(i,:)=[populacio(i,1:vagopont), populacio(i+1,vagopont+1:n)];
        utod(i+1,:)=[populacio(i+1,1:vagopont), populacio(i,vagopont+1:n)];
    else
        utod(i,:)=populacio(i,:); 
        utod(i+1,:)=populacio(i+1,:);
    end
end

%-------------------------------------------------------------------------

function utod=mutacio_egybit(populacio,mutacioval)
%random helyen lévő 1 bitet változtat
%végigmegy az összes egyeden
utod=populacio;

for i=1:size(populacio,1)   
    for j=1:size(populacio,2)
        if rand<mutacioval
            if populacio(i,j)==0
                utod(i,j)=1; 
            else
                utod(i,j)=0;
            end
        end
    end
end

%-----------------------------------------------------------
function szam=szkema(populacio,szkemak)

populaciomeret=size(populacio,1);
targyakszama=size(populacio,2);
osszesszkema=zeros(1,3^targyakszama);

for i=1:populaciomeret
    for j=1:3^targyakszama
        flag=1;
        for k=1:targyakszama
            if ~(populacio(i,k)==szkemak(j,k) || szkemak(j,k)==2)
                flag=0; break;
            end
        end
        if flag==1; osszesszkema(j)=1; end
    end
end

szam=sum(osszesszkema);


%---------------------------------------------------

function sz=szkemaepito(n)
sz=uint8(zeros(3^n,n));

for i=2:3^n
    m=0;
    for j=1:n
        if     sz(i-1,j)==0,         sz(i,j)=1+m; sz(i,j+1:end)=sz(i-1,j+1:end); break; 
        elseif sz(i-1,j)==1 && m==0, sz(i,j)=2;   sz(i,j+1:end)=sz(i-1,j+1:end); break;
        elseif sz(i-1,j)==1 && m==1, sz(i,j)=0; m=1;
        elseif sz(i-1,j)==2 && m==0; sz(i,j)=0; m=1;
        elseif sz(i-1,j)==2 && m==1; sz(i,j)=1; m=1;
        end
    end
end