人工鱼群算法学习 超详细解析 附JAVA和matlab示例

人工鱼群算法

1 人工鱼群算法

人工鱼群算法为山东大学副教授李晓磊2002年从鱼找寻食物的现象中表现的种种移动寻觅特点中得到启发而阐述的仿生学优化方案。

1.1 定义

在一片水域中,鱼往往能自行或尾随其他鱼找到营养物质多的地方,因而鱼生存数目最多的地方一般就是本水域中营养物质最多的地方,人工鱼群算法就是根据这一特点,通过构造人工鱼来模仿鱼群的觅食、聚群及追尾行为,从而实现寻优。
人工鱼拥有以下几种典型行为:

  1. 觅食行为:一般情况下鱼在水中随机地*游动,当发现食物时,则会向食物逐渐增多的方向快速游去。
  2. 聚群行为: 鱼在游动过程中为了保证自身的生存和躲避危害会自然地聚集成群,鱼聚群时所遵守的规则有三条:
    分隔规则:尽量避免与临近伙伴过于拥挤;
    对准规则:尽量与临近伙伴的平均方向一致;
    内聚规则:尽量朝临近伙伴的中心移动。
  3. 追尾行为:当鱼群中的一条或几条鱼发现食物时,其临近的伙伴会尾随其快速到达食物点。
  4. 随机行为:单独的鱼在水中通常都是随机游动的,这是为了更大范围地寻找食物点或身边的伙伴。

1.2 算法具体过程

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

  1. 初始化设置,包括种群规模N、每条人工鱼的初始位置、人工鱼的视野Visual、步长step、拥挤度因子δ、重复次数Trynumber;
  2. 计算初始鱼群各个体的适应值,取最优人工鱼状态及其值赋予给公告牌;
  3. 对每个个体进行评价,对其要执行的行为进行选择,包括觅食Pray、聚群Swarm、追尾Follow和评价行为bulletin;
  4. 执行人工鱼的行为,更新自己,生成新鱼群;
  5. 评价所有个体。若某个体优于公告牌,则将公告牌更新为该个体;
  6. 当公告牌上最优解达到满意误差界内或者达到迭代次数上限时算法结束,否则转步骤3。

1.3 算法流程图

人工鱼群算法学习  超详细解析 附JAVA和matlab示例

1.4 算法伪代码

人工鱼群算法学习  超详细解析 附JAVA和matlab示例

2 参数解析

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

2.1 视野visual

动物的观察力是及其深奥的,它可以很快的洞察到周边的物体,鱼类的视野中分为连续型视野和离散型视野两类。应用如下方法实现虚拟人工鱼的视觉:
图2.1(a)表示具有连续型视野的一条假设的人工鱼个体,它能看到的区域 Visual 为以现在位置 Xi为圆心一定距离为半径的圆形区域,地点 Xj为它在一个时候巡视到的视点种另一地方,如果这个地点的食物量比之前地方的多,就决定去这个地方前进步长的随机数达到地点 Xnext;
人工鱼的离散型视野为与节点位置 Xi 相邻且相通的所有节点,如图 2.1(b)所示,根据判断边的代价来选择下一步位置 Xnext。
人工鱼群算法学习  超详细解析 附JAVA和matlab示例
由于视野对算法中个行为都有较大影响,因此,它的变化对收敛性能影响也比较复杂。
当视野范围较小时,人工鱼的觅食行为和随机行为比较突出;视野范围较大时,人工鱼的追尾行为和聚群行为将变得比较突出,相应的算法的复杂度也会有所上升。
总的来说:视野越大,越容易使人工鱼发现全局最优解并收敛。

2.2 步长step

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

2.3 群规模N

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

2.4 尝试次数Trynumber

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

2.5 拥挤度因子δ

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

2.6 小结

  1. 群规模:N越大收敛越快,越容易寻得全局最优解,但是计算量越大;
  2. 感知范围:视野越大,越易发现全局最优解;
  3. 步长:决定收敛速度;
  4. 拥挤因子:适当选择可避免局部最优
  5. 重复次数:越大收敛越快,可调整随机游走概率,克服局部最优解

3 四种基本行为

人工鱼有四种基本行为,包括觅食Pray、聚群Swarm、追尾Follow和评价行为bulletin。

