差分进化算法DE(学习笔记_06)

1. 特点

  • 采用概率转移规则,不需要确定性的规则。

  • 具有内在的并行性,利用个体局部信息、群体全局信息指导进一步搜索。

  • 算法操作简单,利于求解高维度的函数优化问题。

2. 基本参数

  • np: 种群规模,np >= 4

  • f: 变异算子,决定偏差向量的缩放比例。 f∈[0,2]

    • 大 (f>1):差分向量的扰动过大,种群收敛性能差

    • 小:易陷入局部最优

  • cr: 交叉算子,控制一个实验向量参数来自于随机选择的变异向量而非原向量的概率。cr∈[0,1]

    • 大:加速收敛

3. 基本流程

  1. 初始化参数,随机产生初始种群,进化代数 i = 1

  2. 评价初始种群(计算每个个体的目标函数值)

  3. for i = 2:iter_max

    1. 变异操作

    2. 交叉操作

    3. 边界条件处理,得到临时种群

    4. 评价临时种群

    5. 选择操作(一对一),得到新种群

  4. end

  5. 输出结果

4. 差分进化算法的其他形式

  • 符号:DE/x/y/z

  • x :当前被变异的向量是“随机的”或“最佳的”。

  • y : 所利用的差向量的个数

  • z :交叉程序的操作方法 (bin、exp)

5. DE/rand/1/bin

  • r1 = randi([1,np]);
    v(j,:) = x(r1,:) + f * (x(r2,:) - x(r3,:));
  • 源代码如下:

%% DE/rand/1/bin
% DE/被变异的向量是随机的/差向量1个/交叉操作bin

clear;
close all;
clc;

np = 30;  %种群数量
d = 2;  %维度
iter_max = 200;  %最大迭代次数
f = 0.5;  %变异算子
cr = 0.1;  %交叉算子

x_max = 5;
x_min = -5;

x = zeros(np,d);  %初始种群
u = zeros(np,d);  %变异后的种群
v = zeros(np,d);  %交叉后的种群

%% 1.初始化种群
x = rand(np,d) * (x_max - x_min) + x_min;

%% 2.评价初始种群
for i = 1:np
    ob(i) = func(x(i,:));
end
trace(1) = min(ob);

for i = 1:iter_max-1
    %% 3.变异操作
    for j = 1:np
        r1 = randi([1,np]);
        while(r1 == j)
            r1 = randi([1,np]);
        end
        r2 = randi([1,np]);
        while(r2 == j)
            r2 = randi([1,np]);
        end
        r3 = randi([1,np]);
        while(r3 == j)
            r3 = randi([1,np]);
        end
        v(j,:) = x(r1,:) + f * (x(r2,:) - x(r3,:));
    end
    
    %% 4.交叉操作
    r = randi([1,np]);
    for j = 1:d
        cr_t = rand(1);
        if (cr_t <= cr) | (j == r)
            u(j,:) = v(j,:);
        else
            u(j,:) = x(j,:);
        end
    end
    
    %% 5.边界处理(边界吸收)
    for j = 1:d
        for k = 1:np
            if u(k,j) < x_min
                u(k,j) = x_min;
            end
            if u(k,j) > x_max
                u(k,j) = x_max;
            end
        end
    end
    
    %% 6.选择操作
    %计算变异、交叉、边界处理后的种群的适应度值
    for j = 1:np
        f1(j) = func(u(j,:));
    end
    for j = 1:np
        if f1(j) < ob(j)
            x(j,:) = u(j,:);
        end
    end
    %重新计算适应度值
    for j = 1:np
        ob(j) = func(x(j,:));
    end
    trace(i + 1) = min(ob);
end

%% 6.输出
disp( '最小值位置为:');
[sortf,index] = sort(ob);
x = x(index,:);
x = x(1,:);
x
disp( '最小值为:');
min(ob)

figure
plot(trace);
hold on;
legend_str = {'DE/rand/1/bin','DE/best/2/bin','自适应的DE/best/2/bin'};
xlabel('迭代次数');
ylabel('适应度值');
title("适应度进化曲线")

function results = func(x)
    results = 5 * cos(x(1) * x(2))+ x(1) * x(2) + x(2) * x(2) * x(2);
end

6. DE/best/2/bin

  • v(j,:) = x(best,:) - f * (x(r1,:) - x(r2,:) + x(r3,:) - x(r4,:));
  • 源代码如下:

%% DE/best/2/bin
% DE/被变异的向量是最佳的/差向量2个/交叉操作bin

np = 20;  %种群数量
d = 2;  %维度
iter_max = 200;  %最大迭代次数
f = 0.5;  %变异算子
cr = 0.1;  %交叉算子

x_max = 5;
x_min = -5;

x = zeros(np,d);  %初始种群
u = zeros(np,d);  %变异后的种群
v = zeros(np,d);  %交叉后的种群

%% 1.初始化种群
x = rand(np,d) * (x_max - x_min) + x_min;

%% 2.评价初始种群
for i = 1:np
    ob(i) = func(x(i,:));
end
trace(1) = min(ob);
for i = 1:np
    if ob(i) == trace(1)
        best = i;
        break;
    end
end
    

