差分进化算法原理及matlab代码实现

差分进化算法介绍:        

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

算法流程:

1. 初始化:(与遗传算法类似)

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

其中: i=1,2,....NP     

初始种群一般在给定的约束边界内随机生成

2. 变异

对于种群中每个个体,差分进化算法的变异向量按照下面的方式产生:

其中:在种群中随机选择且,参数,用于控制偏差的放大作用。

除此之外,偏差向量还可以由其他的方式产生:表示方法:DE/x/y/z,  x当前被变异的向量是随机的还是最优的,y差向量的个数,z交叉程序的操作方法(bin)

DE/best/1/bin:

DE/rand-to-best/1/bin:

DE/best/2/bin:

DE/rand/2/bin:

3. 交叉

这里的交叉和遗传算法的交叉操作有所区别,这里的交叉操作是针对整个种群的某一维度,而遗传算法中的交叉是针对种群中的每一个个体。

4.选择:

差分进化算法按照贪婪准则,从实验种群u中选择个体作为下一代种群x中的个体,具体的选择方式是:

其中:fit(x)为x的适应度。

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

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

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

基本差分进化算法的流程:

算法中的参数:

1. 种群大小NP

2. 变异算子F ,

一般取[0,2],决定偏差向量的放大比例。F过小,造成算法早熟,F过大,导致算法的收敛性变差

3.交叉算子CR

4. 进化代数G

5.终止条件

matlab代码实现:

测试函数为:

取n=10,决策变量的范围为[-20,20]

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);

寻优结果:

差分进化算法的该改进:

自适应差分进化算法:

差分进化算法的变异系数F的确定:在实际的应用中,若果F取为常数,F过大,则会导致算法的收敛速度变慢,求得的全局最优解精度降低,F过小,会导致种群的多样性降低,出现早熟,所以可以将参数F设置为一个随着迭代次数变化的值,在迭代初期的时候,F较大,可以保持种群的多样性,随着迭代次数的增加,F减小,能够保存优良的种群信息,避免破坏最优解。

自适应算子如下所示:

其中Gm表示最大迭代次数,G表示当前迭代次数

变异系数F表示为:

改进的差分进化算法:

clear all;
close all;
clc;
NP=40;    % 种群大小
G=100;    % 迭代次数
D=2;      % 决策变量个数
F0=0.3;   % 初始的变异系数
CR=0.5*(1+rand());
X_min=-100;
X_max=100;

% 偏差向量的生成方式
DE_vector = 4;
% DE_vector=1,2,3,4,0
% DE_vector=0    表示DE/best/1/bin
% DE_vector=1    表示DE/best/1/bin
% DE_vector=2    表示DE/rand-to-best/1/bin
% DE_vector=3    表示DE/best/2/bin
% DE_vector=4    表示DE/rand/2/bin

mode = 'Schaffer';    % 测试函数
% mode = 'self_define';

if strcmp(mode, 'Schaffer')
    figure(1)
    x = -4:0.1:4;
    y = -4:0.1:4;
    [X,Y] = meshgrid(x,y);
    % Z = 3*cos(X.*Y)+X+Y.^2;
    Z = 0.5-((sin(sqrt(X.^2+Y.^2)).^2)-0.5)./(1+0.001.*(X.^2+Y.^2)).^2;
    surf(X,Y,Z);
    title('Schaffer Function');
    xlabel('X-轴');
    ylabel('Y-轴');
    zlabel('Z-轴');
    
    figure(2);
    contour(X, Y, Z, 8);
    title('Schaffer函数等高线');
    xlabel('X-轴');
    ylabel('Y-轴');
end
 
if strcmp(mode, 'self_define')
    figure(1);
    x = -4:0.1:4;
    y = -4:0.1:4;
    [X,Y] = meshgrid(x,y);
    % Z = 100.*(Y-X.^2).^2+(1-X).^2;
    Z = (cos(X.^2+Y.^2)-0.1)./(1+0.3*(X.^2+Y.^2).^2)+3;
    surf(X,Y,Z);
    %title('Rosen Brock valley Function');
    title('Self define Function');
    xlabel('X-轴');
    ylabel('Y-轴');
    zlabel('Z-轴');
