%naleznete minimum zadane testovaci ucelove fce  D promennych pomoci
%genetickeho algoritmu s presnosti na 4 des mista

clc
close all
clear all


for pool = 16: -1 : 1
    
    
dependencies = {'genPopulation.m', 'FUNKCE.m', 'defObor.m', 'randInteger.m','Migration.m'};
matlabpool('open','hpcServ',pool, 'FileDependencies', dependencies )
pause(10)

for funkce = 1 : 6
    
for opak = 1 : 30



gallery = [1 6 9 10 12 13];     % numbers of test function De Jong 4, Schwefell, Easom, Salomon, Step, Powel Fletcher
CisFce = gallery(funkce);
TOTALNIMAX = -inf;
A = []; C = []; alp = [];   % set to empty array, variables for generating Flechter and Powel function

tic;
%% %%%%%%%%%%%%%%%%%%%%%%% KONSTANTY GA
D = 30;               %dimenze
NP = 300;             %velikost populace, min 2 aby bylo mozno krizit

KK = 0.80;           %krizici konstanta - composite
MK = 0.01;           %mutacni konstanta - composite
B = 1.5;               %parametr nelinearity mutace - composite
GENERACE = 1000;      %pocet generaci k ukonceni evoluce
K = ceil(GENERACE*0.05);   % amount of loops need to migration
AMMIG = Composite();    % amount of migrants

stop = 0;            %citac nezmenenych minim v generacich
gen = 0;             %citac poctu uskutecnenych generaci - composite + vytvorit globalniho elitaka

psi = 0.0001;        %udava presnost reseni
pocStejRes = 50;     %pocet stejnych minim v generacich po sobe k zastaveni programu 

typ=1;               %promenna pro generovani prvni nahodne populace 1 GA,0 DE

ELITISMUS = Composite();      %archivace nejlepsiho jedince z generace
MINIMUM = Composite();  % keep values of fitness minimum of generation during generation
PRUMER = Composite();   % keep values of fitness average of generation during generation
prubeh = Composite();   % keep fitness values of all specimens during all generation - 3D view

%% %%%%%%%%%%%%%%%%%%%%%% Inicialization of the composite variables
for i = 1 : 1 : numel(MINIMUM)
    MINIMUM{i} = zeros(1,GENERACE);
    PRUMER{i} = zeros(1,GENERACE);
    prubeh{i} = zeros(GENERACE,NP);
end

%% %%%%%%%%%%%%%%%%%%%%%% Vyber hranic def oboru podle cisla fce
switch CisFce
    case 1
        defDolni = -1.28;
        defHorni = 1.28;
    case 2
        defDolni = -5;
        defHorni = 5;
    case 3
        defDolni = -2.048;
        defHorni = 2.048;
    case 4
        defDolni = -2.048;
        defHorni = 2.048;
    case 5
        defDolni = -5.12;
        defHorni = 5.12;
    case 6
        defDolni = -500;
        defHorni = 500;
    case 7
        defDolni = -100;
        defHorni = 100;
    case 8
        defDolni = -5;
        defHorni = 5;
    case 9
        defDolni = -50;
        defHorni = 50;
    case 10
        defDolni = -4;
        defHorni = 4;
    case 11
        defDolni = -30;
        defHorni = 30;
    case 12
        defDolni = -40;
        defHorni = 60;
    case 13
        defDolni = -pi;
        defHorni = pi;
        alp = -pi + 2*pi*rand(1,D);
        A = -100 + 200*rand(D,D);
        C = -100 + 200*rand(D,D);
end        
   

%% %%%%%%%%%%%%%%%%%%%% DEFINICNI OBOR
  defOborXY = zeros(D,2);
  defOborXY(:,1) = defDolni;      %x1 dolni
  defOborXY(:,2) = defHorni;      %x1 horni  

time(1) = toc;
%% %%%%%%%%%%%%%%%%%%%%%%%% GENEROVANI NAHODNE POCATECNI POPULACE
tic;

DPopulation = genPopulation(NP,defOborXY,typ,D,CisFce,A,C,alp);

