01 前言

本着学习的心态,还是想把这个算法写一写,给大家科普一下的吧。

02 人工鱼群算法

2.1 定义

人工鱼群算法为山东大学副教授李晓磊2002年从鱼找寻食物的现象中表现的种种移动寻觅特点中得到启发而阐述的仿生学优化方案。在一片水域中,鱼往往能自行或尾随其他鱼找到营养物质多的地方,因而鱼生存数目最多的地方一般就是本水域中营养物质最多的地方,人工鱼群算法就是根据这一特点,通过构造人工鱼来模仿鱼群的觅食、聚群及追尾行为,从而实现寻优。人工鱼拥有以下几种典型行为:

(1)觅食行为:一般情况下鱼在水中随机地自由游动,当发现食物时,则会向食物逐渐增多的方向快速游去。

(2)聚群行为:鱼在游动过程中为了保证自身的生存和躲避危害会自然地聚集成群,鱼聚群时所遵守的规则有三条:分隔规则:尽量避免与临近伙伴过于拥挤;对准规则:尽量与临近伙伴的平均方向一致;内聚规则:尽量朝临近伙伴的中心移动。

(3)追尾行为:当鱼群中的一条或几条鱼发现食物时,其临近的伙伴会尾随其快速到达食物点。

(4)随机行为:单独的鱼在水中通常都是随机游动的,这是为了更大范围地寻找食物点或身边的伙伴。

2.2 算法具体过程

人工鱼群算法实现的步骤:

初始化设置,包括种群规模N、每条人工鱼的初始位置、人工鱼的视野Visual、步长step、拥挤度因子δ、重复次数Trynumber;

计算初始鱼群各个体的适应值,取最优人工鱼状态及其值赋予给公告牌;

对每个个体进行评价,对其要执行的行为进行选择,包括觅食Pray、聚群Swarm、追尾Follow和评价行为bulletin;

执行人工鱼的行为,更新自己,生成新鱼群;

评价所有个体。若某个体优于公告牌,则将公告牌更新为该个体;

当公告牌上最优解达到满意误差界内或者达到迭代次数上限时算法结束,否则转步骤3。

2.3 算法流程图

2.4 算法伪代码

procedure code :

Artificial_Fishswarm_Algorithm

::AF_init();

while the result isnot satisfied do

switch(::AF_evaluate())

case value1:

::AF_follow();

case value2:

::AF_swarm();

default:

::AF_prey();

end switch

::AF_move();

get_result();

end while

end Artificial_FFishswarm_Algorithm

03 参数解析

人工鱼群算法有5个基本参数:群规模N、人工鱼的视野Visual、步长Step、拥挤度因子δ、重复次数Trynumber。

视野Visual:

动物的观察力是及其深奥的,它可以很快的洞察到周边的物体,鱼类的视野中分为连续型视野和离散型视野两类,应用如下方法实现虚拟人工鱼的视觉:图2.1(a)表示具有连续型视野的一条假设的人工鱼个体,它能看到的区域 Visual 为以现在位置 Xi为圆心一定距离为半径的圆形区域,地点 Xj为它在一个时候巡视到的视点种另一地方,如果这个地点的食物量比之前地方的多,就决定去这个地方前进步长的随机数达到地点 Xnext;人工鱼的离散型视野为与节点位置 Xi 相邻且相通的所有节点,如图 2.1(b)所示,根据判断边的代价来选择下一步位置 Xnext。

由于视野对算法中个行为都有较大影响,因此,它的变化对收敛性能影响也比较复杂。当视野范围较小时,人工鱼的觅食行为和随机行为比较突出;视野范围较大时,人工鱼的追尾行为和聚群行为将变得比较突出,相应的算法的复杂度也会有所上升。总的来说:视野越大,越容易使人工鱼发现全局最优解并收敛。

步长Step:对于固定步长,随着步长的增加,收敛的速度得到了一定的加速,但在超过一定的范围后,有使得收敛速度减缓,步长过大时会出现震荡现象而大大影响收敛速度。采用随机步长的方式在一定程度上防止了震荡现象的发生,并使得该参数的敏感度大大降低了,但最快的收敛速度还是最优固定步长的收敛速度,所以,对于特定的优化问题,我们可以考虑采用合适的固定步长或者变尺度方法来提高收敛速度。

