文章目录
- 算法说明:
- 算法流程:
- 代码实现:
- 结果展示:
- 结束
算法说明:
我看了下别人写的,这个粒子群算法的思想来源与鸟类捕食
我按我的理解解释一下:
很多只鸟在草原找食物,所有鸟刚开始都不知道食物在哪里,但是鸟儿们很聪明,会互相交流,同时食物有气味,鸟儿们可以通过气味判断自己离食物的远近,闻到气味最大的鸟儿会大叫告诉其他鸟儿,其他鸟儿也往气味最大的鸟身边飞,在它周围区域寻找。
因此,人们就使用这个模型来解决某些问题。也即是让鸟儿帮我们解决问题了
算法流程:
首先,我们要明白算法里面有什么元素:
1,群体规模N,鸟儿的数量
2,维度n,鸟儿所处世界维度,鸟儿是二次元鸟儿的话,那维度就是2
3,惯性权重w,鸟儿是有惯性的,这里表示鸟儿保持速度的能力吧
4,个体学习因子c1,鸟儿的学习能力
5,群体学习因子c2,鸟儿们的学习能力
6,随机数r1,r2,用这两个数保证随机性
7,鸟儿位置X,这个X可以用一个二维数组表示,记录每只鸟儿的位置
8,鸟儿速度V,这个V可以用一个二维数组表示,记录每只鸟儿的速度
9,个体适应度P,这个P可以用一个一维数组表示,记录每只鸟儿的适应度
10,最佳适应度PD,P中最小的值就是当前最佳适应度,当前最佳和历史最佳对比,谁小谁最佳
11,最佳位置pos_best,最佳适应度所在的位置
12,迭代次数k,我们迭代运算的次数
13,满意值t,这个值表示我们能够接受的最小界限,即当最佳适应度PD低于这个值时,我们也大差不差得到了我们满意的结果
接下来开始:
第一步,初始化
鸟儿们的位置和速度都是随机的,但是位置和速度都是有限制的
我们要随机给每只鸟儿安排位置和速度
第二步,算适应度
算适应度需要相应的公式来算,一般情况下,我们要通过我们要解决的问题来算这个适应度
选择当前最佳适应度,选最小的,并保留这个值相对应的位置,同时比对当前最佳适应度和历史最佳适应度,选最小的最佳
第三步,更新速度与位置
我们要根据公式来更新速度与位置
速度公式:
位置更新公式:
要注意的是,当我们更新速度和位置的时候要注意范围,即不要让它们超出范围,它们超出范围的话,就按边界值算
第四步 判断是否结束
当次数达到了规定迭代次数时可以结束
当最佳适应度值小于最小界限的时候可以结束
如果没有满足以上条件,那就返回第二步重新执行
代码实现:
目前只写了python的,能够展示粒子群的移动:
PSO.py
import math
import sys
from math import cos, sqrt
import numpy as np
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
import random
# 1 初始化粒子群参数
import time
class PSO(QWidget):up = QtCore.pyqtSignal(int, int, np.ndarray)def __init__(self):"""列表:X: 记录粒子位置(-400,400)V: 记录粒子速度(-20,20)P: 记录响应粒子搜索到的最佳位置PD: 群体最优位置单值:Fp: 个体历史最优位置Fg: 群体历史最优位置:return:"""super().__init__()# 初始化位置与速度def ini(self):self.N = 1000 # 群规模self.D = 2 # 群维度self.K = 1000 # 迭代次数self.w = 1 # 惯性权重self.c1 = 2 # 个体学习因子self.c2 = 2 # 群体学习因子self.r1 = random.uniform(0, 1) # 随机数1self.r2 = random.uniform(0, 1) # 随机数2self.MAX_X = 400 # 位置最大self.MIN_X = -400 # 位置最小self.MAX_V = 5 # 速度最大self.MIN_V = -5 # 速度最小self.X = np.zeros((self.N, self.D))self.V = np.zeros((self.N, self.D))self.XN = np.zeros((self.N, self.D))self.VN = np.zeros((self.N, self.D))self.P = []self.PD = 10086self.ans = []# self.choose = 1 # 公式选择for i in range(self.N):for j in range(self.D):a = random.uniform(self.MIN_X, self.MAX_X)self.X[i][j] = ab = random.uniform(self.MIN_V, self.MAX_V)self.V[i][j] = bdef check_x(self, x):if self.MAX_X <= x:return self.MAX_Xelif self.MIN_X >= x:return self.MIN_Xreturn xdef check_v(self, v):if self.MAX_V <= v:return self.MAX_Velif self.MIN_V >= v:return self.MIN_Vreturn v# 公式计算:def Cal1(self):for i in range(self.N):res1 = 0 # X平方res2 = 1for j in range(self.D):res1 = res1 + self.X[i][j]*self.X[i][j]res2 = res2 * cos(self.X[i][j] / sqrt(j + 1))ans = 1+1/4000 * res1 - res2self.P.append(ans)# 更新速度与位置def Cal2(self):for i in range(self.N):ans = 20 + self.X[i][0]*self.X[i][0] + \self.X[i][1]*self.X[i][1] - \10*(cos(2*math.pi*self.X[i][0])+cos(2*math.pi*self.X[i][1]))self.P.append(ans)def Update_X_Y(self):# print("更新")# 获取下一步速度for i in range(self.N):for j in range(self.D):self.VN[i][j] = self.w * self.V[i][j] + \self.c1*self.r1*(self.P[i]-self.X[i][j])+\self.c2*self.r2*(self.P[i]-self.X[i][j])self.VN[i][j] = self.check_v(self.VN[i][j])# 更新位置self.XN[i][j] = self.X[i][j] + self.VN[i][j]self.XN[i][j] = self.check_x(self.XN[i][j])# 下一次迭代了,该换换了for i in range(self.N):for j in range(self.D):self.V[i][j] = self.VN[i][j]self.X[i][j] = self.XN[i][j]self.P = []self.r1 = random.uniform(0, 1) # 随机数1self.r2 = random.uniform(0, 1) # 随机数2def go1(self):self.ini()print("开始,初始化")print("群初始位置:")for i in range(self.N):print(f'X{i+1}: ', end=' ')print(self.X[i])print("群初始速度:")for i in range(self.N):print(f'V{i + 1}: ', end=' ')print(self.V[i])# 最佳适应度公式选择def go2(self):if self.choose == 1:self.Cal1()elif self.choose == 2:self.Cal2()def start(self):self.go1()self.tol = 1e-6for i in range(self.K):QApplication.processEvents()# time.sleep(0.1)print(f"第{i+1}次迭代", end=" ")self.up.emit(self.N, self.D, self.X)QApplication.processEvents()self.go2()a = min(self.P)pos = self.X[self.P.index(a)]if self.PD > a:self.PD = aself.ans = posif self.PD < self.tol:break# print("取群体历史最优解并更新个体位置")print(f"目前最佳值: {self.PD}")self.Update_X_Y()if self.choose == 1:print("选择公式1")elif self.choose == 2:print("选择公式2")print(f"最终结果: {self.PD}")print(f'最佳位置: {self.ans}')# 只显示结果可运行这个if __name__ == "__main__":app = QApplication(sys.argv)PSO = PSO()PSO.show()PSO.hide()PSO.start()sys.exit(app.exec_())
窗口展示Window.py
import sysfrom PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtCore import Qt, QPointfrom PSO import PSO_translate = QtCore.QCoreApplication.translate # 翻译函数class Window(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("人工智能")menubar = self.menuBar()self.menu = menubar.addMenu('粒子群算法')self.setGeometry(100, 100, 1000, 1000)self.points = [] # 存储点的列表self.central_widget = DrawingWidget()self.setCentralWidget(self.central_widget)QApplication.processEvents()self.actionPSO1 = QAction("公式1", self)self.actionPSO1.triggered.connect(self.PSO1)self.actionPSO2 = QAction("公式2", self)self.actionPSO2.triggered.connect(self.PSO2)self.menu.addAction(self.actionPSO1)self.menu.addAction(self.actionPSO2)QApplication.processEvents()def PSO1(self):self.central_widget.PSO.choose = 1self.central_widget.PSO.start()def PSO2(self):self.central_widget.PSO.choose = 2self.central_widget.PSO.start()class DrawingWidget(QWidget):def __init__(self):super().__init__()self.setGeometry(0, 0, 1000, 1000)self.points = [] # 存储点的列表self.PSO = PSO()self.PSO.up.connect(self.op)QApplication.processEvents()def paintEvent(self, event):painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing)painter.setPen(QColor(0, 0, 255)) # 设置画笔颜色为蓝色painter.setBrush(Qt.SolidPattern)for point in self.points:painter.drawEllipse(point, 2, 2) # 绘制小圆点def op(self, n, d, lis):q = []for i in range(n):p = QPoint(int(lis[i, 0]+400), int(lis[i, 1]+400))q.append(p)self.points = qself.update()if __name__ == '__main__':app = QApplication(sys.argv)window = Window()window.show()sys.exit(app.exec_())
结果展示:
公式1:
公式2:
结束
以上仅代表我个人的见解,或许会出错,请见谅并麻烦指出,谢谢