% 五行算法
function [ gbestval,gbest,Convergence_curve] = FivePA(ps,gen, Xmin, Xmax, D,fun )
%%
% random seeds
stm = RandStream('swb2712','Seed',sum(100*clock));
RandStream.setGlobalStream(stm);
% max_iteration
% gen = Max_nfe/ps;
% 5 labels
NP=5;
ps_subps= floor(ps/NP);
ps_subps_last= ps-floor((ps/NP))*(NP-1);
% constract ps*D matrix
if length(Xmin) ==1
Rmin = repmat(Xmin,1,D);
Rmax = repmat(Xmax,1,D);
end
% VRmin(ps*D) bound matrix
VRmin = repmat(Rmin,ps,1);
VRmax = repmat(Rmax,ps,1);
Convergence_curve=zeros(1,gen );
%% initialize agents
pos = VRmin + (VRmax-VRmin).*rand(ps,D);
%pos = randn(ps,D);
eval = feval(fun,pos'); %return the row of fitness values
fitcount = ps;
[gbestval,gbestid] = min(eval);
gbest = pos(gbestid,:);
% Convergence_curve(1)=gbestval;
for iter = 1:gen
%% Randomly division
% shuffle and separate agents
indexr = randperm(ps)';
pos = pos(indexr,:);
eval = eval(:,indexr);
% wood,fire,earth,metal,water + archive
wo_pos = pos(1:ps_subps,:);
wo_eval = eval(:,1:ps_subps);
f_pos = pos(ps_subps+1:2*ps_subps,:);
f_eval = eval(:,ps_subps+1:2*ps_subps);
e_pos = pos(2*ps_subps+1:3*ps_subps,:);
e_eval = eval(:,2*ps_subps+1:3*ps_subps);
m_pos = pos(3*ps_subps+1:4*ps_subps,:);
m_eval = eval(:,3*ps_subps+1:4*ps_subps);
wa_pos = pos(4*ps_subps+1:ps,:);
wa_eval = eval(:,4*ps_subps+1:ps);
% wood
[wo_bestval,wo_bestid] = min(wo_eval);
wo_best = wo_pos(wo_bestid,:);
[wo_worstval,wo_worstid] = max(wo_eval);
wo_worst = wo_pos(wo_worstid,:);
% fire
[f_bestval,f_bestid] = min(f_eval);
f_best = f_pos(f_bestid,:);
[f_worstval,f_worstid] = max(f_eval);
f_worst = f_pos(f_worstid,:);
% earth
[e_bestval,e_bestid] = min(e_eval);
e_best = e_pos(e_bestid,:);
[e_worstval,e_worstid] = max(e_eval);
e_worst = e_pos(e_worstid,:);
% metal
[m_bestval,m_bestid] = min(m_eval);
m_best = m_pos(m_bestid,:);
[m_worstval,m_worstid] = max(m_eval);
m_worst = m_pos(m_worstid,:);
% water
[wa_bestval,wa_bestid] = min(wa_eval);
wa_best = wo_pos(wa_bestid,:);
[wa_worstval,wa_worstid] = max(wa_eval);
wa_worst = wa_pos(wa_worstid,:);
% internal archieve , wood fire,earth,metal,water
% wood
index_wo = randperm(ps_subps)';
arc_wo_pos = wo_pos(index_wo,:);
arc_wo_eval = wo_eval(:,index_wo);
% fire
index_f = randperm(ps_subps)';
arc_f_pos = f_pos(index_f,:);
arc_f_eval = f_eval(:,index_f);
% earth
index_e = randperm(ps_subps)';
arc_e_pos = e_pos(index_e,:);
arc_e_eval = e_eval(:,index_e);
% metal
index_m = randperm(ps_subps)';
arc_m_pos = m_pos(index_m,:);
arc_m_eval = m_eval(:,index_m);
% water
index_wa = randperm(ps_subps_last)';
arc_wa_pos = wa_pos(index_wa,:);
arc_wa_eval = wa_eval(:,index_wa);
% archive creat and destroy
arc_creat_pos = [wo_best;f_best;e_best;m_best;wa_best];
% arc_creat_val = [wo_bestval,f_bestval,s_bestval,m_bestval,wa_bestval];
arc_destroy_pos = [wo_worst;f_worst;e_worst;m_worst;wa_worst];
% arc_destroy_val = [wo_worstval,f_worstval,s_worstval,m_worstval,wa_worstval];
pos= [wo_pos;f_pos;e_pos;m_pos;wa_pos]; % merge agents
eval= [wo_eval,f_eval,e_eval,m_eval,wa_eval];
%% pos_update
for i=1:NP
switch i
case 1
% wood_update
if rand < rand
for i=1:ps_subps
for j=1:D
wo_posnew(i,j)= wo_pos(i,j)+rand*(arc_creat_pos(5,j)-wo_pos(i,j)) - rand*(arc_destroy_pos(4,j)-wo_pos(i,j)); % Eq.1
end
end
else
wo_bin = (arc_wo_eval< wo_eval)';
num_ones = sum(wo_bin);
wo_posnew(wo_bin==1,:) = wo_pos(wo_bin==1,:)+ rand(num_ones,D).*(arc_wo_pos(wo_bin==1,:)-wo_pos(wo_bin==1,:)); % Eq.2
wo_posnew(wo_bin==0,:) = wo_pos(wo_bin==0,:)+ rand(ps_subps-num_ones,D).*(wo_pos(wo_bin==0,:)-arc_wo_pos(wo_bin==0,:)); % Eq.2
end
case 2
% fire_update
if rand < rand
for i=1:ps_subps
for j=1:D
f_posnew(i,j)=f_pos(i,j)+rand*(arc_creat_pos(1,j)-f_pos(i,j)) - rand*(arc_destroy_pos(5,j)-f_pos(i,j)); %
end
end
else
f_bin = (arc_f_eval< f_eval)';
num_ones = sum(f_bin);
f_posnew(f_bin==1,:) = f_pos(f_bin==1,:)+ rand(num_ones,D).*(arc_f_pos(f_bin==1,:)-f_pos(f_bin==1,:));
f_posnew(f_bin==0,:) = f_pos(f_bin==0,:)+ rand(ps_subps-num_ones,D).*(f_pos(f_bin==0,:)-arc_f_pos(f_bin==0,:));
end
case 3
% soil_update
if rand < rand
for i=1:ps_subps
for j=1:D
e_posnew(i,j)=e_pos(i,j)+rand*(arc_creat_pos(2,j)-e_pos(i,j)) - rand*(arc_destroy_pos(1,j)-e_pos(i,j)); %
end
end
else
e_bin = (arc_e_eval< e_eval)';
num_ones = sum(e_bin);
e_posnew(e_bin==1,:) = e_pos(e_bin==1,:)+ rand(num_ones,D).*(arc_e_pos(e_bin==1,:)-e_pos(e_bin==1,:));
e_posnew(e_bin==0,:) = e_pos(e_bin==0,:)+ rand(ps_subps-num_ones,D).*(e_pos(e_bin==0,:)-arc_e_pos(e_bin==0,:));
end
case 4
% metal_update
if rand < rand
for i=1:ps_subps
for j=1:D
m_posnew(i,j)=m_pos(i,j)+rand*(arc_creat_pos(3,j)-m_pos(i,j)) - rand*(arc_destroy_pos(2,j)-m_pos(i,j)); %
end
end
else
m_bin = (arc_m_eval< m_eval)';
num_ones = sum(m_bin);
m_posnew(m_bin==1,:) = m_pos(m_bin==1,:)+ rand(num_ones,D).*(arc_m_pos(m_bin==1,:)-m_pos(m_bin==1,:));
m_posnew(m_bin==0,:) = m_pos(m_bin==0,:)+ rand(ps_subps-num_ones,D).*(m_pos(m_bin==0,:)-arc_m_pos(m_bin==0,:));
end
case 5
% water_update
if rand < rand
for i=1:ps_subps_last
for j=1:D
wa_posnew(i,j)=wa_pos(i,j)+rand*(arc_creat_pos(4,j)-wa_pos(i,j)) - rand*(arc_destroy_pos(3,j)-wa_pos(i,j)); %
end
end
else
wa_bin = (arc_wa_eval< wa_eval)';
num_ones = sum(wa_bin);
wa_posnew(wa_bin==1,:) = wa_pos(wa_bin==1,:)+ rand(num_ones,D).*(arc_wa_pos(wa_bin==1,:)-wa_pos(wa_bin==1,:));
wa_posnew(wa_bin==0,:) = wa_pos(wa_bin==0,:)+ rand(ps_subps_last-num_ones,D).*(wa_pos(wa_bin==0,:)-arc_wa_pos(wa_bin==0,:));
end
end
end
posnew = [wo_posnew; f_posnew; e_posnew; m_posnew; wa_posnew];
% boundary limit
posnew = ((posnew>=VRmin)&(posnew<=VRmax)).*posnew...
+(posnew<VRmin).*VRmin+...
+(posnew>VRmax).*VRmax;
evalnew = feval(fun,posnew'); % Calculate fitness function
fitcount = fitcount + ps;
%% evolution
bin = (eval > evalnew)';
pos(bin==1,:) = posnew(bin==1,:);
eval(bin==1) = evalnew(bin==1);
[gbestval,gbestid] = min(eval);
gbest = pos(gbestid,:);
Convergence_curve(iter)=gbestval-1;
end
end