上一篇介绍了蚁狮算法的数学模型:
【蚁狮算法】《The Ant Lion Optimizer》原文翻译(附源代码)
蚁狮算法matlab源代码下载地址:
http://www.alimirjalili.com/SourceCodes/ALO.zip
地址2:下载地址
下载之后可以看到代码目录如下:
接下来将一一解析m文件
目录
main.m
设置参数并显示优化结果
参数:
fobj:成本函数
dim:变量维度
Max_iteration:最大迭代次数
SearchAgents_no:蚁狮的数量
lb=[lb1,lb2,...,lbn]:lb 是n个变量中最小的数
ub=[ub1,ub2,...,ubn]:ub 是n个变量中最大的数
(参考各函数对应的取值范围,如果所有的变量都有相等的下限,你可以直接将 lb 和 ub 定义为同一个的数字)
Function_name:测试函数,可设为 F1~F23,函数的定义见 Get_Functions_details.m
代码:
% You can simply define your cost in a seperate file and load its handle to fobj
% The initial parameters that you need are:
%__________________________________________
% fobj = @YourCostFunction
% dim = number of your variables
% Max_iteration = maximum number of generations
% SearchAgents_no = number of search agents
% lb=[lb1,lb2,...,lbn] where lb is the lower bound of variable n
% ub=[ub1,ub2,...,ubn] where ub is the upper bound of variable n
% If all the variables have equal lower bound you can just
% define lb and ub as two single number numbers
% To run ALO: [Best_score,Best_pos,cg_curve]=ALO(SearchAgents_no,Max_iteration,lb,ub,dim,fobj)
%__________________________________________
clear all
clc
SearchAgents_no=40; % Number of search agents
Function_name='F1'; % Name of the test function that can be from F1 to F23 (Table 1,2,3 in the paper)
Max_iteration=500; % Maximum numbef of iterations
% Load details of the selected benchmark function
[lb,ub,dim,fobj]=Get_Functions_details(Function_name);
[Best_score,Best_pos,cg_curve]=ALO(SearchAgents_no,Max_iteration,lb,ub,dim,fobj);
figure('Position',[500 500 660 290])
%Draw search space
subplot(1,2,1);
func_plot(Function_name);
title('Test function')
xlabel('x_1');
ylabel('x_2');
zlabel([Function_name,'( x_1 , x_2 )'])
grid off
%Draw objective space
subplot(1,2,2);
semilogy(cg_curve,'Color','r')
title('Convergence curve')
xlabel('Iteration');
ylabel('Best score obtained so far');
axis tight
grid off
box on
legend('ALO')
display(['The best solution obtained by ALO is : ', num2str(Best_pos)]);
display(['The best optimal value of the objective funciton found by ALO is : ', num2str(Best_score)]);
Get_Functions_details.m
测试所用的函数。根据论文中函数的定义,利用 switch-case 结构编写代码。
单峰基准函数:
多峰基准函数:
复合基准函数:
代码:
function [lb,ub,dim,fobj] = Get_Functions_details(F)
switch F
case 'F1'
fobj = @F1;
lb=-100;
ub=100;
dim=10;
case 'F2'
fobj = @F2;
lb=-10;
ub=10;
dim=10;
case 'F3'
fobj = @F3;
lb=-100;
ub=100;
dim=10;
case 'F4'
fobj = @F4;
lb=-100;
ub=100;
dim=10;
case 'F5'
fobj = @F5;
lb=-30;
ub=30;
dim=10;
...
% F1
function o = F1(x)
o=sum(x.^2);
end
% F2
function o = F2(x)
o=sum(abs(x))+prod(abs(x));
end
% F3
function o = F3(x)
dim=size(x,2);
o=0;
for i=1:dim
o=o+sum(x(1:i))^2;
end
end
...
func_plot.m
绘制函数图像
代码:
% This function draws the benchmark functions
function func_plot(func_name)
[lb,ub,dim,fobj]=Get_Functions_details(func_name);
switch func_name
case 'F1'
x=-100:2:100; y=x; %[-100,100]
case 'F2'
x=-100:2:100; y=x; %[-10,10]
case 'F3'
x=-100:2:100; y=x; %[-100,100]
case 'F4'
x=-100:2:100; y=x; %[-100,100]
case 'F5'
x=-200:2:200; y=x; %[-5,5]
case 'F6'
x=-100:2:100; y=x; %[-100,100]
case 'F7'
x=-1:0.03:1; y=x %[-1,1]
case 'F8'
x=-500:10:500;y=x; %[-500,500]
case 'F9'
x=-5:0.1:5; y=x; %[-5,5]
case 'F10'
x=-20:0.5:20; y=x;%[-500,500]
case 'F11'
x=-500:10:500; y=x;%[-0.5,0.5]
case 'F12'
x=-10:0.1:10; y=x;%[-pi,pi]
case 'F13'
x=-5:0.08:5; y=x;%[-3,1]
case 'F14'
x=-100:2:100; y=x;%[-100,100]
case 'F15'
x=-5:0.1:5; y=x;%[-5,5]
case 'F16'
x=-1:0.01:1; y=x;%[-5,5]
case 'F17'
x=-5:0.1:5; y=x;%[-5,5]
case 'F18'
x=-5:0.06:5; y=x;%[-5,5]
case 'F19'
x=-5:0.1:5; y=x;%[-5,5]
case 'F20'
x=-5:0.1:5; y=x;%[-5,5]
case 'F21'
x=-5:0.1:5; y=x;%[-5,5]
case 'F22'
x=-5:0.1:5; y=x;%[-5,5]
case 'F23'
x=-5:0.1:5; y=x;%[-5,5]
end
L=length(x);
f=[];
for i=1:L
for j=1:L
if strcmp(func_name,'F15')==0 && strcmp(func_name,'F19')==0 && strcmp(func_name,'F20')==0 && strcmp(func_name,'F21')==0 && strcmp(func_name,'F22')==0 && strcmp(func_name,'F23')==0
f(i,j)=fobj([x(i),y(j)]);
end
if strcmp(func_name,'F15')==1
f(i,j)=fobj([x(i),y(j),0,0]);
end
if strcmp(func_name,'F19')==1
f(i,j)=fobj([x(i),y(j),0]);
end
if strcmp(func_name,'F20')==1
f(i,j)=fobj([x(i),y(j),0,0,0,0]);
end
if strcmp(func_name,'F21')==1 || strcmp(func_name,'F22')==1 ||strcmp(func_name,'F23')==1
f(i,j)=fobj([x(i),y(j),0,0]);
end
end
end
surfc(x,y,f,'LineStyle','none');
end
initialization.m
产生第一代蚂蚁和蚁狮的随机位置
ub 和 lb 由 Get_Functions_details(Function_name) 给出
X=rand(SearchAgents_no,dim).*(ub-lb)+lb 和 X(:,i)=rand(SearchAgents_no,1).*(ub_i-lb_i)+lb_i 都是归一化操作
对照原文:
其中 是第 i 个变量的随机游走的最小值, 是第 i 个变量中的随机游走的最大值, 是在第 t 次迭代时第 i 个变量的最小值, 表示第 t 次迭代的第 i 个变量的最大值。
代码:
function X=initialization(SearchAgents_no,dim,ub,lb)
Boundary_no= size(ub,2); % 边界数量
% 如果所有变量的边界相等
if Boundary_no==1
X=rand(SearchAgents_no,dim).*(ub-lb)+lb;
end
% 如果不同变量的边界不同
if Boundary_no>1
for i=1:dim
ub_i=ub(i);
lb_i=lb(i);
X(:,i)=rand(SearchAgents_no,1).*(ub_i-lb_i)+lb_i;
end
end
ALO.m
初始化蚁狮 antlion_position 和蚂蚁的位置 ant_position,初始化排序后蚁狮位置 Sorted_antlions 、精英蚁狮位置 Elite_antlion_position 、精英蚁狮适应度 Elite_antlion_fitness 、收敛曲线 Convergence_curve 、蚁狮适应度 antlions_fitness 、蚂蚁适应度 ants_fitness 。
% 初始化蚁狮和蚂蚁的位置
antlion_position=initialization(N,dim,ub,lb);
ant_position=initialization(N,dim,ub,lb);
% 初始化排序后蚁狮位置、精英蚁狮位置、精英蚁狮适应度、收敛曲线、蚁狮适应度、蚂蚁适应度
Sorted_antlions=zeros(N,dim);
Elite_antlion_position=zeros(1,dim);
Elite_antlion_fitness=inf;
Convergence_curve=zeros(1,Max_iter);
antlions_fitness=zeros(1,N);
ants_fitness=zeros(1,N);
根据损失函数 fobj (由Get_Functions_details.m给出)计算第一代的蚁狮适应度并用 sort 函数排序,将计算结果最小即适应度最大的蚁狮设为精英蚁狮。
for i=1:size(antlion_position,1)
antlions_fitness(1,i)=fobj(antlion_position(i,:));
end
[sorted_antlion_fitness,sorted_indexes]=sort(antlions_fitness);
for newindex=1:N
Sorted_antlions(newindex,:)=antlion_position(sorted_indexes(newindex),:);
end
Elite_antlion_position=Sorted_antlions(1,:);
Elite_antlion_fitness=sorted_antlion_fitness(1);
设 Max_iter = 500 , N = 40 , ub = 100 , lb = -100 , dim = 10 , fobj 选择 F1,运行后得到40个蚁狮适应度 antlions_fitness 如下:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
3.1682E+04 | 2.6423E+04 | 3.4530E+04 | 2.5782E+04 | 2.5871E+04 | 2.0789E+04 | 2.2776E+04 | 2.9961E+04 | 3.3678E+04 | 2.2502E+04 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
3.9170E+04 | 5.4611E+04 | 3.1453E+04 | 5.1486E+04 | 2.9454E+04 | 3.6621E+04 | 3.1134E+04 | 3.7848E+04 | 2.2054E+04 | 3.3569E+04 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
3.2711E+04 | 1.8926E+04 | 4.8014E+04 | 3.5212E+04 | 3.8204E+04 | 2.7096E+04 | 3.9511E+04 | 2.1456E+04 | 2.4023E+04 | 3.6770E+04 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
3.2601E+04 | 3.8330E+04 | 3.7943E+04 | 3.1210E+04 | 2.5815E+04 | 2.3642E+04 | 3.7308E+04 | 2.0577E+04 | 2.0519E+04 | 4.3865E+04 |
经过排序后的蚁狮适应度 sorted_antlion_fitness:(利用 sort 函数升序排列)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1.8926E+04 | 2.0519E+04 | 2.0577E+04 | 2.0789E+04 | 2.1456E+04 | 2.2054E+04 | 2.2502E+04 | 2.2776E+04 | 2.3642E+04 | 2.4023E+04 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
2.5782E+04 | 2.5815E+04 | 2.5871E+04 | 2.6423E+04 | 2.7096E+04 | 2.9454E+04 | 2.9961E+04 | 3.1134E+04 | 3.1210E+04 | 3.1453E+04 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
3.1682E+04 | 3.2601E+04 | 3.2711E+04 | 3.3569E+04 | 3.3678E+04 | 3.4530E+04 | 3.5212E+04 | 3.6621E+04 | 3.6770E+04 | 3.7308E+04 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
3.7848E+04 | 3.7943E+04 | 3.8204E+04 | 3.8330E+04 | 3.9170E+04 | 3.9511E+04 | 4.3865E+04 | 4.8014E+04 | 5.1486E+04 | 5.4611E+04 |
排序后的索引 sorted_indexes:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
22 | 39 | 38 | 6 | 28 | 19 | 10 | 7 | 36 | 29 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
4 | 35 | 5 | 2 | 26 | 15 | 8 | 17 | 34 | 13 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
1 | 31 | 21 | 20 | 9 | 3 | 24 | 16 | 30 | 37 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
18 | 33 | 25 | 32 | 11 | 27 | 40 | 23 | 14 | 12 |
最后得到的精英蚁狮的适应度 Elite_antlion_fitness 为18926.1875069310 。(当然,每次运行的结果都不一样,因为初始位置为随机数)接着用轮盘赌算法选择蚁狮。
for i=1:size(ant_position,1)
% 选择适应度更高的蚁狮,适应度高的蚁狮捕获蚂蚁的概率越高
Rolette_index=RouletteWheelSelection(1./sorted_antlion_fitness);
if Rolette_index==-1
Rolette_index=1;
end
% RA是通过轮盘赌的方式在选定的蚁狮周围随机行走
RA=Random_walk_around_antlion(dim,Max_iter,lb,ub, Sorted_antlions(Rolette_index,:),Current_iter);
% RE是随机游走的蚁狮精英(目前为止最好的蚁狮)
RE=Random_walk_around_antlion(dim,Max_iter,lb,ub, Elite_antlion_position(1,:),Current_iter);
% 根据公式计算出蚂蚁位置
ant_position(i,:)= (RA(Current_iter,:)+RE(Current_iter,:))/2; % Equation (2.13) in the paper
end
根据公式 进行精益化。
(其中 是在第 t 次迭代时轮盘选择的蚁狮随机游走, 是第 t 次迭代时围绕精英的随机游走, 表示第 只蚂蚁在第 次迭代的位置)
代码:
% You can simply define your cost in a seperate file and load its handle to fobj
% The initial parameters that you need are:
%__________________________________________
% fobj = @YourCostFunction
% dim = number of your variables
% Max_iteration = maximum number of generations
% SearchAgents_no = number of search agents
% lb=[lb1,lb2,...,lbn] where lbn is the lower bound of variable n
% ub=[ub1,ub2,...,ubn] where ubn is the upper bound of variable n
% If all the variables have equal lower bound you can just
% define lb and ub as two single number numbers
% To run ALO: [Best_score,Best_pos,cg_curve]=ALO(SearchAgents_no,Max_iteration,lb,ub,dim,fobj)
function [Elite_antlion_fitness,Elite_antlion_position,Convergence_curve]=ALO(N,Max_iter,lb,ub,dim,fobj)
% Initialize the positions of antlions and ants
antlion_position=initialization(N,dim,ub,lb);
ant_position=initialization(N,dim,ub,lb);
% Initialize variables to save the position of elite, sorted antlions,
% convergence curve, antlions fitness, and ants fitness
Sorted_antlions=zeros(N,dim);
Elite_antlion_position=zeros(1,dim);
Elite_antlion_fitness=inf;
Convergence_curve=zeros(1,Max_iter);
antlions_fitness=zeros(1,N);
ants_fitness=zeros(1,N);
% Calculate the fitness of initial antlions and sort them
for i=1:size(antlion_position,1)
% antlions_fitness(1,i)=fobj(antlion_position(i,:));
antlions_fitness(1,i)=sum((antlion_position(i,:)).^2);
end
[sorted_antlion_fitness,sorted_indexes]=sort(antlions_fitness);
for newindex=1:N
Sorted_antlions(newindex,:)=antlion_position(sorted_indexes(newindex),:);
end
Elite_antlion_position=Sorted_antlions(1,:);
Elite_antlion_fitness=sorted_antlion_fitness(1);
% Main loop start from the second iteration since the first iteration
% was dedicated to calculating the fitness of antlions
Current_iter=2;
while Current_iter<Max_iter+1
% This for loop simulate random walks
for i=1:size(ant_position,1)
% Select ant lions based on their fitness (the better anlion the higher chance of catching ant)
Rolette_index=RouletteWheelSelection(1./sorted_antlion_fitness);
if Rolette_index==-1
Rolette_index=1;
end
% RA is the random walk around the selected antlion by rolette wheel
RA=Random_walk_around_antlion(dim,Max_iter,lb,ub, Sorted_antlions(Rolette_index,:),Current_iter);
% RA is the random walk around the elite (best antlion so far)
RE=Random_walk_around_antlion(dim,Max_iter,lb,ub, Elite_antlion_position(1,:),Current_iter);
ant_position(i,:)= (RA(Current_iter,:)+RE(Current_iter,:))/2; % Equation (2.13) in the paper
end
for i=1:size(ant_position,1)
% Boundar checking (bring back the antlions of ants inside search
% space if they go beyoud the boundaries
Flag4ub=ant_position(i,:)>ub;
Flag4lb=ant_position(i,:)<lb;
ant_position(i,:)=(ant_position(i,:).*(~(Flag4ub+Flag4lb)))+ub.*Flag4ub+lb.*Flag4lb;
ants_fitness(1,i)=fobj(ant_position(i,:));
end
% Update antlion positions and fitnesses based of the ants (if an ant
% becomes fitter than an antlion we assume it was cought by the antlion
% and the antlion update goes to its position to build the trap)
double_population=[Sorted_antlions;ant_position];
double_fitness=[sorted_antlion_fitness ants_fitness];
[double_fitness_sorted I]=sort(double_fitness);
double_sorted_population=double_population(I,:);
antlions_fitness=double_fitness_sorted(1:N);
Sorted_antlions=double_sorted_population(1:N,:);
% Update the position of elite if any antlinons becomes fitter than it
if antlions_fitness(1)<Elite_antlion_fitness
Elite_antlion_position=Sorted_antlions(1,:);
Elite_antlion_fitness=antlions_fitness(1);
end
% Keep the elite in the population
Sorted_antlions(1,:)=Elite_antlion_position;
antlions_fitness(1)=Elite_antlion_fitness;
% Update the convergence curve
Convergence_curve(Current_iter)=Elite_antlion_fitness;
% Display the iteration and best optimum obtained so far
if mod(Current_iter,50)==0
display(['At iteration ', num2str(Current_iter), ' the elite fitness is ', num2str(Elite_antlion_fitness)]);
end
Current_iter=Current_iter+1;
end
RouletteWheelSelection.m
用轮盘赌算法选择蚁狮。用一组权重代表在一组中每个蚁狮被选中的概率,返回被选中的蚁狮的索引。例如:fortune_wheel ([1 5 3 15 8 1]),最有可能的结果是4(权重15)。
代码:
function choice = RouletteWheelSelection(weights)
accumulation = cumsum(weights); % 计算权重总和
p = rand() * accumulation(end); % rand()生成0-1的随机数
chosen_index = -1;
for index = 1 : length(accumulation)
if (accumulation(index) > p)
chosen_index = index; % 被选中的概率最大
break;
end
end
choice = chosen_index;
Random_walk_around_antlion.m
由于蚁狮从坑的中心向外射沙,蚂蚁随机游走超球面的半径会自适应地减小:
lb=lb/(I);
ub=ub/(I);
其中 为比率,根据以下公式可以修改比率 的大小:
I=1; % 当 current_iter <= 0.1 * max_iter 时
% 当 current_iter > 0.1 * max_iter 时
if current_iter>max_iter/10
I=1+100*(current_iter/max_iter);
end
if current_iter>max_iter/2
I=1+1000*(current_iter/max_iter);
end
if current_iter>max_iter*(3/4)
I=1+10000*(current_iter/max_iter);
end
if current_iter>max_iter*(0.9)
I=1+100000*(current_iter/max_iter);
end
if current_iter>max_iter*(0.95)
I=1+1000000*(current_iter/max_iter);
end
根据以下公式移动蚁狮位置:
if rand<0.5
lb=lb+antlion;
else
lb=-lb+antlion;
end
if rand>=0.5
ub=ub+antlion;
else
ub=-ub+antlion;
end
创建n次游走,并初始化向量 lb 和 ub:
for i=1:Dim
X = [0 cumsum(2*(rand(max_iter,1)>0.5)-1)'];
%[a b]--->[c d]
a=min(X);
b=max(X);
c=lb(i);
d=ub(i);
X_norm=((X-a).*(d-c))./(b-a)+c;
RWs(:,i)=X_norm;
end
代码:
% This function creates random walks
function [RWs]=Random_walk_around_antlion(Dim,max_iter,lb, ub,antlion,current_iter)
if size(lb,1) ==1 && size(lb,2)==1 %Check if the bounds are scalar
lb=ones(1,Dim)*lb;
ub=ones(1,Dim)*ub;
end
if size(lb,1) > size(lb,2) %Check if boundary vectors are horizontal or vertical
lb=lb';
ub=ub';
end
I=1; % I is the ratio in Equations (2.10) and (2.11)
if current_iter>max_iter/10
I=1+100*(current_iter/max_iter);
end
if current_iter>max_iter/2
I=1+1000*(current_iter/max_iter);
end
if current_iter>max_iter*(3/4)
I=1+10000*(current_iter/max_iter);
end
if current_iter>max_iter*(0.9)
I=1+100000*(current_iter/max_iter);
end
if current_iter>max_iter*(0.95)
I=1+1000000*(current_iter/max_iter);
end
% Dicrease boundaries to converge towards antlion
lb=lb/(I); % Equation (2.10) in the paper
ub=ub/(I); % Equation (2.11) in the paper
% Move the interval of [lb ub] around the antlion [lb+anlion ub+antlion]
if rand<0.5
lb=lb+antlion; % Equation (2.8) in the paper
else
lb=-lb+antlion;
end
if rand>=0.5
ub=ub+antlion; % Equation (2.9) in the paper
else
ub=-ub+antlion;
end
% This function creates n random walks and normalize accroding to lb and ub
% vectors
for i=1:Dim
X = [0 cumsum(2*(rand(max_iter,1)>0.5)-1)']; % Equation (2.1) in the paper
%[a b]--->[c d]
a=min(X);
b=max(X);
c=lb(i);
d=ub(i);
X_norm=((X-a).*(d-c))./(b-a)+c; % Equation (2.7) in the paper
RWs(:,i)=X_norm;
end