人工鱼群算法

人工鱼群算法(Artificial Fish School,AFS)是由国内李晓磊博士等人提出的一种新型仿生群智能优化算法,李博士从分析鱼类的活动出发,采用有别于传统的设计方法,以自下而上的设计思想,应用基于行为的智能方法,提出了一种新的鱼群模式。

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

鱼类在觅食或者寻找同伴的过程中,会根据对环境信息的感知,在这些行为中不停地进行转换,以达到寻找食物或同伴的目的。

1.算法描述
通常一片水域里富含营养的地方,就是鱼类数目最多的地方,人工鱼群算法就是根据这一特点,模拟单条鱼的觅食、聚群、追尾、随机行为,来实现寻找全局最优值的目的。

在解决函数优化问题时,人工鱼个体可用向量X(x1.x2…)表示,称为一个解(即决策变量),该解向量对应的目标函数值为Y=f(X),在算法中表示为人工鱼当前状态的食物浓度。

在描述人工鱼模拟鱼类的具体行为之前,首先定义几个相关参数:
N:水域中人工鱼的数目
visual:人工鱼的视力范围,即人工鱼的感知距离
δ:拥挤度因子,用来调节鱼群的拥挤度
step:人工鱼的最大运动步长
trynumber:人工鱼在移动前的最大试探次数

以寻找目标函数最大值为例,人工鱼群算法中人工鱼寻优的几种行为描述如下:

(1)觅食行为:在算法寻优过程中,若人工鱼当前状态为X,可在其感知距离visual内随机的选择一个状态X1,比较两状态对应的目标函数值,如果满足f(X)<f(X1),则向该方向前进一步,反之,在感知距离内重新选择一个状态X2,若尝试trynumber次后,仍达不到前进条件,则随机移动一步。人工鱼Xi向Xj状态前进一步所处的Xnext可按下式计算:
在这里插入图片描述
(2)随机行为:人工鱼个体在水域中自主的随机游动的过程,此过程也是人工鱼自主探索新的食物丰富区域的途径,在算法中有利于摆脱局部最优,帮助算法找到全局最优解。
(3)聚群行为:人工鱼个体要向人工鱼数量较多的区域聚集,设计人工鱼的聚群行为要遵循两个原则:一是要使人工鱼个体尽量向周围伙伴的中心方向移动;二是要尽量避免鱼群过于拥挤。设人工鱼当前状态为X,探索当前感知距离内的伙伴数目为n,中心位置为Xc,如果n/N<δ,表示伙伴中心Xc处有比较多的食物且伙伴之间不太拥挤,如果人工鱼的伙伴中心状态比其当前状态目标函数值更优,则该人工鱼可以向伙伴的中心位置Xc前进一步,否则执行觅食行为。
(4)追尾行为:当人工鱼发现其周围伙伴处食物丰富时,会尾随处在最优状态的伙伴,向其所在方向靠近。若人工鱼当前状态为X,让其探索其感知距离内的状态最优的伙伴Xbest,如果满足f(x)<f(Xbest),并且Xbest的感知距离内的伙伴数目n/N<δ,表示最优伙伴Xbest处有较多的食物且伙伴之间不太拥挤,则该人工鱼向最优伙伴的方向前进一步,否则执行觅食行为。

2.算法步骤

step1.设置迭代次数计数器iter,最大迭代次数Maxiter;设定人工鱼个体数目N,表示人工鱼状态的个体维数d;定义人工鱼算法相关参数,即人工鱼的感知距离visual、拥挤度因子δ、人工鱼每次移动前的最大试探次数trynumber,最大运动步长step。
step2.鱼群初始化,在定义域内随机生成N个解。
step3.对每条鱼i都分别执行:(1)追尾行为(包含觅食行为);(2)聚群行为(包含觅食行为),比较人工鱼原状态与探测到的新状态目标函数值,若新状态更优,则更新人工鱼状态为新状态,否则取原状态。
step4.记录当前所有与的最佳状态及寻找到的最优值。
step5.更新迭代器次数iter = iter + 1,若满足当前迭代次数iter>Maxiter,则搜索停止,输出全局最优结果,否则执行step3.

3.示例
例: max Z = X1 ** 2 + X2 ** 2 - 12 * X1 + 16 * X2 (-5 <= X1 <= 5, -5 <= X2 <= 5)

#人工鱼群算法
import random as rd
from math import sqrt

'''ex:max Z = X1 ** 2 + X2 ** 2 - 12 * X1 + 16 * X2
        subject to : -5 <= X1 <= 5
                     -5 <= X2 <= 5 '''

def objFunction(x1,x2):   #目标函数
    return x1 ** 2 + x2 ** 2 - 12 * x1 + 16 * x2

def subject(fish):
    if fish[0] < -5 or fish[0] > 5:
        if abs(fish[0] + 5) < abs(fish[0] - 5):
            fish[0] = -5
        else:
            fish[0] = 5
    if fish[1] < -5 or fish[1] > 5:
        if abs(fish[1] + 5) < abs(fish[1] - 5):
            fish[1] = -5
        else:
            fish[1] = 5

def move(fish,objFish):   #fish向objFish移动一步
    if objFish[0] == fish[0]:
        fish[1] += (objFish[1] - fish[1]) / abs(objFish[1] - fish[1]) * step * rd.random()
    elif objFish[1] == fish[1]:
        fish[0] += (objFish[0] - fish[0]) / abs(objFish[0] - fish[0]) * step * rd.random()
    else:
        tan = abs(objFish[0] - fish[0]) / abs(objFish[1] - fish[1])
        x = (objFish[0] - fish[0]) / abs(objFish[0] - fish[0]) * step * rd.random()
        fish[0] += x
        fish[1] += (objFish[1] - fish[1]) / abs(objFish[1] - fish[1]) * x / tan
        subject(fish)

def getCrowdFac(fish):    #人工鱼感知旁边的伙伴
    nearByFish = []
    for everyFish in fishCluster:
        if sqrt((fish[0] - everyFish[0]) ** 2 + (fish[1] - everyFish[1]) ** 2) < visual:
            nearByFish.append(everyFish)
    if len(nearByFish) / len(fishCluster) < crowdFac:
        return True,nearByFish,len(nearByFish) / len(fishCluster)
    else:
        return False,nearByFish,len(nearByFish) / len(fishCluster)

def forage(fish):    #觅食行为
    judge = False
    for i in range(tryNumber):
        x1new = rd.uniform(fish[0] - visual, fish[0] + visual)
        x2new = rd.uniform(fish[1] - visual, fish[1] + visual)
        if objFunction(fish[0],fish[1]) < objFunction(x1new,x2new):  #(x1,x2)向(x1new,x2new)移动一步
            move(fish,[x1new,x2new])
            judge = True
            break
    if not judge:    #随机移动
        x3,x4 = 100,100
        while sqrt((x3 - fish[0]) ** 2 + (x4 - fish[1]) ** 2) >step:
            x3 = fish[0] + rd.uniform(-1, 1) * step
            x4 = fish[1] + rd.uniform(-1, 1) * step
        fish[0] = x3
        fish[1] = x4
        subject(fish)

# def rand(fish):           #随机行为
#     fish[0] += rd.uniform(-1, 1) * visual
#     fish[1] += rd.uniform(-1, 1) * visual

def clustering(fish):     #聚群行为
    judge,nearByFish,nearByCrowdFac = getCrowdFac(fish)
    if judge:
        if nearByCrowdFac < crowdFac:
            x1new,x2new = 0,0
            for fishi in nearByFish:
                x1new += fishi[0]
                x2new += fishi[1]
            x1new /= len(nearByFish)
            x2new /= len(nearByFish)
            if objFunction(fish[0],fish[1]) < objFunction(x1new,x2new):
                move(fish,[x1new,x2new])
            else:
                forage(fish)
    else:
        pass

def rearEnd(fish):        #追尾行为
    judge,nearByFish,nearByCrowdFac = getCrowdFac(fish)
    xMax = -float("inf")
    nearByBestFish = []
    for fishi in nearByFish:
        if objFunction(fishi[0],fishi[1]) > xMax:
            xMax = objFunction(fishi[0],fishi[1])
            nearByBestFish = fishi
    if objFunction(fish[0],fish[1]) < objFunction(nearByBestFish[0],nearByBestFish[1]):
        judgeNew,bestNearByFish,nearByBestFishCrowdFac = getCrowdFac(nearByBestFish)
        if nearByBestFishCrowdFac < crowdFac:
           move(fish,nearByBestFish)
        else:
            forage(fish)

def getBest(fishCluster):
    bestObj = -float("inf")
    bestFsih = []
    for everyFish in fishCluster:
        if objFunction(everyFish[0],everyFish[1]) > bestObj:
            bestObj = objFunction(everyFish[0],everyFish[1])
            bestFsih = everyFish
    return bestFsih,bestObj

iterx, maxIterx = 0, 10
N = 30
visual = 2
crowdFac = 0.3
tryNumber = 6
step = 0.1

if __name__ == '__main__':
    fishCluster = []
    for i in range(N):
        x1 = rd.uniform(-5, 5)
        x2 = rd.uniform(-5, 5)
        fishCluster.append([x1,x2])

    while iterx < maxIterx:
        for fish in fishCluster:
            rearEnd(fish)
            clustering(fish)
        bestFsih,bestObj = getBest(fishCluster)
        iterx += 1
    print(bestFsih,bestObj)
  • 4
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值