人工鱼群算法(AF)

该博客介绍了人工鱼群算法(Artificial Fish School Algorithm, AFSA)的基本思想和核心步骤,包括觅食、聚群、追尾和随机行为,并通过C++和MATLAB代码展示了如何模拟这些行为以解决二维空间中的优化问题。算法利用鱼的行为模式寻找最佳解决方案,具有较好的全局寻优能力。
摘要由CSDN通过智能技术生成

基本思想

        一片水域,如果某个地方的鱼类数目最多,那么这个地方一般来说就是水域内富含营养物质最多的地方,依据这一特点来模仿鱼群的觅食、聚群、追尾、随机行为,以实现全局寻优的目的。

算法的主要行为(核心步骤)

1、觅食行为

        人工鱼​在其视野内随机选择一个状态,分别计算它们的目标函数值进行比较,如果发现比当前值优,则向优化的方向移动一步;否则,继续在其视野内随机选择状态,判断是否满足前进条件;这样反复尝试n次(为设定值)后,如果仍不满足前进条件,则随机移动一步。

2、聚群行为

        大量或少量的鱼都能聚集成群,这是它们在进化过程中形成的一种生存方式,可以进行集体觅食和躲避敌害。

抽象成规则:

        分割规则,尽量避免与邻近伙伴过于拥挤;

        对准规则,尽量与邻接伙伴的平均方向一致;

        内聚规则,尽量朝邻近伙伴的重心移动。

        人工鱼搜索其视野内的伙伴数目及中心位置,若单位食物密度比现在大,表明伙伴中心有较多的食物(位置状态较优)且不太拥挤,则朝伙伴的中心位置移动一步,否则执行觅食行为。

3、追尾行为

鱼向其可视区域内的最优方向移动的一种行为。

     人工鱼搜索其视野内所有伙伴中的函数最优伙伴。如果,表明最优伙伴X j X_jX j​ 具有较高的食物浓度并且其周围不太拥挤,则朝伙伴的方向前进;否则执行觅食行为。

4、随机行为

        随机行为指人工鱼在视野内随机移动,当发现食物时,会向食物逐渐增多的方向快速移动。随机行为的实现较为简单,就是向视野中随机选择一个状态的方向移动,加一个随机因子,懂得都懂。

图像的例子

       假设X是一条鱼所处的位置,这个圆为这条鱼的视野范围,xn1.xn2为另外两条鱼,Xv为这条鱼再某时刻看到的位置,然后就判断Xv点的食物浓度是否比原位置高,如果高就往这个方向去。

                               离散值                                                         连续值

应用实例

 求以上这个函数,其中 s.t.  x ∈ [ − 10 , 10 ] x∈[-10,10]x∈[−10,10] y ∈ [ − 10 , 10 ] y∈[-10,10]y∈[−10,10]

 通过matlab画图得到函数图像如下所示:

matlab代码如下:

X=-10:0.1:10;
Y=-10:0.1:10;X=-10:0.1:10;
Y=-10:0.1:10;
[XX,YY]=meshgrid(X,Y);
Z=sin(XX).*sin(YY)./(XX.*YY);
figure
subplot(1,2,1)
mesh(XX,YY,Z);title('Meshplot');
subplot(1,2,2)
contour(XX,YY,Z);title('Meshplot'); 

[XX,YY]=meshgrid(X,Y);
Z=sin(XX).*sin(YY)./(XX.*YY);
figure
subplot(1,2,1)
mesh(XX,YY,Z);title('Meshplot');
subplot(1,2,2)
contour(XX,YY,Z);title('Meshplot'); 

 AF算法C++代码实现如下:

