差分进化算法
-
参数:
-
种群大小:N
-
染色体长度:D(待求参数向量的长度)
-
迭代次数: G m G_m Gm 或者 停止进化条件
-
变异算子: F 0 F_0 F0
-
决定差分过程中的变异大小
-
一般取[0,2]
-
为了避免早熟,可以增加具有自适应变异的算子,具体如下:
λ = e 1 − G m G m + 1 − G F = F 0 ⋅ 2 λ \displaystyle\lambda=e^{1-\frac{G_m}{G_m+1-G}} \\ F=F_0\cdot2^\lambda λ=e1−Gm+1−GGmF=F0⋅2λ
通过该种方式,变异算子可以随着迭代次数的增加,实现由 F 0 ⟹ 0 F_0\Longrightarrow 0 F0⟹0的转变
-
-
交叉(遗传)算子:CR (表示某一个体的某一基因遗传给下一代的概率) 介于[0,1]
-
寻优区间:[ x j,i L x_{\text{j,i}}^L xj,iL, x j,i U x_{\text{j,i}}^U xj,iU] 限制每一个体每一染色体的大小
-
x(g):当前进化代数下的个体合集;
v(g):当前进化代数下产生的等待遗传的所有染色体合集;
u(g):当前代数下v(g)与x(g)按照交叉算子的限制相互结合形成的新个体。
-
(i , j):第i个个体的第j个染色体;
-
-
算法流程
-
初始化种群
x j,i ( 0 ) = x j,i L + r a n d ( 0 , 1 ) ⋅ ( x j,i U − x j,i L ) x_{\text{j,i}}(0)=x_{\text{j,i}}^L+rand(0,1)\cdot(x_{\text{j,i}}^U-x_{\text{j,i}}^L) xj,i(0)=xj,iL+rand(0,1)⋅(xj,iU−xj,iL) -
变异
常见的差分策略为随机选取中区中两个不同的个体,将其向量差缩放后形成变异中间个体v(g)
v i ( g + 1 ) = x r1 ( g ) + F ⋅ ( x r2 ( g ) − x r3 ( g ) ) v_\text{i}(g+1)=x_{\text{r1}}(g)+F\cdot(x_{\text{r2}}(g)-x_{\text{r3}}(g)) vi(g+1)=xr1(g)+F⋅(xr2(g)−xr3(g))
⟹ 边 界 判 断 : \Longrightarrow 边界判断: ⟹边界判断:- x ′ = { x j,i L , x ′ < x j,i L ; x j,i U , x ′ > x j,i U ; x ′ , e l s e ; x'=\left\{\begin{array}{l}x_{\text{j,i}}^L\ \ \ ,\ \ \ x'<x_{\text{j,i}}^L\ ;\\x_{\text{j,i}}^U\ \ \ ,\ \ \ x'>x_{\text{j,i}}^U\ ;\\x'\ \ \ \ \ ,\ \ \ else\ ;\end{array}\right. x′=⎩⎨⎧xj,iL , x′<xj,iL ;xj,iU , x′>xj,iU ;x′ , else ;
- x ′ = { x j,i L + r a n d ( 0 , 1 ) ⋅ ( x j,i U − x j,i L ) , i f x ′ < x o r x ′ > x ; x ′ , e l s e x'=\left\{\begin{array}{l}x_{\text{j,i}}^L+rand(0,1)\cdot(x_{\text{j,i}}^U-x_{\text{j,i}}^L)\ \ ,\ \ if\ x'<x\ \ or\ \ x'>x\ ;\\x'\ \ \ \ \ ,\ \ \ else\end{array}\right. x′={xj,iL+rand(0,1)⋅(xj,iU−xj,iL) , if x′<x or x′>x ;x′ , else
-
交叉
对第 g g g代种群 { x i ( g ) } \{x_\text{i}(g)\} {xi(g)}及其变异的中间体 { v i ( g + 1 ) } \{v_\text{i}(g+1)\} {vi(g+1)}进行个体间的交叉操作;
u j,i = { v j,i ( g + 1 ) , i f r a n d ( 0 , 1 ) ⩽ C R o r j = r a n d i ( [ 1 , D ] , 1 , 1 ) x j,i ( g ) , e l s e u_{\text{j,i}}= \left\{ \begin{array}{l} v_{\text{j,i}}(g+1)\ \ \ ,\ \ \ if\ \ rand(0,1)\leqslant CR\ \ or\ \ j=randi([1,D],1,1)\newline x_{\text{j,i}}(g)\ \ \ \ \ \ \ \ \ \ ,\ \ \ else \end{array} \right. uj,i={vj,i(g+1) , if rand(0,1)⩽CR or j=randi([1,D],1,1)xj,i(g) , else
在交叉过程中, j = r a n d i ( [ 1 , D ] , 1 , 1 ) j=randi([1,D],1,1) j=randi([1,D],1,1)是为了确保每一个变异中间体一定有一个变异染色体遗传下去;其他的交叉过程,则是通过交叉概率CR来选取变异中间体的该染色体是否遗传给下一代
-
选择
设置一目标函数:
f ( X ) = ∑ i = 1 n x i 2 ; X = { x 1 , x 2 , x 3 , ⋯ , x n } f(X)=\sum_{i=1}^n x_i^2\ ;\\ X = \{x_1,x_2,x_3,\cdots,x_n\} f(X)=i=1∑nxi2 ;X={x1,x2,x3,⋯,xn}
DE采用采用贪婪算法来选择进入下一代种群的个体:
x i ( g + 1 ) = { u i ( g + 1 ) , i f f ( u i ( g + 1 ) ) ⩽ f ( x i ( g ) ) ; x i ( g ) , e l s e x_\text{i}(g+1)= \left\{ \begin{array}{l} u_\text{i}(g+1)\ \ \ ,\ \ \ if\ \ f(u_\text{i}(g+1))\leqslant f(x_\text{i}(g))\ ; \\ x_\text{i}(g)\ \ \ \ \ \ \ \ \ \ ,\ \ \ else \end{array} \right. xi(g+1)={ui(g+1) , if f(ui(g+1))⩽f(xi(g)) ;xi(g) , else
-
-
流程总结
-
代码示例
以下代码式差分进化算法具体实现,这里的优化模型为:
目标函数: f ( X ) = ∑ i = 1 10 x i 2 \displaystyle f(X)=\sum_{i=1}^{10}x_i^2 f(X)=i=1∑10xi2 X = { x 1 , x 2 , x 3 , ⋯ , x 10 } X=\{x_1,x_2,x_3,\cdots,x_{10}\} X={x1,x2,x3,⋯,x10};决策变量: X X X ;
限制条件: f o r x i ∈ [ − 20 , 20 ] for\ \ x_i\ \in\ [-20,20] for xi ∈ [−20,20] ;
clear
close all
clc
N = 1000; % 种群数量
D = 10; % 决策变量维度
G_Max = 3000; % 迭代次数
F0 = 2; % 变异算子初值
CR = 0.4; % 交叉概率
X_Min = -20; % 决策变量区间
X_Max = 20;
WaitbarInter = G_Max / 100; % 为了生成进度条的一个数字
% 种群初始化
X = rand(N, D) * (X_Max - X_Min) + X_Min;
X_Fitness = Fitness(X,N);
V = zeros(N, D);
U = zeros(N, D);
U_Fitness = Fitness(U,N);
Best_X = X(1, :);
MinFitness_List = zeros(1, G_Max + 1); % 存放每一次迭代的目标函数值
MinFitness_List(1) = min(X_Fitness);
Fitness_List = zeros(1, G_Max + 1);
Fitness_List(1) = MinFitness_List(1);
tic
h = waitbar(0, ['已完成:0% 运算中...用时:', num2str(toc)]);
for g = 1:G_Max
% 变异算子迭代
lambda = exp(1 - G_Max / (G_Max + 1 - g));
F = F0 * 2^lambda;
% 差分变异操作
for i = 1:N
% 产生不同的r1,r2,r3
r1 = randi([1, N], 1, 1);
r2 = randi([1, N], 1, 1);
r3 = randi([1, N], 1, 1);
while (r1 == i)
r1 = randi([1, N], 1, 1);
end
while (r2 == r1) || (r2 == i)
r2 = randi([1, N], 1, 1);
end
while (r3 == i) || (r3 == r1) || (r3 == r2)
r3 = randi([1, N], 1, 1);
end
V(i, :) = X(r1, :) + F * (X(r2, :) - X(r3, :));
end
% % 交叉操作1
% % 该交叉操作是一次性对整个种群进行交叉,而不是针对单个个体
% r = randi([1,D],1,1);
% for d = 1:D
% if(rand<=CR)||(d==r)
% U(:,d) = V(:,d);
% else
% U(:,d) = X(:,d);
% end
% end
% 交叉操作2
% 该交叉操作是对单个个体进行交叉,而不是一次性针对整个种群进行
for n = 1:N
r = randi([1, D], 1, 1);
for d = 1:D
if (rand <= CR) || (d == r)
U(n, d) = V(n, d);
else
U(n, d) = X(n, d);
end
end
end
% 边界处理
U = BoundaryLimit(U, X_Min, X_Max);
% 自然选择
U_Fitness = Fitness(U, N);
Fitness_List(g + 1) = min(U_Fitness);
for n = 1:N
if X_Fitness(n) > U_Fitness(n)
X(n, :) = U(n, :);
X_Fitness(n) = U_Fitness(n);
end
end
[MinFitness_List(g + 1), index_Min] = min(X_Fitness);
Best_X = X(index_Min, :);
if mod(g, WaitbarInter) == 0
waitbar(g / G_Max, h, ['已完成:', num2str(g / G_Max * 100), ...
'% 运算中...用时:', num2str(toc),'/',num2str(toc/(g / G_Max))]);
end
end
close(h)
display(['The best solution obtained by DE is : ', num2str(Best_X)]);
display(['The best optimal value of the objective funciton found by DE is : ', num2str(MinFitness_List(end))]);
figure
semilogy(MinFitness_List,'linewidth',1.2)
hold on
semilogy(Fitness_List,'linewidth',1.2)
legend(['最小适应度变化'],['适应度变化'])
title('Convergence Curve')
xlabel('Iteration');
ylabel('Best score obtained so far');
axis tight
grid on
box on
% 目标函数
function result = Fitness(X, N)
result = zeros(N, 1);
for i = 1:N
result(i) = sum(X(i, :).^2);
end
end
% 边界限制函数
function result = BoundaryLimit(X, Min, Max)
for i_temp = 1:length(X(:, 1))
for j_temp = 1:length(X(1, :))
if X(i_temp, j_temp) > Max
X(i_temp, j_temp) = Max;
end
if X(i_temp, j_temp) < Min
X(i_temp, j_temp) = Min;
end
end
end
result = X;
end
toc