I find your fitness function the hardest to understand. Instead of averaging the corners or finding the center, he adds up the corners and then finds the distance. What is the geometric interpretation?
Also your code refers to ga.logGenerations, which is not part of the current version of pyeasyga 0.3.1.
Below is my approximation to what I think you are requesting. If this does not match the value, please expand 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 example is rough code (for example, it does not always support common points and rectangles of a domain regardless of graphic points and rectangles.) But this should give you something to experiment with:

It creates rectangles in the lower left corner of the window, which the genetic algorithm mutates to the target in the upper right corner, removing the rectangles as they reach the target.
Part of the complexity of my code is that pyeasyga does not provide a functional hook to visualize what happens in each generation. A better approach might be to subclass pyeasyga to add such a hook to simplify the logic of the code.