人工鱼群算法及其python实现过程

得益于仿生学的研究和发展,群智能优化领域近年来衍生出了多种细化的方法,包括遗传算法、粒子群优化算法(附代码)杂草算法(附代码)、果蝇算法以及人工鱼群算法。其中,李晓磊博士于2003年提出的鱼群算法具有避免最优解提前收敛即能够跳出局部最优解而寻求全局最优解的优点。

0 自然界中的鱼群特征

捕食行为:鱼向着生存环境中富集度高的地方游去并捕食。

追尾行为:鱼A能够察觉视线范围内鱼B所处的富集度最高,若鱼B周围不太拥挤,那么鱼A朝着鱼B游去。

聚群行为:鱼找到视线范围内所有的鱼,并能够衡量这些鱼的中间位置,如果这个中间位置不是很拥挤,那么鱼朝着中间位置游去

随机行为:鱼在当前环境中随机游动

1 人工鱼群算法

1.0 初始化鱼群及算法参数

div—————–解的自变量个数。 e.g: div = 3 –> X = x1, x2, x3

number———-自变量向量 

visual————-鱼群视觉范围

step—————鱼移动一步的最大步长

try_time———-鱼进行捕食行为时搜索周围环境更优解的次数

delta————–拥挤程度,[0, 1),影响追尾和聚群

tag—————-公告牌,记录每次循环过后,目标函数的最优值

1.1 进入循环,鱼群中的鱼分别进行如下操作:(伪代码如下)

捕食行为

def prey()
	pre_score = fish.func()  # 原来fish的目标函数值
	for(i in 0 : try_time)    
		newfish = new Fish(rnorm(fish.number, sigma))    # 以fish为中心生成新的new_fish
		if(newfish.func() > pre_score)   # 产生了更优解
			fish = new_fish

追尾行为

def follow()
	fo = 鱼fish视线范围内所有鱼的集合
	best_fish = fo集合中目标函数值最高的鱼
	if(best_fish周围拥挤)
		执行其他操作,如捕食行为、随机行为
	else
		fish向best_fish移动,最大移动距离为step

聚群行为

def swarm()
	sw = 鱼fish视线范围内所有鱼的集合
	center_fish = sw的中心位置
	if(center_fish周围拥挤)
		执行其他行为,如随机操作、捕食操作
	else
		fish向center_fish移动,最大移动step长

随机行为

def rand()
    以当前fish位置为中心,随机向四周移动,每个维度上最多移动step长

2 python实现过程

import math
import matplotlib.pyplot as plt
import numpy

my_flag = 1
# my_flag == 0 计算第一个函数最大值
# my_flag == 1 计算第二个函数最大值


class fish:
    def __init__(self, div, number, visual, step, try_time, delta):
        # 初始化
        self.div = div
        self.number = number
        self.visual = visual
        self.step = step
        self.try_time = try_time
        self.delta = delta

    def distance(self, f):
        # 计算self鱼和f鱼之间的距离
        ll = len(self.number)
        res = 0.0
        for i in range(ll):
            res = res + (self.number[i] - f.number[i]) * (self.number[i] - f.number[i])
        return math.sqrt(res)

    def func(self, flag):
        # 计算鱼在当前位置的函数
        ll = len(self.number)
        if flag == 0:
            res = 0
            for i in range(ll):
                res = res + self.number[i] * self.number[i]
            return 500-res
        else:
            res = 0
            mul = 1
            for i in range(ll):
                res = res + math.fabs(self.number[i])
                mul = mul * math.fabs(self.number[i])
            return 500-(res + mul)


    def prey(self):
        # 捕食操作
        pre = self.func(my_flag)
        for i in range(self.try_time):
            rand = numpy.random.randint(-99, 99, self.div) / 100 * self.visual
            for j in range(self.div):
                self.number[j] = self.number[j] + rand[j]
            cur = self.func(my_flag)
            if cur > pre:
                # 捕食成功
                # print('原始分数:' + str(pre) + '新分数:' + str(cur) + '捕食成功!!')
                return cur
            else:
                # 捕食失败
                for j in range(self.div):
                    self.number[j] = self.number[j] - rand[j]
        # print("捕食失败!")
        return pre

    def swarm(self, fishes):
        # 聚群行为:向视觉内鱼群中心前进step
        close_swarm = find_close_swarm(fishes, self)
        center_f = center_fish(close_swarm)
        n = len(close_swarm) - 1
        if n != 0 and (center_f.func(my_flag) / n > self.delta * self.func(my_flag)):
            # print("聚群运动")
            for i in range(self.div):
                self.number[i] = self.number[i] + self.step * center_f.number[i]
            return self.func(my_flag)
        else:
            # print("随机运动")
            return self.rand()

    def rand(self):
        for i in range(self.div):
            self.number[i] = self.number[i] + self.step * numpy.random.uniform(-1, 1, 1)

    def follow(self, fishes):
        # 追尾行为:向着视觉内鱼群中目标函数值最优的鱼前进step
        close_swarm = find_close_swarm(fishes, self)
        best_f = best_fish(close_swarm)
        n = len(close_swarm) - 1
        if n != 0 and (best_f.func(my_flag) / n > self.delta * self.func(my_flag)):
            # 向前移动
            # print("向前移动")
            for i in range(self.div):
                self.number[i] = self.number[i] + self.step * (best_f.number[i] - self.number[i])
            return self.func(my_flag)
        else:
            # 随机运动
            # print("随机运动")
            return self.rand()


