人工鱼群算法是一种受鱼群聚集规律而启发的优化算法. 在人工鱼群算法中, 我们假定鱼群的活动行为分为: 觅食行为, 群聚行为, 追随行为和随机行为.
觅食行为, 基于 “鱼倾向于游向食物最多的水域” 这一假设, 等价于在寻找最优解的过程中, 向相对较优的方向行进的迭代原则.
群聚行为, 借鉴了真实鱼群中, 落单的个体总倾向于回到群体的特性. 这一行为受三条子规则所限定:
追尾行为, 确保了每一个人工鱼个体均会追逐临近的最活跃个体. 它等价于在优化过程中, 向位于当前点附近的, 极优化点前进的过程.
随机行为, 保证了人工鱼在 “目力所及范围内” 随机移动. 这样有助于在寻找最优解过程中跳出局部最优.
我们规定以下变量和符号:
n
目标空间维度N
人工鱼数量X
每条人工鱼状态 X = ( x 1 , x 2 , ⋯ , x n ) X = (x_1, x_2, \cdots, x_n) X=(x1,x2,⋯,xn), 各分量为需要寻找最优的变量Y
Y = f ( X ) Y = f(X) Y=f(X), 人工鱼所在位置的食物浓度, 即寻优过程中的适应度.d
人工鱼个体间距离, d = ∣ ∣ x i − x j ∣ ∣ d = ||x_i - x_j|| d=∣∣xi−xj∣∣v
人工鱼感知范围s
人工鱼移动步长δ
拥挤度因子, 反映拥挤程度t
人工鱼每次觅食最大尝试次数觅食行为, 指人工鱼总是倾向于沿食物较多的方向游动的行为. 逻辑如下:
对于每一条人工鱼 X i X_i Xi, 它按照规则
X j = X i + r a n d ( ) ⋅ v X_j = X_i + rand()\cdot v Xj=Xi+rand()⋅v
随机选定一个新状态 X j X_j Xj, 并比照新旧两个状态的适应度.
若 X j X_j Xj 适应度高于 X i X_i Xi, 则该鱼按照规则
X i ′ = X i + r a n d ( ) ⋅ s ⋅ X j − X i ∣ ∣ X j − X i ∣ ∣ X_i' = X_i + rand()\cdot s\cdot \frac{X_j - X_i}{||X_j - X_i||} Xi′=Xi+rand()⋅s⋅∣∣Xj−Xi∣∣Xj−Xi
向 X j X_j Xj 方向前进一个步长.
若反复判断 t t t 次后仍然无法在附近找到优于现有状态 X i X_i Xi 的新状态, 人工鱼将依据规则
X i ′ = X i + r a n d ( ) ⋅ s X_i' = X_i + rand()\cdot s Xi′=Xi+rand()⋅s
随机移动一个步长.
真实世界中的鱼群在游弋过程中为了躲避敌害会自然地群聚. 逻辑如下:
function [x_swarm, x_swarm_fitness] = swarm(x,i,N,v,f,delta,t,d,ub,lb,s)
%% Compute fitness rate under the circunstance of SWARMING
nf_swarm = 0;
Xc = 0;
label_swarm = 0; % The sign of swarming happened or not
% Fix the Position of the center, compute the number of companions
for j = 1:N
if norm(x(j,:) - x(i,:)) < v
nf_swarm = nf_swarm + 1; % COunt the number of companions
Xc = Xc + x(j,:); % Add up the number of Sakanas
end
end
Xc = Xc - x(i,:); % Delete myself
nf_swarm = nf_swarm - 1;
Xc = Xc / nf_swarm;
% Judge the center is narrow or not
if (f(Xc)/nf_swarm < delta*f(x(i,:))) && (f(Xc) < f(x(i,:)))
x_swarm = x(i,:) + rand*s.*(Xc - x(i,:)) ./ norm(Xc - x(i,:));
%Bound processing
ub_flag = x_swarm > ub;
lb_flag = x_swarm < lb;
x_swarm = (x_swarm .* (~(ub_flag + lb_flag))) + ub .* ub_flag + lb .* lb_flag;
x_swarm_fitness = f(x_swarm);
else
% PREYING
label_prey = 0; % A sign of whether preying will find a better state than current state
for j = 1:t
%Find a state randomly
x_prey_rand = x(i,:) + v .* (-1 + 2 .* rand(1,d));
ub_flag2 = x_prey_rand > ub;
lb_flag2 = x_prey_rand < lb;
x_prey_rand = (x_prey_rand .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
%judgement: better, or not?
if f(x(i,:)) > f(x_prey_rand)
x_swarm = x(i,:) + rand*s .* (x_prey_rand - x(i,:)) ./ norm(x_prey_rand - x(i,:));
ub_flag2 = x_swarm > ub;
lb_flag2 = x_swarm < lb;
x_swarm = (x_swarm .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
x_swarm_fitness = f(x_swarm);
label_prey = 1;
break;
end
end
% Acting randomly
if label_prey == 0
x_swarm = x(i,:) + s * (-1 + 2*rand(1,d));
ub_flag2 = x_swarm > ub;
lb_flag2 = x_swarm < lb;
x_swarm = (x_swarm .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
x_swarm_fitness = f(x_swarm);
end
end
end
执行追尾过程时, 人工鱼将向其视野内适应度最高的个体移动. 逻辑如下:
function [x_follow, x_follow_fitness] = follow(x,i,N,v,f,delta,t,d,ub,lb,s)
fitness_follow = inf;
label_follow = 0; % A Sign marking following has happened or not
% Search the *best* individual in sight
for j = 1:N
if (norm(x(j,:) - x(i,:)) < v) && (f(x(j,:)) < fitness_follow)
best_pos = x(j,:);
fitness_follow = f(x(j,:));
end
end
%Search The Number Of Companions In Sight
nf_follow = 0;
for j = 1:N
if norm(x(j,:) - best_pos) < v
nf_follow = nf_follow + 1;
end
end
nf_follow = nf_follow - 1; % Delete myself
% Judge: The Center Is Narrow or not?
if (fitness_follow/nf_follow) ub;
lb_flag2 = x_follow < lb;
x_follow = (x_follow .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
label_follow = 1;
x_follow_fitness = f(x_follow);
else
% PREYING
label_prey = 0; % A sign of whether preying will find a better state than current state
for j = 1:t
%Find a state randomly
x_prey_rand = x(i,:) + v .* (-1 + 2 .* rand(1,d));
ub_flag2 = x_prey_rand > ub;
lb_flag2 = x_prey_rand < lb;
x_prey_rand = (x_prey_rand .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
%judgement: better, or not?
if f(x(i,:)) > f(x_prey_rand)
x_follow = x(i,:) + rand*s .* (x_prey_rand - x(i,:)) ./ norm(x_prey_rand - x(i,:));
ub_flag2 = x_follow > ub;
lb_flag2 = x_follow < lb;
x_follow = (x_follow .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
x_follow_fitness = f(x_follow);
label_prey = 1;
break;
end
end
%random behaviour
if label_prey == 0
x_follow = x(i,:) + s .* (-1 + 2*rand(1,d));
ub_flag2 = x_follow > ub;
lb_flag2 = x_follow < lb;
x_follow = (x_follow .* (~(ub_flag2 + lb_flag2))) + ub .* ub_flag2 + lb .* lb_flag2;
x_follow_fitness = f(x_follow);
end
end
在上文所提到的 “觅食行为” 的最后一种判断情况中, 人工鱼将会执行的行为就是随机行为.
附主函数代码如下:
clc; clear all;
%% Define variables
v = 25; %Perception Distance
s = 3; %Maximum Step Size
N = 30; %The Number Of Artificial Sakana
d = 10; %Current Dimension
t = 50; %Maximum Iteration Time
delta = 27; %Factor of Congestion
%% Construct a function for testing
f = @(x) sum(3*x.^4);
ub = 100; %Upper Limit Of Boundrary
lb = -100; %Lower Limit Of Boundrary
df = []; %Store Target Function value of 50 states
Iteration = 1; %Initialize Iteration Rate
Max_iteration = 500; %Maximum Iteration Rate
%% Initialize Artificial Sakana Group
x = lb + rand(N,d).*(ub - lb);
%% Compute fitness rate of 10 initial state
for i = 1:N
fitness_sakana(i) = f(x(i,:));
end
%% Define Best Fitness of Initial State
[best_fitness,I] = min(fitness_sakana);
best_x = x(I); %Best Artificial Sakana At Initial State
while Iteration <= Max_iteration
for i = 1:N
%%Swarm
[x_swarm, x_swarm_fitness] = swarm(x,i,N,v,f,delta,t,d,ub,lb,s);
%%Follow
[x_follow, x_follow_fitness] = follow(x,i,N,v,f,delta,t,d,ub,lb,s);
%%Judgement
if x_follow_fitness < x_swarm_fitness
x(i,:) = x_follow;
else
x(i,:) = x_swarm;
end
end
%% Update Information In Time
for i = 1:N
if (f(x(i,:)) < best_fitness)
best_fitness = f(x(i,:));
best_x = x(i,:);
end
end
Convergence_curve(Iteration) = best_fitness;
Iteration = Iteration + 1;
%% Display Iteration Time And Current Best Fit Rate
if mod(Iteration, 25) == 0
display(['Iteration times: ',num2str(Iteration),'BestFitRate: ',num2str(best_fitness)]);
display(['BestArtificialSakana: ', num2str(best_x)]);
end
end
%% Print
figure('Position', [284 214 660 290])
subplot(1,2,1);
x = -100:1:100;
y = x;
L = length(x);
for i = 1:L
for j = 1:L
F(i,j) = (3*x(i) .^4) + (3*y(j) .^4);
end
end
surfc(x,y,F,'LineStyle', 'none');
title('Test Function')
xlabel('x_1');
ylabel('y_1');
zlabel(['sum','(x_1,x_2)'])
grid on
subplot(1,2,2);
semilogy(Convergence_curve, 'Color','r')
title('Convergence Curve')
xlabel('Iteration');
ylabel('Best Fitness');
axis tight
grid on
box on