数学建模 of python(粒子群优化算法)

1. 基本思想
粒子群优化算法(PSO)是一种进化计算技术,由Eberhart博士和kennedy博士于1995年提出。源于对鸟群捕食的行为研究。
基本思想:
一个由多个个体组成的群体对多维搜索空间进行搜索,每个个体在搜索时,考虑到了自己搜索到的历史最好点和群体内(或邻域内)其他个体的历史最好点,在此基础上进行位置(状态,也就是解)的变化.

2.标准PSO

2. 算法构成要素
• 群体大小: m
m是个整型参数。当m很小的时候,陷入局优的可能性很大。然而,群体过大将导致计算时间的大幅增加。并且当群体数目增长至一定水平时,再增长将不再有显著的作用。当m =1的时候, PSO算法变为基于个体搜索的技术,一旦陷入局优,将不可能跳出。当m很大时, PSO的优化能力很好,可是收敛的速度将非常慢。

• 学习因子: c1和c2
学习因子使粒子具有自我总结和向群体中优秀个体学习的能力,从而向群体内或邻域内最优点靠近。 c1和c2通常等于2,不过在文献中也有其他的取值。但是一般c1等于c2,并且范围在0和4之间。
• 最大速度: Vmax 一般设定为变量范围
• 惯性权重
智能优化方法的运行是否成功, 探索能力(全局搜索) 和开发能力(局部搜索)的平衡是非常关键的。对于粒子群优化算法来说,这两种能力的平衡就是靠惯性权重来实现.

3.代码(求解多项式的最大值,最小值问题)

# -*- coding: utf-8 -*-
"""
Created on Sat Aug 11 18:19:18 2018

@author: jj
"""

import numpy as np
import matplotlib.pyplot as plt
import random
'''
* ━━━━━━神兽出没━━━━━━
*    ┏┓   ┏┓
*   ┏┛┻━━━┛┻┓
*   ┃       ┃
*   ┃   ━   ┃
*   ┃ ┳┛ ┗┳ ┃
*   ┃       ┃
*   ┃   ┻   ┃
*   ┃       ┃
*   ┗━┓   ┏━┛Code is far away from bug with the animal protecting
*     ┃   ┃ 神兽保佑,代码无bug
*     ┃   ┃
*     ┃   ┗━━━┓
*     ┃       ┣┓
*     ┃       ┏┛
*     ┗┓┓┏━┳┓┏┛
*      ┃┫┫ ┃┫┫
*      ┗┻┛ ┗┻┛
*
* ━━━━━━感觉萌萌哒━━━━━━
'''



# 定义“粒子”类
class parti(object):
    def __init__(self, v, x):
        self.v = v                    # 粒子当前速度
        self.x = x                    # 粒子当前位置
        self.pbest = x                # 粒子历史最优位置
        
class PSO(object):
    def __init__(self, interval, tab, partisNum=10, iterMax=1000, w=1, c1=2, c2=2):
        self.interval = interval                                            # 给定状态空间 - 即待求解空间
        self.tab = tab                                              # 求解最大值还是最小值的标签: 'min' - 最小值;'max' - 最大值
        self.iterMax = iterMax                                              # 最大迭代求解次数
        self.w = w                                                          # 惯性因子
        self.c1, self.c2 = c1, c2                                           # 学习因子
        self.v_max = (interval[1] - interval[0]) * 0.1                      # 设置最大迁移速度
        self.partis_list, self.gbest = self.initPartis(partisNum)                 # 完成粒子群的初始化,并提取群体历史最优位置
        self.x_seeds = np.array(list(parti_.x for parti_ in self.partis_list))    # 提取粒子群的种子状态 
        self.solve()                                                              # 完成主体的求解过程
        self.display()                                                            # 数据可视化展示
        
    def initPartis(self, partisNum):
        partis_list = list()
        for i in range(partisNum):
            v_seed = random.uniform(-self.v_max, self.v_max)
            x_seed = random.uniform(*self.interval)
            partis_list.append(parti(v_seed, x_seed))                       #确定目标找最大值还是最小值
        temp = 'find_' + self.tab
        if hasattr(self, temp):                                            
            gbest = getattr(self, temp)(partis_list)
        else:
            exit('>>>tab标签传参有误:"min"|"max"<<<')
        return partis_list, gbest
        
    def solve(self):
        for i in range(self.iterMax):
            for parti_c in self.partis_list:
                f1 = self.func(parti_c.x)
                # 更新粒子速度,并限制在最大迁移速度之内
                parti_c.v = self.w * parti_c.v + self.c1 * random.random() * (parti_c.pbest - parti_c.x) + self.c2 * random.random() * (self.gbest - parti_c.x)
                if parti_c.v > self.v_max: 
                    parti_c.v = self.v_max
                elif parti_c.v < -self.v_max: 
                    parti_c.v = -self.v_max
                # 更新粒子位置,并限制在待解空间之内
                if self.interval[0] <= parti_c.x + parti_c.v <=self.interval[1]:
                    parti_c.x = parti_c.x + parti_c.v 
                else:
                    parti_c.x = parti_c.x - parti_c.v
                f2 = self.func(parti_c.x)
                getattr(self, 'deal_'+self.tab)(f1, f2, parti_c)             # 更新粒子历史最优位置与群体历史最优位置      
        
    def func(self, x):                                                       # 状态产生函数 - 即待求解函数
        value = np.sin(x**2) * (x**2 - 5*x)
        return value
        
    def find_min(self, partis_list):                                         # 按状态函数最小值找到粒子群初始化的历史最优位置
        parti = min(partis_list, key=lambda parti: self.func(parti.pbest))
        return parti.pbest
        
    def find_max(self, partis_list):
        parti = max(partis_list, key=lambda parti: self.func(parti.pbest))   # 按状态函数最大值找到粒子群初始化的历史最优位置
        return parti.pbest
        
    def deal_min(self, f1, f2, parti_):
        if f2 < f1:                          # 更新粒子历史最优位置
            parti_.pbest = parti_.x
        if f2 < self.func(self.gbest):
            self.gbest = parti_.x            # 更新群体历史最优位置
            
    def deal_max(self, f1, f2, parti_):
        if f2 > f1:                          # 更新粒子历史最优位置
            parti_.pbest = parti_.x
        if f2 > self.func(self.gbest):
            self.gbest = parti_.x            # 更新群体历史最优位置
            
    def display(self):
        print('solution: {}'.format(self.gbest))
        plt.figure(figsize=(8, 4))
        x = np.linspace(self.interval[0], self.interval[1], 300)
        y = self.func(x)
        plt.plot(x, y, 'g-', label='function')
        plt.plot(self.x_seeds, self.func(self.x_seeds), 'b.', label='seeds')
        plt.plot(self.gbest, self.func(self.gbest), 'r*', label='solution')
        plt.xlabel('x')
        plt.ylabel('f(x)')
        plt.title('solution = {}'.format(self.gbest))
        plt.legend()
        plt.savefig('PSO.png', dpi=500)
        plt.show()
        plt.close()

        
if __name__ == '__main__':
    PSO([-9, 5],'max')#此处选择模式和求解空间


 

猜你喜欢

转载自blog.csdn.net/weixin_41503009/article/details/81805748