2024年最新智能优化算法——差分进化算法(Python实现)


1 引言


在遗传、选择和变异的作用下,自然界生物体优胜劣汰,不断由低级向高级进化和发展。人们注意到,适者生存的进化规律可以模式化,从而构成一些优化算法;近年来发展的进化计算类算法受到了广泛的关注。

**差分进化算法(Differential Evolution, DE)**是一种新兴的进化计算技术"。

它是由Storn等人于1995年提出的,其最初的设想是用于解决切比雪夫多项式问题,后来发现它也是解决复杂优化问题的有效技术。**差分进化算法是基于群体智能理论的优化算法,是通过群体内个体间的合作与竞争而产生的智能优化搜索算法。**但相比于进化计算,它保留了基于种群的全局搜索策略,采用实数编码、基于差分的简单变异操作和“一对一”的竞争生存策略,降低了进化计算操作的复杂性。同时,差分进化算法特有的记忆能力使其可以动态跟踪当前的搜索情况,以调整其搜索策略,它具有较强的全局收敛能力和稳健性,且不需要借助问题的特征信息,适用于求解一些利用常规的数学规划方法很难求解甚至无法求解的复杂优化问题。因此,差分进化算法作为一种高效的并行搜索算法,对其进行理论和应用研究具有重要的学术意义和工程价值。

目前,差分进化算法已经在许多领域得到了应用,如人工神经元网络、电力、机械设计、机器人、信号处理、生物信息、经济学、现代农业和运筹学等。然而,尽管差分进化算法获得了广泛研究,但相对于其他进化算法而言,其研究成果相当分散,缺乏系统性,尤其在理论方面还没有重大突破。

2 差分进化法原理


差分进化算法是一种随机的启发式搜索算法,简单易用,有较强的鲁棒性和全局寻优能力。它从数学角度看是一种随机搜索算法,从工程角度看是一种自适应的迭代寻优过程。除了具有较好的收敛性外,差分进化算法非常易于理解与执行,它只包含不多的几个控制参数,并且在整个迭代过程中,这些参数的值可以保持不变。

差分进化算法是一种自组织最小化方法,用户只需很少的输入。它的关键思想与传统进化方法不同:传统方法是用预先确定的概率分布函数决定向量扰动;而差分进化算法的自组织程序利用种群中两个随机选择的不同向量来干扰一个现有向量,种群中的每一个向量都要进行干扰。差分进化算法利用一个向量种群,其中种群向量的随机扰动可独立进行,因此是并行的。如果新向量对应函数值的代价比它们的前辈代价小,它们将取代前辈向量。同其他进化算法一样, 差分进化算法也是对候选解的种群进行操作,但其种群繁殖方案与其他进化算法不同:它通过把种群中两个成员之间的加权差向量加到第三个成员上来产生新的参数向量,该操作称为**“变异”;然后将变异向量的参数与另外预先确定的目标向量参数按一定规则混合来产生试验向量,该操作称为“交叉”**;最后,若试验向量的代价函数比目标向量的代价函数低,试验向量

就在下一代中代替目标向量,该操作称为**“选择”**。种群中所有成员必须当作目标向量进行一次这样的操作,以便在下一代中出现相同个数竞争者。在进化过程中对每一代的最佳参数向量都进行评价,以记录最小化过程。这样利用随机偏差扰动产生新个体的方式,可以获得一个收敛性非常好的结果,引导搜索过程向全局最优解逼近。

3 差分进化法特点


差分进化算法从提出到现在,在短短二十几年内人们对其进行了广泛的研究并取得了成功的应用。该算法主要有如下特点:.

(1)结构简单,容易使用。差分进化算法主要通过差分变异算子来进行遗传操作,由于该算子只涉及向量的加减运算,因此很容易实现;该算法采用概率转移规则,不需要确定性的规则。此外,差分进化算法的控制参数少,这些参数对算法性能的影响已经得到- -定的研究,并得出了一些指导性的建议,因而可以方便使用人员根据问题选择较优的参数设置。

