本算法是参照李晓磊博士的论文实现的,详细的算法原理可阅读《一种新型的智能优化方法_人工鱼群算法_李晓磊》
算法基于鱼群的生存行为:在一片水域中,鱼存在的数目最多的地方就是本水域中富含营养物质最多的地方,依据这一特点来模仿鱼群的觅食,聚群,追尾等行为,从而实现全局最优,这就是鱼群算法的基本思想。
鱼类的活动中,觅食行为,聚群行为,追尾行为和随机行为与寻优命题的解决有较密切的关系,如何利用简单有效的方式来构造实现这些行为将是算法实现的主要问题。
行为模式
觅食行为(AF-prey):指鱼循着食物多的方向游动的一种行为,人工鱼Xi在其视野内随机选择一个状态Xj,分别计算它们的目标函数值进行比较,如果发现Yj比Yi优,则Xi向Xj的方向移动一步;否则,Xi继续在其视野内选择状态Xj,判断是否满足前进条件,反复尝试trynumber次后,仍没有满足前进条件,则随机移动一步使Xi到达一个新的状态。
聚群行为(AF-swarm):鱼在游动过程中为了保证自身的生存和躲避危害会自然地聚集成群 。鱼聚群时所遵守的规则有三条:分隔规则:尽量避免与临近伙伴过于拥挤;对准规则:尽量与临近伙伴的平均方向一致;内聚规则:尽量朝临近伙伴的中心移动。 人工鱼Xi搜索其视野内的伙伴数目nf及中心位置Xc,若Yc/ nf > δYi,表明伙伴中心位置状态较优且不太拥挤,则Xi朝伙伴的中心位置移动一步,否则执行觅食行为。
追尾行为(AF-follow):指鱼向其可视区域内的最优方向移动的一种行为。人工鱼Xi搜索其视野内所有伙伴中的函数最优伙伴Xj,如果Yj/nf> δYi,表明最优伙伴的周围不太拥挤,则Xi朝Xj移动一步,否则执行觅食行为。
PS:公告板,是记录最优人工鱼个体状态的地方。每条人工鱼在执行完一次迭代后将自身当前状态与公告板中记录的状态进行比较,如果优于公告板中的状态则用自身状态更新公告板中的状态,否则公告板的状态不变。当整个算法的迭代结束后,输出公告板的值,就是我们所求的最优值。
模拟仿真:
参数设定:
初始鱼群数量N=20,移动步长AF_step=2.5,感知距离AF_visual=0.3 ,最大尝试次数try_number=50 ,拥挤度因子delta=0.618
(食物浓度)目标函数: sin(x)*sin(y)/(x*y)
编程语言:Python
绘图工具:matplotlib
AF.py
from __future__ import division
from random import uniform,random
from math import pi,sin,cos,sqrt
def Y(fish_pos):
return sin(fish_pos[0])*sin(fish_pos[1])/(fish_pos[0]*fish_pos[1])
def distance(x , y):
return sqrt((x[0]-y[0])**2+(x[1]-y[1])**2)
class AF():
def __init__(self, AF_X, AF_step, AF_visual, try_number,delta):
self.AF_step = AF_step
self.AF_visual = AF_visual
self.try_number = try_number
self.AF_X = AF_X
self.delta = delta
self.forumboard = None #定义公告板
#定义觅食行为
def AF_prey(self, fish_pos):
for i in range(self.try_number):
randangle = uniform(0, 2 * pi)
randlength = uniform(0, self.AF_visual)
tempa, tempb = fish_pos[0] + cos(randangle) * randlength, fish_pos[1] + sin(randangle) * randlength
if Y((fish_pos[0], fish_pos[1])) < Y((tempa, tempb)):
r = random()
fish_pos = (fish_pos[0] + r * cos(randangle) * self.AF_step,
fish_pos[1] + r * sin(randangle) * self.AF_step)
return fish_pos
else:
fish_pos = self.AF_move(fish_pos)
return fish_pos
#定义聚群行为
def AF_swarm(self, fish_pos):
nf = 0
AF_XC = (0, 0)
for j in range(len(self.AF_X)):
if distance(fish_pos, self.AF_X[j]) < self.AF_visual:
nf += 1
AF_XC = (AF_XC[0] + self.AF_X[j][0], AF_XC[1] + self.AF_X[j][1])
AF_XC = (AF_XC[0] / nf, AF_XC[1] / nf)
if distance(fish_pos, AF_XC) != 0 and (Y(AF_XC) / nf) > (self.delta * Y(fish_pos)):
r = random()
fish_pos = ((AF_XC[0] + fish_pos[0]) * (r * self.AF_step / distance(fish_pos, AF_XC)),
(AF_XC[1] + fish_pos[1]) * (r * self.AF_step / distance(fish_pos, AF_XC)))
return fish_pos
else:
fish_pos = self.AF_prey(fish_pos)
return fish_pos
#定义追尾行为
def AF_follow(self,fish_pos):
dis_dic= {}
nf = 0
dis_dic[fish_pos] = Y(fish_pos)
for j in range(len(self.AF_X)):
if distance(fish_pos, self.AF_X[j]) < self.AF_visual:
dis_dic[self.AF_X[j]] = Y(self.AF_X[j])
nf += 1
max_Element = max(dis_dic.items(), key=lambda x: x[1])
max_X = max_Element[0]
#更新公告板
if self.forumboard == None:
self.forumboard = max_Element[1]
self.forumboard = self.forumboard if self.forumboard > max_Element[1] else max_Element[1]
print(self.forumboard)
if Y(max_X) / nf > self.delta * Y(fish_pos) and distance(fish_pos, max_X) != 0:
r = random()
fish_pos = ((max_X[0] + fish_pos[0]) * (r * self.AF_step / distance(fish_pos, max_X)),
(max_X[1] + fish_pos[1]) * (r * self.AF_step / distance(fish_pos, max_X)))
return fish_pos
else:
fish_pos = self.AF_prey(fish_pos)
return fish_pos
#定义随机行为
def AF_move(self, fish_pos):
randangle = uniform(0,2*pi)
fish_pos = (fish_pos[0] + cos(randangle)*self.AF_step, fish_pos[1] + sin(randangle)*self.AF_step)
return fish_pos
主函数
import random
from AF import AF
import numpy as np
import matplotlib.pyplot as plt
#定义随机生成number个点
def randpoint(number):
init = []
for i in range(number):
a = random.uniform(-10, 10)
b = random.uniform(-10, 10)
init.append((a, b))
return init
init1 = randpoint(20)
init2 = init1[:]
init3 = init1[:]
af1 = AF(init1,AF_step=2.5, AF_visual=0.3, try_number=50, delta=0.618)
af2 = AF(init2,AF_step=2.5, AF_visual=0.3, try_number=50, delta=0.618)
af3 = AF(init3,AF_step=2.5, AF_visual=0.3, try_number=50, delta=0.618)
optimum = []
iteration = []
for i in range(20):
for j in range(len(init1)):
init1[j]=af1.AF_swarm(init1[j])
init1[j]=af1.AF_follow(init1[j])
for i in range(50):
for j in range(len(init2)):
init2[j]=af2.AF_swarm(init2[j])
init2[j]=af2.AF_follow(init2[j])
for i in range(100):
for j in range(len(init3)):
init3[j]=af3.AF_swarm(init3[j])
init3[j]=af3.AF_follow(init3[j])
optimum.append(af3.forumboard)
iteration.append(i)
x1 = [i[0] for i in init1]
y1 = [i[1] for i in init1]
x2 = [i[0] for i in init2]
y2 = [i[1] for i in init2]
x3 = [i[0] for i in init3]
y3 = [i[1] for i in init3]
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax1.scatter(x1,y1)
ax1.set_xlabel("迭代20次")
ax2 = fig.add_subplot(222)
ax2.scatter(x2,y2)
ax2.set_xlabel("迭代50次")
ax3 = fig.add_subplot(223)
ax3.scatter(x3, y3)
ax3.set_xlabel("迭代100次")
ax4 = fig.add_subplot(224)
ax4.plot(iteration, optimum)
ax4.set_xlabel("迭代100次时的最优解")
plt.show()
分别迭代20次,50次,100次的情况:
以上结果表明:在(0,0)时目标函数取得最大值为1
人工鱼群算法python代码_人工鱼群算法python_鱼群算法 - Brillou的个人空间 - OSCHINA - 中文开源技术交流社区......