spmd
    NPl = size(getLocalPart(DPopulation),2);                 % number of specimens in each labs, l - local
    [globIdxS globIdxE] = globalIndices(DPopulation,2);      % global index within the local population (S - Start, E - end)
    globIdxS = globIdxS - 1;                                 % index starts in border possiotion in order to be use with
    globIdxE = globIdxE - 1;                                 % another indexes
    [minim elitIdx] = min(getLocalPart(DPopulation(1,:)));   %vyber nejlepsiho jedince generace pro elitismus
    ELITISMUS = getLocalPart(DPopulation(:,elitIdx + globIdxS));
    pomPopulation = zeros(D+2,NPl);                          % store for selection
    AMMIG = ceil(NP*0.2/numlabs);                           % 20% of each subpopulation will migrate

%% %%%%%%%%%%%%%%%%%%%%% MAIN PROGRAM - zastavi se pokud projde GENERACE generaci, nebo pokud

    Population = getLocalPart(DPopulation);
    
    while (gen < GENERACE) %(stop < pocStejRes)        
       
        gen = gen + 1;              % generation counter
        
        [minim elitIdx] = min(Population(1,:));   %vyber nejlepsiho jedince generace pro elitismus
        if (Population(1,elitIdx) < ELITISMUS(1,1))
            ELITISMUS = Population(:,elitIdx);
        end        

        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SELEKCE - pozicni selekce
        
        [~, idx] = sort(Population(1,:));  % ziskani indexu serazenych cisel        
        
        for i = 1:NPl
            pomPopulation(1:D+2,i) = Population(1:D+2,idx(i));        %serazeni populace podle ziskanych indexu
            pomPopulation(D+2,i) = NPl+1-i;                           %kvalita jedince pro pozicni selekci NP nejkvalitnejsi
        end      

        sumMoznosti = NPl*(NPl+1)/2;            %poc moznosti pro vazenou ruletu
       
        for i = 1:NPl    %pozicni selekce
            
            pom = rand;
            inc = NPl;          %promenna pro zvysovani psti u rulety
            a = 1;              %promenna pro indexaci vybraneho genu
            
            while (pom > (inc/sumMoznosti))      %smycka zjistuje pst(interval) kde se nachazi nahodne cislo
                inc = inc + (NPl-a);             % soucet psti, klesajici tendence
                a = a+1;
            end
                Population(1:D+2,i) = pomPopulation(1:D+2,a);  
        end
        
        pomPopulation = Population;
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% KRIZENI - dle tri vzorcu
        
        sor = [];         % mazani promennych pro indexaci razeni
        idx = [];
        
        for i = 2 : 2 : NPl            
            
            pom1 = randInteger(NPl);                      % nahodny vyber jedincu pro krizeni
            pom2 = randInteger(NPl);
            
            while (pom1 == pom2)                          % aby se rodice sobe nerovnali
                pom2 = randInteger(NPl);
            end
            
            if (rand < KK)     %krizi jen pokud je nahodne cislo mensi nez krizici konstanta
                % tvorba potomku pomoci tri ruznych vzorcu
                
                Potomci(2:D+1,1) = (Population(2:D+1,pom1)+Population(2:D+1,pom2))./2;
                Potomci(2:D+1,2) = (3.*Population(2:D+1,pom1)-Population(2:D+1,pom2))./2;
                Potomci(2:D+1,3) = (-Population(2:D+1,pom1)+3.*Population(2:D+1,pom2))./2;
              
                Potomci(1,1) = inf;   %nastaveni na nekonecno abychom poznali zda uz
                Potomci(1,2) = inf;   %byl potomek ohodnocen ve fci kontroly def oboru
                Potomci(1,3) = inf;
  
                Potomci = defObor(defOborXY,Potomci,3,D,CisFce,A,C,alp);
                                            
                %ohodnoceni potomku
                if (Potomci(1,1) == inf)
                    Potomci(1,1) = FUNKCE(Potomci(2:D+1,1),D,CisFce,A,C,alp);
                end
                if (Potomci(1,2) == inf)
                    Potomci(1,2) = FUNKCE(Potomci(2:D+1,2),D,CisFce,A,C,alp);
                end
                if (Potomci(1,3) == inf)
                    Potomci(1,3) = FUNKCE(Potomci(2:D+1,3),D,CisFce,A,C,alp);
                end
                %vyber a prirazeni dvou nejlepsich jedincu ze tri
                [sor idx] = sort(Potomci(1,:));               
                pomPopulation(1:D+1,i) = Potomci(:,idx(1));
                pomPopulation(1:D+1,i-1) = Potomci(:,idx(2));
            else
                pomPopulation(:,i) = Population(:,pom1);  %nah cislo je vetsi nez krizici konstanta
                pomPopulation(:,i-1) = Population(:,pom2);%oba rodice se kopiruji                
            end
        end        
          
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  MUTACE - dynamicka Michalewicz
     
        for i = 1:1:NPl            
            for a = 1:1:D
                if (rand<MK)          %pst mutace dana MK, pro prvni parametr
                    if (rand<0.5)     %definuje zda se epsilon bude pricitat nebo odcitat
                        eps = pomPopulation(a+1,i)-defOborXY(a,1);
                        delta = eps*(1-rand^((1-(gen/GENERACE))^B));
                        pomPopulation(a+1,i) = pomPopulation(a+1,i)-delta;
                        pomPopulation(1,i) = inf;
                    else
                        eps = defOborXY(a,2)-pomPopulation(a+1,i);
                        delta = eps*(1-rand^((1-(gen/GENERACE))^B));
                        pomPopulation(a+1,i) = pomPopulation(a+1,i)+delta;
                        pomPopulation(1,i) = inf;
                    end
                end
            end
            if(pomPopulation(1,i) == inf)
                pomPopulation(:,i) = defObor(defOborXY,pomPopulation(:,i),1,D,A,C,alp);
                pomPopulation(1,i) = FUNKCE(pomPopulation(2:D+1,i),D,CisFce,A,C,alp);
            end
        end
        
        Population = pomPopulation;
        
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ELITISMUS
        [maxim badIdx] = max(Population(1,:));  %vymena nejhorsiho jedince za elitniho
        if (maxim > ELITISMUS(1,1))
            Population(:,badIdx) = ELITISMUS;       %vybraneho pred selekci,krizenim a mutaci
        end
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DATA PRO GRAFY
        MINIMUM(gen) = min(Population(1,:));  %historie minim po generacich
        PRUMER(gen) = (sum(Population(1,:)))/NPl;  %historie prumernych hodnot v prubehu generaci
        
        %pocita pocet nezmenenych minim
        if ( gen > 1 && (abs(MINIMUM(gen) - MINIMUM(gen-1))) < psi)
            stop = stop + 1;
        else
            stop=0;            
        end
