在这里插入图片描述

作者:非妃是公主
专栏:《智能优化算法》
博客地址https://blog.csdn.net/myf_666
个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩
在这里插入图片描述

专栏推荐

专栏名称专栏地址
软件工程专栏——软件工程
计算机图形学 专栏——计算机图形学
操作系统专栏——操作系统
软件测试专栏——软件测试
机器学习专栏——机器学习
数据库专栏——数据库
算法专栏——算法

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


一、概论

差分进化算法(Differential Evolution,DE)是一种新兴的进化计算技术。在1995年,由Storn等人提出用来解决切比雪夫多项式问题,后来发现它也是解决复杂优化问题的有效技术。

差分进化算法和遗传算法很相似,也是一种基于群体智能理论的优化算法,通过群体内个体间的合作与竞争而产生的全局搜索策略,采用实数编码、基于差分的简单变异操作和“一对一”的竞争生存策略,降低了进化计算操作的复杂性。

同时,差分进化算法具有记忆能力使其可以动态跟踪当前的搜索情况,以调整其搜索策略,具有较强的全局收敛能力和稳健性,且不需要借助问题的特征信息,适用于求解一些利用常规的数学规划方法很难求解,甚至无法求解的复杂优化问题。


二、差分进化算法(DE)原理

同其它进化算法一样(尤其和遗传算法,具有很强的相似性),差分进化算法,也是对候选解的种群进行操作,具体地说,它包含了三个主要的操作:

  • 变异:通过把种群中两个成员之间的加权差向量加到第三个成员上来产生新的参数向量,该操作称为“变异”;
  • 交叉:将变异向量的参数与另外预先确定的目标向量参数按照一定的规则混合来产生试验向量。
  • 选择:如果试验向量的目标函数比目标向量的代价函数低,那么就利用试验向量替换掉目标向量。

种群中所有成成员必须要当作目标向量进行一次这样的操作,以便在下一代中出现相同个数的竞争者。在进化过程中,对每一代的向量都进行评价,记录最小化过程。

这种利用随机偏差扰动产生新个体的方式,可以获得一个收敛性非常好的结果,引导搜索过程向全局最优解逼近。


三、差分进化算法的优点

差分进化算法从提出到现在,短短二十几年的时间,取得了很多成功的应用。它具有以下优点:

  • 结构简单,容易使用。一个是很容易实现,变异操作只涉及了向量的加减运算。再有就是算法的控制参数较少,这些参数对算法的性能影响已经有了一定的研究,可以供参考,因此,使用起来十分方便。
  • 性能优越。差分进化算法具有较好的可靠性、高效性、鲁棒性。对于大空间、非线性和不可求导的连续问题,其求解速率比其他进化方法好,而且很多学者还在对差分进化算法继续改良,以不断提高其性能。
  • 自适应性。差分变异算子可以根据不同的目标函数进行调整,从而提高搜索质量。
  • 存在内在的并行性,可协同搜索。它具有利用个体局部信息和群体全局信息指导算法进一步搜索的能力。
  • 算法通用,可直接对结构对象进行操作,不依赖于问题信息,不存在对目标函数的限定。比如许多问题是高维的,甚至是不可求导的,在这种情况下,使用差分进化算法就十分简单并不会增加求解的复杂性,而如果使用其它算法,很可能使得求解变得十分复杂。

四、算法具体流程

学习的过程是广度优先,层层深入的,前面大致了解了差分进化算法的原理及思想,下面我们看一看差分进化算法的具体算法流程。


1. 整体流程

  1. 初始化;
  2. 变异;
  3. 交叉;
  4. 选择;
  5. 边界条件处理。

算法流程图如下:

在这里插入图片描述

Ⅰ. 初始化

初始化就是给种群中的每个个体的每个维度进行一个赋值,实现一个初始化的操作。每个个体表示如下:

x i , G ( i = 1 , 2 , . . . , N P ) x_{i,G}(i=1,2,...,NP) xi,G(i=1,2,...,NP)

其中, i i i 表示个体在种群中的编号, G G G 表示进化代数, N P NP NP 代表种群规模。

