采用概率转移规则,不需要确定性的规则。
具有内在的并行性,利用个体局部信息、群体全局信息指导进一步搜索。
算法操作简单,利于求解高维度的函数优化问题。
np: 种群规模,np >= 4
f: 变异算子,决定偏差向量的缩放比例。 f∈[0,2]
大 (f>1):差分向量的扰动过大,种群收敛性能差
小:易陷入局部最优
cr: 交叉算子,控制一个实验向量参数来自于随机选择的变异向量而非原向量的概率。cr∈[0,1]
大:加速收敛
初始化参数,随机产生初始种群,进化代数 i = 1
评价初始种群(计算每个个体的目标函数值)
for i = 2:iter_max
变异操作
交叉操作
边界条件处理,得到临时种群
评价临时种群
选择操作(一对一),得到新种群
end
输出结果
符号:DE/x/y/z
x :当前被变异的向量是“随机的”或“最佳的”。
y : 所利用的差向量的个数
z :交叉程序的操作方法 (bin、exp)
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
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
自适应的变异算子
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