Python: PSO сгущается <s>и код работает только при перемещении мыши </s> - PullRequest
0 голосов
/ 31 мая 2019

Я пытаюсь создать простую программу PSO (оптимизация частиц).

Ниже приведен мой текущий код, и я настраивал веса только для того, чтобы найти, что «оптимизация» не работает.

import random as ran
import math
# import threading as thr

import pygame as gm
# import pycuda as cuda
# import matplotlib.pyplot as plt

p_max = 10 # Maximum number of particles
rand_max = 100 # Maximum random vector value
# history = 10 # Number of iterations to record as history (including most current)
width = 600
height = 600

func_dict = {
            "sphere" : ( lambda x, y: ( (x-(width/2))**2 + (y-(height/2))**2 ) ),
            "booth" : ( lambda x, y: (((x-(width/2)) + 2*(y-(height/2)) - 7) ** 2) + ((2*(x-(width/2)) + (y-(height/2)) - 5) ** 2) ),
            "matyas" : ( lambda x, y: (0.26 * ((x-(width/2))**2 + (y-(height/2))**2) - 0.48*(x-(width/2))*(y-(height/2))) )
            } # (x-(width/2)) and (y-(height/2)) to shift the Zero to the display center
func = "sphere" # Choose function from func_dict

# Weights (0<w<1)
wLocal = 0.4 # Explore weight
wGlobal = 0.8 # Exploit weight
wRandom = 0.02 # Weight of random vector

global_best = [None, None, None] # Initial blank

class particle: # particles
    global global_best

    def __init__(self):
        global global_best
        global width, height
        global func_dict, func
        self.vel_x = 0
        self.vel_y = 0
        self.pos_x = ran.randint(0, width)
        self.pos_y = ran.randint(0, height)
        self.pos_z = func_dict[func](self.pos_x, self.pos_y)
        self.local_best = [self.pos_x, self.pos_y, self.pos_z]
        if (global_best[0] == None) or (global_best[1] == None) or (global_best[2] == None): # Is 1st particle
            global_best = self.local_best

    def update(self): # Update vectors
        global width, height
        global rand_max
        global wGlobal, wLocal, wRandom
        global global_best
        self.vel_x = (wGlobal * (global_best[0] - self.pos_x)) + (wLocal * (self.local_best[0] - self.pos_x)) + (wRandom * ran.randint(-rand_max, rand_max))
        self.vel_y = (wGlobal * (global_best[1] - self.pos_y)) + (wLocal * (self.local_best[1] - self.pos_y)) + (wRandom * ran.randint(-rand_max, rand_max))
        # self.pos_x = (self.pos_x + self.vel_x) % width
        # self.pos_y = (self.pos_y + self.vel_y) % height
        self.pos_x += self.vel_x
        self.pos_y += self.vel_y
        if self.pos_x < 0:
            self.pos_x = 0
        if self.pos_y < 0:
            self.pos_y = 0
        if self.pos_x > width:
            self.pos_x = width
        if self.pos_y > height:
            self.pos_y = height

        self.pos_z = func_dict[func](self.pos_x, self.pos_y)
        if self.pos_z < global_best[2]:
            global_best = [self.pos_x, self.pos_y, self.pos_z]

particles = [None for _ in range(p_max)]

def initialize():
    global_best = [None, None, None]
    for foo in range(p_max):
        particles[foo] = particle() # create new particles

# def dist(p1, p2): # distance
#     return(math.sqrt( ( (p1.pos_x - p2.pos_y)**2) + ((p1.pos_y - p2.pos_y)**2) ) )

# def update(this): # this = particle
#     this.vel_x = (wGlobal * (global_best[0] - this.pos_x)) + (wLocal * (this.local_best[0] - this.pos_x)) + (wRandom * ran.randint(0, rand_max))
#     this.vel_y = (wGlobal * (global_best[1] - this.pos_y)) + (wLocal * (this.local_best[1] - this.pos_y)) + (wRandom * ran.randint(0, rand_max))
#     # this.pos_x = (this.pos_x + this.vel_x) % width
#     # this.pos_y = (this.pos_y + this.vel_y) % height
#     this.pos_x += this.vel_x
#     this.pos_y += this.vel_y
#     if this.pos_x < 0:
#         this.pos_x = 0
#     if this.pos_y < 0:
#         this.pos_y = 0
#     if this.pos_x > width:
#         this.pos_x = width
#     if this.pos_y > height:
#         this.pos_y = height
#     # return this

# def update_multi(things): # things = list() of particles
#     these = things
#     for item in these:
#         item = update(item)
#     return these

gm.init()
main = gm.display.set_mode((width, height))
end_program = False
initialize()
main.fill((255, 255, 255))

while end_program == False:

    # main.fill((255, 255, 255)) #Comment/Uncomment to leave trace
    # plt.plot() # Plot functions

    for event in gm.event.get():
        if event.type == gm.QUIT:
            end_program = True

        for foo in range(len(particles)):
            particles[foo].update()

            gm.draw.circle(main, (0, 0, 0), (int(particles[foo].pos_x), int(particles[foo].pos_y)), 5, 0)

    gm.display.flip()

Проблема 1: Программа запускается только при движении мыши
Я не уверен, почему, но программа работает довольно быстро в течение нескольких итераций, но после этого, кажется, просто останавливается, но продолжается, когда мышь перемещается.

Проблема 2: частицы остаются локальными
Когда я двигаю мышь, она вроде как работает. То, что появляется, является скоплениями следов, оставленных, когда 2 # main.fill((255, 255, 255)) не закомментирован. Первые начальные следы до того, как программа остановилась без движения мыши, кажутся более распространенными, и я не уверен, что это глобальные переменные или случайные значения в работе.

Редактировать: я исправил проблему, когда программа запускается только при перемещении мыши с помощью отступа:

    for foo in range(len(particles)):
        particles[foo].update()

        gm.draw.circle(main, (0, 0, 0), (int(particles[foo].pos_x), int(particles[foo].pos_y)), 5, 0)

Однако частицы, похоже, все еще едва ли движутся со своих собственных позиций, колебаясь локально.

1 Ответ

0 голосов
/ 16 июля 2019

Проблема 1 была решена благодаря Мариусу. Я исправил это, просто поместив update вне цикла event.

Проблема 2 была решена путем добавления локального обновления, которое я забыл.

if self.pos_z < global_best[2]: # This was not forgotten
            global_best = [self.pos_x, self.pos_y, self.pos_z]
if self.pos_z < local_best[2]: # This was forgotten
            local_best = [self.pos_x, self.pos_y, self.pos_z]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...