一、算法原理
黏菌算法(Slime mould algorithm,SMA)是模拟黏菌捕食行为的一种仿生算法。黏菌根据气味识别到食物后,通过细胞质的流动形成多个叶脉,同时向多个食物进行移动,当叶脉接近食物源时,黏菌的生物振荡器产生一种传播 波,增加细胞质流动速度,细胞质流动越快,叶脉就越厚。这种正反馈机制,使得黏菌能以一种较优的方式建立连接食物的路径。SMA具有收敛速度快,寻优能力强的优点。
借鉴黏菌的生物行为,可以抽象出三个规则:
寻找食物:黏菌通过空气中的气味接近食物,黏菌接近食物时呈圆形与扇形结构运动。
包围食物:黏菌静脉接触的食物浓度越高,生物振荡器产生的传播波越强,细胞质流动越快。
抓取食物:黏菌在食物浓度低时更慢地接近食物,找到优质食物时更快地接近食物。
二、代码实战
%%
clear
clc
close all
addpath(genpath(pwd))
number='F10'; %选定优化函数,自行替换:F1~F23
[lb,ub,dim,y]=CEC2005(number); % [lb,ub,D,y]:下界、上界、维度、目标函数表达式
MaxIteration=1000; %最大迭代次数
Solution_no=50; %种群规模
%调用SMA算法
[Destination_fitness,bestPositions,Convergence_curve]=SMA(Solution_no,MaxIteration,lb,ub,dim,y);
disp(['最佳适应度值',num2str(Destination_fitness)])
disp(['最佳粒子位置',num2str(bestPositions)])
%% 绘图
subplot(1,2,1)
func_plot(number)
title(number)
xlabel('x')
ylabel('y')
zlabel('z')
subplot(1,2,2)
CNT=50;
k=round(linspace(1,MaxIteration,CNT)); %随机选50个点
% 注意:如果收敛曲线画出来的点很少,随机点很稀疏,说明点取少了,这时应增加取点的数量,100、200、300等,逐渐增加
% 相反,如果收敛曲线上的随机点非常密集,说明点取多了,此时要减少取点数量
iter=1:1:MaxIteration;
semilogy(iter(k),Convergence_curve(k),'m-x','linewidth',1);
grid on;
title(['函数收敛曲线',number])
xlabel('Iterations');
ylabel('Objective function value');
box on
legend('SMA')
set (gcf,'position', [200,300,700,300])
function [Destination_fitness,bestPositions,Convergence_curve]=SMA(N,Max_iter,lb,ub,dim,fobj)
%% 初始化位置
bestPositions=zeros(1,dim);
Destination_fitness=inf;%将此更改为 -inf 以解决最大化问题
AllFitness = inf*ones(N,1);%记录所有粘菌的适应度
weight = ones(N,dim);%每个粘菌的适应度权重
%% 初始化随机解集
X=initialization(N,dim,ub,lb);
Convergence_curve=zeros(1,Max_iter);
it=1; %迭代次数
lb=ones(1,dim).*lb; % 变量下限
ub=ones(1,dim).*ub; % 变量上限
z=0.03; % 参数
%% 主循环
while it <= Max_iter
%=====适应度排序======
for i=1:N
% 检查解决方案是否超出搜索空间并将其带回
Flag4ub=X(i,:)>ub;
Flag4lb=X(i,:):)=(X(i,:).*(~(Flag4ub+Flag4lb)))+ub.*Flag4ub+lb.*Flag4lb;
AllFitness(i) = fobj(X(i,:));
end
[SmellOrder,SmellIndex] = sort(AllFitness);
worstFitness = SmellOrder(N);
bestFitness = SmellOrder(1);
S=bestFitness-worstFitness+eps; %加上 eps 以避免分母为零
%====计算每个粘菌的适应度权重=====
for i=1:N
for j=1:dim
if i<=(N/2)
weight(SmellIndex(i),j) = 1+rand()*log10((bestFitness-SmellOrder(i))/(S)+1);
else
weight(SmellIndex(i),j) = 1-rand()*log10((bestFitness-SmellOrder(i))/(S)+1);
end
end
end
%====更新最佳适应度值和最佳位置=====
if bestFitness < Destination_fitness
bestPositions=X(SmellIndex(1),:);
Destination_fitness = bestFitness;
end
a = atanh(-(it/Max_iter)+1);
b = 1-it/Max_iter;
%====更新搜索代理的位置=====
for i=1:N
if rand:) = (ub-lb)*rand+lb;
else
p =tanh(abs(AllFitness(i)-Destination_fitness));
vb = unifrnd(-a,a,1,dim);
vc = unifrnd(-b,b,1,dim);
for j=1:dim
r = rand();
A = randi([1,N]); % 从总体中随机选择两个位置
B = randi([1,N]);
if r
else X(i,j) = vc(j)*X(i,j); end end end end Convergence_curve(it)=Destination_fitness; display(['At iteration ', num2str(it), ' the best solution fitness is ', num2str(Destination_fitness)]); it=it+1; end end