赞
踩
粒子群算法的思想源于对鸟群觅食行为的研究,鸟群通过集体的信息共享使群体找到最优的目的地。如下图,设想这样一个场景:鸟群在森林中随机搜索食物,它们想要找到食物量最多的位置。但是所有的鸟都不知道食物具体在哪个位置,只能感受到食物大概在哪个方向。每只鸟沿着自己判定的方向进行搜索,并在搜索的过程中记录自己曾经找到过食物且量最多的位置,同时所有的鸟都共享自己每一次发现食物的位置以及食物的量,这样鸟群就知道当前在哪个位置食物的量最多。在搜索的过程中每只鸟都会根据自己记忆中食物量最多的位置和当前鸟群记录的食物量最多的位置调整自己接下来搜索的方向。鸟群经过一段时间的搜索后就可以找到森林中哪个位置的食物量最多(全局最优解)。
粒子群算法寻找(-10*x1) - (math.e ** ((-x2/10)-x3))最小值,约束条件见代码中;
- import numpy as np
- import random
- import math
- import time
- import matplotlib.pyplot as plt
-
- """PSO参数设置"""
- class PSO:
- def __init__(self, D, N, M, p_low, p_up, v_low, v_high, w = 1., c1 = 2., c2 = 2.):
- self.w = w # 惯性权值
- self.c1 = c1 # 个体学习因子
- self.c2 = c2 # 群体学习因子
- self.D = D # 粒子维度
- self.N = N # 粒子群规模,初始化种群个数
- self.M = M # 最大迭代次数
- self.p_range = [p_low, p_up] # 粒子位置的约束范围
- self.v_range = [v_low, v_high] # 粒子速度的约束范围
- self.x = np.zeros((self.N, self.D)) # 所有粒子的位置
- self.v = np.zeros((self.N, self.D)) # 所有粒子的速度
- self.p_best = np.zeros((self.N, self.D)) # 每个粒子的最优位置
- self.g_best = np.zeros((1, self.D))[0] # 种群(全局)的最优位置
- self.p_bestFit = np.zeros(self.N) # 每个粒子的最优适应值
- self.g_bestFit = float('Inf') # float('-Inf'),始化种群(全局)的最优适应值,由于求极小值,故初始值给大,向下收敛,这里默认优化问题中只有一个全局最优解
-
- # 初始化所有个体和全局信息
- for i in range(self.N):
- for j in range(self.D):
- self.x[i][j] = random.uniform(self.p_range[0][j], self.p_range[1][j])
- self.v[i][j] = random.uniform(self.v_range[0], self.v_range[1])
- self.p_best[i] = self.x[i] # 保存个体历史最优位置,初始默认第0代为最优
- fit = self.fitness(self.p_best[i])
- self.p_bestFit[i] = fit # 保存个体历史最优适应值
- if fit < self.g_bestFit: # 寻找并保存全局最优位置和适应值
- self.g_best = self.p_best[i]
- self.g_bestFit = fit
-
- def fitness(self,x):
- """
- 根据粒子位置计算适应值,可根据问题情况自定义
- """
- return (-10*x[0]) - (math.e ** ((-x[1]/10)-x[2]))
-
- def update(self):
- for i in range(self.N):
- # 更新速度(核心公式)
- self.v[i] = self.w * self.v[i] + self.c1 * random.uniform(0, 1) * (
- self.p_best[i] - self.x[i]) + self.c2 * random.uniform(0, 1) * (self.g_best - self.x[i])
- # 速度限制
- for j in range(self.D):
- if self.v[i][j] < self.v_range[0]:
- self.v[i][j] = self.v_range[0]
- if self.v[i][j] > self.v_range[1]:
- self.v[i][j] = self.v_range[1]
- # 更新位置
- self.x[i] = self.x[i] + self.v[i]
- # 位置限制
- for j in range(self.D):
- if self.x[i][j] < self.p_range[0][j]:
- self.x[i][j] = self.p_range[0][j]
- if self.x[i][j] > self.p_range[1][j]:
- self.x[i][j] = self.p_range[1][j]
- # 更新个体和全局历史最优位置及适应值
- _fit = self.fitness(self.x[i])
- if _fit < self.p_bestFit[i]:
- self.p_best[i] = self.x[i]
- self.p_bestFit[i] = _fit
- if _fit < self.g_bestFit:
- self.g_best = self.x[i].copy()
- self.g_bestFit = _fit
-
- def pso(self, draw = 1):
- best_fit = [] # 记录每轮迭代的最佳适应度,用于绘图
- w_range = None
- if isinstance(self.w, tuple):
- w_range = self.w[1] - self.w[0]
- self.w = self.w[1]
- time_start = time.time() # 记录迭代寻优开始时间
- for i in range(self.M):
- self.update() # 更新主要参数和信息
- if w_range:
- self.w -= w_range / self.M # 惯性权重线性递减
- print("\rIter: {:d}/{:d} fitness: {:.4f} ".format(i, self.M, self.g_bestFit, end = '\n'))
- print("x:",self.g_best)
- best_fit.append(self.g_bestFit.copy())
- time_end = time.time() # 记录迭代寻优结束时间
- print(f'Algorithm takes {time_end - time_start} seconds') # 打印算法总运行时间,单位为秒/s
- if draw:
- plt.figure()
- plt.plot([i for i in range(self.M)], best_fit)
- plt.xlabel("iter")
- plt.ylabel("fitness")
- plt.title("Iter process")
- plt.show()
-
- if __name__ == '__main__':
- low = [0, 1, 0]
- up = [1, 80, 120]
- pso = PSO(3, 100, 100, low, up, -1, 1, w = 0.9)
- pso.pso()
-
-
鸣谢:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。