在差分进化算法中,一般假定所有随机初始化种群均符合均匀分布。设参数变量的界限为 x j ( L ) < x j < x j U x_j^{(L)}<x_j<x_j^{U} xj(L)<xj<xjU,则 x j i , 0 = r a n d [ 0 , 1 ] × ( x j ( U ) − x j ( L ) ) + x j L x_{ji,0}=rand[0,1] \times (x_j^{(U)}-x_j^{(L)})+x_j^{L} xji,0=rand[0,1]×(xj(U)xj(L))+xjL

其中, r a n d [ 0 , 1 ] rand[0,1] rand[0,1]表示在 [ 0 , 1 ] [0,1] [0,1]之间产生均匀的实数

当然,均匀产生随机数只是一种可能,如果可以预先知道解的概率分布,就不需要均匀产生,可以通过其分布规律,产生涵盖更多信息的解,进而提高重建效果。

Ⅱ. 变异

产生完初始种群后,进行变异操作,对于每个目标 x i , G ( i = 1 , 2 , . . . , N P ) x_{i,G}(i=1,2,...,NP) xi,G(i=1,2,...,NP),基本差分进化算法的变异向量产生方式如下:

v i , G + 1 = x r 1 , G + F ⋅ ( x r 2 , G − x r 3 , G ) v_{i,G+1}=x_{r_1,G}+F\cdot(x_{r_2,G}-x_{r_3,G}) vi,G+1=xr1,G+F(xr2,Gxr3,G)

其中,要求随机选择的个体序号 r 1 , r 2 , r 3 r_1,r_2,r_3 r1,r2,r3互不相同,且与目标向量序号 i i i也不能相同,所以必须满足 N P ≥ 4 NP\geq4 NP4

变异算子 F ∈ [ 0 , 2 ] F\in[0,2] F[0,2]是一个实常数因数,它控制偏差变量的缩放。

Ⅲ. 交叉

这一步进行变异向量和目标向量的总体交叉。为了增加干扰参数向量的多样性,引入交叉操作,测试向量变为:

u i , G + 1 = ( u 1 i , G + 1 , u 2 i , G + 1 , . . . , u D i , G + 1 ) u_{i,G+1}=(u_{1_i,G+1},u_{2_i,G+1},...,u_{D_i,G+1}) ui,G+1=(u1i,G+1,u2i,G+1,...,uDi,G+1)