(2)性能优越。差分进化算法具有较好的可靠性、高效性和鲁棒性,对于大空间、非线性和不可求导的连续问题,其求解效率比其他进化方法好,而且很多学者还在对差分进化算法继续改良,以不断提高其性能。

(3)自适应性。差分进化算法的差分变异算子可以是固定常数,也可以具有变异步长和搜索方向自适应的能力,根据不同目标函数进行自动调整,从而提高搜索质量。

(4)差分进化算法具有内在的并行性,可协同搜索,具有利用个体局部信息和群体全局信息指导算法进一步搜索的能力。在同样精度要求下,差分进化算法具有更快的收敛速度。

(5)算法通用,可直接对结构对象进行操作,不依赖于问题信息,不存在对目标函数的限定。差分进化算法操作十分简单,易于编程实现,尤其利于求解高维的函数优化问题。

4 操作程序


基本差分进化算法的操作程序如下:

(1)初始化;

(2)变异:

(3)交叉;

(4)选择;

(5)边界条件处理。

4.1 初始化

差分进化算法利用NP个维数为D的实数值参数向量,将它们作为每一代的

种群,每个个体表示为:

X_{iG})(i=1 ,2.,…NP)

式中: i表示个体在种群中的序列: G表示进化代数: NP表示种群规模,在最小化过程中NP保持不变。

为了建立优化搜索的初始点,种群必须被初始化。通常,寻找初始种群的一个方法是从给定边界约束内的值中随机选择。在差分进化算法研究中,一般假定所有随机初始化种群均符合均匀概率分布。 rand[0, 1]表示在[0,1]之间产生的均匀随机数。如果可以预先得到问题的初步解,则初始种群也可以通过对初步解加入正态分布随机偏差来产生,这样可以提高重建效果。

4.2 变异

对于每个目标向量X_{iG})(i=1, 2, .,. NP),基本差分进化算法的变异向量由

下式产生:

v_{i,G+1}=x_{r1,G}+F(x_{r2,G}-x_{r3,G})

式中:随机选择的序号小r2和r3互不相同,且r1、r2和r3与目标向量序号i也应不同,所以必须满足NP≥4;变异算子F∈[0, 2]是一个实常数因数,它控制偏差变量的放大作用。

4.3 交叉

4.4 选择

为决定试验向量u_{i,G+1}是否会成为下一-代中的成员,差分进化算法按照贪婪准则将试验向量与当前种群中的目标向量x_{i,G})进行比较。如果目标函数要被最小化,那么具有较小目标函数值的向量将在下一代种群中出现。下一代中的所

有个体都比当前种群的对应个体更佳或者至少一样好。注意:在差分进化算法选择程序中,试验向量只与一个个体相比较,而不是与现有种群中的所有个体相比较。

4.5 边界条件处理

5 自适应差分进化算法


作为一种高效的并行优化算法,差分进化算法发展很快,出现了很多改进的

差分进化算法。下面介绍一种具有自适应算子的差分进化算法。

基本差分进化算法在搜索过程中变异算子取实常数,实施中变异算子较难确定:变异率太大,算法搜索效率低下,所求得的全局最优解精度低;变异率太小,种群多样性降低,易出现“早熟”现象。因此可设计具有自适应变异算子的差分进化算法,根据算法搜索进展情况,自适应变异算子可设计如下:

式中: Fo 表示变异算子,Gm表示最大进化代数,G表示当前进化代数。在算法开始时自适应变异算子为2Fo,具有较大值,在初期保持个体多样性,避免“早熟”;随着算法的进展,变异算子逐步降低,到后期变异率接近Fo,保留优良信息,避免最优解遭到破坏,增加搜索到全局最优解的概率。还可设计一个随机范围的交叉算子CR: 0.5x[1 + rand(0,1)],这样交叉算子的

平均值保持在0.75,考虑到了差分向量放大中可能的随机变化,有助于在搜索过程中保持群体多样性。

6 差分进化算法流程



差分进化算法采用实数编码、基于差分的简单变异操作和“一对一”的竞争

生存策略,其具体步骤如下:

