% experiment 3 
% Martin Radvansky 
% Diplomova prace 2022
% Zakladni PSO algoritmus optimalizaci vah vystupnich funkci FIS Sugeno
% Optimalizujeme pet vah pro vystupni pravidla dostavame vektor dimenze 5
% Spousti se v ramci RunOptimalizace.bat 
function [best_Out,best_RMSE,cas_celk] = DoPSO_Weight()
	
    % Zakladni vlastnosti generovanych hodnot pro PSO
    VarSize = [1 5];    % Velikost matice parametru
    VarMin = 0.0001;    % Nejmensi hodnota prohledavaciho rozsahu
    VarMax = 1;         % Nejvetsi hodnota prohledavaciho rozsahu
    CostFunction=@(x,v) FitnessFunction(x,v); % Minimalizujeme RMSE pro zmenu vahy pravidel

    % Nastaveni vlastnosti PSO
    populace=100;          % Velikost populace castic (hejna)
    Iterace=1000;      % Maximalni pocet iteraci
	
    % Koeficienty PSO s použitím varianty omezení prohledávaného prostoru
     phi1=2.05;
     phi2=2.05;
     phi=phi1+phi2;
     chi=2/(phi-2+sqrt(phi^2-4*phi));
     w=chi;          % Vaha setrvacnosti hejna
     wdamp=1;        % Poměr zatlumeni setrvacnosti
     c1=chi*phi1;    % Koeficient c1 pro castici hejna
     c2=chi*phi2;    % Globalni koeficient c2 pro cele hejno
	 
    % Omezovani rychlosti pohybu castic
    VelMax=0.1*(VarMax-VarMin);
    VelMin=-VelMax;

    % Uvodni inicializace
	init_particle.Best.Cost=[];
    init_particle.Cost=[];
	init_particle.Velocity=[];
	init_particle.Position=[];
    init_particle.Best.Position=[];

	%vytvoreni castic populace
    particle=repmat(init_particle,populace,1);
    GlobalBest.Cost=inf;
    tic;
	%Nastaveni pocatecnich hodnot pro celou populaci
    for i=1:populace

        % Inicializace pozice kazde hodnoty castice v hejnu
        particle(i).Position=unifrnd(VarMin,VarMax,VarSize);

        % Nastaveni pocatecni rychlosti kazde hodnoty castice
        particle(i).Velocity=zeros(VarSize);

        % overeni postupu miminamlizace RMSE       
        try
          particle(i).Cost=CostFunction(particle(i).Position, true);
        catch ME
          msgText = getReport(ME);
          warning(sprintf("** Problem v COST function pro funkce prislusnosti. \n%s",msgText));  
          particle(i) = 10000;  %penalizace pri chybe
        end
        
        % Aktualizace nejlepsi dosazene pozice castice
        particle(i).Best.Position=particle(i).Position;
        particle(i).Best.Cost=particle(i).Cost;

        % Pokud se RMSE zmensilo, tak ulozime globalni pozici castice (hodnoty 15-ti koeficientu)
        if particle(i).Best.Cost<GlobalBest.Cost
            GlobalBest=particle(i).Best;
        end

    end
    toc;
    BestCost=zeros(Iterace,1);
    
    t=tic;
	%Hlavni smycka pres vsechny iterace
    for it=1:Iterace
        t1=tic;
        for i=1:populace

            % aktualizujeme rychlost castice dle vztahu pro PSO
            particle(i).Velocity = w*particle(i).Velocity ...
                +c1*rand(VarSize).*(particle(i).Best.Position-particle(i).Position) ...
                +c2*rand(VarSize).*(GlobalBest.Position-particle(i).Position);

            % Omezeni hodnoty rychlosti na min a max
            particle(i).Velocity = max(particle(i).Velocity,VelMin);
            particle(i).Velocity = min(particle(i).Velocity,VelMax);

            % Aktualizujeme pozici castice pridanim rychlosti
            particle(i).Position = particle(i).Position + particle(i).Velocity;

            % Velocity Mirror Effect
            IsOutside=(particle(i).Position<VarMin | particle(i).Position>VarMax);
            particle(i).Velocity(IsOutside)=-particle(i).Velocity(IsOutside);

            % Musime provest omezeni pozice na Min/Max hodnoty
            particle(i).Position = max(particle(i).Position,VarMin);
            particle(i).Position = min(particle(i).Position,VarMax);

            % Vyhodnoceni pozice castice a zjisteni vysledne RMSE
            try
              particle(i).Cost=CostFunction(particle(i).Position, true);
            catch ME
              msgText = getReport(ME);
              warning(sprintf("** Problem v COST function pro vahy. \n%s",msgText));  
              continue;
            end

            % Aktualizace nejlepsi pozice jedne castice
            if particle(i).Cost<particle(i).Best.Cost
                particle(i).Best.Position=particle(i).Position;
                particle(i).Best.Cost=particle(i).Cost;
                % Pokud se RMSE zmensilo, tak ulozime globalni pozici castice (hodnoty 15-ti koeficientu)
                if particle(i).Best.Cost<GlobalBest.Cost
                    GlobalBest=particle(i).Best;
                end
            end
        end
        toc(t1);
        BestCost(it)=GlobalBest.Cost;
        disp(['Iterace ' num2str(it) ': Nejlepsi RMSE = ' num2str(BestCost(it))]);
        w=w*wdamp;
    end
    cas_celk = toc(t);  %celkovy cas
    best_RMSE = GlobalBest.Cost; %RMSE
    best_Out = GlobalBest; %nejlepsi vysledek
end