u j i , G + 1 = { v j i , G + 1 若 randb(j) <= CR 或 j = rnbr(i) x j i , G + 1 若 x != 0 且 j != rnbr(i) u_{ji,G+1}= \begin{cases} v_{ji,G+1}& \text{若 randb(j) <= CR 或 j = rnbr(i)}\\ x_{ji,G+1}& \text{若 x != 0 且 j != rnbr(i)} \end{cases} uji,G+1={vji,G+1xji,G+1 randb(j) <= CR  j = rnbr(i) x != 0  j != rnbr(i)

其中, r a n d b ( j ) randb(j) randb(j) 表示产生 [ 0 , 1 ] [0,1] [0,1] 之间的随机数发生器的第j个估计值。 r n b r ( i ) ∈ ( 1 , 2 , . . . , D ) rnbr(i) \in (1,2,...,D) rnbr(i)(1,2,...,D) 表示一个随机选择的序列(这个序列必然在 [ 1 , D ] [1,D] [1,D] 之间,因此必然会有一个与 j j j 相等),用它来确保 u i , G + 1 u_{i,G+1} ui,G+1 至少从 v i , G + 1 v_{i,G+1} vi,G+1 获得一个参数;CR 表示交叉算子(表示一个概率),其取值范围为 [ 0 , 1 ] [0,1] [0,1]

Ⅳ. 选择

经过上面的变异、交叉操作,差分进化算法按照贪婪准则将试验向量与当前种群中的目标向量 x i , G x_{i,G} xi,G 进行比较,在下一代中,如果目标向量好,就选择目标向量,如果试验向量好,就选择试验向量。

值得注意的实,试验向量只与目标向量进行个体比较,而不是现有种群中的所有个体(锦标赛选择)。

Ⅴ. 边界条件的处理

如果在变异过程中,我们编译出了可行域外的解(可以理解为函数变量的定义域),即: u j i , G + 1 < x j ( L ) u_{ji,G+1}<x_j^{(L)} uji,G+1<xj(L) u j i , G + 1 > x j U u_{ji,G+1}>x_j^{U} uji,G+1>xjU,那么

u j i , G + 1 = r a n d [ 0 , 1 ] ⋅ ( x j ( U ) − x j ( L ) ) + x j ( L ) ( i = 1 , 2 , . . . , N P ; j = 1 , 2 , . . . , D ) u_{ji,G+1}=rand[0,1] \cdot (x_j^{(U)}-x_j^{(L)})+x_j^{(L)} \quad \quad \quad (i=1,2,...,NP;j=1,2,...,D) uji,G+1=rand[0,1](xj(U)xj(L))+xj(L)(i=1,2,...,NP;j=1,2,...,D)


2. 细节处理

Ⅰ. 种群数量 N P NP NP

NP 越大,说明个体越多,种群多样性越好,寻优能力也越强,但同时也增加了计算难度。所以NP不能无限取大。一般取 5 D ≤ N P ≤ 10 D 5D\leq NP \leq10D 5DNP10D 之间,必须满足的是 N P ≥ 4 NP \geq 4 NP4,因为只有 NP 大于4,才能有空间进行变异和杂交。(这两个操作要求个体编号是不同的,也就是应该有3个不同的个体,但是如果NP恰好为3,那么就没有一点随机性可言了= =。)


Ⅱ. 变异算子 F F F

变异算子 F ∈ [ 0 , 2 ] F\in [0,2] F[0,2]是一个实常数因数,它决定偏差向量的放大比例。

  • 如果太小,容易“早熟”,即陷入局部最优解。
  • 如果太大,不容易“收敛”。当 F > 1 F>1 F>1 的时候,算法收敛到最优值变得十分困难,因为差分向量的扰动已经大于两个个体之间的距离了。

目前研究表面标明, F F F 小于 0.4 0.4 0.4 F F F 大于 1 1 1 的值仅偶尔有效,通常, F = 0.5 F=0.5 F=0.5是一个较好的初始选择。如果种群收敛过早,那么应该增大 F F F N P NP NP

Ⅲ. 交叉算子 C R CR CR

一个 [ 0 , 1 ] [0,1] [0,1] 之间的数,它控制着试验向量参数来自于随机选择的目标向量,还是变异向量。 C R CR CR 越大,发生交叉的可能性就越大, C R CR CR 的一个较好的选择实 0.1 0.1 0.1,但较大的 C R CR CR 通常会加速收敛。可以先尝试 C R = 0.9 CR=0.9 CR=0.9 C R = 1.0 CR=1.0 CR=1.0,查看是否可以快速产生一个快速解。

Ⅳ. 最大进化代数 G G G

最大进化代数 G G G 表示差分进化算法运行结束的一个参数,最多更新 G G G 代后就结束了,并将当前群体中最佳个体作为最优解输出。一般, 100 ≤ G ≤ 500 100\leq G \leq 500 100G500

Ⅴ. 终止条件

除最大进化代数可作为差分进化算法的终止条件外,还可以增加其他判定准则。一般当目标函数值小于阈值时程序终止,阈值常选为 1 0 − 6 10^{-6} 106


五、仿真实例:差分进化求解函数最小值

1. 题目

求解函数 f ( x ) = ∑ i = 1 n x i 2 ( − 20 ≤ x i ≤ 20 ) f(x)=\sum_{i=1}^n x_i^2 (-20\leq x_i \leq 20) f(x)=i=1nxi2(20xi20) 的最小值,其中个体 x x x 的维数 n = 10 n=10 n=10


2. 分析

这个案例和之前模拟退火以及遗传算法的案例是相同的,函数只有一个极小值点 x = ( 0 , 0 , . . . , 0 ) x=(0,0,...,0) x=(0,0,...,0),理论最小值 f ( 0 , 0 , . . . , 0 ) = 0 f(0,0,...,0)=0 f(0,0,...,0)=0

求解思路如下

  1. 初始化参数,各参数设置如下
参数名参数值
个体数 N P NP NP 50 50 50
维度 D D D 10 10 10
最大进化代数 G G G 200 200 200
变异算子 F 0 F_0 F0 0.4 0.4 0.4
交叉算子 C R CR CR 0.1 0.1 0.1
结束阈值 y z yz yz 1 0 − 6 10^{-6} 106
  1. 产生初始种群。
  2. 计算临时种群个体目标函数。并进行变异、交叉、选择。
  3. 判断是否满足终止条件:如果满足,结束;不满足,继续迭代。

3. matlab求解

matlab的求解源码如下:

%%%%%%%%%%%%%%%%%差分进化算法求函数极值%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;                            %清除所有变量
close all;                            %清图
clc;                                  %清屏
NP=50;                                %个体数目
D=10;                                 %变量的维数
G=200;                                %最大进化代数
F0=0.4;                               %初始变异算子
CR=0.1;                               %交叉算子
Xs=20;                                %上限
Xx=-20;                               %下限
yz=10^-6;                             %阈值
%%%%%%%%%%%%%%%%%%%%%%%%%赋初值%%%%%%%%%%%%%%%%%%%%%%%%
x=zeros(D,NP);                        %初始种群
v=zeros(D,NP);                        %变异种群
u=zeros(D,NP);                        %选择种群
x=rand(D,NP)*(Xs-Xx)+Xx;              %赋初值
   %%%%%%%%%%%%%%%%%%%%计算目标函数%%%%%%%%%%%%%%%%%%%%
for m=1:NP                            % 评价原始种群
    Ob(m)=func1(x(:,m));
end
trace(1)=min(Ob);                     % 跟踪原始种群中的最优个体
%%%%%%%%%%%%%%%%%%%%%%%差分进化循环%%%%%%%%%%%%%%%%%%%%%
for gen=1:G
    %%%%%%%%%%%%%%%%%%%%%%变异操作%%%%%%%%%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%%%%%自适应变异算子%%%%%%%%%%%%%%%%%%%
    lamda=exp(1-G/(G+1-gen));         % 自适应差分进化算法
    F=F0*2^(lamda);                   % 动态的设置的变异算子(交叉概率)
    %%%%%%%%%%%%%%%%%r1,r2,r3和m互不相同%%%%%%%%%%%%%%%%
    for m=1:NP
        r1=randi([1,NP],1,1);         % 变异操作,取r1
        while (r1==m)
            r1=randi([1,NP],1,1);     % 保证 r1!=m
        end
        r2=randi([1,NP],1,1);         % 变异操作,取r2
        while (r2==m)||(r2==r1)       % 保证r2!=m r2!=r1
            r2=randi([1,NP],1,1);
        end
        r3=randi([1,NP],1,1);         % 变异操作,取r3
        while (r3==m)||(r3==r1)||(r3==r2)   % 保证r3!=m r3!=r1 r3!=r2
            r3=randi([1,NP],1,1);
        end
        v(:,m)=x(:,r1)+F*(x(:,r2)-x(:,r3)); % 计算变异个体
    end
    %%%%%%%%%%%%%%%%%%%%%%交叉操作%%%%%%%%%%%%%%%%%%%%%%%
    r=randi([1,D],1,1);               % 取 r 防止 u == x
    for n=1:D                         % 遍历种群
        cr=rand(1);                   % 生成[0,1]随机数
        if (cr<=CR)||(n==r)           % 以CR的概率交叉(接受变异向量)
            u(n,:)=v(n,:);
        else
            u(n,:)=x(n,:);            % 不接受变异向量
        end
    end
    %%%%%%%%%%%%%%%%%%%边界条件的处理%%%%%%%%%%%%%%%%%%%%%
    for n=1:D                           % 遍历所有维度
        for m=1:NP                      % 遍历种群
            if (u(n,m)<Xx)||(u(n,m)>Xs) % 如果超过边界值
                u(n,m)=rand*(Xs-Xx)+Xx; % 重新生成
            end
        end
    end
    %%%%%%%%%%%%%%%%%%%%%%选择操作%%%%%%%%%%%%%%%%%%%%%%%
    for m=1:NP                       % 遍历新种群
        Ob1(m)=func1(u(:,m));        % 评价新种群的个体
    end
    for m=1:NP                       % 遍历种群
        if Ob1(m)<Ob(m)              % 进行锦标赛选择
            x(:,m)=u(:,m);           % 选择更优的
        end
    end  
    for m=1:NP                       % 遍历种群所有个体
        Ob(m)=func1(x(:,m));         % 重新评价种群所有个体
    end
    trace(gen+1)=min(Ob);            % 记录 G+1 代的最优值
    if min(Ob(m))<yz                 % 如果小于 yz 这个阈值,说明已经足够收敛了
        break                        % 那么就不再搜了
    end
end
[SortOb,Index]=sort(Ob);             % 对新种群个体的适应度进行排序,并获取它的索引
x=x(:,Index);                        % 获取 第 index 个个体
X=x(:,1)                               %最优变量,并打印输出
Y=min(Ob)                              %最优值,并打印输出
%%%%%%%%%%%%%%%%%%%%%%%%%画图%%%%%%%%%%%%%%%%%%%%%%%%%%
figure
plot(trace);
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')

func1(平方求和函数,目标函数),定义如下:

%%%%%%%%%%%%%%%%%%%%%%%适应度函数%%%%%%%%%%%%%%%%%%%%%%%%
function result=func1(x)
summ=sum(x.^2);
result=summ;

4. 求解结果及分析

适应度进化曲线如下:

在这里插入图片描述

求解的最优值,以及对应的最优解如下:

在这里插入图片描述


六、差分进化算法的一些改进方向

1. 自适应差分进化算法

对于变异算子 F F F的设置,可以采用如下模型:

λ = e 1 − G m G m + 1 − G , F = F 0 × 2 λ \lambda = e^{1-\frac{G_m}{G_m+1-G}}, F=F_0\times 2^\lambda λ=e1Gm+1GGm,F=F0×2λ

这个模型的好处是,在初期 F F F具有较大值为 2 F 0 2F_0 2F0,可以保持个体多样性,避免早熟,在后期变异率接近 F 0 F_0 F0,保留优良信息,避免最优解遭到破坏,增加全局最优解的概率。

还可以设计随机范围的交叉算子,比如 C R : 0.5 × [ 1 + r a n d ( 0 , 1 ) ] CR: 0.5\times[1+rand(0,1)] CR:0.5×[1+rand(0,1)],这样交叉算子的平均值维持在0.75附近,考虑到了差分向量放大中可能的随机变化,有助于在搜索过程中保持群体多样性。


2. 离散差分进化算法

我们上述采用的编码都是实数编码,如果对于整数规划等问题,还可以采用离散差分进化算法。主要思路很简单,就是将变异操作中的值进行取整(比如向下取整),模型如下1

v i , G + 1 = f l o o r [ x r 1 , G + F ⋅ ( x r 2 , G − x r 3 , G ) ] v_{i,G+1}=floor[x_{r_1,G}+F\cdot(x_{r2,G}-x_{r_3,G})] vi,G+1=floor[xr1,G+F(xr2,Gxr3,G)]

floor指向下取整的四舍五入方法。


the end……

差分进化算法到这里就要结束啦~~到此既是缘分,欢迎您的点赞评论收藏关注我,不迷路,我们下期再见!!

😘😘😘 我是Cherries,一位计算机科班在校大学生,写博客用来记录自己平时的所思所想!
💞💞💞 内容繁杂,又才疏学浅,难免存在错误,欢迎各位大佬的批评指正!
👋👋👋 我们相互交流,共同进步!

:本文由非妃是公主发布于https://blog.csdn.net/myf_666,转载请务必标明原文链接:https://blog.csdn.net/myf_666/article/details/129278838


  1. 包子阳,智能优化算法及其matlab实例.电子工业出版社. ↩︎

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