(1)确定差分进化算法的控制参数和所要采用的具体策略。差分进化算法的控制参数包括:种群数量、变异算子、交叉算子、最大进化代数、终止条件等。

(2)随机产生初始种群,进化代数k=1。

(3)对初始种群进行评价,即计算初始种群中每个个体的目标函数值。

(4)判断是否达到终止条件或达到最大进化代数:若是,则进化终止,将此时的最佳个体作为解输出;否则,继续下一步操作 。

(5)进行变异操作和交叉操作,对边界条件进行处理,得到临时种群。

(6)对临时种群进行评价,计算临时种群中每个个体的目标函数值。

(7)对临时种群中的个体和原种群中对应的个体,进行“一对一”的选择操

作,得到新种群。

(8)进化代数k=k+ 1,转步骤(4)

差分进化算法运算流程如上图所示。

7 案例1


7.1 案例

7.2 Python实现

import numpy as np

import matplotlib.pyplot as plt

from pylab import *

mpl.rcParams[‘font.sans-serif’] = [‘SimHei’]

mpl.rcParams[‘axes.unicode_minus’] = False

#=适应度函数=

def func1(x):

SUM = [i * i for i in x]

return np.sum(SUM)

#初始化======

NP = 50 # 个体数目

D = 10 # 变量的维数

G = 200 # 最大进化代数

F0 = 0.4 # 初始变异算子

CR = 0.1 # 交叉算子

Xs = 20; # 上限

Xx = -20 # 下限

yz = 10e-6 # 阈值

ob = np.zeros(NP) # 存放个体目标函数值(父辈)

ob1 = np.zeros(NP) # 存放个体目标函数值(子代)

#=赋初值=========

x = np.zeros((NP, D)) # 初始种群 (个体数目,维数)

v = np.zeros((NP, D)) # 变异种群 (个体数目,维数)

u = np.zeros((NP, D)); # 选择种群 (个体数目,维数)

x = np.random.uniform(Xx, Xs, (NP, D)) # 赋初值 (xx-xs之间的随机数 ,(个体数目,维数)

trace = [] # 记录每次迭代的最小适应值

#=计算当前群体个体目标函数值

for i in range(NP): # 遍历每一个个体

ob[i] = func1(x[i, :])

trace.append(np.min(ob))

#差分进化循环=======

for gen in range(G): # 遍历每一代

#=变异操作====

#自适应变异算子=

lambda1 = np.exp(1 - G / (G + 1 - gen))

F = F0 * np.power(2, lambda1)

#=r1,r2,r3和m互不相同=

for m in range(NP): # 遍历每一个个体

r1=np.random.randint(0,NP,1)

while r1==m: #r1不能取m

r1 = np.random.randint(0, NP, 1)

r2=np.random.randint(0,NP,1)

while (r2m) or (r2r1): #r2不能取m 和r1

r2 = np.random.randint(0, NP, 1)

r3 = np.random.randint(0, NP, 1)

while (r3m) or (r3r2) or (r3==r1):#r3不能取m,r2,r1

r3 = np.random.randint(0, NP, 1)

v[m,:]=x[r1,:]+F*(x[r2,:]-x[r3,:]) #v.shape =(50, 10) 存放的是变异后的种群

#交叉操作===

r = np.random.randint(0, D, 1) #随机选择维度 (即选择x的一维)

for n in range(D):#遍历每一个维度

cr=np.random.random() #生成一个0-1之间的随机数

if (cr<CR) or (n==r):#如果随机数小于交叉算子 或者 当前维数 等于r

u[:,n]=v[:,n] #则选择群体个体维数 为变异后的维数

else:

u[:, n]=x[:,n] #为原始维度

#=边界条件处理===

for m in range(NP):#遍历每一个个体

for n in range(D): # 遍历每一个维度

if (u[m,n]<Xx) or (u[m,n]>Xs):#如果当前元素不处于最大值和最小值之间

u[m, n]=np.random.uniform(Xx, Xs)#则重新初始化该元素

#选择操作=

for m in range(NP):#遍历每一个个体