%         prubeh(gen,:) = Population(1,:); %3D prubeh evoluce vsech jedincu        

        %%%%%%%%%%%%%%%%%%%%%%%%%%%% MIGRATION
        if (mod(gen,K) == 0)
             Population = Migration(Population,AMMIG, NPl);
        end
        
    end
    
    ELITISMUS(1,1);
    for i = 1:NPl
        DPopulation(:,i + globIdxS) = Population(:,i);
    end
end
time(2) = toc;
tic;

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Data display and save

minGraph = zeros(numel(MINIMUM),GENERACE);
avGraph = zeros(numel(MINIMUM),GENERACE);
if(numel(MINIMUM) > 1)
    for i = 1 : numel(MINIMUM)
         minGraph(i,:) = MINIMUM{i};    % naskladani do matice
         avGraph(i,:) = PRUMER{i};
    end
    elitGraph = min(minGraph);          % vekt
    prumGraph = min(avGraph);
else
    elitGraph = MINIMUM{1};
    prumGraph = PRUMER{1};
end

time(3) = toc;
ElitMat(opak,funkce,:) = elitGraph;
TimeMat(opak,funkce,:) = time;
MinimMat(opak,funkce) = elitGraph(end);


% figure
% plot(1:GENERACE,elitGraph);
% hold on
% plot(1:GENERACE,prumGraph,'r');

% figure
% mesh(1:1:NP,1:1:gen,prubeh);
% xlabel('Jedinec [-]');
% ylabel('Generace [-]');
% zlabel('Ohodnoceni ucelovou funkci [-]');



txt = ['Pool : ' num2str(pool),', repetition : ' num2str(opak) ', function : ' num2str(funkce)]
end
end
save(['Results\Pool_' num2str(pool) '.mat'], 'ElitMat', 'TimeMat', 'MinimMat')
matlabpool close
pause(5)
clear all
end