#------------------------------------------------------------------------------+
#
# Python 3.6
#
#------------------------------------------------------------------------------+
#--- 导入依赖 --------------------------------------------------------+
from random import random
from random import uniform
#--- 主要代码 --------------------------------------------------------+
class Particle:
def __init__(self, x0):
self.position_i = [] # 粒子位置
self.velocity_i = [] # 粒子速度
self.pos_best_i = [] # 粒子的最佳位置
self.err_best_i = -1 # 粒子的最佳误差
self.err_i = -1 # 粒子当前误差
for i in range(0, num_dimensions):
self.velocity_i.append(uniform(-1, 1)) # 初始化速度为随机值
self.position_i.append(x0[i]) # 初始化位置
# 评估当前适应度
def evaluate(self, costFunc):
self.err_i = costFunc(self.position_i) # 计算当前误差
# 判断当前误差是否为个体最佳
if self.err_i < self.err_best_i or self.err_best_i == -1:
self.pos_best_i = self.position_i.copy() # 更新个体最佳位置
self.err_best_i = self.err_i # 更新个体最佳误差
# 更新粒子速度
def update_velocity(self, pos_best_g):
w = 0.5 # 惯性权重(前一个速度的权重)
c1 = 1 # 认知常数
c2 = 2 # 社会常数
for i in range(0, num_dimensions):
r1 = random()
r2 = random()
# 认知部分的速度
vel_cognitive = c1 * r1 * (self.pos_best_i[i] - self.position_i[i])
# 社会部分的速度
vel_social = c2 * r2 * (pos_best_g[i] - self.position_i[i])
# 更新速度
self.velocity_i[i] = w * self.velocity_i[i] + vel_cognitive + vel_social
# 根据新速度更新粒子位置
def update_position(self, bounds):
for i in range(0, num_dimensions):
self.position_i[i] = self.position_i[i] + self.velocity_i[i] # 更新位置
# 如果超出最大边界则调整
if self.position_i[i] > bounds[i][1]:
self.position_i[i] = bounds[i][1]
# 如果超出最小边界则调整
if self.position_i[i] < bounds[i][0]:
self.position_i[i] = bounds[i][0]
def minimize(costFunc, x0, bounds, num_particles, maxiter, verbose=False):
global num_dimensions
num_dimensions = len(x0)
err_best_g = -1 # 全局最佳误差
pos_best_g = [] # 全局最佳位置
# 初始化粒子群
swarm = []
for i in range(0, num_particles):
swarm.append(Particle(x0))
# 开始优化循环
i = 0
while i < maxiter:
if verbose:
print(f'迭代次数: {i:>4d}, 最佳解决方案: {err_best_g:10.6f}')
# 遍历粒子群,评估适应度
for j in range(0, num_particles):
swarm[j].evaluate(costFunc)
# 判断当前粒子是否为全局最优
if swarm[j].err_i < err_best_g or err_best_g == -1:
pos_best_g = list(swarm[j].position_i)
err_best_g = float(swarm[j].err_i)
# 更新粒子的速度和位置
for j in range(0, num_particles):
swarm[j].update_velocity(pos_best_g)
swarm[j].update_position(bounds)
i += 1
# 打印最终结果
if verbose:
print('\n最终解决方案:')
print(f' > {pos_best_g}')
print(f' > {err_best_g}\n')
return err_best_g, pos_best_g
#--- 结束 -----------------------------------------------------------+
代码解释:
这个代码实现了一个简单的粒子群优化(PSO)算法。PSO 是一种基于群体的优化方法,模仿了自然界中群体运动(如鸟群或鱼群)的行为。
-
粒子类(
Particle
):- 每个粒子有自己的位置、速度、个体最佳位置和误差值。
- 每个粒子通过函数
evaluate
评估它当前位置的适应度(即误差值),并更新其个体最佳位置和误差。 - 函数
update_velocity
负责更新粒子的速度,速度的更新受三个因素影响:惯性权重(过去的速度)、认知(粒子自己的经验)和社会(群体的经验)。 update_position
负责根据速度更新粒子的位置,并确保位置在给定的边界范围内。
-
minimize
函数:- 这是 PSO 的核心优化算法。首先,初始化一群粒子,每个粒子的初始位置基于输入的
x0
。 - 在每次迭代中,算法会让每个粒子评估其适应度,并检查是否有更好的个体或全局位置。然后,它会根据全局最佳位置更新每个粒子的速度和位置。
- 这个过程持续
maxiter
次迭代,最终输出全局最优的解决方案和对应的误差值。
- 这是 PSO 的核心优化算法。首先,初始化一群粒子,每个粒子的初始位置基于输入的
PSO 是一种非常常用的全局优化方法,适用于连续空间的优化问题。