#include <iostream>
#include <random>
#include<time.h>
#include <math.h>
using namespace std;
double Xmax = 10, Xmin = -10;//变量的可行域
std::default_random_engine random((unsigned int)time(NULL));
std::uniform_real_distribution<double> u(Xmin, Xmax); //随机数分布对象
std::uniform_real_distribution<double> r(-1, 1); //随机数分布对象
struct AF
{
public:
	int dimension;//个体变量维数
	double *X;
	void Init(int Dim)//初始化函数
	{
		dimension = Dim;
		X = new double[dimension];
		for (int j = 0; j < dimension; j++)
			*(X+j) = u(random);
	}
	double fitfunctionvalue()//个体适应值计算函数
	{
		double f = sin(*X)*sin(*(X + 1)) / ((*X) * (*(X + 1)));
		return f;
	}
};
struct YUQUN
{
	public:
		int N;//种群规模
		int Dimension;//维数
		double step = 0;
		double visual = 0;
		double try_number = 0;
		double delta = 0;
		AF *af;
		AF Bestfish;
		void Init(int num, int Dim, double Step, double Visual, double Try_number, double Delta)//初始化函数
		{
			N = num;
			Dimension = Dim;
			step = Step;
			visual = Visual;
			try_number = Try_number;
			delta = Delta;
			af = new AF[num];
			for (int i = 0; i < N; i++)
				(af + i)->Init(Dimension);
			Bestfish.Init(Dimension);
			/*double bestfitvalue = Bestfish.fitfunctionvalue();
			for(int i=0;i<N;i++)
				if ((af + i)->fitfunctionvalue() > bestfitvalue)
				{
					for (int j = 0; j < Dimension; j++)
						Bestfish.X[j] = (af + i)->X[j];
				}*/
		}
		double Distance(AF af1, AF af2)//计算两条鱼距离的函数
		{
			double dist = 0;
			for (int i = 0; i < Dimension; i++)
				dist += pow(af1.X[i] - af2.X[i], 2.0);
			dist = sqrt(dist / float(Dimension));
			return dist;
		}
		void prey(int id)//觅食行为
		{
			AF AFNew;
			AFNew.Init(Dimension);
			for (int i = 0; i < try_number; i++)
			{
				for (int j = 0; j < Dimension; j++)
					AFNew.X[j] = (af+id)->X[j] + r(random) * visual;
				double Yi = 0, Yj = 0;
				Yi = (af + id)->fitfunctionvalue();
				Yj = AFNew.fitfunctionvalue();
				if (Yi < Yj)
				{
					for (int j = 0; j < Dimension; j++)
						(af + id)->X[j] = (af + id)->X[j] + r(random)*step*(AFNew.X[j] - (af + id)->X[j]) / Distance(AFNew, *(af+id));
				}
				else
				{
					for (int j = 0; j < Dimension; j++)
						(af + id)->X[j] = (af + id)->X[j] + r(random)*step;
				}
			}
		}
		void swarm(int id)//聚群行为
		{
			AF AFXc;
			AFXc.Init(Dimension);
			for (int j = 0; j < Dimension; j++) AFXc.X[j] = 0;
			double nf = 0;
			for (int i = 0; i < N; i++)
				if ((Distance(*(af + id), *(af + i)) < visual) && (Distance(*(af+id), *(af + i)) != 0))
				{
					nf++;
					for (int j = 0; j < Dimension; j++) 
						AFXc.X[j] += (af + i)->X[j];
				}
			for (int j = 0; j < Dimension; j++)
				AFXc.X[j] = AFXc.X[j] / nf;//计算邻域伙伴的中心位置
			double Yc= AFXc.fitfunctionvalue(), Yi=(af+id)->fitfunctionvalue();
			if (Yc / nf > delta*Yi)
			{
				for (int j = 0; j < Dimension; j++)
					(af + id)->X[j] = (af + id)->X[j] + r(random)*step*(AFXc.X[j] - (af + id)->X[j]) / Distance(AFXc, *(af + id));
			}
			else
				prey(id);
		}
		void follow(int id)//追尾行为
		{
			double Ymax = -INFINITY;
			AF AFXmax;
			AFXmax.Init(Dimension);
			for (int j = 0; j < Dimension; j++) AFXmax.X[j] = 0;
			for (int i = 0; i < N; i++)
			{
				double dij = Distance(*(af+id), *(af+i)), Yj = (af+i)->fitfunctionvalue();
				if (dij != 0 && dij<visual && Yj >Ymax)
				{
					Ymax = Yj;
					for (int j = 0; j < Dimension; j++)
						AFXmax.X[j] = (af+i)->X[j];
				}
			}
			double nf = 0;
			for (int i = 0; i < N; i++)
			{
				double dmaxj = Distance(AFXmax,*(af+i));
				if (dmaxj != 0 && dmaxj < visual) 
					nf++;
			}
			double Yi = (af + id)->fitfunctionvalue();
			if (Ymax / nf > delta *Yi)
			{
				for (int j = 0; j < Dimension; j++)
					(af+id)->X[j] = (af + id)->X[j] + r(random)*step*(AFXmax.X[j] - (af+id)->X[j]) / Distance(AFXmax, *(af+id));
			}
			else
				prey(id);
		}
		void evaluate(int id)
		{
			if ((af + id)->fitfunctionvalue() > Bestfish.fitfunctionvalue())
			{
				for (int j = 0; j < Dimension; j++)
					Bestfish.X[j] = (af + id)->X[j];
			}
		}
		void run(int itetime)//运行函数
		{
			for (int k = 0; k < itetime; k++)
			{
				for (int i = 0; i < N; i++)
				{
					prey(i);
					swarm(i);
					follow(i);
					evaluate(i);
				}
				std::cout << "第" << k + 1 << "次迭代最优位置为Bestfish:";
				for (int j = 0; j<Dimension; j++)
				{
					if (j == Dimension - 1) std::cout << Bestfish.X[j] <<" "<<Bestfish.fitfunctionvalue()<< endl;
					else std::cout << Bestfish.X[j] << ",";
				}
			}
			std::cout << "迭代结束后最优位置为Bestfish:";
			for (int j = 0; j<Dimension; j++)
			{
				if (j == Dimension - 1) std::cout << Bestfish.X[j] << " " << Bestfish.fitfunctionvalue() << endl;
				else std::cout << Bestfish.X[j] << ",";
			}
		}
		void shuchu()
		{
			for (int i = 0; i < N; i++)
			{
				for (int j = 0; j < Dimension; j++)std::cout << (af + i)->X[j] << " ";
				std::cout << endl;
			}
		}
		void doAFAS(int num, int Dim, double Step, double Visual, double Try_number, double Delta,int Itetime)
		{
			Init(num, Dim, Step, Visual, Try_number, Delta);
			shuchu();
			run(Itetime);
		}
};
int main()
{
	YUQUN yq;
	while (true)
	{
		int num=0;
		std::cout << "请输入迭代的次数:";
		cin >> num;
		if (num == 0)break;
		else yq.doAFAS(10, 2, 0.3, 2.5, 5, 0.618, num);
	}
	system("pause");
	return 0;
}

 AF算法MATLAB实现

