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

算法说明:

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

算法流程:

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

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日晚上更新,查出错误了,改正了,错误地方在速度更新公式没搞清楚

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
这是配套教材的源码。教材我已经传过。 第1章 基本图形的生成 1 1.1 直线 1 1.1.1 DDA(数值微分)算法 2 1.1.2 生成直线的中点画线法 2 1.1.3 Bresenham算法 2 1.1.4 程序设计 3 1.2 圆 7 1.2.1 直角坐标法 7 1.2.2 中点画圆法 8 1.2.3 圆的Bresenham算法 8 1.3 椭圆扫描转换中点算法 11 1.4 多边形的扫描转换与区域填充 13 1.4.1 多边形的扫描转换 14 1.4.2 区域填充算法 15 1.5 字符的生成 22 1.5.1 点阵字符 22 1.5.2 矢量字符 23 1.5.3 字符属性 23 1.6 图形裁剪 23 1.6.1 线裁剪 24 1.6.2 多边形裁剪 25 1.6.3 字符裁剪 26 1.6.4 图形裁剪编程 26 1.7 Visual C++中基本绘图函数 38 练习题 41 第2章 二维图形 42 2.1 用户坐标到屏幕坐标的变换 42 2.1.1 窗口到视口的变换内容 42 2.1.2 窗口区到视口区的坐标变换 43 2.2 二维几何变换 44 2.2.1 基本变换 44 2.2.2 二维几何变换的级联 47 2.3 几何变换程序设计案例 49 2.4 平面曲线图 59 2.4.1 正叶线 60 2.4.2 正叶线蝴蝶结 60 2.5 平面曲线程序设计案例 60 练习题 63 第3章 交互技术 64 3.1 用户接口设计 64 3.2 逻辑输入设备与输入处理 65 3.2.1 逻辑输入设备 65 3.2.2 输入模式 66 3.3 交互式绘图技术 67 3.4 交互技术程序设计案例 68 练习题 75 第4章 简单CAD绘图系统开发实例 76 4.1 计算机图形学绘图基础 76 4.1.1 Visual C++开发系统基本绘图知识 77 4.1.2 计算机图形学绘图系统设计基本原则 79 4.1.3 图形程序设计步骤 79 4.1.4 在Visual C++集成开发环境下程序的调试 81 4.1.5 计算机程序结构设计基础 81 4.1.6 绘图程序设计基本方法 82 4.2 图形的数据结构 85 4.2.1 图形信息的分类 85 4.2.2 图形数据结构 85 4.2.3 计算机对数据的管理——数据文件 86 4.2.4 图形数据的存储状态 87 4.2.5 动态文件数据结构的组织原则 87 4.2.6 简单CAD绘图系统编程实例中的数据结构 87 4.3 简单CAD绘图系统功能简介 103 4.3.1 简单CAD绘图系统运行界面 103 4.3.2 简单CAD绘图系统功能 103 第5章 三维图形变换 107 5.1 三维图形几何变换矩阵 107 5.2 三维图形基本变换矩阵 107 5.2.1 平移变换 107 5.2.2 比例变换 108 5.2.3 绕坐标轴的旋转变换 109 5.2.4 对称变换 110 5.2.5 错切变换 112 5.3 图形的投影变换 113 5.3.1 投影变换分类 113 5.3.2 平行投影 114 5.4 三维变换程序设计案例 118 练习题 146 第6章 曲线和曲面 147 6.1 曲线曲面参数表示的基础知识 147 6.1.1 非参数表示和参数表示 147 6.1.2 参数表示的基本特征 148 6.1.3 曲线段之间的连续性 150 6.1.4 曲线曲面设计中的几个概念 151 6.2 常用参数曲线 151 6.2.1 一般规则空间曲线 151 6.2.2 Bezier曲线 152 6.2.3 B样条曲线 158 6.3 参数曲面 164 6.3.1 函数式曲面 164 6.3.2 旋转曲面 165 6.4 常用曲面 166 6.4.1 双曲线曲面 166 6.4.2 Bezier曲面 166 6.4.3 B样条曲面 168 6.5 曲面与曲线编程案例 169 练习题 195 第7章 几何造型技术 196 7.1 实体的表示模型 196 7.1.1 分解表示 197 7.1.2 构造表示 198 7.1.3 边界表示 200 7.1.4 形体的边界表示模型 200 7.2 求交分类 202 7.2.1 求交分类 202 7.2.2 基本的求交算法 203 7.3 图形相交-相切程序设计案例 207 7.4 非传统造型技术 220 7.4.1 基本概念 221 7.4.2 分形造型对模型的基本要求 221 7.4.3 分形造型的常用模型 221 7.5

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

泉绮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值