智能优化算法之萤火虫算法(FA)的实现(Python附源码)

一、萤火虫算法的实现思路

萤火虫算法(Firefly Algorithm,FA)是由Yang于2010年提出的一种群智能优化算法,在自然界中,萤火虫之间通过自身发光来吸引异性前来交配以及吸引猎物进行捕猎,而该算法主要仿照自然界中萤火虫之间受彼此亮度而相互吸引的行为来进行目标范围内的寻优过程。
在萤火虫算法的基本思想中,主要涉及到的两个概念有两个,分别为吸引力与个体间的移动,下面将分别从这两个方面进行介绍。

1、吸引力

在萤火虫算法中,每个萤火虫的位置代表了一个待求问题的可行解,而萤火虫的亮度表示该萤火虫位置的适应度值,亮度越高的萤火虫个体在解空间内的位置越好,在解空间内,每个萤火虫会向着亮度比自己高的萤火虫飞行来搜寻更优的位置,亮度越大对其他的萤火虫的吸引度越大。同时,萤火虫之间光的传播介质会吸收光,降低光的亮度,影响光的传播,所以萤火虫之间的吸引度会随着空间距离成反比,即两只萤火虫之间的吸引度会随着这两只萤火虫之间距离的增大而减小。基于此,使用相互吸引度公式对萤火虫之间的吸引力进行计算。

其中β0为初始吸引度值,即两只萤火虫之间的距离为0时的吸引度,初始β0取值为1,γ为传播介质对光的吸收系数,一般取值为1,r为两只萤火虫之间的空间距离。
在对两个萤火虫之间的空间距离进行计算时,采用下列公式进行计算:

其中d表示位置信息的具体位置,x_ik与x_jk分别表示个体i与个体j在第k个维度的具体位置信息。

2、个体间的位置移动

受到吸引力的影响,种群中的每一只萤火虫均会被亮度比其大的萤火虫所吸引,进而向其所在的方向进行移动,具体的位置更新公式如下,而依次向所有亮度更大的个体移动完之后的位置才是萤火虫的最终确定位置。

其中个体更新后的位置信息等于更新前的位置信息加上其他个体对其的吸引移动量以及移动过程的干扰量,β为个体j对个体i的吸引度;α为步长的扰动因子,一般为0到1之间的随机数;rand()是-0.5到0.5之间满足均匀分布的随机数,由于萤火虫是朝向亮度比自己高的萤火虫进行飞行,因此在上述公式中个体j的适应度值高于个体i的适应度值。

二、算法步骤

使用萤火虫算法对优化问题进行求解时的具体步骤可以归纳如下:

  1. 设置种群的个体数量、初始吸引度值β0、传播介质对光的吸收系数γ以及步长的扰动因子α;
  2. 以萤火虫个体的位置信息作为待优化问题的解,以萤火虫个体的亮度作为解对应的适应度值,根据待优化问题的解的范围,随机初始化种群所有个体的位置信息;
  3. 根据待求解问题,计算种群中每个个体的适应度值,之后对种群个体的适应度值进行比较,将最高适应度值作为种群的历史最优适应度值,将其对应的位置信息作为种群的历史最优位置信息;
  4. 依次将每个个体与其它个体进行适应度值的比较,同时计算个体之间的空间距离,按照适应度值低的个体被适应度高的个体吸引的原则,确定每个个体分别被种群内哪些个体吸引并根据空间距离计算出每个个体受到的所有吸引力;
  5. 每个个体依次向所有适应度值比它高的个体位置方向进行移动,按照相关公式进行位置更新;
  6. 计算每个个体更新后的适应度值,对种群的历史最优适应度值、历史最优位置信息进行更新;
  7. 根据预设的迭代次数重复步骤4到步骤6,当达到最大迭代次数时停止迭代过程,输出种群的历史最优位置信息,此位置信息即为算法优化后获得的问题最优解。

三、实例

待求解问题:
Rosenbrock’s,取值范围为[-10,10],取值范围内的理想最优解为0,将其搜索的空间维度设为20。

实现源码:

#库的导入
import numpy as np
import matplotlib.pyplot as plt

#待求解问题
def function(x):
    y1 = 0
    for i in range(len(x) - 1):
        y2 = 100 * ((x[i + 1] - x[i] ** 2) ** 2) + (x[i] - 1) ** 2
        y1 = y1 + y2
    y = abs(0 - y1)
    return y

#计算个体间的空间距离
def distance(x,y):
    r = np.linalg.norm(x-y)
    return r

rangepop=[-10,10]  #取值范围
m = 50  #种群数量
gama = 1.0  #传播介质对光的吸收系数
belta0 = 1.0  #初始吸引度值
alpha = 1  #步长扰动因子
ite = 100  #迭代次数
#pop用于存储种群个体的位置信息,fitness用于存储个体对应的适应度值
pop = np.zeros((m,20))
fitness=np.zeros(m)
#对种群个体进行初始化并计算对应适应度值
for j in range(m):
    pop[j] = np.random.uniform(low=-10, high=10,size=(1, 20))
    fitness[j] = function(pop[j])
#bestpop,bestfit分别表示种群历史最优解和适应度值
bestpop, bestfit = pop[fitness.argmin()].copy(), fitness.min()
#bestfitness用于存储每次迭代时的种群历史最优适应度值
bestfitness=np.zeros(ite)
#开始训练
for i in range(ite):
    print("the iteration is :",i+1)
    #对每个个体位置与适应度值进行更新
    for j in range(m):
        #当前个体适应度值为种群最优的位置更新方式
        if fitness[j] == fitness.min():
            pop[j] = pop[j] + alpha * (np.random.rand()-0.5)
            # 确保更新后的位置在取值范围内
            pop[j][pop[j] < rangepop[0]] = rangepop[0]
            pop[j][pop[j] > rangepop[1]] = rangepop[1]
            fitness[j] = function(pop[j])
        #其他个体的位置更新方式
        else:
            #当前个体被其他适应度值优于自身的个体所吸引,然后进行位置移动
            for q in range(m):
                if fitness[q]<fitness[j]:
                    d = distance(pop[j],pop[q])
                    belta = belta0 * np.exp((-gama) * (d ** 2))
                    pop[j] = pop[j] + belta * (pop[q] - pop[j]) + alpha * (np.random.rand()-0.5)
                    # 确保更新后的位置在取值范围内
                    pop[j][pop[j] < rangepop[0]] = rangepop[0]
                    pop[j][pop[j] > rangepop[1]] = rangepop[1]
                    fitness[j] = function(pop[j])
        # 更新种群历史最优解以及对应的适应度值
        if fitness[j] < bestfit:
            bestfit = fitness[j]
            bestpop = pop[j]
    # 存储当前迭代时的种群历史最优适应度值
    bestfitness[i] = bestfit
    print("The historical best fitness is:",bestfitness[i])
print("After iteration, the best individual is:",bestpop)
print("After iteration, the best fitness is:",bestfit)
#输出训练后种群个体适应度值的均值与标准差
mean = np.sum(fitness)/m
std = np.std(fitness)
print("After iteration, the mean fitness of the swarm is:","%e"%mean)
print("After iteration, the std fitness of the swarm is:","%e"%std)

#将结果进行绘图
fig=plt.figure(figsize=(12, 10), dpi=300)
plt.rcParams['font.sans-serif']=['Arial Unicode MS']
plt.title('最优适应度值的变化情况',fontdict={'weight':'normal','size': 30})
x=range(1,101,1)
plt.plot(x,bestfitness,color="red",label="FA",linewidth=3.0, linestyle="-")
plt.tick_params(labelsize=25)
plt.xlim(0,101)
plt.yscale("log")
plt.xlabel("迭代次数",fontdict={'weight':'normal','size': 30})
plt.ylabel("适应度值",fontdict={'weight':'normal','size': 30})
plt.xticks(range(0,101,10))
plt.savefig("FA.png")
plt.show()

图中横轴为迭代次数,纵轴为最优适应度值。

参考源码

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2023年11月13日
下一篇 2023年11月13日

相关推荐