%sum(sin(x)./x) 极小值
clear all; 
close all;
clc;

Visual = 25;   %人工鱼的感知距离
Step = 3;     %人工鱼的移动最大步长
N = 30;         %人工鱼的数量
dim=10;          %人工鱼维度
Try_number = 50;%迭代的最大次数
delta=27;     %拥挤度因子

%测试函数
f=@(x) sum(x.^2);
ub=100;%边界上限
lb=-100;%边界下限

d = [];%存储50个状态下的目标函数值;
Iteration = 1; %
Max_iteration = 500;%迭代次数

%初始化人工鱼种群
x=lb+rand(N,dim).*(ub-lb);


%计算10个初始状态下的适应度值;
for i = 1:N
    fitness_fish(i) = f(x(i,:));   
end
[best_fitness,I] = min(fitness_fish);         % 求出初始状态下的最优适应度;
best_x = x(I,:);             % 最优人工鱼;



while Iteration<=Max_iteration
    for i = 1:N
        %% 聚群行为
        nf_swarm=0;
        Xc=0;
        label_swarm =0;  %群聚行为发生标志
        %确定视野范围内的伙伴数目与中心位置
        for j = 1:N 
            if norm(x(j,:)-x(i,:))<Visual
                nf_swarm = nf_swarm+1;  %统计在感知范围内的鱼数量   
                Xc = Xc+x(j,:);       %将感知范围内的鱼进行累加
            end
        end
        Xc=Xc-x(i,:);   %需要去除本身;因为在 一开始计算时,i=j,把中心的鱼也进行了一次计算
        nf_swarm=nf_swarm-1;
        Xc = Xc/nf_swarm; %此时Xc表示视野范围其他伙伴的中心位置; 
        %判断中心位置是否拥挤
        if  (f(Xc)/nf_swarm < delta*f(x(i,:))) && (f(Xc)<f(x(i,:)))     
            x_swarm=x(i,:)+rand*Step.*(Xc-x(i,:))./norm(Xc-x(i,:)); 
            %边界处理
            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
            %觅食行为
            label_prey =0;    %判断觅食行为是否找到优于当前的状态
            for j = 1:Try_number
                %随机搜索一个状态
                x_prey_rand = x(i,:)+Visual.*(-1+2.*rand(1,dim));
                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;   
                %判断搜索到的状态是否比原来的好
                if f(x(i,:))>f(x_prey_rand)
                    x_swarm = x(i,:)+rand*Step.*(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
            %随机行为
            if label_prey==0
                x_swarm = x(i,:)+Step*(-1+2*rand(1,dim));
                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

        %% 追尾行为
        fitness_follow = inf;  
        label_follow =0;%追尾行为发生标记
        %搜索人工鱼Xi视野范围内的最高适应度个体Xj
        for j = 1:N     
            if (norm(x(j,:)-x(i,:))<Visual) && (f(x(j,:))<fitness_follow)      
                best_pos = x(j,:);      
                fitness_follow = f(x(j,:));     
            end
        end
         %搜索人工鱼Xj视野范围内的伙伴数量
        nf_follow=0;
        for j = 1:N     
            if norm(x(j,:)-best_pos)<Visual   
                nf_follow=nf_follow+1;
            end
        end
        nf_follow=nf_follow-1;%去掉他本身
        %判断人工鱼Xj位置是否拥挤
        if (fitness_follow/nf_follow)<delta*f(x(i,:)) && (fitness_follow<f(x(i,:)))  
            x_follow = x(i,:)+rand*Step.*(best_pos-x(i,:))./norm(best_pos-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;   

            label_follow =1;
            x_follow_fitness=f(x_follow);
        else
            %觅食行为
            label_prey =0;    %判断觅食行为是否找到优于当前的状态
            for j = 1:Try_number
                %随机搜索一个状态
                x_prey_rand = x(i,:)+Visual.*(-1+2.*rand(1,dim));
                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;   
                %判断搜索到的状态是否比原来的好
                if f(x(i,:))>f(x_prey_rand)
                    x_follow = x(i,:)+rand*Step.*(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
            %随机行为
            if label_prey==0
                x_follow = x(i,:)+Step*(-1+2*rand(1,dim));
                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
    
        % 两种行为找最优
        if x_follow_fitness<x_swarm_fitness
            x(i,:)=x_follow;
        else
            x(i,:)=x_swarm;
        end
    end

    %% 更新信息
    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;
    if mod(Iteration,50)==0
        display(['迭代次数:',num2str(Iteration),'最优适应度:',num2str(best_fitness)]);
        display(['最优人工鱼:',num2str(best_x)]);
    end
end

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)=x(i).^2+y(j).^2;
    end
end
surfc(x,y,F,'LineStyle','none');  
title('Test function') 
xlabel('x_1'); 
ylabel('x_2'); 
zlabel(['sum','( x_1 , x_2 )']) 
grid off 

subplot(1,2,2); 
semilogy(Convergence_curve,'Color','b') 
title('Convergence curve') 
xlabel('Iteration'); 
ylabel('Best fitness'); 
axis tight 
grid off 
box on 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值