今天不会,问ai给的,自己慢慢的解释了代码,现在明白了,但是不会写,看还是能看懂的
import random
import matplotlib.pyplot as plt
import numpy as np
class Particle:
def __init__(self, x, y, vx, vy):
# [x,y] pos结果 [-10,10] x,y 的位置
self.pos = np.array([x, y]) # 粒子的位置
#[-10,10] vel x,y方向的速度 相当与速度分解了
self.vel = np.array([vx, vy]) # 粒子的速度
self.best_pos = self.pos # 粒子最好的位置
self.best_score = None # 粒子最好的适应度值
def update_position(self):
#两个数组相加 数组里面一对一相加 [1,2]+[3,4]=[4,6] 然后复制pos 相当于位置加速度 得到新的位置
self.pos += self.vel
#第二个参数的要解决问题的函数 该函数两个参数是x,y 可以表示一个点
def evaluate_score(self, fitness_func):
#score 是一个元组里面有一个数把x**2+y**2 的结果 这个也算适应度
score = fitness_func(*self.pos)
#如果这次的位置比之前的位置要好,就把这个记下来 适应度也记录下面
if self.best_score is None or score > self.best_score:
self.best_pos = self.pos
self.best_score = score
class PSO:
def __init__(self, num_particles, range_x, range_y, fitness_func, weight, learning_rate, c1, c2):
#粒子数量
self.num_particles = num_particles
#粒子位置 x,y 元组
self.range_x = range_x
#粒子速度 x,y 分量
self.range_y = range_y
#优化的目标函数
self.fitness_func = fitness_func
# 权重
self.weight = weight
#学习因子 控制粒子的速度变化的幅度
self.learning_rate = learning_rate
self.c1 = c1
self.c2 = c2
#在[-10,10] 生成一个数 x ,y 速度都是0 然后一次生成了50个粒子 [0,50)
self.particles = [Particle(random.uniform(range_x[0], range_x[1]), random.uniform(range_y[0], range_y[1]), 0, 0)
for _ in range(num_particles)]
#粒子群最好的位置
self.gbest_pos = None
#粒子群的最好位置对应的适应度
self.gbest_score = None
#存储粒子群的历史最优解
self.history = []
#遍历每个粒子并计算对目标函数的适应度 然后 从中找到一个最优的粒子 作为粒子群的最优位置和最优适应度
def evaluate_fitness(self):
#遍历粒子
for particle in self.particles:
#算粒子的对目标函数的适应度 粒子会判断这次的位置和自己的历史位置,哪个最好,最好就记录下来,位置和适应度
particle.evaluate_score(self.fitness_func)
#因为第一次是None 不得不这么写 ,判断粒子的最优适应度是否比种群的适应度要大?
if self.gbest_score is None or particle.best_score > self.gbest_score:
#如果有最优的,就更新 并记录下适应度
self.gbest_pos = particle.best_pos
self.gbest_score = particle.best_score
#移动粒子
def update_particles(self):
#遍历粒子
for particle in self.particles:
#生成[0,1]之间的随机数 r1控制个体的位置 r2控制群体的位置 r1 和 r2 来影响粒子的搜索方向和速度调整,但是这种影响是间接的
r1 = random.uniform(0, 1)
r2 = random.uniform(0, 1)
#使用公式计算粒子要移动的速度 不知道这种公式是如何想出来的 particel.vel是一个numpy的列表 [x,y] 这样的 best_pos和pos一样 [x,y] 也是numpy的
particle.vel = self.weight * particle.vel + self.c1 * r1 * (
particle.best_pos - particle.pos) + self.c2 * r2 * (self.gbest_pos - particle.pos)
#该循环上面完成了速度计算 下面两行是限制速度的,可能超过最大速度和低于最小速度
# 可以枚举,比如如果比learning_rate还小 或者还大,最终的结果一定是[-self.learning_rate,self.learning_rate]
#速度变化不可以超过0.1 不可低于-0.1
particle.vel[0] = max(-self.learning_rate, min(particle.vel[0], self.learning_rate))
particle.vel[1] = max(-self.learning_rate, min(particle.vel[1], self.learning_rate))
#至此 循环完整了 合法的速度 速度没有问题了,然后更新位置,就会用我们最新的速度去移动了,得到新的位置
particle.update_position()
# 确保粒子位置在指定范围内 x,y 坐标不可以超过范围-10 到10 以确保在搜索空间内搜索 其它以外不要
particle.pos[0] = max(self.range_x[0], min(particle.pos[0], self.range_x[1]))
particle.pos[1] = max(self.range_y[0], min(particle.pos[1], self.range_y[1]))
#至此完成了位置的限制 速度和位置都完成了 依次重复即可
def run(self, num_iterations):
#开始迭代(每次迭代全部粒子移动一次) 不断求适应度,然后记录最优值 ,然后移动 ,这样重复
for i in range(num_iterations):
#遍历每个粒子并求适应度,然后找到最优秀的作为粒子群的最优粒子,然后记录下来
self.evaluate_fitness()
#计算速度,修正速度超出范围,然后移动,更新位置
self.update_particles()
#记录最优秀粒子
self.history.append(self.gbest_score)
#每迭代10次就输出一次目前最优的粒子
if i % 10 == 0:
print("Iteration {}: Best Score = {}".format(i, self.gbest_score))
print("Optimization finished.")
print("Best solution found at:")
#最优的位置
print(self.gbest_pos)
print("Best score:")
#对应的适应度
print(self.gbest_score)
# 绘制适应度值历史记录
plt.plot(self.history)
plt.title("Fitness Value History")
plt.xlabel("Iteration")
plt.ylabel("Fitness Value")
plt.show()
# 定义一个二维函数作为优化目标
def fitness_func(x, y):
return (x**2 + y**2)
# 创建一个PSO对象并运行算法
#粒子的数量,粒子x范围位置(只能在这个区域搜索),后面在这个范围里面得到一个随机数 粒子y范围 优化的目标函数
# 惯性权重(控制当前迭代中速度对下一代的运动状态的影响程度) 学习因子(粒子速度更新幅度) c1控制自身位置对速度的影响程度 c2同理
pso = PSO(num_particles=50, range_x=(-10, 10), range_y=(-10, 10), fitness_func=fitness_func, weight=1, learning_rate=0.1, c1=0.5, c2=0.5)
#迭代次数
pso.run(num_iterations=100)