ob1[m]=func1(u[m,:]) #计算子代个体适应度值

for m in range(NP): # 遍历每一个个体

if ob1[m]<ob[m]:#如果子代个体适应度值小于父代个体适应度值

x[m,:]=u[m,:]#则替换个体

for m in range(NP): # 遍历每一个个体

ob[m]=func1(x[m,:]) #修改父代适应度值

trace.append(min(ob))#记录当代最优适应度值

index=np.argmin(ob)#取出最小值所在位置索引

print(‘最优值解\n’,x[index,:])

print(‘最优值\n’,func1(x[index,:]))

plt.plot(trace)

plt.title(‘迭代曲线’)

plt.show()

7.3 结果

最优值解

[-5.89325075e-04 7.66296863e-04 -8.03461860e-04 4.19070900e-04

5.02012066e-04 2.78923440e-04 6.83655920e-04 3.75556622e-04

-5.35755777e-05 3.49538162e-04]

最优值

2.81897616751295e-06

8 案例2


8.1 案例

求函数f(x, y) = 3cos(xy) +x +y的最小值,其中x的取值范围为[-4,4], y的取值范围为[-4, 4]。 这是一个有多个局部极值的函数。

8.2 代码

import numpy as np

import matplotlib.pyplot as plt

from pylab import *

mpl.rcParams[‘font.sans-serif’] = [‘SimHei’]

mpl.rcParams[‘axes.unicode_minus’] = False

#=适应度函数=

def func2(x):

value = 3 * np.cos(x[0] * x[1]) + x[0] + x[1]

return value

#初始化

NP=20 #个体数目

D=2 #变量的维数

G=12 #最大进化代数

F=0.5 #变异算子

CR=0.1 #交叉算子

Xs=4 #上限

Xx=-4 #下限

ob = np.zeros(NP) # 存放个体目标函数值(父辈)

ob1 = np.zeros(NP) # 存放个体目标函数值(子代)

#赋初值====

x = np.zeros((NP, D)) # 初始种群 (个体数目,维数)

v = np.zeros((NP, D)) # 变异种群 (个体数目,维数)

u = np.zeros((NP, D)); # 选择种群 (个体数目,维数)

x = np.random.uniform(Xx, Xs, (NP, D)) # 赋初值 (xx-xs之间的随机数 ,(个体数目,维数)

trace = [] # 记录每次迭代的最小适应值

#=计算当前群体个体目标函数值

for i in range(NP): # 遍历每一个个体

ob[i] = func2(x[i, :])

trace.append(np.min(ob))

#==差分进化循环

for gen in range(G): # 遍历每一代

#=变异操作=

#=r1,r2,r3和m互不相同

for m in range(NP): # 遍历每一个个体

r1 = np.random.randint(0, NP, 1)

while r1 == m: # r1不能取m

r1 = np.random.randint(0, NP, 1)

r2 = np.random.randint(0, NP, 1)

while (r2 == m) or (r2 == r1): # r2不能取m 和r1

r2 = np.random.randint(0, NP, 1)

r3 = np.random.randint(0, NP, 1)

while (r3 == m) or (r3 == r2) or (r3 == r1): # r3不能取m,r2,r1

r3 = np.random.randint(0, NP, 1)

v[m, :] = x[r1, :] + F * (x[r2, :] - x[r3, :]) # v.shape =(20, 2) 存放的是变异后的种群

#交叉操作=

r = np.random.randint(0, D, 1) # 随机选择维度 (即选择x的一维)

for n in range(D): # 遍历每一个维度

cr = np.random.random() # 生成一个0-1之间的随机数

if (cr < CR) or (n == r): # 如果随机数小于交叉算子 或者 当前维数 等于r

u[:, n] = v[:, n] # 则选择群体个体维数 为变异后的维数

else:

u[:, n] = x[:, n] # 为原始维度

#=边界条件处理====

for m in range(NP): # 遍历每一个个体

for n in range(D): # 遍历每一个维度

if (u[m, n] < Xx) or (u[m, n] > Xs): # 如果当前元素不处于最大值和最小值之间

