实验课一 -- 粒子群算法PSO

本文详细介绍了粒子群算法的原理,包括其源自鸟群觅食行为,以及算法流程中的关键元素如群体规模、维度、速度更新等。提供了Python代码实现,展示了如何初始化粒子位置和速度,计算适应度,更新速度与位置,以及终止条件。
摘要由CSDN通过智能技术生成

算法说明:

我看了下别人写的,这个粒子群算法的思想来源与鸟类捕食
我按我的理解解释一下:
很多只鸟在草原找食物,所有鸟刚开始都不知道食物在哪里,但是鸟儿们很聪明,会互相交流,同时食物有气味,鸟儿们可以通过气味判断自己离食物的远近,闻到气味最大的鸟儿会大叫告诉其他鸟儿,其他鸟儿也往气味最大的鸟身边飞,在它周围区域寻找。
因此,人们就使用这个模型来解决某些问题。也即是让鸟儿帮我们解决问题了

算法流程:

首先,我们要明白算法里面有什么元素:

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,当前最佳位置PPOS, 这个PPOS可以用一个二维数组表示,记录每只鸟儿的局部最佳位置
12,最佳位置Best,一个一维数组,记录最佳适应度所在的位置
13,迭代次数k,我们迭代运算的次数
14,满意值t,这个值表示我们能够接受的最小界限,即当最佳适应度PD低于这个值时,我们也大差不差得到了我们满意的结果

接下来开始:

第一步,初始化
鸟儿们的位置和速度都是随机的,但是位置和速度都是有限制的
我们要随机给每只鸟儿安排位置和速度

第二步,算适应度
算适应度需要相应的公式来算,一般情况下,我们要通过我们要解决的问题来算这个适应度
算出当前这只鸟儿的适应度后,要保存相应的位置,将这次的适应度和上一次的对比,谁最小就最佳,并对位置进行更新
最后在这群鸟儿的适应度中找最小的,并记录位置,这就是全局最佳适应度和全局最佳位置

第三步,更新速度与位置
我们要根据公式来更新速度与位置
速度公式:
pbest就是当前这只鸟儿的局部最佳位置,gbest就是这群鸟儿的全局最佳位置
在这里插入图片描述位置更新公式:
在这里插入图片描述
要注意的是,当我们更新速度和位置的时候要注意范围,即不要让它们超出范围,它们超出范围的话,就按边界值算

第四步 判断是否结束
当次数达到了规定迭代次数时可以结束
当最佳适应度值小于最小界限的时候可以结束
如果没有满足以上条件,那就返回第二步重新执行

代码实现:

目前只写了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__()
        self.choose = 1



    # 初始化位置与速度
    def ini(self):
        self.N = 1000  # 群规模
        self.D = 2  # 群维度
        self.K = 500  # 迭代次数
        self.w = 1  # 惯性权重
        self.c1 = 2  # 个体学习因子
        self.c2 = 2  # 群体学习因子
        self.r1 = random.uniform(0, 1)  # 随机数1
        self.r2 = random.uniform(0, 1)  # 随机数2
        self.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.PPOS = np.zeros((self.N, self.D))  # 当前最佳位置
        self.Best = np.zeros(self.D)            # 全局最佳位置
        print(self.Best)

        self.P = []
        self.PD = 10086

        # self.choose = 1     # 公式选择
        for i in range(self.N):
            self.P.append(1e+6)
            for j in range(self.D):
                a = random.uniform(self.MIN_X, self.MAX_X)
                self.X[i][j] = a
                b = random.uniform(self.MIN_V, self.MAX_V)
                self.V[i][j] = b
                self.PPOS[i][j] = self.X[i][j]


    def check_x(self, x):
        if self.MAX_X <= x:
            return self.MAX_X
        elif self.MIN_X >= x:
            return self.MIN_X
        return x

    def check_v(self, v):
        if self.MAX_V <= v:
            return self.MAX_V
        elif self.MIN_V >= v:
            return self.MIN_V
        return v


    # 公式计算:
    def Cal1(self):

        for i in range(self.N):
            res1 = 0  # X平方
            res2 = 1
            pos_tmp = self.X[i]
            for 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 - res2

            #   更新每只鸟儿的局部最优解
            if self.P[i] > ans:
                self.P[i] = min(self.P[i], ans)
                for j in range(self.D):
                    self.PPOS[i][j] = self.X[i][j]

    # 更新速度与位置

    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]))

            #   更新每只鸟儿的局部最优解
            if self.P[i] > ans:
                self.P[i] = min(self.P[i], ans)
                for j in range(self.D):
                    self.PPOS[i][j] = self.X[i][j]

            self.P[i] = min(self.P[i], 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.PPOS[i][j]-self.X[i][j]) + \
                                self.c2*self.r2*(self.Best[j]-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.r1 = random.uniform(0, 1)  # 随机数1
        self.r2 = random.uniform(0, 1)  # 随机数2


    def 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):

        # 步骤1 初始化
        self.go1()
        self.tol = 1e-6
        for i in range(self.K):
            QApplication.processEvents()
            # 控制时间
            # time.sleep(0.5)

            self.up.emit(self.N, self.D, self.X)
            QApplication.processEvents()

            # 步骤2 进行计算
            self.go2()

            self.PD = min(self.P)
            self.Best = self.X[self.P.index(self.PD)]


            if 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.Best}')



# 只显示结果可运行这个

if __name__ == "__main__":
    app = QApplication(sys.argv)
    PSO = PSO()
    PSO.show()
    PSO.hide()
    PSO.start()
    sys.exit(app.exec_())


窗口展示Window.py

import sys

from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPainter,  QColor
from PyQt5.QtCore import Qt, QPoint

from 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 = 1
        self.central_widget.PSO.start()

    def PSO2(self):
        self.central_widget.PSO.choose = 2
        self.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 = q
        self.update()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

结果展示:

公式1:
在这里插入图片描述
在这里插入图片描述

公式2:
在这里插入图片描述
在这里插入图片描述

结束

以上仅代表我个人的见解,或许会出错,请见谅并麻烦指出,谢谢
9月13日晚上更新,查出错误了,改正了,错误地方在速度更新公式没搞清楚

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泉绮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值