【问题标题】:Python - Genetic Algorithm mutation function is not workingPython - 遗传算法变异功能不起作用
【发布时间】:2019-02-08 06:58:25
【问题描述】:

我在 python/pygame 中创建了一个 AI,但即使经过数小时的调试,我也无法找到个体(点)没有发生变异的原因。几代之后,所有个体只是相互重叠并遵循相同的确切路径。但是在突变之后,它们的移动方式应该会有所不同。

这是每 2-3 代后 10 人的种群规模。

Image 1Image 2Image 3

如您所见,仅仅几代之后,它们就重叠了,种群中的所有个体都一起移动,沿着完全相同的路径!我们需要突变!!!

如果您能发现任何错误,我将非常感谢您。谢谢!

我看到代码来自:https://www.youtube.com/watch?v=BOZfhUcNiqk&t 并试图用python制作它。这是我的代码

import pygame, random
import numpy as np

pygame.init()
width = 800
height = 600
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("The Dots")

FPS = 30
clock = pygame.time.Clock()
gameExit = False

grey = [30, 30, 30]
white = [255, 255, 255]
black = [0, 0, 0]
red = [255, 0, 0]

goal = [400, 10]

class Dot():
    def __init__(self):
        self.x = int(width/2)
        self.y = int(height - 150)
        self.r = 3
        self.c = black
        self.xVel = self.yVel = 0
        self.xAcc = 0
        self.yAcc = 0
        self.dead = False
        self.steps = 0
        self.reached = False
        self.brain = Brain(200)

    def show(self):
        pygame.draw.circle(screen, self.c, [int(self.x), int(self.y)], self.r)

    def update(self):
        if (self.x >= width or self.x <= 0 or self.y >= height or self.y <= 0):
            self.dead = True
        elif (np.sqrt((self.x-goal[0])**2 + (self.y-goal[1])**2) < 5):
            self.reached = True
        if not self.dead and not self.reached:
            if len(self.brain.directions) > self.steps:
                self.xAcc = self.brain.directions[self.steps][0]
                self.yAcc = self.brain.directions[self.steps][1]
                self.steps += 1

                self.xVel += self.xAcc
                self.yVel += self.yAcc
                if self.xVel > 5:
                    self.xVel = 5
                if self.yVel > 5:
                    self.yVel = 5
                self.x += self.xVel
                self.y += self.yVel
            else: self.dead = True

    def calculateFitness(self):
        distToGoal = np.sqrt((self.x-goal[0])**2 + (self.y-goal[1])**2)
        self.fitness = 1/(distToGoal**2)
        return self.fitness

    def getChild(self):
        child = Dot()
        child.brain = self.brain
        return child

class Brain():
    def __init__(self, size):
        self.size = size
        self.directions = []
        self.randomize()

    def randomize(self):
        self.directions.append((np.random.normal(size=(self.size, 2))).tolist())
        self.directions = self.directions[0]

    def mutate(self):
        for i in self.directions:
            rand = random.random()
            if rand < 1:
                i = np.random.normal(size=(1, 2)).tolist()[0]

class Population():
    def __init__(self, size):
        self.size = size
        self.dots = []
        self.fitnessSum = 0

        for i in range(self.size):
            self.dots.append(Dot())

    def show(self):
        for i in self.dots:
            i.show()

    def update(self):
        for i in self.dots:
            i.update()

    def calculateFitness(self):
        for i in self.dots:
            i.calculateFitness()

    def allDead(self):
        for i in self.dots:
            if not i.dead and not i.reached:
                return False
        return True

    def calculateFitnessSum(self):
        self.fitnessSum = 0
        for i in self.dots:
            self.fitnessSum += i.fitness

    def SelectParent(self):
        rand = random.uniform(0, self.fitnessSum)
        runningSum = 0
        for i in self.dots:
            runningSum += i.fitness
            if runningSum > rand:
                return i

    def naturalSelection(self):
        newDots = []
        self.calculateFitnessSum()
        for i in self.dots:
            parent = self.SelectParent()
            newDots.append(parent.getChild())

        self.dots = newDots

    def mutate(self):
        for i in self.dots:
            i.brain.mutate()

test = Population(100)

while not gameExit:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameExit = True
    screen.fill(white)

    if test.allDead():
        #Genetic Algorithm
        test.calculateFitness()
        test.naturalSelection()
        test.mutate()

    else:
        test.update()
        test.show()

    pygame.draw.circle(screen, red, goal, 4)
    clock.tick(FPS)
    pygame.display.update()
pygame.quit()

感谢您的帮助!

【问题讨论】:

  • 你的意思是他们没有变异?你能说得更具体点吗?
  • 嘿,我刚刚添加了几张图片并澄清了我的观点。我建议您自己测试代码以更好地理解它。谢谢!
  • 欢迎来到 StackOverflow。请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。请参阅这个可爱的 debug 博客寻求帮助。

标签: python algorithm artificial-intelligence mutation genetic


【解决方案1】:

我没有通读整个代码,但在这里

def mutate(self):
    for i in self.directions:
        rand = random.random()
        if rand < 1:
            i = np.random.normal(size=(1, 2)).tolist()[0]

您正在尝试为 i(它是一个迭代器)分配一个新值,因此它不会改变任何东西,这就解释了为什么您在突变时遇到问题。

你应该有这样的东西:

def mutate(self):
    for i in range(len(self.directions)):
        rand = random.random()
        if rand < 1:
            self.directions[i] = np.random.normal(size=(1, 2)).tolist()[0]

或者你可以使用列表推导 https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions

【讨论】:

    猜你喜欢
    • 2016-03-10
    • 2020-11-14
    • 2015-06-25
    • 2017-10-10
    • 2011-06-11
    • 1970-01-01
    • 2012-03-27
    • 2015-03-01
    • 1970-01-01
    相关资源
    最近更新 更多