def find_close_swarm(fishes, fish_):
    # 在种群fishes中查找fish_视觉范围内的鱼
    # 输入为fishes,是一个list型变量 和一个fish对象
    # 输出为一个fish list
    res = []
    for fi in fishes:
        if fish_.distance(fi) < fish_.visual:
            res.append(fi)
    return res


def center_fish(fishes):
    # 计算当前种群的中心位置,并将其中心位置记为certer_fish以完成聚群操作
    # 输入为fishes,是一个list型变量
    # 输出为一个fish对象
    ll = len(fishes)
    if ll == 0 or ll == 1:
        return None
    res = fish(fishes[0].div, fishes[0].number, fishes[0].visual, fishes[0].step, fishes[0].try_time, fishes[0].delta)
    for i in range(fishes[0].div):
        res.number[i] = 0
    for i in range(ll):
        for j in range(res.div):
            res.number[j] = res.number[j] + fishes[i].number[j]
    return res


def best_fish(fishes):
    # 计算当前种群最优个体的位置,并将其返回用于追尾操作
    # 输入为fishes,是一个list型变量
    # 输出为一个fish对象
    ll = len(fishes)
    if ll == 0 or ll == 1:
        return None
    index = -1
    max = 0
    for i in range(ll):
        if index == -1 or max < fishes[i].func(my_flag):
            index = i
            max = fishes[i].func(my_flag)
    return fishes[index]


def main():     # 主函数
    fishes = []
    div = 3         # xi中i的大小,e.g. div == 3 --> x1, x2, x3
    fish_num = 50   # 鱼群个体数目
    gmax = 100      # 循环最大次数
    tag = 0         # 公告牌
    visual = 1
    step = 0.2
    try_time = 10
    delta = 0.3
    list_of_fishes = []
    # 初始化鱼群
    for i in range(fish_num):
        num = numpy.random.uniform(10, 20, div)
        fi = fish(div, num, visual, step, try_time, delta)
        fishes.append(fi)
    for i in range(fish_num):
        list_of_fishes.append([])
    for g in range(gmax):
        for i in range(fish_num):
            if fishes[i].func(my_flag) > tag:
                tag = fishes[i].func(my_flag)
        # print(g, tag)
        for i in range(fish_num):
            if g >= 50:
                list_of_fishes[i].append(fishes[i].func(my_flag))
        for i in range(fish_num):
            if tag == fishes[i].func(my_flag):
                fishes[i].prey()
                continue
            tmp = numpy.random.randint(0, 3, 1)
            if tmp == 0:
                fishes[i].swarm(fishes)
            elif tmp == 1:
                fishes[i].follow(fishes)
            else:
                fishes[i].prey()
    print(tag)
    x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
    # print(x)
    for i in range(fish_num):
        # print(list_of_fishes[i][49] < 0.5)
        if math.fabs(list_of_fishes[i][49] - 500) < 20:
            plt.plot(x, list_of_fishes[i], color='orangered', marker='o', linestyle='-', label='A')
        else:
            plt.plot(x, list_of_fishes[i], color='green', marker='*', linestyle=':', label='C')

    plt.ylim(20, 50)
    plt.ylim(-500, 500)
    plt.xlabel("Loop_time")  # X轴标签
    plt.ylabel("Value")  # Y轴标签
    plt.show()


if __name__ == '__main__':
    main()

3 结果展示

目标函数为F(X) = 500 – x1^2 – x2 ^ 2 – x3 ^2

最优解为F(0, 0, 0) = 500 (最大值)

附:

其他群智能优化算法:
粒子群优化算法(附代码)icon-default.png?t=M4ADhttps://blog.csdn.net/cccddduil/article/details/123671197?spm=1001.2014.3001.5501

杂草算法(附代码)icon-default.png?t=M4ADhttps://blog.csdn.net/cccddduil/article/details/124843486?spm=1001.2014.3001.5502

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2022年5月23日
下一篇 2022年5月23日

相关推荐