单目标优化算法——差分进化算法(DE)+matlab代码

76 阅读6分钟

Differential Evolution – A Simple and Efficient Heuristic for Global Optimization over Continuous Spaces(差分进化——一种简单有效的连续空间全局优化启发式方法)

一、算法简介

DE一种新的启发式算法,用于最小化可能非线性和不可微的连续空间函数。通过广泛的试验台,证明了新方法比许多其他广受好评的全局优化方法收敛更快、更确定。新方法需要很少的控制变量,鲁棒性强,易于使用,非常适合并行计算

在自然界中,遗传,变异,选择的作用,使得生物体优胜略汰,不断由低级向高级进化,人们发现适者生存这一规律可以模式化,从而构成一些列优化算法。差分进化算法就是从这种模式中产生的一种智能优化算法。差分进化算法是基于群体智能理论的优化算法,与进化算法相比,保留了基于种群的全局搜索策略,采用实数编码,基于差分的简单变异操作和“一对一”的竞争生存策略。降低了操作的复杂性,差分进化算法特有的记忆能力使其可以动态的跟踪当前的搜索情况,以调整其搜索策略,具有较强的收敛能力和稳健性,且不需要借助问题的特征信息。适用于求解一些利用常规的数学规划方法很难求解,甚至无法求解的复杂优化问题。

二、DE算法原理

对候选解的种群进行操作,主要包含以下几个主要操作:

  • 种群初始化

  • 变异(突变):通过把种群中两个成员之间的加权差向量加到第三个成员上来产生新的参数向量

  • 交叉:将变异向量的参数与另外预先确定的目标向量参数按照一定的规则混合来产生试验向量。

  • 选择 :如果试验向量的目标函数比目标向量的代价函数低,那么就利用试验向量替换掉目标向量。

三、DE算法流程

算法流程图

  1. 种群初始化种:

​ 群中的个体可以表示为:(种群大小为NP)

xi,G,i=1,2,...,NPx_{i,G},i=1,2,...,NP
 **其中,i 表示个体在种群中的编号,G表示进化代数,NP代表种群规模。**
  • NP 越大,说明个体越多,种群多样性越好,寻优能力也越强,但同时也增加了计算难度。所以NP不能无限取大。

    一般取 5*D ≤ NP ≤ 10 * D 之间,必须满足的是 NP ≥ 4 ,因为只有NP大于4,才能有空间进行变异和杂交。

  1. **变异:**对于每个目标向量:
    xi,G,i=1,2,...,NPx_{i,G},i=1,2,...,NP
    都需要依据以下公式来生成突变向量:
    vi,G+1=xr1,G+F(xr2,Gxr3,G)v_{i,G+1}=x_{r_1,G}+F·(x_{r_2,G}-x_{r_3,G})
  • 说明:

    r1,r2 ,r3 :

    其中r1,r2 ,r3 ∈ {1,2, ... , NP}且互不相同,并且都是不同于i的整数

    F:

    F是一个正实数,F>0,且F∈[0,2],控制差分变化的放大倍数,取(0,1)时V减小,取(1,2)时放大

    • F如果太小,容易“早熟”,即陷入局部最优解。
    • 目前研究表面标明,F 小于0.4和 F大于1的值仅偶尔有效,通常,F=0.5是一个较好的初始选择。如果种群收敛过早,那么应该增大F或NP。
    • F如果太大,不容易“收敛”。当F>1的时候,算法收敛到最优值变得十分困难,因为差分向量的扰动已经大于两个个体之间的距离了。

    以下是一个二维向量进行突变的例子: image-20241029212958627.png

  1. 交叉:为了增加扰动参数向量的多样性,引入了交叉
ui,G+1=(u1i,G+1,u2i,G+1,...,uDi,G+1)u_{i,G+1}=(u_{1i,G+1},u_{2i,G+1},...,u_{Di,G+1})

​ 公式如下: image.png

  • 说明:

    **randb(j)**是第j次随机生成的一个∈[0,1]的数。

    **rnbr(i)**是随机选择索引,rnbr(i)∈1,2,3,...,D,确保Ui,G+1至少有一个参数来自于Vi,G+1。

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

    以下是D=7时的例子:

image.png

  1. 选择:采用贪婪准则

    为了决定它是否应该成为G+1代的成员,使用贪婪准则将试验向量Ui,G+1与目标向量Xi,G进行比较。如果向量Ui,G+1的代价函数值小于Xi,G,则将Xi,G设为Ui,G+1;否则,保留旧值Xi,G

四、DE算法的其它变体

上述方案并不是已被证明有用的DE的唯一变体。为了对不同的变体进行分类,在其中引入了符号:DE/x/y/z

x表示目标向量的选择方式,可以是“rand”(随机选择的种群向量)或“best”(当前种群中成本函数值最小的向量)。 y表示执行差分操作的向量的个数。 z表示执行交叉操作的方式。目前的变体为“bin”

DE/best/2/bin方法效果更好: image-20241101163003900.png

五、边界条件处理

对于这一类的算法,通常会对种群中的个体执行一些列的操作(如交叉,变异),这会导种群中个体的范围(即决策变量的范围)超出给定的范围,所以需要对上述操作后所得到种群进行边界条件检查和处理,对于边界之外的个体一般有两种处理方法:

  1. **边界吸收:**假设x的范围是x_max, x_min, x'是经过变异或者交叉操作后所得的新的个体:则新个体的边界检查和处理规则为:

img

  1. 重新随机生成新的个体:

img

六、实例测试

f=x12+x22+x32+...+xn2f=x_1^2+x_2^2+x_3^2+...+x_n^2
close all;
clear all;
clc;
NP=50;		%种群中个体的数量
D=10;       %个体维数
G=200;		%代数
F0=0.4;
CR=0.1;
a=-20;     % 寻优区间
b=20;
yz=10^-6;
 
x=zeros(NP,D);    % 初始种群
v=zeros(NP,D);    % 变异种群
u=zeros(NP,D);    % 选择种群
%   种群赋初值
x=rand(NP,D)*(b-a)+a;
%   计算目标函数
for i=1:1:NP
    ob(i)=sum(x(i,:).^2);  
end
trace(1)=min(ob);
%   差分进化循环
for gen=1:G
    %   变异操作
    for m=1:NP
        r1=randi([1,NP],1,1);
        while(r1==m)
            r1=randi([1,NP],1,1);
        end
        
        r2=randi([1,NP],1,1);
        while(r2==r1)||(r2==m)
            r2=randi([1,NP],1,1);
        end
        
        r3=randi([1,NP],1,1);
        while(r3==m)||(r3==r2)||(r3==r1)
            r3=randi([1,NP],1,1);
        end
        %  产生不同的r1,r2,r3
        
        v(m,:)=x(r1,:)+F0*(x(r2,:)-x(r3,:));
 
    end
    
    %   交叉操作
    r=randi([1,D],1,1);   % 这个变异是针对整个种群的变异,不针对单个个体
    for n=1:D
        cr=rand;
        if (cr<=CR)||(n==r)
            u(:,n)=v(:,n);
        else
            u(:,n)=x(:,n);
        end
    end
    %     边界条件处理
    for m=1:NP
        for n=1:D
            if u(m,n)<a
                u(m,n)=a;
            end
            if u(m,n)>b
                u(m,n)=b;
            end
        end
    end
    % 自然选择
    % 计算新的适应度
    for m=1:NP
        ob_1(m)=sum(u(m,:).^2);
    end
    
    for m=1:NP
        if ob_1(m)<ob(m)
            x(m,:)=u(m,:);
        else
            x(m,:)=x(m,:);
        end
        
    end
    % 现在x为经过选择后的种群
    for m=1:NP
        ob(m)=sum(x(m,:).^2);
    end
    
    trace(gen+1)=min(ob);
    tt=min(ob);
end
 
x(1,:);
 
figure(1);
title(['差分进化算法(DE)', '最小值: ', num2str(tt)]);
xlabel('迭代次数'); 
ylabel('目标函数值');
plot(trace);

运行结果:

image-20241101193435429.png