算法核心思想:飞蛾以螺旋线运动方式不断靠近火焰,痛过对火焰的筛选,不断选出离目标函数极值最接近的位置。刚刚开始时候,飞蛾和火焰位置是一致的;以螺旋线方程更新飞蛾位置,接着以飞蛾位置计算火焰位置,再对火焰位置进行筛选,选出最优,不断重复迭代这个过程,得到的最优解位置就会不断接近于目标函数极值。具体内容在代码注释中。 论文地址 ---好像要期刊会员才能下载
In [17]
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#初始化边界值以及目标函数
data_fun = {
'F1':[-100,100,10],
'F8':[-500,500,10]
}
class Fun_class():
'''
lb:下界
ub:上界
dim:初始化的飞蛾对应的矢量个数,也就是初始化数据的列数
'''
def __init__(self,F = 'F1'):
self.lb,self.ub,self.dim = data_fun[F]
#定义自适应函数(目标函数),此处列举2种目标函数F1和F8
if F is 'F1':
self.fobj = self.F1
elif F is 'F8':
self.fobj = self.F8
else:
raise Exception("未添加此目标函数")
def __call__(self):
return [self.lb,self.ub,self.dim,self.fobj]
def F1(self,x):#单模态函数
return np.sum(np.power(x,2),axis=1)#按照第二维度求和
def F8(self,x):#多模态函数
return np.sum(-x*np.sin(np.sqrt(np.abs(x))),axis=1)#按照第二维度求和
#还有第三种复合模态函数,略
#初始化飞蛾的位置
def initialization(N,lb,ub,dim):
if isinstance(ub,(int,float)):#判断是否是该种数据类型,所有边界值都是相同情况
x = (ub - lb) * np.random.rand(N,dim) + lb
elif isinstance(ub,(list,tuple)):#边界值不同情况,详细对照原论文公式说明
for i in range(dim):
#x = np.insert(x,(ub(i) - lb(i)) * np.random.rand(N,1) + lb(i),axis=1)#按列插入数据
x = np.hstack((x,(ub(i) - lb(i)) * np.random.rand(N,1) + lb(i)))
else:
raise Exception("边界数据错误")
return x
#飞蛾火焰算法MFO
def MFO(N,Max_iteration,lb,ub,dim,fobj):
moth_pos = initialization(N,lb,ub,dim)#初始化飞蛾位置
Convergence_curve = np.zeros((Max_iteration))#用于记录每一次迭代过程中,最优的飞蛾对应的自适应度的值
#进行循环迭代,搜索最优解
for Iteration in range(Max_iteration): #python中的此循环取值是从:0到Max_iteration-1
#火焰数目自适应减少机制,火焰一开始数量与飞蛾一直,迭代过程中,按着迭代的轮数去平均减少火焰的数量,飞蛾数量不变
Flame_no=round(N-Iteration*((N-1)/Max_iteration))
#每一次迭代完都需要检查一下我们的飞蛾有没有飞出我们设定的边界值,如果有飞出,就将他们位置调回边界值
flag_lb = moth_pos < lb#判断是否超出范围,返回布尔值矩阵
flag_ub = moth_pos > ub
moth_pos = moth_pos * (1 - (flag_lb+flag_ub)) + flag_lb * lb + flag_ub * ub#超出部分调整回来
Moth_fitness = fobj(moth_pos)#求得飞蛾对应的自适应度
#对飞蛾自适应度排序,并更新火焰
if Iteration is 0:
ids = np.argsort(Moth_fitness)#自适应度升序排序后的索引
fitness_sorted = np.sort(Moth_fitness)#自适应度升序排序后的值
sorted_population = moth_pos[ids]#按照排序顺序去重新排序对应的飞蛾位置
#由飞蛾来更新火焰,即第一次是直接将飞蛾的位置以及自适应度赋值给火焰
best_flames = sorted_population#位置
best_flame_fitness = fitness_sorted#自适应度
else:
double_population = np.vstack((previous_population,best_flames))#位置按行拼接
double_fitness = np.hstack((previous_fitness,best_flame_fitness))#自适应度按列拼接
ids = np.argsort(double_fitness)#排序索引
double_fitness_sorted = np.sort(double_fitness)##将前一次迭代的结果和这一次的结果进行升序排序
double_sorted_population = double_population[ids]
fitness_sorted = double_fitness_sorted[0:N]#取出前N个最小的自适应度
sorted_population = double_sorted_population[0:N]#取出前N个最小的自适应度对应的位置
# Update the flames 由飞蛾更新火焰
best_flames = sorted_population#位置
best_flame_fitness = fitness_sorted#自适应度
#记录最优位置以及最优值
Best_flame_score = sorted_population[0]#本次迭代最优的位置
Best_flame_pos = fitness_sorted[0]#本次迭代最优的自适应度
#更新飞蛾位置
previous_population = moth_pos #位置
previous_fitness = Moth_fitness #自适应度
a=-1+Iteration * ((-1) / Max_iteration)#a从-1到-2线性分割以计算t,详细对照原论文公式说明
#遍历所有飞蛾,迭代过程中,飞蛾数是不变的,火焰数是在不段减少。飞蛾围绕着火焰做螺旋靠近。
#火焰是进行筛选,保留距离我们目标函数最近的火焰,即自适应度最小的火焰,最后火焰就只有一个,这个火焰的值无限接近于目标函数的极值。
for i in range(moth_pos.shape[0]):
if i < Flame_no:#飞蛾数和火焰数一致时候
distance_to_flame=np.abs(sorted_population[i,:] - moth_pos[i,:])#求火焰和飞蛾直接的距离,是一个一维向量,具体对照论文公式说明
#print(distance_to_flame.shape)
b = 1
t = (a - 1) * np.random.rand(1,1) + 1 #t是在[-2,1]之间动态变化,受前面的a影响,详细对照原论文公式说明
#对数螺旋公式,飞蛾围绕着火焰做螺旋运动,更新其位置
moth_pos[i,:]=distance_to_flame * np.exp(b*t) * np.cos(t * 2 * np.pi) + sorted_population[i,:];
else:#飞蛾数大于火焰数时候,用最后一个火焰与这些飞蛾计算
distance_to_flame=np.abs(sorted_population[i,:] - moth_pos[i,:])#求火焰和飞蛾直接的距离,是一个一维向量,具体对照论文公式说明
b = 1
t = (a - 1) * np.random.rand(1,1) + 1 #t是在[-2,1]之间动态变化,受前面的a影响,详细对照原论文公式说明
#对数螺旋公式,飞蛾围绕着火焰做螺旋运动,更新其位置
moth_pos[i,:]=distance_to_flame * np.exp(b * t) * np.cos(t * 2 * np.pi) + sorted_population[Flame_no-1,:]#使用最后一个火焰
Convergence_curve[Iteration] = Best_flame_pos#记录每一次的最优自适应度
if Iteration % 50 is 0:
print(Best_flame_pos)
return Best_flame_score,Best_flame_pos,Convergence_curve
#主函数
if __name__ == "__main__":
N = 30#粒子数量,即飞蛾数量
Max_iteration = 1000#最大迭代数量
#初始化一些变量
fun = Fun_class('F1')
lb,ub,dim,fobj = fun()
#飞蛾火焰算法MFO
Best_flame_score,Best_flame_pos,Convergence_curve=MFO(N,Max_iteration,lb,ub,dim,fobj)
print("最优解:{}".format(Best_flame_score))
print("函数近似极值:{}".format(Best_flame_pos))
print("每一次迭代的最优值维度:{}".format(Convergence_curve.shape))
#画个曲线图
plt.subplot(1,2,1)
plt.plot(Convergence_curve)
plt.title("Convergence_curve")
plt.xlabel("iter")
plt.ylabel("Best flame (score) obtained so far")
17119.536235460364
3218.906451394564
2172.8645838721854
1350.650895752926
1350.650895752926
1211.9943280737493
1122.7824779693876
1053.7494395636131
1019.832800861471
862.890984008977
488.5987825947539
396.76299619398867
396.76299619398867
396.76299619398867
396.76299619398867
335.19998325834916
335.19998325834916
335.19998325834916
304.81867060250653
304.81867060250653
最优解:[ -0.29300351 -8.42585415 -16.65158052 -5.39207436 0.60597754
0.32618419 -5.16099647 -3.88361087 -0.15208169 6.92920333]
函数近似极值:304.81867060250653
每一次迭代的最优值维度:(1000,)
<Figure size 432x288 with 1 Axes>
算法核心思想:与前面的MFO相似,区别就是位置更新的公式不同。此算法的在每一次的调整边界时,计算自适应度,之后的位置更新操作有改变,它只记录了最小自适应度对应的位置(一只距离目标函数极值最近的鲸鱼)。接着在主循环中更新了鲸鱼的位置,有3种更新公式:
算法核心思想:与MFO类似,初始化鱼群后,对其求自适应度,然后进行排序,记录最小位置(也就是最优位置),作为食物位置。接下来的迭代循环阶段做的是,遍历鱼群中的所有鱼,其中一半的鱼群用(3.1)的公式去更新鱼群位置,另一半鱼群用(3.4)的公式去更新鱼群。最后在对这些更新后的鱼群进行排序,自适应度最小的鱼群位置作为新的食物位置。
算法核心思想:与前面几种都是类似
In [ ]
In [ ]
In [ ]
In [ ]
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。