一、 莲花算法
1.1 算法原理
莲花算法(Lotus flower algorithm,LFA)是一种受自然启发的优化算法,其灵感来源于莲花的自清洁特性和授粉过程。莲花的自清洁特性,即所谓的“莲花效应”,是由其叶片表面的微纳米结构和蜡质层共同作用实现的。这种特性使得水滴能够在叶片表面形成球状,并带走灰尘和污垢,从而使叶片始终保持清洁。在算法中,这种自清洁效应被用来模拟优化过程中的局部搜索和全局搜索的平衡。
授粉过程是莲花繁衍的重要方式,包括生物授粉和非生物授粉。生物授粉是指昆虫等生物在花丛中穿梭,将花粉从一朵花传播到另一朵花;非生物授粉则是通过风、水等自然因素传播花粉。在算法中,生物授粉被用来模拟全局搜索,而非生物授粉则被用来模拟局部搜索。
1.2 算法介绍
1.2.1 LEA 探索阶段
LEA 的探索阶段(Exploration Phase)主要基于蜻蜓算法(Dragonfly Algorithm)的全局授粉过程,模拟蜻蜓在花粉传播中的行为。蜻蜓算法通过模拟蜻蜓的群体行为,包括分离(Separation)、对齐(Alignment)、内聚(Cohesion)以及对食物的吸引和对敌人的回避,来实现对解空间的全局搜索。
-
分离(Separation):避免个体与邻近个体发生碰撞,计算公式为:
S i = − ∑ j = 1 N ( X i − X j ) S_i = -\sum_{j=1}^{N} (X_i - X_j) Si=−j=1∑N(Xi−Xj)
其中, X i X_i Xi 表示当前个体的位置, X j X_j Xj 表示邻近个体的位置, N N N 为邻近个体的数量。 -
对齐(Alignment):个体的速度与邻近个体的速度保持一致,计算公式为:
A i = 1 N ∑ j = 1 N V j A_i = \frac{1}{N} \sum_{j=1}^{N} V_j Ai=N1j=1∑NVj
其中, V j V_j Vj 表示邻近个体的速度。 -
内聚(Cohesion):个体向邻近个体的中心位置移动,计算公式为:
C i = 1 N ∑ j = 1 N ( X j − X i ) C_i = \frac{1}{N} \sum_{j=1}^{N} (X_j - X_i) Ci=N1j=1∑N(Xj−Xi)
其中, X j X_j Xj 表示邻近个体的位置。 -
食物吸引(Food Attraction):个体向食物源移动,计算公式为:
F i = X food − X i F_i = X_{\text{food}} - X_i Fi=Xfood−Xi
其中, X food X_{\text{food}} Xfood 表示食物源的位置。 -
敌人回避(Enemy Distraction):个体远离敌人,计算公式为:
E i = X enemy − X i E_i = X_{\text{enemy}} - X_i Ei=Xenemy−Xi
其中, X enemy X_{\text{enemy}} Xenemy 表示敌人的位置。
通过上述五个因素的综合作用,蜻蜓算法能够有效地探索解空间。在 LEA 中,这些机制被用来模拟蜻蜓在全局搜索中的行为,以实现对问题的全局优化。
1.2.2 LEA 开发阶段
LEA 的开发阶段(Exploitation Phase)主要基于局部授粉过程,模拟植物的自花授粉行为。在这个阶段,算法通过局部搜索来细化和优化已找到的解。
- 局部搜索:在局部授粉过程中,每个解(花)会围绕当前最优解进行局部搜索。搜索的步长会随着迭代次数的增加而逐渐减小,以实现对最优解的精细化搜索。计算公式为:
X i t + 1 = X i t + R ( X i t − g ∗ ) X_{i}^{t+1} = X_i^t + R (X_i^t - g^*) Xit+1=Xit+R(Xit−g∗)
其中, X i t X_i^t Xit 表示当前解, g ∗ g^* g∗ 表示当前最优解, R R R 为步长衰减系数,计算公式为:
R = 2 e − ( 4 t L ) 2 R = 2e^{-\left(\frac{4t}{L}\right)^2} R=2e−(L4t)2
其中, t t t 为当前迭代次数, L L L 为最大迭代次数。
通过局部搜索,LEA 能够在已找到的解附近进行更深入的搜索,从而提高算法的开发能力。
1.2.3 LEA 开发阶段强化
为了进一步增强开发阶段的搜索能力,LEA 引入了水滴在荷叶上移动的局部搜索机制。这个机制模拟了水滴在荷叶表面的流动,通过水滴的移动来寻找最优解。
-
水滴移动:每个解(水滴)在搜索空间中移动,寻找最优解。水滴的移动速度和位置更新公式为:
V i t + 1 = q V i t V_i^{t+1} = q V_i^t Vit+1=qVit
X i t + 1 = X i t + V i t + 1 X_i^{t+1} = X_i^t + V_i^{t+1} Xit+1=Xit+Vit+1
其中, V i t V_i^t Vit 表示当前速度, q q q 为速度衰减系数。 -
水滴溢出:当水滴在一个坑(局部最优解)中积累过多时,会溢出并流向其他坑。溢出的水滴会根据坑的容量(适应度值)选择下一个目标坑。计算公式为:
c i = ∣ ∣ f i − f max ∣ ∣ ∣ ∣ f min − f max ∣ ∣ × const c_i = \frac{||f_i - f_{\text{max}}||}{||f_{\text{min}} - f_{\text{max}}||} \times \text{const} ci=∣∣fmin−fmax∣∣∣∣fi−fmax∣∣×const
其中, f i f_i fi 表示当前坑的适应度值, f max f_{\text{max}} fmax 和 f min f_{\text{min}} fmin 分别表示最大和最小适应度值, const \text{const} const 为常数。
通过水滴的移动和溢出机制,LEA 能够在局部搜索中更有效地找到最优解。
1.2.4 LEA 步骤
LEA 的主要步骤如下:
- 初始化:生成初始解,随机分布蜻蜓(解)在搜索空间中。
- 评估:计算每个解的适应度值,确定当前最优解。
- 更新:根据蜻蜓算法的机制更新解的位置,包括分离、对齐、内聚、食物吸引和敌人回避。
- 局部搜索:在当前最优解附近进行局部搜索,模拟水滴在荷叶上的移动。
- 终止条件:检查是否达到最大迭代次数或满足其他终止条件。如果未满足,则返回步骤 2。
1.3 算法流程
莲花算法的流程主要包括以下步骤:
- 初始化:随机生成一群蜻蜓(每个蜻蜓代表一个候选解),并设定算法的参数,如种群大小、最大迭代次数等。
- 评估:计算每个蜻蜓的位置对应的适应度值,确定当前最优解。
- 更新:根据蜻蜓算法的机制更新蜻蜓的位置,包括分离、对齐、内聚、食物吸引和敌人回避。
- 局部搜索:在当前最优解附近进行局部搜索,模拟水滴在荷叶上的移动。
- 终止条件:检查是否达到最大迭代次数或满足其他终止条件。如果未满足,则返回步骤 2。
1.4 算法描述
-
分离(Separation):避免个体与邻近个体发生碰撞,计算公式为: S i = − ∑ j = 1 N ( X i − X j ) S_i = -\sum_{j=1}^{N} (X_i - X_j) Si=−j=1∑N(Xi−Xj)其中, X i X_i Xi 表示当前个体的位置, X j X_j Xj 表示邻近个体的位置, N N N 为邻近个体的数量。
-
对齐(Alignment):个体的速度与邻近个体的速度保持一致,计算公式为: A i = 1 N ∑ j = 1 N V j A_i = \frac{1}{N} \sum_{j=1}^{N} V_j Ai=N1j=1∑NVj其中, V j V_j Vj 表示邻近个体的速度。
-
内聚(Cohesion):个体向邻近个体的中心位置移动,计算公式为: C i = 1 N ∑ j = 1 N ( X j − X i ) C_i = \frac{1}{N} \sum_{j=1}^{N} (X_j - X_i) Ci=N1j=1∑N(Xj−Xi)其中, X j X_j Xj 表示邻近个体的位置。
-
食物吸引(Food Attraction):个体向食物源移动,计算公式为: F i = X food − X i F_i = X_{\text{food}} - X_i Fi=Xfood−Xi其中, X food X_{\text{food}} Xfood 表示食物源的位置。
-
敌人回避(Enemy Distraction):个体远离敌人,计算公式为: E i = X enemy − X i E_i = X_{\text{enemy}} - X_i Ei=Xenemy−Xi其中, X enemy X_{\text{enemy}} Xenemy 表示敌人的位置。
莲花算法通过模拟莲花的自清洁特性和授粉过程,实现了全局搜索和局部搜索的平衡。它的主要特点是结合了蜻蜓算法的群体行为和水滴在荷叶上的移动机制,能够在复杂的问题空间中有效地寻找最优解。
参考文献:
[1]Dalirinia, Elham, Mehrdad Jalali, Mahdi Yaghoobi and Hamid Tabatabaee. “Lotus effect optimization algorithm (LEA): a lotus nature-inspired algorithm for engineering design optimization.” J. Supercomput. 80 (2023): 761-799.
二、核心MATLAB代码
function [Best_score,Best_pos,cg_curve]=LEA(SearchAgents_no,Max_iteration,lb,ub,dim,fobj)
% display('optimizing your problem');
cg_curve=zeros(1,Max_iteration);
if size(ub,2)==1
ub=ones(1,dim)*ub;
lb=ones(1,dim)*lb;
end
r=(ub-lb)/10;
Delta_max=(ub-lb)/10;
Food_fitness=inf;
Food_pos=zeros(dim,1);
Enemy_fitness=-inf;
Enemy_pos=zeros(dim,1);
X=initialization(SearchAgents_no,dim,ub,lb);
Fitness=zeros(1,SearchAgents_no);
DeltaX=initialization(SearchAgents_no,dim,ub,lb);
for iter=1:Max_iteration
r=(ub-lb)/4+((ub-lb)*(iter/Max_iteration)*2);
w=0.9-iter*((0.9-0.4)/Max_iteration);
my_c=0.1-iter*((0.1-0)/(Max_iteration/2));
if my_c<0
my_c=0;
end
s=2*rand*my_c;
a=2*rand*my_c;
c=2*rand*my_c;
f=2*rand;
e=my_c;
for i=1:SearchAgents_no
Fitness(1,i)=fobj(X(:,i)');
if Fitness(1,i)<Food_fitness
Food_fitness=Fitness(1,i);
Food_pos=X(:,i);
end
if Fitness(1,i)>Enemy_fitness
if all(X(:,i)<ub') && all( X(:,i)>lb')
Enemy_fitness=Fitness(1,i);
Enemy_pos=X(:,i);
end
end
end
for i=1:SearchAgents_no
index=0;
neighbours_no=0;
clear Neighbours_DeltaX
clear Neighbours_X
%find the neighbouring solutions
for j=1:SearchAgents_no
Dist2Enemy=distance(X(:,i),X(:,j));
if (all(Dist2Enemy<=r) && all(Dist2Enemy~=0))
index=index+1;
neighbours_no=neighbours_no+1;
Neighbours_DeltaX(:,index)=DeltaX(:,j);
Neighbours_X(:,index)=X(:,j);
end
end
S=zeros(dim,1);
if neighbours_no>1
for k=1:neighbours_no
S=S+(Neighbours_X(:,k)-X(:,i));
end
S=-S;
else
S=zeros(dim,1);
end
if neighbours_no>1
A=(sum(Neighbours_DeltaX')')/neighbours_no;
else
A=DeltaX(:,i);
end
if neighbours_no>1
C_temp=(sum(Neighbours_X')')/neighbours_no;
else
C_temp=X(:,i);
end
C=C_temp-X(:,i);
Dist2Food=distance(X(:,i),Food_pos(:,1));
if all(Dist2Food<=r)
F=Food_pos-X(:,i);
else
F=0;
end
Dist2Enemy=distance(X(:,i),Enemy_pos(:,1));
if all(Dist2Enemy<=r)
Enemy=Enemy_pos+X(:,i);
else
Enemy=zeros(dim,1);
end
for tt=1:dim
if X(tt,i)>ub(tt)
X(tt,i)=lb(tt);
DeltaX(tt,i)=rand;
end
if X(tt,i)<lb(tt)
X(tt,i)=ub(tt);
DeltaX(tt,i)=rand;
end
end
if any(Dist2Food>r)
if neighbours_no>1
for j=1:dim
DeltaX(j,i)=w*DeltaX(j,i)+rand*A(j,1)+rand*C(j,1)+rand*S(j,1);
if DeltaX(j,i)>Delta_max(j)
DeltaX(j,i)=Delta_max(j);
end
if DeltaX(j,i)<-Delta_max(j)
DeltaX(j,i)=-Delta_max(j);
end
X(j,i)=X(j,i)+DeltaX(j,i);
end
else
% Eq. (3.8)
X(:,i)=X(:,i)+Levy(dim)'.*X(:,i);
DeltaX(:,i)=0;
end
else
for j=1:dim
% Eq. (3.6)
DeltaX(j,i)=(a*A(j,1)+c*C(j,1)+s*S(j,1)+f*F(j,1)+e*Enemy(j,1)) + w*DeltaX(j,i);
if DeltaX(j,i)>Delta_max(j)
DeltaX(j,i)=Delta_max(j);
end
if DeltaX(j,i)<-Delta_max(j)
DeltaX(j,i)=-Delta_max(j);
end
X(j,i)=X(j,i)+DeltaX(j,i);
end
end
Flag4ub=X(:,i)>ub';
Flag4lb=X(:,i)<lb';
X(:,i)=(X(:,i).*(~(Flag4ub+Flag4lb)))+ub'.*Flag4ub+lb'.*Flag4lb;
end
Best_score=Food_fitness;
Best_pos=Food_pos';
cg_curve(iter)=Best_score;
end
end
function o=Levy(d)
beta=3/2;
%Eq. (3.10)
sigma=(gamma(1+beta)*sin(pi*beta/2)/(gamma((1+beta)/2)*beta*2^((beta-1)/2)))^(1/beta);
u=randn(1,d)*sigma;
v=randn(1,d);
step=u./abs(v).^(1/beta);
% Eq. (3.9)
o=0.01*step;
end