3.1 觅食行为

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

3.2 聚群行为

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

3.3 追尾行为

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

3.4 随机行为

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

4 行为选择

公告牌是记录最优人工鱼个体状态的地方。每条人工鱼在执行完一次迭代后将自身当前状态与公告牌中记录的状态进行比较,如果优于公告牌中的状态则用自身状态更新公告牌中的状态,否则公告牌的状态不变。
当整个算法的迭代结束后,公告牌的值就是最优解。
行为评价是用来反映鱼自主行为的一种方式,在解决优化问题时选用两种方式评价:一种是选择最优行为执行;另一种是选择较优方向。
对于解决极大值问题,可以使用试探法,即模拟执行群聚、追尾等行为,然后评价行动后的值选择最优的来执行,缺省的行为为觅食行为。
一般通过试探法,模拟执行上述几种行为,评价后选择最大者实行;

5 终止条件

迭代终止条件:

  1. 通常的方法是判断连续多次所得值得均方差小鱼允许的误差;

  2. 或判断聚集于某个区域的人工鱼的数目达到某个比例;

  3. 或连续多次所得的均值不超过已寻找的极值;

  4. 或限制最大迭代次数。

若满足终止条件,则输出公告牌的最优记录;否则继续迭代。

6 求解示例,java代码

求解x2-160x+640+y2-260y+16900这个二元函数的最小值;

6.1 主函数测试类

package optimaze_algorithm.AFAS_PACK;

/**
 * 人工鱼群算法求解二元函数最优值问题
 */
public class MainTest {
    public static void main(String[] args) {
        System.out.println("begin");
        AFAS run = new AFAS(10,5,2,5,0.2,10);
        run.doAFAS(40 );//括号内为迭代次数
    }
}

6.2 人工鱼类

package optimaze_algorithm.AFAS_PACK;

public class Fish {
    public int dim;    //每条鱼的维度
    public int[] x;    //每条鱼的具体多维坐标
    public  double fit;  //鱼的适应值,浓度
    public int visual;   //每条鱼的视野
    public final double[] H = new double[256];
    public final double[] W = new double[256];

    public Fish(int dim, int visual){
        this.dim = dim;
        this.visual = visual;
        x = new int[dim];
        for (int i = 0; i < dim; i++) {
            x[i] = (int) Math.floor(256*Math.random());
        }
        fit = 0;
    }

    public double distance(Fish f){
        double a = 0;
        for (int i = 0; i < dim; 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){
        return -(w[0]*w[0] - 160*w[0]+640+w[1]*w[1]-260*w[1]+16900);
    }

}

6.3 人工鱼群算法类

package optimaze_algorithm.AFAS_PACK;

import java.util.Date;

public class AFAS {
    private int fishNum; //鱼群数目
    private int tryTimes; //尝试次数
    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 tryTimes, int dim, int step, double delta, int visual) {
        this.fishNum = fishNum;
        this.tryTimes = tryTimes;
        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){
        long startTime = new Date().getTime();
        double a = 0.0;
        int count = 1;
        int len = 0;
        while (count <= num){
            for (int i = 0; i < fishNum; 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 < dim; 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 < dim; i++) {
            System.out.print("位置"+(i+1)+":  "+bestfish.x[i]);
        }
        System.out.println();
        long endTime = new Date().getTime();
        System.out.println("本程序运行计时: "+(endTime-startTime)+" 毫秒。");
    }

    /**
     * 评价行为
     * @param i
     */
    private void bulletin(int i){
        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 < fish[i].fit){
            return;
        }
        fish[i] = maxfish;
        if (maxfish.fit > bestfish.fit){
            bestfish = maxfish;
        }
    }

