2023년 전국 대회 수학적 모델링 아이디어 - 사례: 입자 군집 최적화 알고리즘

# 0 대회 아이디어

(대회 질문 나오는 대로 CSDN에 공유하세요)

https://blog.csdn.net/dc_sinor?type=blog

1 입자군집 알고리즘이란?

PSO(Particle Swarm Optimization)는 새와 물고기의 먹이 활동을 모방하여 개발된 진화 알고리즘입니다. 그 개념은 간단하고 프로그래밍 및 실현이 쉽고 작동 효율이 높으며 매개 변수가 상대적으로 적기 때문에 널리 사용됩니다. 입자군집 최적화 알고리즘은 1995년에 제안되었으며, 24년(2019년)의 역사를 가지고 있습니다.
  
  PSO 알고리즘에서 각 입자의 위치는 찾고자 하는 문제에 대한 후보 솔루션을 나타냅니다. 공간 내 각 입자의 위치 품질은 구하려는 문제에서 입자 위치의 적합도 값에 따라 결정됩니다. 다음 세대의 각 입자의 위치는 이 세대의 위치와 자체 속도 벡터에 의해 결정되며, 속도는 입자의 각 비행 방향과 거리를 결정합니다. 비행 중에 입자는 최적의 위치 P를 기록하고 그룹은 그룹이 있었던 최적의 위치 G도 업데이트합니다. 입자의 비행 속도는 현재 위치, 입자 자체가 있었던 최적 위치, 그룹이 있었던 최적 위치, 이때 입자의 속도에 따라 결정됩니다.

여기에 이미지 설명을 삽입하세요

2 예를 들어봐

여기에 이미지 설명을 삽입하세요
호수에는 서로 의사소통이 가능하고 자신의 위치가 가장 낮은 지점을 감지할 수 있는 두 사람이 있습니다. 초기 위치는 위 그림과 같으며, 오른쪽이 상대적으로 깊기 때문에 왼쪽 사람이 배를 오른쪽으로 이동하게 됩니다.

여기에 이미지 설명을 삽입하세요

이제 왼쪽이 어두워지므로 오른쪽에 있는 사람이 배를 왼쪽으로 이동시킵니다.

마침내 두 배가 만날 때까지 이 과정을 계속 반복하세요.

여기에 이미지 설명을 삽입하세요
국소 최적해를 구하고
여기에 이미지 설명을 삽입하세요각 개체를 입자로 표현합니다. 특정 순간에 각 개인의 위치는 x(t)로 표현되고, 방향은 v(t)로 표현됩니다.

여기에 이미지 설명을 삽입하세요

p(t)는 시간 t에서 개인 x의 최적해, g(t)는 시간 t에서 모든 개체의 최적해, v(t)는 시간 t에서 개인의 방향, x(t)는 다음과 같습니다. 시간 t에서의 개별 위치

여기에 이미지 설명을 삽입하세요

다음 위치는 위 그림과 같이 x, p, g에 의해 결정됩니다.

여기에 이미지 설명을 삽입하세요

인구 내 입자는 자신과 인구의 역사적 정보를 지속적으로 학습함으로써 문제에 대한 최적의 해결책을 찾을 수 있습니다.

3은 여전히 ​​예입니다

입자 떼 최적화는 새의 먹이 활동 행동에서 파생된 알고리즘입니다. 이제 우리의 주인공은 새 떼로 바뀌었습니다.
여기에 이미지 설명을 삽입하세요

작은 새들의 목표는 간단합니다. 이 지역에서 먹이가 가장 많은 장소를 찾아 정착하고 회복하는 것입니다. 1. 이곳에서의 검색 전략은 다음과 같습니다
  . 각 새는 무작위로 장소를 찾아 이곳에 있는 먹이의 양을 평가합니다.
  2. 모든 새들이 모여서 먹이가 가장 많은 곳을 정착할 후보지점 G로 선택한다.
  삼. 각 새는 자신의 여행을 되돌아보고 먹이가 가장 많은 장소 P를 기억합니다.
  4. 더 많은 먹이가 있는 곳을 찾기 위해 새들은 각각 G를 향해 날아간다. 그러나 그것이 선택의 어려움 때문인지 P에 대한 향수 때문인지, G에 대한 불신 때문인지는 모르겠다. 사실 P를 향해 날아가는 것은 사실이다. , G 쪽으로 더 많이 날아가고 있는지 P 쪽으로 더 많이 날아가고 있는지 알 수 없습니다.
  5. 다시 만날 시간입니다. 새들이 찾기를 멈추기로 결정하면 현재의 G를 선택하여 정착하고, 그렇지 않으면 2->3->4->5를 계속하여 서식지를 찾습니다.

여기에 이미지 설명을 삽입하세요

위 그림에 설명된 전략 4의 경우 새가 A 지점에 있고, G 지점은 새들이 먹이를 가장 많이 찾은 곳이며, P 지점은 먹이를 가장 많이 방문한 곳입니다. V는 현재 비행 속도(속도는 방향과 크기가 있는 벡터)이고 이제 P와 G를 향해 비행하기로 결정했지만 이것은 불교 새이므로 얼마나 나는지는 상황에 따라 다릅니다. 속도 V가 없으면 B 지점으로 비행해야 합니다. 속도 V의 영향으로 결합된 속도는 마침내 다음 목적지인 C 지점으로 비행하게 됩니다. C가 P보다 좋으면 C가 다음 P가 되고, C가 G보다 좋으면 다음 G가 됩니다.

알고리즘 프로세스

여기에 이미지 설명을 삽입하세요

알고리즘 구현

여기서 선배들은 Python을 사용하여 입자 떼 솔루션 기능의 최적 솔루션을 시연합니다.

여기에 이미지 설명을 삽입하세요

import numpy as np
import matplotlib.pyplot as plt
import random


# 定义“粒子”类
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='min', partisNum=10, iterMax=1000, w=1, c1=2, c2=2):
        self.interval = interval                                            # 给定状态空间 - 即待求解空间
        self.tab = tab.strip()                                              # 求解最大值还是最小值的标签: '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')

효과
여기에 이미지 설명을 삽입하세요

모델링 데이터

데이터 공유: 가장 강력한 모델링 데이터
여기에 이미지 설명을 삽입하세요
여기에 이미지 설명을 삽입하세요

Guess you like

Origin blog.csdn.net/dc_sinor/article/details/132429242