function [xbest,bfit,bfith] = SHO(N,itern,xd,xu,dims,f)
%% SELFISH HERD OPTIMIZER (SHO) 自私兽群优化器
A = xd+(xu-xd).*rand(N,dims);
preys_rate = [0.7,0.9];
rate = preys_rate(1)+(preys_rate(2) - preys_rate(1))*rand;
N_h = round(N*rate);
N_p = N - N_h;
% 2.2. Assign N_h individuals from "A" as herd members and
% calculate their fintess values
H = A(1:N_h,:);
f_h = zeros(N_h,1);
for ind = 1:N_h
f_h(ind) = f(H(ind,:));
end
% 2.3. Assign N_p individuals from "A" as predators and
% calculate their fitness values
P = A(N_h+1:N,:);
f_p = zeros(N_p,1);
for ind = 1:N_p
f_p(ind) = f(P(ind,:));
end
% 2.4. Initialize Global Memory
fit = [f_h;f_p];
[~,b_idx] = min(fit);
xbest = A(b_idx,:);
bfit = fit(b_idx);
[~,w_idx] = max(fit);
wfit = fit(w_idx);
% 2.5. Initialize Historical Global Memory
xbesth = zeros(itern,dims);
bfith = zeros(itern,1);
%% STEP 3: Calculate Survival Values for each member in "H" and "P"
[SV_h, SV_p] = SV(bfit, wfit, f_h, f_p);
%% STEP EX1: Build Function Contour (For Visualization Purposes)
[X,Y,Z] = contour_plot(f,xd,xu);
%% B. INITIALIZE ITERATIONS
for it=1:itern
%% STEP 4: Move all members in "H" by appying herd movement operators
H = HerdMove(H,SV_h,P,SV_p,xbest,dims,xd,xu);
%% STEP 5: Move all members in "P" by applying predators movement operators
P = PredMove(P,H,SV_h,dims,xd,xu);
%% STEP 6: Re-calculate Survival Values for each member in "H" and "P"
for i=1:N_h
f_h(i)=f(H(i,:));
end
for i=1:N_p
f_p(i)=f(P(i,:));
end
[SV_h, SV_p] = SV(bfit, wfit, f_h, f_p);
%% STEP 7: Perform Predation Phase
[L_idx, K_idx] = Predation(P,H,SV_p,SV_h,dims);
%% STEP 8: Perform Herd Restoration Phase
if any(K_idx)
[H, f_h] = Restoration(H,f_h,SV_h,L_idx,K_idx,dims,f);
[SV_h, SV_p] = SV(bfit, wfit, f_h, f_p);
end
%% STEP EX2: Update Global Memory
A = [H; P];
fit = [f_h; f_p];
[~,b_idx] = min(fit);
gbest2 = A(b_idx,:);
bfit2 = fit(b_idx);
if bfit2 <= bfit
bfit = bfit2;
xbest = gbest2;
end
[~,w_idx] = max(fit);
wfit2 = fit(w_idx);
if wfit2 >= wfit
wfit = wfit2;
end
xbesth(it,:) = xbest;
bfith(it) = bfit;
end
end
function [SV_h, SV_p] = SV(bfit, wfit, f_h, f_p)
% Calculate Survival Values for all members in "H" and "P"
SV_h = (f_h - wfit)./(bfit - wfit);
SV_p = (f_p - wfit)./(bfit - wfit);
% NaN and Inf values are set to 1 and 0 respectively (Sigular cases)
SV_h(isnan(SV_h)) = 1; SV_h(isinf(SV_h)) = 0;
SV_p(isnan(SV_p)) = 1; SV_p(isinf(SV_p)) = 0;
end
function [H] = HerdMove(H,SV_h,P,SV_p,xbest,dims,xd,xu)
scale = abs(xu-xd);
hL_idx = find(SV_h == max(SV_h));
if size(hL_idx,1) > 1
hL_idx = hL_idx(randi([1,size(hL_idx,1)]));
end
HF_idx = find(1:size(H,1)~=hL_idx);
SV_mean = mean(SV_h);
SV_h_wgt = repmat(SV_h,[1,dims]);
h_M = sum(SV_h_wgt.*H)./(sum(SV_h_wgt)+.00001);
SV_p_wgth = repmat(SV_p,[1,dims]);
p_M = sum(SV_p_wgth.*P)./(sum(SV_p_wgth)+.00001);
%% Herd Leader Movement Operators
h_L = H(hL_idx,:);
if SV_h(hL_idx) == 1
% Seemingly Cooperative Leadership Movement
v_bi = p_M - h_L;
r_bi = sqrt(sum(v_bi.^2,2))./scale;
W_L = exp(-r_bi^2);
move_L = -2*W_L*(v_bi);
else
% Openly Selfish Leadership Movement
v_bi = xbest - h_L;
r_bi = sqrt(sum(v_bi.^2,2))./scale;
W_L = exp(-r_bi^2);
move_L = 2*W_L*(v_bi);
end
alpha = rand(1,dims);
H(hL_idx,:) = H(hL_idx,:) + alpha.*move_L;
%% Herd Members Movement Operators
for i = HF_idx
if SV_h(i)>=rand
% Apply Herd Following Members Movement Operators
if SV_h(i)>SV_mean
% Apply Nearest Neighbor Movement Rule
HF_idx = find(SV_h(HF_idx) > SV_h(i));
if isempty(HF_idx)
move_iCi = zeros(1,dims);
else
v_bi = H(HF_idx,:) - repmat(H(i,:),[size(HF_idx,1),1]);
r_bi = sqrt(sum(v_bi.^2,2))./scale;
Ci_idx = find(r_bi == min(r_bi));
if size(Ci_idx,1) > 1
Ci_idx = Ci_idx(randi([1,size(Ci_idx,1)]));
end
h_Ci = H(HF_idx(Ci_idx),:);
W_iCi = SV_h(HF_idx(C