代码摘自:
https://blog.csdn.net/winycg/article/details/79120154
思路参考自:
https://zhuanlan.zhihu.com/p/107485342
原文采用的是固定权值,此处采用线性递减的权值策略,以提供另一种思路
'''
参考:
https://blog.csdn.net/winycg/article/details/79120154
https://zhuanlan.zhihu.com/p/107485342
原文采用的是固定权值,此处采用线性递减的权值策略,以提供另一种思路
'''
import numpy as np
import matplotlib.pyplot as plt
import time
class PSO:
def __init__(self, max_steps, max_size):
self.max_steps = max_steps # 最大迭代次数
self.max_size = max_size # 粒子数量
self.init_weight = self.cur_weight = 0.6 # 初始惯性权重与当前惯性权重
self.end_weight = 0.1
self.c1 = self.c2 = 2 # 个体学习因子、社会学习因子
self.boundary = [-10, 10] # 粒子群取值范围(解空间范围)
self.dim = 2 # 维度
# 初始化粒子群位置
self.x = np.random.uniform(low=self.boundary[0],
high=self.boundary[1],
size=(max_size, self.dim)) # max_num行,2列
# 初始化粒子群速度
self.v = np.random.rand(self.max_size, self.dim)
# 计算当前所有粒子的适应值向量,所有粒子历史最佳适应度及其对应位置
self.curFitness = self.get_fitness(self.x)
self.individualBestFitness = self.curFitness
self.pbest = self.x
# 获取全局最佳适应度及其最佳位置
self.globalBestFitness = np.min(self.individualBestFitness)
self.gbest = self.x[np.argmin(self.individualBestFitness)] # np.argmin 给出水平方向最小值的下标
def get_fitness(self, x):
# 按行求平方和,即 X^2 + Y^2
return np.sum(np.square(x), axis=1)
def evolve(self):
self.iter = 0
for step in range(self.max_steps):
self.iter = self.iter + 1
self.cur_weight = (self.init_weight - self.end_weight) * float(self.max_steps - self.iter) / float(self.max_steps) + self.end_weight
# 生成两个随机数,分别代表飞向当前粒子历史最佳位置、全局历史最佳位置的程度
r1 = np.random.rand(self.max_size, self.dim)
r2 = np.random.rand(self.max_size, self.dim)
# 更新速度和权重
self.v = self.cur_weight * self.v + self.c1 * r1 * (self.pbest - self.x) \
+ self.c2 * r2 * (self.gbest - self.x)
self.x = self.x + self.v
# 画图
plt.clf() # 清除当前 figure, 不关闭窗口
plt.scatter(self.x[:, 0], self.x[:, 1], s=30, color='r') # s代表大小,k代表black
# x、y轴作图范围
plt.xlim(self.boundary[0], self.boundary[1])
plt.ylim(self.boundary[0], self.boundary[1])
# 画面停顿,以秒为单位
plt.pause(0.01)
# 计算当前所有粒子的适应值向量,所有粒子历史最佳适应度及其对应位置
self.curFitness = self.get_fitness(self.x)
update_id = np.greater(self.curFitness, self.individualBestFitness)
self.individualBestFitness[update_id] = self.curFitness[update_id]
self.pbest[update_id] = self.x[update_id]
# 获取全局最佳适应度及其最佳位置
if self.globalBestFitness > np.min(self.individualBestFitness):
self.globalBestFitness = np.min(self.individualBestFitness)
self.gbest = self.x[np.argmin(self.individualBestFitness)]
# 增加一个终止条件,以便计算寻找到最优值的耗时与迭代次数
if self.globalBestFitness - 0.0 < 1e-10:
break
print('global best fitness: %.5f, current mean fitness: %.5f' % (self.globalBestFitness, np.mean(self.curFitness)), end=" ")
print("最优位置:", self.gbest)
if __name__ == "__main__":
pso = PSO(100, 100)
start = time.time()
pso.evolve()
print("寻找到近似最优解时,共迭代了", pso.iter, "次,总共耗费了", (time.time() - start), "秒")
plt.show()