算法概述
粒子群算法是根据鸟群觅食演化出的算法,我们的每个智能体相当于一只鸟,鸟的目标非常简单,就是要在食物最充足的地方安家,他们的策略是
1.每只鸟随机找一个地方,评估这个地方的食物量
2.所有的鸟一起开会,选出食物最多的地方作为候选点G
3.所有的鸟回顾自己的旅程,记住自己去过的食物最多的地方P
4.每只鸟为了找到食物量更多的地方,于是向着G飞行,但是呢,不知是出于选择困难症还是对P的留恋,或者是对G的不信任,小鸟向G飞行时,时不时也向P飞行,其实它自己也不知道到底是向G飞行的多还是向P飞行的多。
5.又到了开会的时间,如果小鸟们决定停止寻找,那么它们会选择当前的G来安家
算法流程
粒子群算法通过设计一种无质量的粒子来模拟鸟群中的鸟,粒子仅具有两个属性:速度和位置 ,速度代表移动的快慢,位置代表移动的方向。每个粒子在搜索空间中单独的搜寻最优解,并将其记为当前个体极值 ,并将个体极值与整个粒子群里的其他粒子共享,找到最优的那个个体极值作为整个粒子群的当前全局最优解 ,粒子群中的所有粒子根据自己找到的当前个体极值和整个粒子群共享的当前全局最优解来调整自己的速度和位置。粒子群算法的思想相对比较简单,主要分为
1、初始化粒子群
2、评价粒子,即计算适应值
3、寻找个体极值
4、寻找全局最优解
5、修改粒子的速度和位置。
更新速度和位置的公式
V i d = ω V i d + C 1 r a n d o m ( 0 , 1 ) ( P i d − X i d ) + C 2 r a n d o m ( 0 , 1 ) ( G i d − X i d ) % MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqiVu0Je9sqqr % pepC0xbbL8F4rqqrFfpeea0xe9Lq-Jc9vqaqpepm0xbba9pwe9Q8fs % 0-yqaqpepae9pg0FirpepeKkFr0xfr-xfr-xb9adbaqaaeGaciGaai % aabeqaamaabaabauaakeGabaaQpiaabAfadaWgaaWcbaGaamyAaiaa % dsgaaeqaaOGaeyypa0JaeqyYdCNaamOvamaaBaaaleaacaWGPbGaam % izaaqabaGccqGHRaWkcaWGdbWaaSbaaSqaaiaaigdaaeqaaOGaamOC % aiaadggacaWGUbGaamizaiaad+gacaWGTbGaaiikaiaaicdacaGGSa % GaaGymaiaacMcacaGGOaGaamiuamaaBaaaleaacaWGPbGaamizaaqa % baGccqGHsislcaWGybWaaSbaaSqaaiaadMgacaWGKbaabeaakiaacM % cacqGHRaWkcaWGdbWaaSbaaSqaaiaaikdaaeqaaOGaamOCaiaadgga % caWGUbGaamizaiaad+gacaWGTbGaaiikaiaaicdacaGGSaGaaGymai % aacMcacaGGOaGaam4ramaaBaaaleaacaWGPbGaamizaaqabaGccqGH % sislcaWGybWaaSbaaSqaaiaadMgacaWGKbaabeaakiaacMcaaaa!7005! {{\rm{V}}_{id}} = \omega {V_{id}} + {C_1}random(0,1)({P_{id}} - {X_{id}}) + {C_2}random(0,1)({G_{id}} - {X_{id}}) Vid=ωVid+C1random(0,1)(Pid−Xid)+C2random(0,1)(Gid−Xid)
X i d = X i d + V i d % MathType!MTEF!2!1!+- % feaahqart1ev3aaatCvAUfeBSjuyZL2yd9gzLbvyNv2CaerbuLwBLn % hiov2DGi1BTfMBaeXatLxBI9gBaerbd9wDYLwzYbItLDharqqtubsr % 4rNCHbWexLMBbXgBd9gzLbvyNv2CaeHbl7mZLdGeaGqiVu0Je9sqqr % pepC0xbbL8F4rqqrFfpeea0xe9Lq-Jc9vqaqpepm0xbba9pwe9Q8fs % 0-yqaqpepae9pg0FirpepeKkFr0xfr-xfr-xb9adbaqaaeGaciGaai % aabeqaamaabaabauaakeaacaWGybWaaSbaaSqaaiaadMgacaWGKbaa % beaakiabg2da9iaadIfadaWgaaWcbaGaamyAaiaadsgaaeqaaOGaey % 4kaSIaamOvamaaBaaaleaacaWGPbGaamizaaqabaaaaa!49B8! {X_{id}} = {X_{id}} + {V_{id}} Xid=Xid+Vid
其中w为惯性因子,较大的w有利于全局搜索,较小的w有利于局部搜索,所以可以将w设置为递减的函数,C1和C2称为加速常数,一般取C1C2在0到4以内,random代表[0,1]的随机数,这两个随机数增加了算法的随机性,一定程度上避免了算法调入局部最优,Pid表示个体极值的第i个变量的第d维,Ggd表示全局最优解的第d维
实验
我们的测试函数是x*x + y*y,我们设置的区间是x属于[-10,10],y属于[-10,10],训练次数为100次
'''
@author: LyaJpunov
@date: 2022年10月1日18:56:06
@purpose: 粒子群算法的演示
'''
import random
random.seed(9)
# 训练次数
epoch = 200
# 粒子个数
pos_number = 100
# 惯性因子w
w = 0.5
# 加速度常数c1 c2
c1 = 2
c2 = 2
# 历史上最好的适应度与粒子位置
best_fitness = float('-inf')
best_list = [0, 0]
class Pos():
def __init__(self, x_, y_, v_x_, v_y_, max_x_, max_y_, max_v_x_, max_v_y_):
self.x = x_
self.y = y_
self.v_x = v_x_
self.v_y = v_y_
self.max_x = max_x_
self.max_y = max_y_
self.max_v_x = max_v_x_
self.max_v_y = max_v_y_
# 最优的适应度
self.max_fitness = float('-inf')
# 最优适应度的x与y
self.max_fitness_x = x_
self.max_fitness_y = y_
def __str__(self):
return f"{self.x} - {self.y}"
def update(self):
global best_list
global best_fitness
self.v_x = w * self.v_x + c1 * random.random() * (self.max_fitness_x - self.x) + c2 * random.random() * (
best_list[0] - self.x)
self.v_y = w * self.v_y + c1 * random.random() * (self.max_fitness_y - self.y) + c2 * random.random() * (
best_list[1] - self.y)
if abs(self.v_x) > self.max_v_x:
if self.v_x > 0:
self.v_x = self.max_v_x
else:
self.v_x = - self.max_v_x
if abs(self.v_y) > self.max_v_y:
if self.v_y > 0:
self.v_y = self.max_v_y
else:
self.v_y = - self.max_v_y
self.x = self.x + self.v_x
self.y = self.y + self.v_y
if abs(self.x) > self.max_x:
if self.x > 0 :
self.x = self.max_x
else:
self.x = -self.max_x
if abs(self.y) > self.max_y:
if self.y > 0:
self.y = self.max_y
else:
self.y = -self.max_y
# 更新粒子的最佳适应度
if fitness(self) > self.max_fitness:
self.max_fitness = fitness(self)
self.max_fitness_x = self.x
self.max_fitness_y = self.y
# 更新全局的最佳适应度
if self.max_fitness > best_fitness:
best_fitness = self.max_fitness
best_list[0] = self.x
best_list[1] = self.y
# 适应度函数,适应度函数的值越高,代表这个粒子越适合生存
def fitness(pos):
return pos.x * pos.x + pos.y * pos.y
# 创建粒子并初始化
pos_list = []
for i in range(pos_number):
pos_list.append(
Pos(random.randint(-10, 10), random.randint(-10, 10), (random.random()-0.5) * 2, (random.random()-0.5) * 2, 10, 10, 2, 2))
# 初始化最初的粒子
for pos in pos_list:
if fitness(pos) > best_fitness:
best_x = pos.x
best_y = pos.y
# 开始迭代
for i in range(epoch):
for pos in pos_list:
pos.update()
# 输出适应度最高的位置
print(best_list)