u[m, n] = np.random.uniform(Xx, Xs) # 则重新初始化该元素

#选择操作=

for m in range(NP): # 遍历每一个个体

ob1[m] = func2(u[m, :]) # 计算子代个体适应度值

for m in range(NP): # 遍历每一个个体

if ob1[m] < ob[m]: # 如果子代个体适应度值小于父代个体适应度值

x[m, :] = u[m, :] # 则替换个体

for m in range(NP): # 遍历每一个个体

ob[m] = func2(x[m, :]) # 修改父代适应度值

trace.append(min(ob)) # 记录当代最优适应度值

index=np.argmin(ob)#取出最小值所在位置索引

print(‘最优值解\n’,x[index,:])

print(‘最优值\n’,func2(x[index,:]))

plt.plot(trace)

plt.title(‘迭代曲线’)

plt.show()

8.3 结果

最优值解

[-3.92989959 -3.99847196]

最优值

-10.92832400647969

9 案例3——离散差分算法


9.1 案例

用离散差分进化算法求函数f(x,y)=-[(x{2}+y-1){2}+(x+y{2}-7){2}]/200+10的最大值,其中x的取值为- 100~ 100之间的整数, y的取值为一100~ 100之间的整数。

9.2 Python实现

import numpy as np

import matplotlib.pyplot as plt

from pylab import *

mpl.rcParams[‘font.sans-serif’] = [‘SimHei’]

mpl.rcParams[‘axes.unicode_minus’] = False

#=适应度函数=====

def func3(x):

value=-(np.power(x[0]*x[0]+x[1]-1,2)+np.power(x[0]+x[1]*x[1]-7,2)/200)+10

return value

#print(func3([-2,-3]))

#初始化=======

NP=20 #个体数目

D=2 #变量的维数

G=100 #最大进化代数

F=0.5 #变异算子

CR=0.1 #交叉算子

Xs=100 #上限

Xx=-100 #下限

ob = np.zeros(NP) # 存放个体目标函数值(父辈)

ob1 = np.zeros(NP) # 存放个体目标函数值(子代)

#赋初值===

x = np.zeros((NP, D)) # 初始种群 (个体数目,维数)

v = np.zeros((NP, D)) # 变异种群 (个体数目,维数)

u = np.zeros((NP, D)); # 选择种群 (个体数目,维数)

x = np.random.randint(Xx, Xs, (NP, D)) # 赋初值 (xx-xs之间的随机整数 ,(个体数目,维数)

trace = [] # 记录每次迭代的最大适应值

#======计算当前群体个体目标函数值

for i in range(NP): # 遍历每一个个体

ob[i] = func3(x[i, :])

trace.append(np.max(ob))

#==差分进化循环=

for gen in range(G): # 遍历每一代

#变异操作====

#===r1,r2,r3和m互不相同=

for m in range(NP): # 遍历每一个个体

r1 = np.random.randint(0, NP, 1)

while r1 == m: # r1不能取m

r1 = np.random.randint(0, NP, 1)

r2 = np.random.randint(0, NP, 1)

while (r2 == m) or (r2 == r1): # r2不能取m 和r1

r2 = np.random.randint(0, NP, 1)

r3 = np.random.randint(0, NP, 1)

while (r3 == m) or (r3 == r2) or (r3 == r1): # r3不能取m,r2,r1

r3 = np.random.randint(0, NP, 1)

v[m, :] = np.floor(x[r1, :] + F * (x[r2, :] - x[r3, :]))

v.shape =(20, 2) 存放的是变异后的种群 np.floor 向下取整

#交叉操作=

r = np.random.randint(0, D, 1) # 随机选择维度 (即选择x的一维)

for n in range(D): # 遍历每一个维度

cr = np.random.random() # 生成一个0-1之间的随机数

if (cr < CR) or (n == r): # 如果随机数小于交叉算子 或者 当前维数等于r

u[:, n] = v[:, n] # 则选择群体个体维数 为变异后的维数

else:

u[:, n] = x[:, n] # 为原始维度

#=边界条件处理==

在这里插入图片描述

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值