群规模N:人工鱼的数目越多,跳出局部最优解的能力越强,同时,收敛的速度也越快。当然,付出的代价就是算法每次迭代的计算量也越大,因此,在使用过程中,满足稳定收敛的前提下,应当尽可能的减少个体数目。

尝试次数Trynumber:尝试次数越多,人工鱼的觅食行为能力越强,收敛的效率也越高。在局部极值突出的情况下,应该适当的减少以增加人工鱼随机游动的概率,克服局部最优解。

拥挤度因子δ:在求极大值问题中,δ=1/(αnmax),α∈(0,1]δ=1/(αnmax),α∈(0,1];在求极小值问题中,δ=αnmax,α∈(0,1]δ=αnmax,α∈(0,1]。其中α为极值接近水平, nmax为期望在该邻域内聚集的最大人工鱼数目。拥挤度因子与nf相结合,通过人工鱼是否执行追尾和聚群行为对优化结果产生影响。以极大值为例(极小值的情况正好与极大值相反),δ越大,表明允许的拥挤程度越小,人工鱼摆脱局部最优解的能力越强;但是收敛速度会有所减缓,这主要因为人工鱼在逼近最优解的同时,会因避免过分拥挤而随机走开或者受其他人工鱼的排斥作用,不能精确逼近极值点。可见,虽然δ的引入避免了人工鱼过度拥挤而陷入局部最优解,但是另一方面,该参数会使得位于极值点附件的人工鱼之间存在相互排斥的影响,而难以想极值点精确逼近。所以,对于某些局部极值不是很严重的具体问题,可以忽略拥挤的因素,从而在简化算法的同时也加快算法的收敛速度和提高结果的精确程度。

小结起来就是:

1.群规模:N越大收敛越快,越容易寻得全局最优解,但是计算量越大;

2.感知范围:视野越大,越易发现全局最优解;

3.步长:决定收敛速度;

4.拥挤因子:适当选择可避免局部最优

5.重复次数:越大收敛越快,可调整随机游走概率,克服局部最优解。

04 四种基本行为

4.1 觅食行为

这是鱼趋向食物的一种活动,一般认为它是通过视觉或味觉来感知水中的食物量或食物浓度来选择行动的方向。设置人工鱼当前状态,并在其感知范围内随机选择另一个状态,如果得到的状态的目标函数大于当前的状态,则向新选择得到的状态靠近一步,反之,重新选取新状态,判断是否满足条件,选择次数达到一定数量后,如果仍然不满足条件,则随机移动一步。

4.2 聚群行为

大量或少量的鱼聚集成群,进行集体觅食和躲避敌害,这是它们在进化过程中形成的一种生存方式。人工鱼探索当前邻居内的伙伴数量,并计算伙伴的中心位置,然后把新得到的中心位置的目标函数与当前位置的目标函数相比较,如果中心位置的目标函数优于当前位置的目标函数并且不是很拥挤,则当前位置向中心位置移动一步,否则执行觅食行为。鱼聚群时会遵守两条规则:一是尽量向邻近伙伴的中心移动,二是避免过分拥挤。

4.3 追尾行为

当某一条鱼或几条鱼发现食物时,它们附近的鱼会尾随而来,导致更远处的鱼也会尾随过来。人工鱼探索周围邻居鱼的最优位置,当最优位置的目标函数值大于当前位置的目标函数值并且不是很拥挤,则当前位置向最优邻居鱼移动一步,否则执行觅食行为。

4.4 随机行为

它是觅食行为的一个缺省行为,指人工鱼在视野内随机移动。当发现食物时,会向食物逐渐增多的方向快速的移动。

05 行为选择

公告牌是记录最优人工鱼个体状态的地方。每条人工鱼在执行完一次迭代后将自身当前状态与公告牌中记录的状态进行比较,如果优于公告牌中的状态则用自身状态更新公告牌中的状态,否则公告牌的状态不变。当整个算法的迭代结束后,公告牌的值就是最优解。

行为评价是用来反映鱼自主行为的一种方式,在解决优化问题时选用两种方式评价:一种是选择最优行为执行;另一种是选择较优方向。对于解决极大值问题,可以使用试探法,即模拟执行群聚、追尾等行为,然后评价行动后的值选择最优的来执行,缺省的行为为觅食行为。

一般通过试探法,模拟执行上述几种行为,评价后选择最大者实行;

06 终止条件

