麻雀搜索算法是中国学者Jiankai Xue和Bo Shen受到麻雀的觅食行为和反捕食行为的启发,提出一种最新的群体优化算法。
麻雀是一种聪明的群居生物,具有良好的记忆力,所以麻雀种群在觅食过程中具有一些生物学特性:麻雀种群通常分为两种类型分别是发现者,也称探索者,和加入者,也被称为追随者。发现者寻找食物来源的搜索空间更大,而加入者则根据生产者寻找食物。麻雀具有较强的抗捕食能力,在觅食过程中,部分麻雀被选择作为侦察者以躲避捕食者。发现者和加入者可以动态转化,以获得更好的食物来源。加入者总能找到生产商提供的更好的食物来源,有些加入者甚至监视发现者以获得更多的食物。
麻雀的位置用下列矩阵表示为:
其中,n表示麻雀数量,d表示待优化变量的维数。
所有麻雀的适应度值表示为:
其中,矩阵的每一行的值表示个体的适应度值。在搜索过程中,先得到食物的是有着较好适应度值发现者,发现者的搜索范围是最大的,因为需要给整个种群寻找食物。发现者的位置更新方法:
其中t是当前迭代次数,j=1,2,3,…,d,Xti,j代表的是在迭代t次时,第i行第j维的值,Itermax表示最大迭代次数,Q表示的是服从正态分布的随机数,L为一个1×d的矩阵,其中每个元素都是1。R2和ST分别表示报警值和安全阈值。当R2<ST时,发现者能够在没有捕食者的情况下继续广泛搜索,当R2≥ST时,意味着麻雀已经被捕食者发现,所有麻雀应该迅速飞到其他安全区域。一些加入者会在整个觅食过程中会盯紧发现者,如果发现者找到了更好的
食物,加入者会立即去争夺食物,加入者的位置更新公式为:
其中,Xp代表当前发现者的最佳位置,Xworst代表麻雀最坏的位置,A表示一个1× d的矩阵,其每个元素值随机被赋值为1或−1,A+=AT(AAT)-1
当i>n/2时表示侦查者没有得到食物,需要飞到其他地方以获得更高的能量。为了注意危险环境,随机选择10% - 20%的麻雀作为侦察麻雀,并根据下式更新侦察麻雀的位置。
其中,Xbest是种群当前的最优位置,β是随机数,服从正态分布,均值为0,方差为1。K是控制因子,它是一个随机数,当前麻雀的适应度值由fi所表示,fg和fw分别表示当前全局最优适应度值以及当前全局最差适应度值,
ε是常数,值为很小,防止分母为0。当fi≠fg时,此时的麻雀正位于种群的边缘,在那里更容易遇到捕食者;当fi=fg时,表示麻雀位于种群的中心,需要接近其他麻雀以防止捕食。
代码如下:
# -*- coding: utf-8 -*-
"""
@Time : 2022/10/20 22:39
@Author : Xu Yong Kang
"""
def SSA(pop,dim,lb,ub,Maxiter,fun):
'''Sparrow Search Algorithm'''
'''
Input:
pop:种群数量
dim:每个个体的维度
ub:上边界
lb:下边界
fun:适应度函数
Maxiter:最大迭代次数
Output:
Bestscore:最优解对应的适应度值
Bestposition:最优解
Itercurve:迭代曲线
'''
ST=0.8 #安全阈值
PD=0.2 #探索者比例
SD=0.1 #意识到危险的麻雀数量占总数比例
PDnumber=int(pop*PD) #探索者数量
SDNumber=int(pop*SD) #意识到有危险的麻雀数量
X=initialization(pop,ub,lb,dim) #种群初始化
fitness=CaculateFitness(X,fun) #适应度值计算
fitness,sortIndex=SortFitness(fitness)
X=SortPosition(X,sortIndex)
Bestscore=copy.copy(fitness[0])
Bestposition=np.zeros([1,dim])
Bestposition[0,:]=copy.copy(X[0,:])
Itercurve=np.zeros([Maxiter])
for t in range(Maxiter):
print("迭代次数:"+str(t))
bestfit=copy.copy(fitness[0])
worstX=copy.copy(X[-1,:])
bestX=copy.copy(X[0,:])
pass
#探索者位置更新
R2=np.random.random() #产生随机报警值
alpha=np.random.random() #产生随机数alpha
Q=np.random.randn()
L=np.ones([1,dim])
for i in range(PDnumber):
if R2<ST:
X[i,:]=X[i,:]*np.exp(-1/(alpha*Maxiter))
else:
X[i,:]=X[i,:]+Q*L
pass
X=BorderCheck(X,ub, lb, pop, dim)
fitness=CaculateFitness(X,fun)
best1=np.argmin(fitness)
bestX=copy.copy(X[best1,:])
#加入者位置更新
for j in range(PDnumber,pop):
if j>pop/2:
X[j,:]=Q*np.exp((worstX-X[j,:])/j**2)
else:
#A=np.ones([1,dim])
A=np.ones([dim,1])
for k in range(dim):
if np.random.random()>0.5:
A[k]=-1
# k=[k for k in range(dim) if np.random.random()>0.5]
# A[k]=-1
AA=np.dot(A,np.linalg.inv(np.dot(A.T,A)))
X[j,:]=X[0,:]+np.abs(X[j,:]-Bestposition)*L*AA.T
pass
X = BorderCheck(X, ub, lb, pop, dim)
fitness = CaculateFitness(X, fun)
pass
#感知到危险的麻雀位置更新
Randpop=random.sample(range(pop),pop) #产生随机种群
SDchoosepop=Randpop[0:SDNumber] #产生意识到危险的种群
beta=np.random.randn()
K=2*np.random.random()-1 #产生控制因子K
for y in range(SDNumber):
if fitness[SDchoosepop[y]]>bestfit:
X[SDchoosepop[y],:]=bestX+beta*np.abs(X[SDchoosepop[y],:]-bestfit)
elif fitness[SDchoosepop[y]]==bestfit:
X[SDchoosepop[y],:]=X[SDchoosepop[y],:]+K*(np.abs(X[SDchoosepop[y],:]-X[-1,:])/(fitness[SDchoosepop[y]]-fitness[-1]
+10e-9))
测试函数仍然为:
def F(X):
n=X.shape[0]
F=-20*np.exp(-0.2*np.sqrt(np.sum(X**2)/n))-np.exp(np.sum(np.cos(2*np.pi*X))/n)+20+np.exp(1)
return F
结果:
The best optional value: [0.0850355]
The bset solution: [[-0.00282788 -0.00146369 0.01408579 -0.00973133 -0.00969662 -0.0088424
-0.00358105 -0.0017604 -0.00982527 -0.02395902 -0.02844884 -0.02027057
-0.03025529 -0.04562353 0.01922214 -0.0099868 -0.0269303 0.00876854
-0.00822057 -0.00665446 0.00968401 0.00882307 -0.00867802 0.00393968
0.0112454 -0.00879882 -0.01709775 -0.03064086 -0.01997446 0.01088274]]
参考文献:
[1]李雅丽.二进制麻雀搜索算法及其在特征选择中的应用[D].天津师范大学,2022.DOI:10.27363/d.cnki.gtsfu.2022.000316.
[2]王子恺,黄学雨,朱东林,闫少强,李权,郭伟.融合边界处理机制的学习型麻雀搜索算法[J/OL].北京航空航天大学学报:1-16[2022-10-21].DOI:10.13700/j.bh.1001-5965.2022.0195.