本期优化算法是对上一期嗅觉优化算法的一个改进。
基于自适应交叉的嗅觉优化算法(Adaptive crossover-based smell agent optimization,ACB-SAO)是一种新型的启发式优化算法。该算法有效克服了传统算法在处理多样化约束和复杂性问题时所面临的局限性,尤其是在解决高度复杂和非线性问题时,传统算法往往难以达到预期的性能。ACB-SAO算法的创新性在于引入了两个关键贡献:首先,采用长尾探索模式,通过将Linnik Flight与黄金比例配置相结合,以提升探索过程的效率和广度,从而增强了算法的全局搜索能力;其次,通过动态调整交叉率,算法能够在优化过程中实时调节局部搜索与全局搜索之间的平衡,从而实现对SAO的优化。两者的协同作用使得该算法在提升解的准确性和稳定性方面表现出色,有效避免了陷入局部最优解的风险,增强了其在工程优化问题中的应用潜力。
该成果于2024年发表在IEEE会议期刊International Computer Science and Engineering上。

1.原理详解
(1)标准SAO
SAO优化方法的灵感来自于这样的想法,即主体能够使用其嗅觉系统追踪气味。该机制分为三个阶段:嗅探、跟随和随机模式。SAO中这三个阶段的详细信息概述如下:
SAO在很大程度上依赖于气味分子向指定位置的分散。这一阶段首先随机产生一组初始的气味分子。本文将初始种群规模定义为NP,表示候选解的数量,将问题的维度定义为D,表示搜索空间内的控制变量,数学表达如下所示:
气味分子的位置由公式中指定的位置矢量 和速度 定义。假定气味分子以布朗运动分散,则它们的速度根据下式修正:
每个气味分子都具有独特的扩散速度,使其能够在搜索空间内蒸发和重新定位。当气味分子不均匀地扩散直到到达个体的位置时,它们速度的更新方式如下
其中vc表示速度更新分量,如下式所定义:
其中k被称为玻尔兹曼常数,而m和T分别代表气味分子的质量和温度。项r2是在范围(0,1]内产生的均匀随机数,其缓和分子性质对气味速度的影响。
用随机生成的气味分子的初始位置启动跟随过程。假设气味分子的总数为N,并且超空间中的总变量表示为D,则气味分子可以使用以下公式初始化:
其中r3和r4是在(0,1]的范围内生成的均匀随机数。
离散的分子可引起强度或浓度随时间的波动。这些波动会使个体感到困惑,导致气味踪迹的丢失和难以跟踪。个体切换到随机模式以克服此挑战:
其中S是任意设置的恒定步长,r5表示范围(0,1]内的均匀随机数,并且Xt i是由拖尾模式确定的分子的位置。
(2)Linnik飞行
Linnik flight是指一类步长遵循重尾概率分布的随机游动,其尾部表现出幂律衰减。这种随机游走模拟了各种自然现象。Linnik分布的随机生成器通过反演技术将Lk(α,σ)表示为两个独立随机变量的乘积,如下式所示:
其中S是随机变量,Z表示平均值为0、标度为1的标准拉普拉斯分布,R表示正随机变量的密度函数。参数α控制分布的尾部沉重程度,从而影响长跳跃的发生;较小的α值导致长跳跃的频率较高。另一方面,σ定义了标准差,它直接决定了跳跃幅度;较大的σ值产生较长的跳跃。所提出的长尾探索模式的行为如下图所示。

(3)二项式交叉
二项式交叉机制首次引入差分进化(DE)。如下式中所概述的二项式交叉方案涉及选择待扰动的目标解:
其中 是当前候选解xt i的第j个位置(维度)处的元素。 是新生成的解的第j个位置处的元素。r6表示在区间[0,1]上的均匀分布。CRi为交叉率。 是随机选择的元素索引。
(4)自适应交叉率策略
交叉率(CR)控制DE中的解决方案的重组,确定目标解决方案组分被供体组分替换的概率。固定的CR值可能会导致不同问题的性能不一致。为了克服这一点,自适应策略如jDE动态调整CR,其数学表达如下所示:
其中,CRt+1i和CRti分别是新生成的CR值和当前CR值。τ2设置为0.1。U(0,1]是区间[0,1]上的均匀分布。
ACB-SAO算法的伪代码如下:

2.结果展示
在23个经典函数运行的结果,随机选几个展示一下:
3.MATLAB核心代码
%% 淘个代码 %%
% 微信公众号搜索:淘个代码,获取更多代码
% 基于自适应交叉的嗅觉优化算法(ACB-SAO)
function [best_cost,best_x,convergence_curve,cul_solution,cul_nfe] = ACB_SAO(SearchAgents_no,max_nfe,lb,ub,dim,fobj)
%disp('SAO is now tackling your problem');
rng(sum(100*clock));
% Evaluation settings
eval_setting.case = fobj;
eval_setting.lb = lb;
eval_setting.ub = ub;
eval_setting.dim = dim;
cul_solution = [];
cul_nfe = [];
convergence_curve = [];
% Parameters
nVar = dim;
nPop = SearchAgents_no; % Number of Smell Molecules
m = 2.4; % mass of molecules.
K = 1.38064852*10^(-23); % The boltzman constant
SN = 2.5;
T = 3; %Temperature of gas molecules.
olf = 3.5;
% Main Loop
% Molecules Initialization
molecules = Initialize(nPop,nVar,lb,ub);
v = molecules*0.1;
molecules = molecules + v;
for i=1:nPop
% Fit(i)=objFun(fitness,molecules(i,:));
feasible_sol = FeasibleFunction(molecules(i,:),eval_setting);
[Fit(i),~,~] = feval(fobj,feasible_sol);
molecules(i,:) = feasible_sol;
end
[Fits,index] = min(Fit); % Obtain the fitness of the best molecule
x_agent = molecules(index,:); % Determin the agent
nfe = 0;
% itr = 0;
% Initial CR
CR = 0.9 * ones(nPop, 1);
tau2 = 0.1;
D = dim;
% Golden ratio
golden_ratio = 2/(1 + sqrt(5));
while nfe < max_nfe
% itr = itr + 1;
CRold = CR;
% Sniffing mode
for i=1:nPop
% Generate CR
if rand < tau2
CR(i) = 0.0 + 1.0 * rand(1, 1);
end
trial(i,:) = molecules(i,:);
% binomial crossover
jrand = randi(D);
for j=1:nVar
if rand <= CR(i) || j == jrand
trial(i,j) = molecules(i,j)+v(i,j)+rand*sqrt(3*K*T/m);
% trial(i,j) = molecules(i,j)+v(i,j);
end
end
% % exponential crossover
% jrand = randi(D);
% L = 0;
% while (rand <= CR(i)) && (L < D)
% j = mod(jrand + L - 1, D) + 1;
% trial(i,j) = molecules(i,j)+v(i,j)+rand*sqrt(3*K*T/m);
% L = L + 1;
% end
% Make sure no smell molecules excape the boundary
trial(i,:) = clipboundry(lb,ub,trial(i,:));
% Evaluation
feasible_sol = FeasibleFunction(trial(i,:),eval_setting);
[Fitsniff(i),~,~] = feval(fobj,feasible_sol);
trial(i,:) = feasible_sol;
nfe = nfe + 1;
if Fitsniff(i) <= Fit(i)
molecules(i,:) = trial(i,:);
Fit(i) = Fitsniff(i);
else
CR(i) = CRold(i);
end
end
% for i=1:nPop
% for j=1:nVar
% % Update the molecular Velocity
% v(i,j)=(v(i,j)+rand*sqrt(3*K*T/m));
% end
% end
[Fitsniffmin,sindex] = min(Fitsniff);
xs_agent = molecules(sindex,:);
[~,sidx] = max(Fitsniff);
x_worst = molecules(sidx,:);
CRold = CR;
% Trailing mode
for i=1:nPop
% Generate CR
if rand < tau2
CR(i) = 0.0 + 1.0 * rand(1, 1);
end
trial(i,:) = molecules(i,:);
% for j=i:nVar
% % molecules(i,j)=molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))...
% % -rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
% mutant(i,j)=molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))...
% -rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
% end
% binomial crossover
jrand = randi(D);
for j=1:nVar
if rand <= CR(i) || j == jrand
trial(i,j) = molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))-rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
end
end
% % exponential crossover
% jrand = randi(D);
% L = 0;
% while (rand <= CR(i)) && (L < D)
% j = mod(jrand + L - 1, D) + 1;
% trial(i,j) = molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))-rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
% L = L + 1;
% end
% Make sure no smell molecules excape the boundary
trial(i,:) = clipboundry(lb,ub,trial(i,:));
% Evaluation
feasible_sol = FeasibleFunction(trial(i,:),eval_setting);
[Fitstrail(i),~,~] = feval(fobj,feasible_sol);
trial(i,:) = feasible_sol;
nfe = nfe + 1;
if Fitstrail(i) <= Fit(i)
molecules(i,:) = trial(i,:);
Fit(i) = Fitstrail(i);
else
CR(i) = CRold(i);
end
end
CRold = CR;
% Random mode
for i=1:nPop
% Generate CR
if rand < tau2
CR(i) = 0.0 + 1.0 * rand(1, 1);
end
trial(i,:) = molecules(i,:);
% binomial crossover
jrand = randi(D);
for j=1:nVar
if rand <= CR(i) || j == jrand
trial(i,j) = molecules(i,j)+LnF2(golden_ratio,0.05,1,1);
end
end
% % exponential crossover
% jrand = randi(D);
% L = 0;
% while (rand <= CR(i)) && (L < D)
% j = mod(jrand + L - 1, D) + 1;
% trial(i,j) = molecules(i,j)+LnF2(golden_ratio,0.05,1,1);
% L = L + 1;
% end
% Make sure no smell molecules excape the boundary
trial(i,:) = clipboundry(lb,ub,trial(i,:));
% Evaluation
feasible_sol = FeasibleFunction(trial(i,:),eval_setting);
[Fitsrand(i),~,~] = feval(fobj,feasible_sol);
trial(i,:) = feasible_sol;
nfe = nfe + 1;
if Fitsrand(i) <= Fit(i)
molecules(i,:) = trial(i,:);
Fit(i) = Fitsrand(i);
else
CR(i) = CRold(i);
end
end
[bestFit,bestIdx] = min(Fit);
best_x = molecules(bestIdx,:);
best_cost = bestFit;
convergence_curve = [convergence_curve best_cost];
cul_solution = [cul_solution best_x];
cul_nfe = [cul_nfe nfe];
end
end
function mole=Initialize(nPop,nVar,lb,ub)
for i=1:nPop
for j=1:nVar
mole(i,j)=lb(j)+rand()*(ub(j)-lb(j)); % Defind the initial positions of the smell molecules.
end
end
end
function molecules=clipboundry(lb,ub,molecules)
[nPop,nVar]=size(molecules);
for i=1:nPop
for j=1:nVar
if molecules(i,j)<lb(j)
molecules(i,j)=lb(j);
elseif molecules(i,j)>ub(j)
molecules(i,j)=ub(j);
end
end
end
end
function trial = binomialCrossover(target, mutant, CR, D)
jrand = randi(D);
trial = target;
for j = 1:D
if rand <= CR || j == jrand
trial(j) = mutant(j);
end
end
end
function trial = exponentialCrossover(target, mutant, CR, D)
jrand = randi(D);
L = 0;
trial = target;
while (rand <= CR) && (L < D)
trial(mod(jrand + L - 1, D) + 1) = mutant(mod(jrand + L - 1, D) + 1);
L = L + 1;
end
end
function xhold = LnF2(alpha,scale,m, n)
xhold = laprnd(m, n, 0, 1);
% xhold = randl(m,n); %Laplacian distributed pseudorandom numbers.
SE = sign(rand(m,n)-0.5) .* xhold;
% U = rand(1,n);
U = rand(m,n);
xhold = (sin(0.5*pi*alpha).*cot(0.5*pi*(alpha*U))-cos(0.5*pi*alpha)).^(1/alpha);
xhold = scale .* SE ./ xhold;
end
function y = laprnd(m, n, mu, sigma)
% LAPRND generate i.i.d. laplacian random number drawn from laplacian distribution
% with mean mu and standard deviation sigma.
% mu : mean
% sigma : standard deviation
% [m, n] : the dimension of y.
% Default mu = 0, sigma = 1.
% For more information, refer to
% http://en.wikipedia.org./wiki/Laplace_distribution
% Author : Elvis Chen (bee33@sjtu.edu.cn)
% Date : 01/19/07
% Check inputs
if nargin < 2
error('At least two inputs are required');
end
if nargin == 2
mu = 0; sigma = 1;
end
if nargin == 3
sigma = 1;
end
% Generate Laplacian noise
u = rand(m, n)-0.5;
b = sigma / sqrt(2);
y = mu - b * sign(u).* log(1- 2* abs(u));
end
%% 淘个代码 %%
% 微信公众号搜索:淘个代码,获取更多代码
% 基于自适应交叉的嗅觉优化算法(ACB-SAO)
function [best_cost,best_x,convergence_curve,cul_solution,cul_nfe] = ACB_SAO(SearchAgents_no,max_nfe,lb,ub,dim,fobj)
%disp('SAO is now tackling your problem');
rng(sum(100*clock));
% Evaluation settings
eval_setting.case = fobj;
eval_setting.lb = lb;
eval_setting.ub = ub;
eval_setting.dim = dim;
cul_solution = [];
cul_nfe = [];
convergence_curve = [];
% Parameters
nVar = dim;
nPop = SearchAgents_no; % Number of Smell Molecules
m = 2.4; % mass of molecules.
K = 1.38064852*10^(-23); % The boltzman constant
SN = 2.5;
T = 3; %Temperature of gas molecules.
olf = 3.5;
% Main Loop
% Molecules Initialization
molecules = Initialize(nPop,nVar,lb,ub);
v = molecules*0.1;
molecules = molecules + v;
for i=1:nPop
% Fit(i)=objFun(fitness,molecules(i,:));
feasible_sol = FeasibleFunction(molecules(i,:),eval_setting);
[Fit(i),~,~] = feval(fobj,feasible_sol);
molecules(i,:) = feasible_sol;
end
[Fits,index] = min(Fit); % Obtain the fitness of the best molecule
x_agent = molecules(index,:); % Determin the agent
nfe = 0;
% itr = 0;
% Initial CR
CR = 0.9 * ones(nPop, 1);
tau2 = 0.1;
D = dim;
% Golden ratio
golden_ratio = 2/(1 + sqrt(5));
while nfe < max_nfe
% itr = itr + 1;
CRold = CR;
% Sniffing mode
for i=1:nPop
% Generate CR
if rand < tau2
CR(i) = 0.0 + 1.0 * rand(1, 1);
end
trial(i,:) = molecules(i,:);
% binomial crossover
jrand = randi(D);
for j=1:nVar
if rand <= CR(i) || j == jrand
trial(i,j) = molecules(i,j)+v(i,j)+rand*sqrt(3*K*T/m);
% trial(i,j) = molecules(i,j)+v(i,j);
end
end
% % exponential crossover
% jrand = randi(D);
% L = 0;
% while (rand <= CR(i)) && (L < D)
% j = mod(jrand + L - 1, D) + 1;
% trial(i,j) = molecules(i,j)+v(i,j)+rand*sqrt(3*K*T/m);
% L = L + 1;
% end
% Make sure no smell molecules excape the boundary
trial(i,:) = clipboundry(lb,ub,trial(i,:));
% Evaluation
feasible_sol = FeasibleFunction(trial(i,:),eval_setting);
[Fitsniff(i),~,~] = feval(fobj,feasible_sol);
trial(i,:) = feasible_sol;
nfe = nfe + 1;
if Fitsniff(i) <= Fit(i)
molecules(i,:) = trial(i,:);
Fit(i) = Fitsniff(i);
else
CR(i) = CRold(i);
end
end
% for i=1:nPop
% for j=1:nVar
% % Update the molecular Velocity
% v(i,j)=(v(i,j)+rand*sqrt(3*K*T/m));
% end
% end
[Fitsniffmin,sindex] = min(Fitsniff);
xs_agent = molecules(sindex,:);
[~,sidx] = max(Fitsniff);
x_worst = molecules(sidx,:);
CRold = CR;
% Trailing mode
for i=1:nPop
% Generate CR
if rand < tau2
CR(i) = 0.0 + 1.0 * rand(1, 1);
end
trial(i,:) = molecules(i,:);
% for j=i:nVar
% % molecules(i,j)=molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))...
% % -rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
% mutant(i,j)=molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))...
% -rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
% end
% binomial crossover
jrand = randi(D);
for j=1:nVar
if rand <= CR(i) || j == jrand
trial(i,j) = molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))-rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
end
end
% % exponential crossover
% jrand = randi(D);
% L = 0;
% while (rand <= CR(i)) && (L < D)
% j = mod(jrand + L - 1, D) + 1;
% trial(i,j) = molecules(i,j)+rand*olf*(x_agent(1,j)-abs(molecules(i,j)))-rand*olf*(x_worst(1,j)-abs(molecules(i,j)));
% L = L + 1;
% end
% Make sure no smell molecules excape the boundary
trial(i,:) = clipboundry(lb,ub,trial(i,:));
% Evaluation
feasible_sol = FeasibleFunction(trial(i,:),eval_setting);
[Fitstrail(i),~,~] = feval(fobj,feasible_sol);
trial(i,:) = feasible_sol;
nfe = nfe + 1;
if Fitstrail(i) <= Fit(i)
molecules(i,:) = trial(i,:);
Fit(i) = Fitstrail(i);
else
CR(i) = CRold(i);
end
end
CRold = CR;
% Random mode
for i=1:nPop
% Generate CR
if rand < tau2
CR(i) = 0.0 + 1.0 * rand(1, 1);
end
trial(i,:) = molecules(i,:);
% binomial crossover
jrand = randi(D);
for j=1:nVar
if rand <= CR(i) || j == jrand
trial(i,j) = molecules(i,j)+LnF2(golden_ratio,0.05,1,1);
end
end
% % exponential crossover
% jrand = randi(D);
% L = 0;
% while (rand <= CR(i)) && (L < D)
% j = mod(jrand + L - 1, D) + 1;
% trial(i,j) = molecules(i,j)+LnF2(golden_ratio,0.05,1,1);
% L = L + 1;
% end
% Make sure no smell molecules excape the boundary
trial(i,:) = clipboundry(lb,ub,trial(i,:));
% Evaluation
feasible_sol = FeasibleFunction(trial(i,:),eval_setting);
[Fitsrand(i),~,~] = feval(fobj,feasible_sol);
trial(i,:) = feasible_sol;
nfe = nfe + 1;
if Fitsrand(i) <= Fit(i)
molecules(i,:) = trial(i,:);
Fit(i) = Fitsrand(i);
else
CR(i) = CRold(i);
end
end
[bestFit,bestIdx] = min(Fit);
best_x = molecules(bestIdx,:);
best_cost = bestFit;
convergence_curve = [convergence_curve best_cost];
cul_solution = [cul_solution best_x];
cul_nfe = [cul_nfe nfe];
end
end
function mole=Initialize(nPop,nVar,lb,ub)
for i=1:nPop
for j=1:nVar
mole(i,j)=lb(j)+rand()*(ub(j)-lb(j)); % Defind the initial positions of the smell molecules.
end
end
end
function molecules=clipboundry(lb,ub,molecules)
[nPop,nVar]=size(molecules);
for i=1:nPop
for j=1:nVar
if molecules(i,j)<lb(j)
molecules(i,j)=lb(j);
elseif molecules(i,j)>ub(j)
molecules(i,j)=ub(j);
end
end
end
end
function trial = binomialCrossover(target, mutant, CR, D)
jrand = randi(D);
trial = target;
for j = 1:D
if rand <= CR || j == jrand
trial(j) = mutant(j);
end
end
end
function trial = exponentialCrossover(target, mutant, CR, D)
jrand = randi(D);
L = 0;
trial = target;
while (rand <= CR) && (L < D)
trial(mod(jrand + L - 1, D) + 1) = mutant(mod(jrand + L - 1, D) + 1);
L = L + 1;
end
end
function xhold = LnF2(alpha,scale,m, n)
xhold = laprnd(m, n, 0, 1);
% xhold = randl(m,n); %Laplacian distributed pseudorandom numbers.
SE = sign(rand(m,n)-0.5) .* xhold;
% U = rand(1,n);
U = rand(m,n);
xhold = (sin(0.5*pi*alpha).*cot(0.5*pi*(alpha*U))-cos(0.5*pi*alpha)).^(1/alpha);
xhold = scale .* SE ./ xhold;
end
function y = laprnd(m, n, mu, sigma)
% LAPRND generate i.i.d. laplacian random number drawn from laplacian distribution
% with mean mu and standard deviation sigma.
% mu : mean
% sigma : standard deviation
% [m, n] : the dimension of y.
% Default mu = 0, sigma = 1.
% For more information, refer to
% http://en.wikipedia.org./wiki/Laplace_distribution
% Author : Elvis Chen (bee33@sjtu.edu.cn)
% Date : 01/19/07
% Check inputs
if nargin < 2
error('At least two inputs are required');
end
if nargin == 2
mu = 0; sigma = 1;
end
if nargin == 3
sigma = 1;
end
% Generate Laplacian noise
u = rand(m, n)-0.5;
b = sigma / sqrt(2);
y = mu - b * sign(u).* log(1- 2* abs(u));
end
4.参考文献
[1]Duankhan P, Sunat K, Soomlek C. An Adaptive Smell Agent Optimization with Binomial Crossover and Linnik Flight for Engineering Optimization Problems[C]//2024 28th International Computer Science and Engineering Conference (ICSEC). IEEE, 2024: 1-6.
完整代码获取
后台回复关键词:
TGDM839
获取更多代码:
或者复制链接跳转:
https://docs.qq.com/sheet/DU3NjYkF5TWdFUnpu