A brief introduction of jellyfish search optimization algorithm
This study developed a new meta-heuristic algorithm inspired by the behavior of jellyfish in the ocean, known as the Artificial Jellyfish Search (JS) Optimizer. Simulations of jellyfish searching behavior included their following ocean currents, their movement through a swarm (active and passive), time-control mechanisms that switched between these movements, and converging to a jellyfish flower state. The new algorithm has been successfully tested on the benchmark function and optimization problems. It is worth noting that JS has only two control parameters, namely population size and iteration number. As a result, JS is very simple to use and can be an excellent metaheuristic algorithm for solving optimization problems.
Two, some source code
%% Main MOJS optimizer
function ARCH = MOJS(params,MultiObj)
% Parameters
Np = params.Np;
Nr = params.Nr;
MaxIt = params.maxiter;
ngrid = params.ngrid;
fun = MultiObj.fun;
nVar = MultiObj.nVar;
var_min = MultiObj.var_min(:);
var_max = MultiObj.var_max(:);
it=1;
% Initialization by Eq. 25
POS=initialchaos(7,Np,nVar,var_max',var_min');
POS_fit = fun(POS);
ELI_POS = POS;
ELI_POS_fit = POS_fit;
DOMINATED = checkDomination(POS_fit);
ARCH.pos = POS(~DOMINATED,:);
ARCH.pos_fit = POS_fit(~DOMINATED,:);
ARCH = updateGrid(ARCH,ngrid);
display(['Iteration #0 - Archive size: ' num2str(size(ARCH.pos,1))); %% Main MOJS loop stopCondition =false;
while ~stopCondition
% Select leader by Eq. 16
h = selectLeader(ARCH);
% Calculate time control by Eq. 15
Ct=abs((1-it*((1)/MaxIt))*(2*rand- 1));
if Ct>=0.5
Meanvl=mean(ELI_POS);
for i=1:Np
% The new position is determined by Eq19. and Eq20.
POS(i,:) = ELI_POS(i,:) + Levy(nVar).*(ARCH.pos(h,:) - 3*rand([1 nVar]).*Meanvl);
end
else
for i=1:Np
if rand<(1-Ct)
% Jellyfish follow type B
% Determine the direction by Eq. 24
j=i;
while j==i
j=randperm(Np,1);
end
Step = ELI_POS(i,:) - ELI_POS(j,:);
if dominates(ELI_POS_fit(j,:),ELI_POS_fit(i,:))
Step = -Step;
end
% The new position is determined by Eq. 22
POS(i,:) =ARCH.pos(h,:) + rand([1 nVar]).*Step;
else
% Jellyfish follow type A
% The new position is determined by Eq. 21
POS(i,:)=ARCH.pos(h,:)+Levy(nVar).*(ELI_POS(i,:)-ARCH.pos(h,:));
end
end
end
%% Update new position by opposition-based jumping using Eq. 26
if rand <(it/MaxIt)
[POS] = OPPOS(POS,var_max,var_min);
end
%% Check boundaries
if rand>=0.5
POS=checksimplebounds(POS,var_min',var_max');
else
POS = checkBoundaries(POS,var_max,var_min);
end
%% Evaluate the population
POS_fit = fun(POS);
pos_best = dominates(POS_fit, ELI_POS_fit);
best_pos = ~dominates(ELI_POS_fit, POS_fit);
best_pos(rand(Np,1) > =0.5) = 0;
if(sum(pos_best)>1)
ELI_POS_fit(pos_best,:) = POS_fit(pos_best,:);
ELI_POS(pos_best,:) = POS(pos_best,:);
end
if(sum(best_pos)>1)
ELI_POS_fit(best_pos,:) = POS_fit(best_pos,:);
ELI_POS(best_pos,:) = POS(best_pos,:);
end
%% Update the archive
if size(ARCH.pos,1)= =1
ARCH.pos= POS;
ARCH.pos_fit= POS_fit;
ARCH = updateArchive(ARCH,ELI_POS,ELI_POS_fit,ngrid);
else
ARCH = updateArchive(ARCH,ELI_POS,ELI_POS_fit,ngrid);
if size(ARCH.pos,1)= =1
ARCH.pos= ELI_POS;
ARCH.pos_fit= ELI_POS_fit;
end
end
if(size(ARCH.pos,1)>Nr)
% Delete the worst members from archive by Eq. 18
ARCH = deleteFromArchive(ARCH,size(ARCH.pos,1)-Nr,ngrid);
end
display(['Iteration #' num2str(it) ' - Archive size: ' num2str(size(ARCH.pos,1)));
it=it+1;
if(it>MaxIt), stopCondition = true; end
end
%% Plotting paretofront
if(size(ARCH.pos_fit,2) = =2)
plot(ARCH.pos_fit(:,1),ARCH.pos_fit(:,2),'or'); hold on;
grid on; xlabel('f1'); ylabel('f2');
end
if(size(ARCH.pos_fit,2) = =3)
plot3(ARCH.pos_fit(:,1),ARCH.pos_fit(:,2),ARCH.pos_fit(:,3),'or'); hold on;
grid on; xlabel('f1'); ylabel('f2'); zlabel('f3');
end
end
%% This function calucates the leader performance by a roulette wheel selection
% based on the quality of each hypercube
function selected = selectLeader(ARCH)
% Roulette wheel
prob = cumsum(ARCH.quality(:,2)); % Cumulated probs
sel_hyp = ARCH.quality(find(rand(1.1)*max(prob)<=prob,1.'first'),1); % Selected hypercube
% Select the index leader as a random selection inside that hypercube
idx = 1:1:length(ARCH.grid_idx);
selected = idx(ARCH.grid_idx==sel_hyp);
selected = selected(randi(length(selected)));
end
%% This function returns 1 if x dominates y and 0 otherwise
function d = dominates(x,y)
d = all(x<=y,2) & any(x<y,2);
end
%% This function checks the domination inside the population.
function domi_vector = checkDomination(fitness)
Np = size(fitness,1);
if Np>2
domi_vector = zeros(Np,1);
all_perm = nchoosek(1:Np,2); % Possible permutations
all_perm = [all_perm; [all_perm(:,2) all_perm(:,1)]];
d = dominates(fitness(all_perm(:,1),:),fitness(all_perm(:,2), :)); dominated_particles = unique(all_perm(d==1.2));
domi_vector(dominated_particles) = 1;
else
domi_vector=ones(Np,1);
end
end
%% This function updates the archive given a new population
function ARCH = updateArchive(ARCH,POS,POS_fit,ngrid)
% Domination between jellyfish
DOMINATED = checkDomination(POS_fit);
ARCH.pos = [ARCH.pos; POS(~DOMINATED,:)];
ARCH.pos_fit= [ARCH.pos_fit; POS_fit(~DOMINATED,:)];
% Domination between nondominated jellyfish and the last archive
DOMINATED = checkDomination(ARCH.pos_fit);
ARCH.pos_fit= ARCH.pos_fit(~DOMINATED,:);
ARCH.pos = ARCH.pos(~DOMINATED,:);
% Updating the grid
ARCH = updateGrid(ARCH,ngrid);
end
%% Function that updates the hypercube grid, the hypercube where belongs
function ARCH = updateGrid(ARCH,ngrid)
% Computing the hypercube limitation
ndim = size(ARCH.pos_fit,2);
ARCH.hypercube_limits = zeros(ngrid+1,ndim);
for dim = 1:1:ndim
ARCH.hypercube_limits(:,dim) = linspace(min(ARCH.pos_fit(:,dim)),max(ARCH.pos_fit(:,dim)),ngrid+1)'; end % Computing where belongs each jellyfish npar = size(ARCH.pos_fit,1); ARCH.grid_idx = zeros(npar,1); ARCH.grid_subidx = zeros(npar,ndim); for n = 1:1:npar idnames = []; for d = 1:1:ndim ARCH.grid_subidx(n,d) = find(ARCH.pos_fit(n,d)<=ARCH.hypercube_limits(:,d)'.1.'first')- 1;
if(ARCH.grid_subidx(n,d)==0), ARCH.grid_subidx(n,d) = 1; end
idnames = [idnames ', ' num2str(ARCH.grid_subidx(n,d))];
end
ARCH.grid_idx(n) = eval(['sub2ind(ngrid.*ones(1,ndim)' idnames '); ']);
end
% Quality based on the number of jellyfish in each hypercube
ARCH.quality = zeros(ngrid,2);
ids = unique(ARCH.grid_idx);
for i = 1:length(ids)
ARCH.quality(i,1) = ids(i);
ARCH.quality(i,2) = 10/sum(ARCH.grid_idx==ids(i));
end
end
%% This function deletes an excess of jellyfish inside the archive using crowding distances
function ARCH = deleteFromArchive(ARCH,n_extra,ngrid)
% Compute the crowding distances
crowding = zeros(size(ARCH.pos,1),1);
for m = 1:1:size(ARCH.pos_fit,2)
[m_fit,idx] = sort(ARCH.pos_fit(:,m),'ascend');
m_up = [m_fit(2:end); Inf];
m_down = [Inf; m_fit(1:end- 1)];
distance = (m_up-m_down)./(max(m_fit)-min(m_fit));
[~,idx] = sort(idx,'ascend');
crowding = crowding + distance(idx);
end
crowding(isnan(crowding)) = Inf;
% This function deletes the extra jellyfish with the smallest crowding distances
[~,del_idx] = sort(crowding,'ascend');
del_idx = del_idx(1:n_extra); ARCH.pos(del_idx,:) = []; ARCH.pos_fit(del_idx,:) = []; ARCH = updateGrid(ARCH,ngrid); end %% This function checks the boundary of jellyfish search space function [POS] = checkBoundaries(POS,var_max,var_min) % Useful matrices Np = size(POS,1);
MAXLIM = repmat(var_max(:)',Np,1); MINLIM = repmat(var_min(:)',Np,1);
POS(POS>MAXLIM) = MAXLIM(POS>MAXLIM);
POS(POS<MINLIM) = MINLIM(POS<MINLIM);
end
function POS=checksimplebounds(POS,Lb,Ub)
for i=1:size(POS,1)
ns_tmp=POS(i,:);
I=ns_tmp<Lb;
while sum(I)~=0
ns_tmp(I)=Ub(I)+(ns_tmp(I)-Lb(I));
I=ns_tmp<Lb;
end
J=ns_tmp>Ub;
while sum(J)~=0
ns_tmp(J)=Lb(J)+(ns_tmp(J)-Ub(J));
J=ns_tmp>Ub;
end
POS(i,:)=ns_tmp;
end
end
Copy the code
3. Operation results
Matlab version and references
1 matlab version 2014A
[1] Yang Baoyang, YU Jizhou, Yang Shan. Intelligent Optimization Algorithm and Its MATLAB Example (2nd Edition) [M]. Publishing House of Electronics Industry, 2016. [2] ZHANG Yan, WU Shuigen. MATLAB Optimization Algorithm source code [M]. Tsinghua University Press, 2017.