迭代终止条件:通常的方法是判断连续多次所得值得均方差小鱼允许的误差;或判断聚集于某个区域的人工鱼的数目达到某个比例;或连续多次所得的均值不超过已寻找的极值;或限制最大迭代次数。若满足终止条件,则输出公告牌的最优记录;否则继续迭代。

07 实现代码

7.1 主函数

package AFAS_PACK;

import java.io.IOException;

public class mainTest {

/**

* @param args

* @throws IOException

* @author sun

*/

public static void main(String[] args) throws IOException {

//int fishNum, int tryTime, int dim, double step, double delta, double visual

System.out.println("begin");

AFAS run = new AFAS(10,5,2,5,0.2,10);

run.doAFAS(40 );//括号内为迭代次数

}

}

7.2 人工鱼

package AFAS_PACK;

import java.io.IOException;

public class Fish {

public int dim; //每条鱼的维度

public int[] x; //每条鱼的具体多维坐标

public double fit; //鱼的适应值,浓度

public int visaul; //每条鱼的视野

public final double[] H = new double[256];

public final double[] W = new double[256];

public Fish(int dim, int visaul) throws IOException {

super();

this.dim = dim;

this.visaul = visaul;

x = new int[dim];

for(int i=0;i

x[i] = (int) Math.floor(256*Math.random());

fit = 0;

//init();

}

/*getfit = newfunction(this.x[0],this.x[1]);*/

public double distance(Fish f)

{

double a = 0;

for(int i=0;i

{

if(this.x[i]-f.x[i]==0)

a = 0.00001;

else

a += (this.x[i]-f.x[i])*(this.x[i]-f.x[i]);

}

return Math.sqrt(a);

}

public double newfunction(int[] w) throws IOException {

return -(w[0]*w[0]-160*w[0]+640+w[1]*w[1]-260*w[1]+16900);

}

}

7.3 AFAS算法部分

package AFAS_PACK;

import java.io.IOException;

import java.util.Date;

public class AFAS {

//鱼群数目

private int fishNum;

//尝试次数

private int tryTime;

//维度

private int dim;

//人工鱼移动步长

private int step;

//拥挤度因子

private double delta;

//视野范围

private int visual;

//人工鱼群、范围内最佳鱼,遍历时的下一条鱼

Fish[] fish;

Fish bestfish;

Fish[] nextfish;

//遍历索引

int index;

double[][] vector;

private int[] choosed;

//范围内鱼群数目 fishCount

public int scopelength;

public AFAS(){

}

public AFAS(int fishNum, int tryTime, int dim, int step, double delta, int visual) throws IOException

{

super();

this.fishNum = fishNum;

this.tryTime = tryTime;

this.dim = dim;

this.step = step;

this.delta = delta;

this.visual = visual;

fish = new Fish[fishNum];

nextfish = new Fish[3];

vector = new double[fishNum][dim];

choosed = new int[fishNum];

index = 0;

init();

}

public void doAFAS(int num) throws IOException

{

long startTime = new Date().getTime();

double a = 0.0;

int count = 1; //计算查找次数

int len = 0;

while(count<=num)

{

for(int i=0; i

{

prey(i);

swarm(i);

follow(i);

bulletin(i);

System.out.println("第"+count+"遍第"+i+"条鱼结束");

}

System.out.println(count+"当前最优值:"+bestfish.fit);

for(int i=0; i

{

System.out.print("位置"+(i+1)+": "+bestfish.x[i]);

}

System.out.println();

count++;

System.out.println("step:"+step+" visaul:"+visual);

}

System.out.println("最优值:"+bestfish.fit);

for(int i=0; i

{

System.out.print("位置"+(i+1)+": "+bestfish.x[i]);

}

long endTime = new Date().getTime();

System.out.println("本程序运行计时: "+(endTime-startTime)+" 毫秒。");

}

private void bulletin(int i) throws IOException {

Fish maxfish = new Fish(dim,visual);

maxfish = nextfish[0];

for(int j=0;j<3;j++)

{

if(nextfish[j].fit>maxfish.fit && nextfish[j].x[0]!=0 && nextfish[j].x[1]!=0)

{

maxfish = nextfish[j];

}

}

if(maxfish.fit

{

return ;

}

fish[i] = maxfish;

if(maxfish.fit>bestfish.fit)

bestfish = maxfish;

}

private void follow(int i) throws IOException {

nextfish[2] = new Fish(dim,visual);

Fish minfish = new Fish(dim,visual); // 中心位置

minfish = fish[i];

Fish[] scope = getScopefish(i);

int key = i;

if(scope!=null)

{

for(int j=0;j

{

if(scope[j].fit

{

minfish = scope[j];

key = j;

}

}

if(minfish.fit>=fish[i].fit)

prey(i);

else{

Fish[] newScope = getScopefish(key);

if(newScope!=null)

{

if(newScope.length*minfish.fit

{

double dis = fish[i].distance(minfish);

for(int k=0;k

{

nextfish[2].x[k] = (int) (fish[i].x[k]+(minfish.x[k]-fish[i].x[k])*step*Math.random()/dis);

}

nextfish[2].fit = nextfish[2].newfunction(nextfish[2].x);

}

else prey(i);

}

else prey(i);

}

}

else prey(i);

}

private void swarm(int i) throws IOException { //swam start

nextfish[1] = new Fish(dim,visual);

int[] center = new int[dim]; // 中心位置

for(int j=0;j

center[j] = 0;

Fish[] scope = getScopefish(i);

if(scope!=null)

{

for(int j=0;j

{

for( i=0; i

center[i] += scope[j].x[i];

}

for( i=0; i

center[i] /= scope.length; // 人工鱼的中心位置

//满足条件

double dis=0.0;

Fish centerfish = new Fish(dim,visual);

centerfish.x = center;

centerfish.fit = centerfish.newfunction(centerfish.x);

dis = fish[i].distance(centerfish);

if(centerfish.fit>fish[i].fit && scope.length*centerfish.fit

{

for(int j=0;j

{

nextfish[1].x[j] = (int) (fish[i].x[j]+(centerfish.x[j]-fish[i].x[j])*step*Math.random()/dis);

}

nextfish[1].fit = nextfish[1].newfunction(nextfish[1].x);

}

else prey(i);

}

else prey(i);

} //swam end

private void prey(int i) throws IOException { //prey start

Fish newfish = new Fish(dim,visual);

newfish.fit = 0;

nextfish[0] = new Fish(dim,visual);

for(int k=0; k

{

for(int j=0; j

{

newfish.x[j] = (int) ((2*(Math.random())-1)*visual);

}

newfish.fit = newfish.newfunction(newfish.x);

if( newfish.fit > fish[i].fit )

{

double dis = fish[i].distance(newfish);

for(int j=0; j

{

nextfish[0].x[j] = (int) (fish[i].x[j]+(newfish.x[j]-fish[i].x[j])*step*Math.random()/dis);

}

nextfish[0].fit =nextfish[0].newfunction(nextfish[0].x);

}

else

{

for(int j=0; j

{

nextfish[0].x[j] = (int) (fish[i].x[j]+visual*(2*(Math.random())-1));

nextfish[0].fit = nextfish[0].newfunction(nextfish[0].x);

}

}

}

}

private Fish[] getScopefish(int i) {

int num = 0;

for(int j=0;j

{

choosed[j] = -1;

if(fish[i].distance(fish[j])

{

choosed[j] = i;

num++;

}

}

if(num!=0)

{

Fish[] scope = new Fish[num];

int k = 0;

for(int j=0;j

{

if(choosed[j]!=-1)

scope[k++] = fish[choosed[j]];

}

return scope;

}

return null;

} //prey end

private void init() throws IOException {

for(int i=0;i

{

fish[i] = new Fish(dim,visual);

fish[i].fit = fish[i].newfunction(fish[i].x);

}

bestfish = new Fish(dim,visual);

bestfish.fit = -999999;

}

}

java聚群_人工鱼群算法超详细解析附带JAVA代码相关推荐

  1. 人工鱼群算法超详细解析附带JAVA代码

    01 前言 本着学习的心态,还是想把这个算法写一写,给大家科普一下的吧. 02 人工鱼群算法 2.1 定义 人工鱼群算法为山东大学副教授李晓磊2002年从鱼找寻食物的现象中表现的种种移动寻觅特点中得到 ...

  2. 回溯算法超详细讲解(附代码)

    因为自己在学习回溯算法的时候一直不清楚回溯的具体过程, 可能是因为自己太笨,这个问题困扰了我好几天.回溯还是挺有用的,树的遍历,全排列问题都可以用回溯算法解.面试的时候好像也比较侧重回溯算法和动态规划 ...

  3. 人工鱼群算法python代码_人工鱼群算法python_鱼群算法 - Brillou的个人空间 - OSCHINA - 中文开源技术交流社区......

    本算法是参照李晓磊博士的论文实现的,详细的算法原理可阅读<一种新型的智能优化方法_人工鱼群算法_李晓磊> 算法基于鱼群的生存行为:在一片水域中,鱼存在的数目最多的地方就是本水域中富含营养物 ...

  4. 推荐系统[二]:召回算法超详细讲解[召回模型演化过程、召回模型主流常见算法(DeepMF/TDM/Airbnb Embedding/Item2vec等)、召回路径简介、多路召回融合]

    搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排).系统架构.常见问题.算法项目实战总结.技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排 ...

  5. 100个python算法超详细讲解:孪生素数

    [100个python算法超详细讲解@谷哥技术] 1.问题描述 本节要研究孪生素数的问题,先来看看什么是孪生素数. 所谓孪生素数指的是间隔为2的两个相邻素数,因为它们之间的距离已经 近得不能再近了,如 ...

  6. 100个python算法超详细讲解:搬山游戏

    [100个python算法超详细讲解]@谷歌学术 1.问题描述 设有n座山,计算机与人作为比赛的双方,轮流搬山.规定每次搬 山数不能超过k座,谁搬最后一座谁输.游戏开始时,计算机请人输入 山的总数n和 ...

  7. 100个python算法超详细讲解:平分7筐鱼

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 2.乙.丙三位渔夫出海打鱼,他们随船带了21只箩筐.当晚返航时, 他们发现有7筐装满了鱼,还有7筐装了半筐鱼,另外7筐是空的,由于他们 ...

  8. 100个python算法超详细讲解:邮票组合

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 我们寄信都要贴邮票,在邮局有一些小面值的邮票,通过这些小 面值邮票中的一张或几张的组合,可以满足不同邮件的不同邮资.现 在,邮局有4种不 ...

  9. 100个python算法超详细讲解:递归解决年龄问题

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 有5个人坐在一起,问第5个人多少岁,他说比第4个人大2岁.问 第4个人多少岁,他说比第3个人大2岁.问第3人多少岁,他说比第2个 人大2 ...

  10. 100个python算法超详细讲解:谁是窃贼

    [100个python算法超详细讲解]@谷哥技术 1.问题描述 警察审问4名窃贼嫌疑犯.现在已知,这4人当中仅有一名是窃 贼,还知道这4个人中的每个人要么是诚实的,要么总是说谎. 下面是这4个人给警察 ...

最新文章

  1. mysql年月分表_MySQL之按月拆分主表并按月分表写入数据提高数据查询速度
  2. linux doc下生成学号,linux的.doc
  3. 关于Android adb实现框架和应用
  4. 水果电池打造柠檬电动汽车!
  5. 中国科协发布 2021 开源创新榜,阿里巴巴 2 大开源社区、5 大开源项目上榜
  6. k8s service:ClusterIP、NodePort、LoadBalancer、ExternalName
  7. linux下C/C++ IDE比较 Code::Blocks还是不错的
  8. python从入门到实践 第12章 武装飞船 之 调整飞船的速度程序实践
  9. pycharm在ubuntu xfce下面Alt+insert快捷键冲突解决
  10. Bootstrap列表组
  11. MFC改变对话框背景颜色
  12. matlab 一阶惯性环节,一阶惯性环节
  13. JetPack之DataStore源码笔记
  14. 树莓派在身份证件核验领域应用
  15. 【数字电子技术 Digital Electronic Technology 2】—— 逻辑代数基础 之 逻辑函数以其描述方法解析
  16. 解决网易云音乐linux-1.2.1无法保存设置
  17. gist feature
  18. 网络安全:大数据问题
  19. AtCoder Beginner Contest 174 C.Repsept
  20. SpringBoot学习-支持JPA

热门文章

  1. 自然语言处理总复习(五)—— 词义消歧
  2. 电镜的成像原理-透射电镜成像原理1
  3. ConditionalDetr论文解读+核心源码解读
  4. 简单的爬图片代码(python)
  5. 回溯法之符号三角形问题
  6. 贴片晶振邻层挖空背后的原理
  7. 使用ARCGIS多重缓冲区分析工具建立颜色渐变行政边界
  8. oracle redo 状态,理解ORACLE REDO与UNDO
  9. 群体遗传学-选择消除分析
  10. 程序员一些有意思的智力题整理