end

%   种群初始化
x=zeros(NP,D);
v=zeros(NP,D);
u=zeros(NP,D);
x=X_min + (X_max-X_min)*rand(NP,D);
for gen=1:1:G
    for i=1:1:NP
        ob(i) = func(x(i,:), mode);
    end
    [fitness_max, index] = max(ob);
    lamb(gen) = exp(1-(G/(G+1-gen)));
    F = F0*2^lamb(gen);
    %   变异
    if(DE_vector==0)
        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
            v(m,:)=x(r1,:)+F*(x(r2,:)-x(r3,:));   % DE/best/1bin
        end
    elseif(DE_vector==1)
        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 
            v(m,:)=x(index,:)+x(r1,:)+F*(x(r1,:)-x(r2,:)); 
        end
    elseif(DE_vector==2)
       lambda = 0.35;
       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 
            v(m,:)=x(m,:)+lambda*(x(index,:)-x(m,:))+F*(x(r1,:)-x(r2,:)); 
       end
    elseif(DE_vector==3)
       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
            
            r4=randi([1,NP],1,1);
            while (r4==m)||(r4==r3)||(r4==r2)||(r4==r1)
                r4=randi([1,NP],1,1);
            end
            
            v(m,:)=x(index,:)+F*(x(r1,:)-x(r2,:)+x(r3,:)-x(r4,:));
       end
    else
        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
            
            r4=randi([1,NP],1,1);
            while (r4==m)||(r4==r3)||(r4==r2)||(r4==r1)
                r4=randi([1,NP],1,1);
            end
            
            r5=randi([1,NP],1,1);
            while (r5==m)||(r5==4)||(r5==r3)||(r5==r2)||(r5==r1)
                r5=randi([1,NP],1,1);
            end
            v(m,:)=x(r5,:)+F*(x(r1,:)-x(r2,:)+x(r3,:)-x(r4,:));
       end
    end
    
    %  交叉操作
    r=randi([1,D],1,1);
    for i=1:D
        cr=rand;
        if (cr<=CR)||(i==r)
            u(:,i)=v(:,i);
        else
            u(:,i)=x(:,i);
        end
    end
   
    % 边界条件处理
    for m=1:NP
        for n=1:D
            if u(m,n)<X_min
                u(m,n)=X_min;
            end
            
            if u(m,n)>X_max
                u(m,n)=X_max;
            end
        end
    end
    
    %  自然选择
    for i=1:NP
        ob_1(i)=func(u(i,:), mode);
    end
    
    for i=1:NP
        if ob_1(i)>ob(i)
            x(i,:)=u(i,:);
        else
            x(i,:)=x(i,:);
        end
    end
    trace(gen+1)=fitness_max;    
end

 
figure(3);
% plot(trace);
title('差分进化算法');
xlabel('迭代次数');
ylabel('目标函数值');
plot(trace);


function f=func(buf, md)
    if strcmp(md, 'Schaffer')
        f=0.5-((sin(sqrt(buf(1).^2+buf(2).^2)).^2)-0.5)./(1+0.001.*(buf(1).^2+buf(2).^2)).^2;
    end
    
    if strcmp(md,'self_define')
        % f = 100*(buf(2)-buf(1).^2).^2+(1-buf(1)).^2;
        f = (cos(buf(1).^2+buf(2).^2)-0.1)./(1+0.3*(buf(1).^2+buf(2).^2).^2)+3;
    end
end

测试函数:

适应度进化曲线:

源代码中只是添加了典型的测试函数,参数只是粗略设置一下。对于其他的测试函数。可以在原代码中添加,并且修改源代码中的一些参数来得到算法最好的性能。

猜你喜欢

转载自blog.csdn.net/zj1131190425/article/details/89438654