%--------------------------------------------------------------------------
% NMSC code
% Developed in MATLAB R2019b
% The code is based on the following papers.
% This code generated by Thanh Cuong-Le and Hoang-Le Minh.
% A novel version of Cuckoo search algorithm for solving optimization problems 
% Expert Systems With Applications,
% https://doi.org/10.1016/j.eswa.2021.115669.
%--------------------------------------------------------------------------
 
%%%%%%%%%%%%%%%% Atom Search Optimization (ASO) Algorithm %%%%%%%%%%%%%%%%

clc
clear all
close all
format shortG
%Select functions
fun='F4';
[lb,ub,dim,fobj]=Get_Functions_details(fun);
NP = 30;       % the number of population
cycle = 2000;  % the number of iteration
pa = 0.25;     % the parameter of abandon
nvar = dim;
lb = lb;                 % lower boundary
ub=  ub;                 % upper boundary  
lb = lb.*ones(1,nvar);   
ub = ub.*ones(1,nvar);    
%% ---------------NMS-CS----------------------------- 
empt.pos =[];          
empt.cost = [];        
empt.velocity = [];     
NMS_CS_particle_nest = repmat(empt,NP,1); 
for i = 1:NP
  
    NMS_CS_particle_nest(i).pos = lb + rand(1,nvar).*(ub-lb);
  
    NMS_CS_particle_nest(i).cost =fobj(NMS_CS_particle_nest(i).pos);
end
[value, index] = min([NMS_CS_particle_nest.cost]);

 Gbest_cooku = NMS_CS_particle_nest(index);
%%  MAIN LOOP
 NMS_CS_best_cooku = zeros(cycle,1);
 NMS_CS_best_solution = zeros(cycle,nvar);
 for t = 1:cycle
     func = randi(3);
     temp1 = NMS_CS_particle_nest;
     [Des_F Index_F]=sort([temp1.cost]); 
     Kbest=round(0.1*NP-(0.1*NP-3)*(t/cycle)^0.5);
     sum_Kbest = zeros(1,nvar);
   for k = 1:Kbest
       j = Index_F(k);
       sum_Kbest = sum_Kbest + temp1(j).pos;
   end    
   first_best = sum_Kbest/Kbest; 
     c = [-1,1];
     f = ft_fun(t,cycle,func); 
     for j = 1:NP
     s = NMS_CS_particle_nest(j).pos;
     step = NMS_CS_levy_fun(1,nvar,f); 
     step_length_CS = CS_levy_fun(1,nvar,1.5);
     stepsize = 0.01*step_length_CS;
     stepsize = stepsize + 2*rand(1).*( first_best.*2*rand(1) - stepsize);
     s = s + (Gbest_cooku.pos.*2*rand(1)-s) + step.*abs(stepsize);
     s = min(s,ub);
     s = max(s,lb);
     new_egg(j,:)=s;
     new_egg_cost(j,:) = fobj(new_egg(j,:));

     if new_egg_cost(j,:) < NMS_CS_particle_nest(j).cost
    
      NMS_CS_particle_nest(j).cost = new_egg_cost(j,:);
      NMS_CS_particle_nest(j).pos = new_egg(j,:);
     end   
     end
     for v = 1:NP 
     new_nest(v,:)=NMS_CS_particle_nest(v).pos;
     K=rand(size( NMS_CS_particle_nest(v).pos))>pa;
     m = randi(NP);
     n = randsample([1:m-1 m+1:NP],1);
     stepsize=rand*(NMS_CS_particle_nest(m).pos - NMS_CS_particle_nest(n).pos);
     stepsize = min(stepsize,ub);
     stepsize = max(stepsize,lb);
     new_nest(v,:) = stepsize.*K+ NMS_CS_particle_nest(v).pos;
     new_nest(v,:) = min(new_nest(v,:),ub);
     new_nest(v,:) = max(new_nest(v,:),lb);
     new_nest_cost(v,:) = fobj( new_nest(v,:));
     NMS_CS_particle_nest(v).pos = NMS_CS_particle_nest(v).pos;
      if new_nest_cost(v,:) < NMS_CS_particle_nest(v).cost
       NMS_CS_particle_nest(v).cost = new_nest_cost(v,:);
       NMS_CS_particle_nest(v).pos = new_nest(v,:);
      end
     end
     [value, index] = min([NMS_CS_particle_nest.cost]);
     Gbest_cuckoo.cost = NMS_CS_particle_nest(index).cost;
     Gbest_cooku.pos = NMS_CS_particle_nest(index).pos;
     NMS_CS_best_cooku(t,:) = NMS_CS_particle_nest(index).cost;
     NMS_CS_best_solution(t,:) = NMS_CS_particle_nest(index).pos; 
 end     
 disp ('====================================')
disp([ ' Best solution = ' num2str(NMS_CS_particle_nest(index).pos)])
disp([ ' Bestofun  = ' num2str(NMS_CS_particle_nest(index).cost)])
figure(1)
plot(NMS_CS_best_cooku(1:cycle),'','lineWidth',2);
xlabel('Cycle')
ylabel('Best')
legend('NMS-CS')