for i = 1:iter_max-1
    %% 3.变异操作
    for j = 1:np
        r1 = randi([1,np]);
        while(r1 == j)
            r1 = randi([1,np]);
        end
        r2 = randi([1,np]);
        while(r2 == j | r2 == r1)
            r2 = randi([1,np]);
        end
        r3 = randi([1,np]);
        while(r3 == j | r3 == r1 | r3 == r2)
            r3 = randi([1,np]);
        end
        r4 = randi([1,np]);
        while(r4 == j | r4 == r1 | r4 == r2 | r4 == r3)
            r4 = randi([1,np]);
        end
        v(j,:) = x(best,:) - f * (x(r1,:) - x(r2,:) + x(r3,:) - x(r4,:));
    end
    
    %% 4.交叉操作
    r = randi([1,np]);
    for j = 1:d
        cr_t = rand(1);
        if (cr_t <= cr) | (j == r)
            u(j,:) = v(j,:);
        else
            u(j,:) = x(j,:);
        end
    end
    
    %% 5.边界处理(边界吸收)
    for j = 1:d
        for k = 1:np
            if u(k,j) < x_min
                u(k,j) = x_min;
            end
            if u(k,j) > x_max
                u(k,j) = x_max;
            end
        end
    end
    
    %% 6.选择操作
    %计算变异、交叉、边界处理后的种群的适应度值
    for j = 1:np
        f1(j) = func(u(j,:));
    end
    for j = 1:np
        if f1(j) < ob(j)
            x(j,:) = u(j,:);
        end
    end
    %重新计算适应度值
    for j = 1:np
        ob(j) = func(x(j,:));
    end
    trace(i + 1) = min(ob);
    
    for pos = 1:np
        if ob(pos) == trace(i + 1)
            best = pos;
            break;
        end
    end
end

%% 6.输出
disp( '最小值位置为:');
[sortf,index] = sort(ob);
x = x(index,:);
x = x(1,:);
x
disp( '最小值为:');
min(ob)

plot(trace);
hold on;
xlabel('迭代次数');
ylabel('适应度值');
title("适应度进化曲线")

function results = func(x)
    results = 5 * cos(x(1) * x(2))+ x(1) * x(2) + x(2) * x(2) * x(2);
end

7. 自适应差分进化算法( DE/best/2/bin基础上改进 )

  • 自适应的变异算子

  • lamuda = exp(1)^(1 - iter_max/(iter_max + 1 - i));
    f = f0 * 2^lamuda;
    v(j,:) = x(best,:) - f * (x(r1,:) - x(r2,:) + x(r3,:) - x(r4,:));
  • 随机范围的交叉算子(平均值0.75),有助于保持群体的多样性

  • cr = 0.5 * (1 + rand);
  • 源代码如下:

%% 自适应机制 DE/best/2/bin
% DE/被变异的向量是最佳的/差向量1个/交叉操作bin
% 自适应变异算子 + 平均值为0.75的随机交叉算子

np = 30;  %种群数量
d = 2;  %维度
iter_max = 200;  %最大迭代次数
f0 = 2;  %变异算子
cr = 0.75;  %交叉算子

x_max = 5;
x_min = -5;

x = zeros(np,d);  %初始种群
u = zeros(np,d);  %变异后的种群
v = zeros(np,d);  %交叉后的种群

%% 1.初始化种群
x = rand(np,d) * (x_max - x_min) + x_min;

%% 2.评价初始种群
for i = 1:np
    ob(i) = func(x(i,:));
end
trace(1) = min(ob);
for i = 1:np
    if ob(i) == trace(1)
        best = i;
        break;
    end
end
    
for i = 1:iter_max-1
    %% 3.变异操作
    for j = 1:np
        r1 = randi([1,np]);
        while(r1 == j)
            r1 = randi([1,np]);
        end
        r2 = randi([1,np]);
        while(r2 == j | r2 == r1)
            r2 = randi([1,np]);
        end
        r3 = randi([1,np]);
        while(r3 == j | r3 == r1 | r3 == r2)
            r3 = randi([1,np]);
        end
        r4 = randi([1,np]);
        while(r4 == j | r4 == r1 | r4 == r2 | r4 == r3)
            r4 = randi([1,np]);
        end
        %自适应变异算子
        lamuda = exp(1)^(1 - iter_max/(iter_max + 1 - i));
        f = f0 * 2^lamuda;
        v(j,:) = x(best,:) - f * (x(r1,:) - x(r2,:) + x(r3,:) - x(r4,:));
    end
    
    %% 4.交叉操作
    r = randi([1,np]);
    cr = 0.5 * (1 + rand);  %平均值为0.75的随机交叉算子
    for j = 1:d
        cr_t = rand(1);
        if (cr_t <= cr) | (j == r)
            u(j,:) = v(j,:);
        else
            u(j,:) = x(j,:);
        end
    end
    
    %% 5.边界处理(边界吸收)
    for j = 1:d
        for k = 1:np
            if u(k,j) < x_min
                u(k,j) = x_min;
            end
            if u(k,j) > x_max
                u(k,j) = x_max;
            end
        end
    end
    
    %% 6.选择操作
    %计算变异、交叉、边界处理后的种群的适应度值
    for j = 1:np
        f1(j) = func(u(j,:));
    end
    for j = 1:np
        if f1(j) < ob(j)
            x(j,:) = u(j,:);
        end
    end
    %重新计算适应度值
    for j = 1:np
        ob(j) = func(x(j,:));
    end
    trace(i + 1) = min(ob);
    
    for pos = 1:np
        if ob(pos) == trace(i + 1)
            best = pos;
            break;
        end
    end
end

%% 6.输出
disp( '最小值位置为:');
[sortf,index] = sort(ob);
x = x(index,:);
x = x(1,:);
x
disp( '最小值为:');
min(ob)

plot(trace);
xlabel('迭代次数');
ylabel('适应度值');
title("适应度进化曲线");
legend(legend_str);

function results = func(x)
    results = 5 * cos(x(1) * x(2))+ x(1) * x(2) + x(2) * x(2) * x(2);
end

  8. 对比

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值