    /**
     * 追尾行为
     * 人工鱼探索周围邻居鱼的最优位置,
     * 当最优位置的目标函数值大于当前位置的目标函数值并且不是很拥挤,则当前位置向最优邻居鱼移动一步,
     * 否则执行觅食行为。
     * @param i
     */
    private void  follow(int i){
        nextfish[2] = new Fish(dim, visual);
        Fish maxfish = new Fish(dim, visual);
        maxfish = fish[i];
        //获得视野范围内的鱼群
        Fish[] scope = getScopefish(i);
        int key = i;
        if (scope != null){
            for (int j = 0; j < scope.length; j++) {
                //最大适应度的鱼
                if (scope[j].fit > maxfish.fit){
                    maxfish = scope[j];
                    key = j;
                }
            }
            //如果最小适应度的鱼也比自己大,就去觅食
            if (maxfish.fit <= fish[i].fit){
                prey(i);
            }else {
                Fish[] newScope = getScopefish(key);
                if (newScope != null){
                    //检查拥挤度,能不能插入,不能插入就去觅食
                    if (newScope.length*maxfish.fit < delta*fish[i].fit){
                        double dis = fish[i].distance(maxfish);
                        //如果能够插入,就往minfish的位置移动
                        for (int k = 0; k < dim; k++) {
                            nextfish[2].x[k] = (int) (fish[i].x[k]+(maxfish.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);
    }

    /**
     * 人工鱼i的聚群行为
     * 人工鱼探索当前邻居内的伙伴数量,并计算伙伴的中心位置,
     * 然后把新得到的中心位置的目标函数与当前位置的目标函数相比较,
     * 如果中心位置的目标函数优于当前位置的目标函数并且不是很拥挤,则当前位置向中心位置移动一步,否则执行觅食行为。
     * 鱼聚群时会遵守两条规则:一是尽量向邻近伙伴的中心移动,二是避免过分拥挤。
     * @param i
     */
    private void swarm(int i){
        nextfish[1] = new Fish(dim,visual);
        int[] center = new int[dim];
        for(int j=0;j<dim;j++){
            center[j] = 0;
        }
        //取得视野内的鱼群
        Fish[] scope = getScopefish(i);
        if(scope!=null){
            for(int j=0;j<scope.length;j++){
                for( i=0; i<dim; ++i ){
                    center[i] += scope[j].x[i];
                }
            }
            //计算中心位置
            for( i=0; i<dim; 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<delta*fish[i].fit){
                for(int j=0;j<dim;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);
    }

    /**
     * 人工鱼i的觅食行为
     * @param i
     */
    private void prey(int i){
        Fish newfish = new Fish(dim,visual);
        newfish.fit = 0;
        nextfish[0] = new Fish(dim,visual);
        //选择次数达到一定数量后,如果仍然不满足条件,则随机移动一步
        for(int k=0; k<tryTimes; k++ ) {           // 进行try_number次尝试
            //在其感知范围内随机选择另一个状态
            for (int j = 0; j < dim; 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<dim; 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<dim; j++){
                    nextfish[0].x[j] = (int) (fish[i].x[j]+visual*(2*(Math.random())-1));
                    nextfish[0].fit = nextfish[0].newFunction(nextfish[0].x);
                }
            }
        }
    }

    /**
     * 获得鱼i视野范围内的鱼群
     * @param i
     * @return
     */
    private Fish[] getScopefish(int i) {
        int num = 0;
        //计算视野范围内的鱼群个数,并且记录下标
        for(int j=0;j<fishNum;j++){
            choosed[j] = -1;
            if(fish[i].distance(fish[j])<visual){
                choosed[j] = i;
                num++;
            }
        }
        //如果视野范围内有其它鱼,标记出来返回
        if (num != 0){
            Fish[] scope = new Fish[num];
            int k = 0;
            for(int j=0;j<fishNum;j++){
                if(choosed[j]!=-1){
                    scope[k++] = fish[choosed[j]];
                }
            }
            return scope;
        }
        return null;
    }

    /**
     * 初始化鱼群,随机生成鱼的位置
     * 并且根据位置计算其适应度
     */
    private void init() {
        for (int i = 0; i < fishNum; i++) {
            fish[i] = new Fish(dim, visual);
            fish[i].fit = fish[i].newFunction(fish[i].x);
        }
        //最优鱼群
        bestfish = new Fish(dim, visual);
        bestfish.fit = -9999999;
    }


}

7 二元函数优化实例 matlab代码实现

一元函数的优化实例:
m a x f ( x ) = x s i n ( 10 π x ) + 2.0 maxf(x) = xsin(10πx) + 2.0 maxf(x)=xsin(10πx)+2.0
s.t. 1 ≤ x ≤ 2 1 ≤ x ≤ 2 1≤x≤2
二元函数的优化实例:
m a x f ( x , y ) = s i n x x s i n y y maxf(x,y) = \frac{sinx}{x} \frac{siny}{y} maxf(x,y)=xsinx​ysiny​
s.t. x ∈ [ − 10 , 10 ] x\in[-10,10] x∈[−10,10] y ∈ [ − 10 , 10 ] y\in[-10,10] y∈[−10,10]

7.1 人工鱼群算法需要用到的matlab函数

具体的源代码放到文末:有需要的同学可以自行查看学习。

序号 函数名 函数功能
1 AF_init 初始化鱼群函数
2 AF_prey 觅食行为函数
3 AF_swarm 聚群行为函数
4 AF_follow 追尾行为函数
5 AF_dist 计算鱼群个体距离函数
6 AF_foodconsistence 当前位置的事物浓度函数

7.2 一元函数优化代码

clc
clear all
close all
tic
figure(1);hold on
ezplot('x*sin(10*pi*x)+2',[-1,2]);
%% 参数设置
fishnum=50; %生成50只人工鱼
MAXGEN=50; %最多迭代次数
try_number=100;%最多试探次数
visual=1; %感知距离
delta=0.618; %拥挤度因子
step=0.1; %步长
%% 初始化鱼群
lb_ub=[-1,2,1];
X=AF_init(fishnum,lb_ub);
LBUB=[];
for i=1:size(lb_ub,1)
    LBUB=[LBUB;repmat(lb_ub(i,1:2),lb_ub(i,3),1)];
end
gen=1;
BestY=-1*ones(1,MAXGEN); %每步中最优的函数值
BestX=-1*ones(1,MAXGEN); %每步中最优的自变量
besty=-100; %最优函数值
Y=AF_foodconsistence(X);
while gen<=MAXGEN
    fprintf(1,'%d\n',gen)
    for i=1:fishnum
          %% 聚群行为
        [Xi1,Yi1]=AF_swarm(X,i,visual,step,delta,try_number,LBUB,Y); 
         %% 追尾行为
        [Xi2,Yi2]=AF_follow(X,i,visual,step,delta,try_number,LBUB,Y); 
        if Yi1>Yi2
            X(:,i)=Xi1;
            Y(1,i)=Yi1;
        else
            X(:,i)=Xi2;
            Y(1,i)=Yi2;
        end
    end
    [Ymax,index]=max(Y);
    figure(1);
    plot(X(1,index),Ymax,'.','color',[gen/MAXGEN,0,0])
    if Ymax>besty
        besty=Ymax;
        bestx=X(:,index);
        BestY(gen)=Ymax;
        [BestX(:,gen)]=X(:,index);
    else
        BestY(gen)=BestY(gen-1);
        [BestX(:,gen)]=BestX(:,gen-1);
    end
    gen=gen+1;
end
plot(bestx(1),besty,'ro','MarkerSize',100)
xlabel('x')
ylabel('y')
title('鱼群算法迭代过程中最优坐标移动')

%% 优化过程图
figure
plot(1:MAXGEN,BestY)
xlabel('迭代次数')
ylabel('优化值')
title('鱼群算法迭代过程')
disp(['最优解X:',num2str(bestx,'%1.4f')])
disp(['最优解Y:',num2str(besty,'%1.4f')])
toc

7.3 二元函数优化代码

clc
clear all
close all
tic
figure(1);hold on
%% 参数设置
fishnum=100; %生成100只人工鱼
MAXGEN=50; %最多迭代次数
try_number=100;%最多试探次数
visual=1; %感知距离
delta=0.618; %拥挤度因子
step=0.1; %步长
%% 初始化鱼群
lb_ub=[-10,10,2;];
X=AF_init(fishnum,lb_ub);
LBUB=[];
for i=1:size(lb_ub,1)
    LBUB=[LBUB;repmat(lb_ub(i,1:2),lb_ub(i,3),1)];
end
gen=1;
BestY=-1*ones(1,MAXGEN); %每步中最优的函数值
BestX=-1*ones(2,MAXGEN); %每步中最优的自变量
besty=-100; %最优函数值
Y=AF_foodconsistence(X);
while gen<=MAXGEN
    fprintf(1,'%d\n',gen)
    for i=1:fishnum
        %% 聚群行为
        [Xi1,Yi1]=AF_swarm(X,i,visual,step,delta,try_number,LBUB,Y); 
        
         %% 追尾行为
        [Xi2,Yi2]=AF_follow(X,i,visual,step,delta,try_number,LBUB,Y);
        if Yi1>Yi2
            X(:,i)=Xi1;
            Y(1,i)=Yi1;
        else
            X(:,i)=Xi2;
            Y(1,i)=Yi2;
        end
    end
    [Ymax,index]=max(Y);
    figure(1);
    plot(X(1,index),X(2,index),'.','color',[gen/MAXGEN,0,0])
    if Ymax>besty
        besty=Ymax;
        bestx=X(:,index);
        BestY(gen)=Ymax;
        [BestX(:,gen)]=X(:,index);
    else
        BestY(gen)=BestY(gen-1);
        [BestX(:,gen)]=BestX(:,gen-1);
    end
    gen=gen+1;
end
plot(bestx(1),bestx(2),'ro','MarkerSize',100)
xlabel('x')
ylabel('y')
title('鱼群算法迭代过程中最优坐标移动')

%% 优化过程图
figure
plot(1:MAXGEN,BestY)
xlabel('迭代次数')
ylabel('优化值')
title('鱼群算法迭代过程')
disp(['最优解X:',num2str(bestx','%1.5f')])
disp(['最优解Y:',num2str(besty,'%1.5f')])
toc

7.4 人工鱼群各功能函数代码

初始化鱼群函数AF_init

function X=AF_init(Nfish,lb_ub)
%输入:
% Nfish 鱼群大小
% lb_ub 鱼的活动范围

%输出:
% X     产生的初始人工鱼群

% example:
% Nfish=3;
% lb_ub=[-3.0,12.1,1;4.1,5.8,1]; 
%%这里的lb_ub是2行3列的矩阵,每行中前两个数是范围的上下限,第3个数是在该范围内的数的个数
% X=Inital(Nfish,lb_ub)  
%%就是产生[-3.0,12.1]内的数1个,[4.1,5.8]内的数1个
%%两个数一组,这样的数一共Nfish个
row=size(lb_ub,1);
X=[];
for i=1:row
    lb=lb_ub(i,1);
    ub=lb_ub(i,2);
    nr=lb_ub(i,3);
    for j=1:nr
        X(end+1,:)=lb+(ub-lb)*rand(1,Nfish);
    end
end

初始化鱼群函数AF_prey

function [Xnext,Ynext]=AF_prey(Xi,ii,visual,step,try_number,LBUB,lastY)
%觅食行为
%输入:
%Xi          当前人工鱼的位置
%ii          当前人工鱼的序号
%visual      感知范围
%step        最大移动步长
%try_number  最大尝试次数
%LBUB        各个数的上下限
%lastY       上次的各人工鱼位置的食物浓度

%输出:
%Xnext       Xi人工鱼的下一个位置  
%Ynext       Xi人工鱼的下一个位置的食物浓度

Xnext=[];
Yi=lastY(ii);
for i=1:try_number
    Xj=Xi+(2*rand(length(Xi),1)-1)*visual;
    Yj=AF_foodconsistence(Xj);
    if Yi<Yj
        Xnext=Xi+rand*step*(Xj-Xi)/norm(Xj-Xi);
        for i=1:length(Xnext)
            if  Xnext(i)>LBUB(i,2)
                Xnext(i)=LBUB(i,2);
            end
            if  Xnext(i)<LBUB(i,1)
                Xnext(i)=LBUB(i,1);
            end
        end
        Xi=Xnext;
        break;
    end
end

%随机行为
if isempty(Xnext)
    Xj=Xi+(2*rand(length(Xi),1)-1)*visual;
    Xnext=Xj;
    for i=1:length(Xnext)
        if  Xnext(i)>LBUB(i,2)
            Xnext(i)=LBUB(i,2);
        end
        if  Xnext(i)<LBUB(i,1)
            Xnext(i)=LBUB(i,1);
        end
    end
end
Ynext=AF_foodconsistence(Xnext);

初始化鱼群函数AF_swarm

function [Xnext,Ynext]=AF_swarm(X,i,visual,step,deta,try_number,LBUB,lastY)
% 聚群行为
%输入:
%X           所有人工鱼的位置
%i           当前人工鱼的序号
%visual      感知范围
%step        最大移动步长
%deta        拥挤度
%try_number  最大尝试次数
%LBUB        各个数的上下限
%lastY       上次的各人工鱼位置的食物浓度

%输出:
%Xnext       Xi人工鱼的下一个位置  
%Ynext       Xi人工鱼的下一个位置的食物浓度
Xi=X(:,i);
D=AF_dist(Xi,X);
index=find(D>0 & D<visual);
nf=length(index);
if nf>0
    for j=1:size(X,1)
        Xc(j,1)=mean(X(j,index));
    end
    Yc=AF_foodconsistence(Xc);
    Yi=lastY(i);
    if Yc/nf>deta*Yi
        Xnext=Xi+rand*step*(Xc-Xi)/norm(Xc-Xi);
        for i=1:length(Xnext)
            if  Xnext(i)>LBUB(i,2)
                Xnext(i)=LBUB(i,2);
            end
            if  Xnext(i)<LBUB(i,1)
                Xnext(i)=LBUB(i,1);
            end
        end
        Ynext=AF_foodconsistence(Xnext);
    else
        [Xnext,Ynext]=AF_prey(Xi,i,visual,step,try_number,LBUB,lastY);
    end
else
    [Xnext,Ynext]=AF_prey(Xi,i,visual,step,try_number,LBUB,lastY);
end

初始化鱼群函数AF_follow

function [Xnext,Ynext]=AF_follow(X,i,visual,step,deta,try_number,LBUB,lastY)
% 追尾行为
%输入:
%X           所有人工鱼的位置
%i           当前人工鱼的序号
%visual      感知范围
%step        最大移动步长
%deta        拥挤度
%try_number  最大尝试次数
%LBUB        各个数的上下限
%lastY       上次的各人工鱼位置的食物浓度

%输出:
%Xnext       Xi人工鱼的下一个位置
%Ynext       Xi人工鱼的下一个位置的食物浓度
Xi=X(:,i);
D=AF_dist(Xi,X);
index=find(D>0 & D<visual);
nf=length(index);
if nf>0
    XX=X(:,index);
    YY=lastY(index);
    [Ymax,Max_index]=max(YY);
    Xmax=XX(:,Max_index);
    Yi=lastY(i);
    if Ymax/nf>deta*Yi;
        Xnext=Xi+rand*step*(Xmax-Xi)/norm(Xmax-Xi);
        for i=1:length(Xnext)
            if  Xnext(i)>LBUB(i,2)
                Xnext(i)=LBUB(i,2);
            end
            if  Xnext(i)<LBUB(i,1)
                Xnext(i)=LBUB(i,1);
            end
        end
        Ynext=AF_foodconsistence(Xnext);
    else
        [Xnext,Ynext]=AF_prey(X(:,i),i,visual,step,try_number,LBUB,lastY);
    end
else
    [Xnext,Ynext]=AF_prey(X(:,i),i,visual,step,try_number,LBUB,lastY);
end

初始化鱼群函数AF_dist

function D=AF_dist(Xi,X)
%计算第i条鱼与所有鱼的位置,包括本身。
%输入:
%Xi   第i条鱼的当前位置  
%X    所有鱼的当前位置
% 输出:
%D    第i条鱼与所有鱼的距离
col=size(X,2);
D=zeros(1,col);
for j=1:col
    D(j)=norm(Xi-X(:,j));
end

初始化鱼群函数AF_foodconsistence

function [Y]=AF_foodconsistence(X)
fishnum=size(X,2);
for i=1:fishnum
     Y(1,i)=X(i)*sin(10*pi*X(i))+2;
end

计算鱼群距离 dist

%计算第i条鱼与所有鱼的位置,包括本身。
function D=dist(Xi,X)
col=size(X,2);
D=zeros(1,col);
for j=1:col
    D(j)=norm(Xi-X(:,j));
end
上一篇:object-fit 属性指定元素的内容应该如何去适应指定容器的高度与宽度


下一篇:sklearn中数据缩放用到的fit_transform()、transform()、fit()方法的区别与联系