简体   繁体   English

遗传编程pyeasyGA和Zelle图形在Python上

[英]Genetic Programming pyeasyGA and Zelle graphics on Python

I wanted to make a simple program to improve my knowledge on this type of programming. 我想制作一个简单的程序来提高我对这类编程的了解。 I found a really useful library, pyeasyGA, and with it I tried to make a simple program using graphics.py that from a randomly generated sequence of "passes" creates a sequence that converges to a point. 我发现了一个非常有用的库,pyeasyGA,并且我尝试使用graphics.py创建一个简单的程序,从随机生成的“pass”序列创建一个收敛到一个点的序列。

That's how it works: 这就是它的工作原理:

def create_individual(data):
    a = [(randint(0,5),randint(0,5)) for n in range(len(data))]
    print(a)
    return a

this function creates a sequence of passes since the graphics.py library allows you to move an object by giving it how many pixels you want to move it. 此函数创建一系列传递,因为graphics.py库允许您通过为对象移动它想要移动它来移动对象。 That's my "individual". 那是我的“个人”。

For calculating fitness I used this: 为了计算健身,我使用了这个:

def fitness(individual, data):
    totX=0
    totY=0
    for elem in individual:

        totX+=elem[0]
        totY+=elem[1]

    tot = (totX,totY)

    return distEuclidea(arrivo, tot)

def distEuclidea(p1,p2):
    x1 = p1[0]
    y1 = p1[1]
    x2 = p2[0]
    y2 = p2[1]

    return ((x2-x1)**2+(y2-y1)**2)**(1/2)

This function calculates the distance from the desired arrival point. 此功能计算距所需到达点的距离。

After these passes, the program generates a lot of generations and takes the individual with the lowest fitness but it doesn't work. 在这些过程之后,程序会产生很多代,并且会使个体具有最低的适应度,但它不起作用。

It doesn't evolve. 它没有发展。 Every sequence of passes seems like it is randomly generated. 每个传递序列似乎都是随机生成的。

Can someone help me please? 有人能帮助我吗?

Here's the full code 这是完整的代码

EDIT: 编辑:

The program seems to work. 该计划似乎有效。 The only problem was the little number generations. 唯一的问题是几代人。

I find your fitness function the hardest to understand. 我发现你的健身功能最难理解。 Rather then average the corners or find the center, it adds up the corners and then finds the distance. 而不是平均角落或找到中心,它将角落相加然后找到距离。 What's the geometric interpretation? 什么是几何解释?

Also your code refers to ga.logGenerations which isn't part of the current pyeasyga 0.3.1 release. 此外,您的代码是指ga.logGenerations,它不是当前pyeasyga 0.3.1版本的一部分。

Below is my approximation to what I think you're requesting. 以下是我对你的要求的近似。 If it's off the mark, then please augment your explanation with examples and/or diagrams: 如果它没有标记,那么请用示例和/或图表来扩充您的解释:

from time import sleep
from random import randint
from itertools import cycle
from graphics import *
from pyeasyga import pyeasyga

NUMBER_OF_RECTANGLES = 4  # make one more than what you want to see
NUMBER_OF_POINTS = 2

arrivo = (90, 90)

colori = ["red", "green", "blue", "cyan", "magenta", "yellow"]

X, Y = 0, 1

def distEuclidea(p1, p2):
    x1, y1 = p1
    x2, y2 = p2

    return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5

def create_individual(colors):
    color = next(colors)

    while color in rectangles and rectangles[color] is None:  # skip over deleted rectangle
        color = next(colors)

    if color in rectangles:
        rectangle = rectangles[color]
        p1, p2 = rectangle.getP1(), rectangle.getP2()
        points = [[p1.getX(), p1.getY()], [p2.getX(), p2.getY()]]
    else:
        points = [[randint(0, 20), randint(0, 20)] for _ in range(NUMBER_OF_POINTS)]

        rectangle = Rectangle(*[Point(x, y) for x, y in points])
        rectangle.setOutline(color)
        rectangle.draw(win)

        rectangles[color] = rectangle

    return [color, points]

def fitness(individual, colors):
    _, points = individual

    rectangle = Rectangle(*[Point(x, y) for x, y in points])

    center = rectangle.getCenter()

    return distEuclidea(arrivo, (center.getX(), center.getY()))

def mutate(individual):
    _, points = individual
    mutate_index = randint(0, NUMBER_OF_POINTS - 1)
    points[mutate_index][X] += randint(-1, 1)
    points[mutate_index][Y] += randint(-1, 1)

def is_point_inside_rectangle(point, rectangle):
    p1, p2 = rectangle.getP1(), rectangle.getP2()

    return min(p1.getX(), p2.getX()) < point.getX() < max(p1.getX(), p2.getX()) and \
        min(p1.getY(), p2.getY()) < point.getY() < max(p1.getY(), p2.getY())

win = GraphWin("Genetic Graphics", 500, 500)
win.setCoords(0, 0, 100, 100)

rectangles = {}
color_generator = cycle(colori[0:NUMBER_OF_RECTANGLES])

arrivoC = Circle(Point(*arrivo), 1)
arrivoC.setFill("orange")
arrivoC.draw(win)

number_of_rectangles = NUMBER_OF_RECTANGLES

while True:

    ga = pyeasyga.GeneticAlgorithm(color_generator, \
        elitism=False, \
        maximise_fitness=False, \
        crossover_probability=0.0, \
        population_size=number_of_rectangles)

    ga.create_individual = create_individual
    ga.fitness_function = fitness
    ga.mutate_function = mutate

    ga.run()

    for member in ga.last_generation():
        my_fitness, (my_color, my_points) = member
        if rectangles[my_color] is None:
            continue  # skip over deleted rectangle

        rectangle = Rectangle(*[Point(x, y) for x, y in my_points])
        rectangle.setOutline(my_color)
        rectangle.draw(win)
        rectangles[my_color] = rectangle

        if is_point_inside_rectangle(arrivoC.getCenter(), rectangle):
            rectangles[my_color] = None  # delete finished rectangle
            number_of_rectangles -= 1

    if number_of_rectangles < 2:
        break

    sleep(0.1)

for value in rectangles.values():
    if value is not None:
        value.undraw()  # delete unfinished rectangle

win.getMouse()
win.close()

The above is rough code (eg it doesn't always keep the generic domain points and rectangles independent of the graphics.py Points and Rectangles.) But it should give you something to experiment with: 以上是粗略的代码(例如,它并不总是保持通用域点和矩形独立于graphics.py点和矩形。)但它应该给你一些实验:

在此输入图像描述

It creates rectangles in the lower left corner of the window that the genetic algorithm mutates towards the target in the upper right corner, dropping out rectangles as they reach the target. 它在窗口的左下角创建矩形,遗传算法在右上角向目标突变,当它们到达目标时丢弃矩形。

Part of the complexity of my code is that pyeasyga doesn't provide a functional hook for visualizing what's happening each generation. 我的代码的一部分复杂性是pyeasyga没有提供一个功能钩子来可视化每一代发生的事情。 A better approach might be to subclass pyeasyga to add such a hook to simplify the logic of the code. 更好的方法可能是将pyeasyga子类化为添加这样的钩子以简化代码的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM