[Python] FuncAnimation only shows one frame

Discussão em 'Python' iniciado por Stack, Dezembro 7, 2024.

  1. Stack

    Stack Membro Participativo

    I am trying to implement a genetic algorithm in Python and to display the result of my algorithm I wanted to create an animation using FuncAnimation from matplotlib.animation.

    However, I ran into the problem that I ended up with only one image. The most interesting thing is that in Google Colab I get one frame, but in Pycharm (the IDE I usually use) I get another one.

    Here is my code:

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.animation import FuncAnimation

    def fitness_function(x, y):
    return x ** 2 + y ** 2

    def initialize_population(pop_size, bounds):
    return np.random.uniform(bounds[0], bounds[1], (pop_size, 2))

    def select(population, fitnesses):
    indices = np.argsort(fitnesses)[:len(population) // 2]
    return population[indices]

    def crossover(parents, offspring_size):
    offsprings = []
    for _ in range(offspring_size):
    p1, p2 = parents[np.random.choice(len(parents), size=2, replace=False)]
    alpha = np.random.rand()
    child = alpha * p1 + (1 - alpha) * p2
    offsprings.append(child)
    return np.array(offsprings)

    def mutate(population, bounds, mutation_rate=0.1):
    for i in range(len(population)):
    if np.random.rand() < mutation_rate:
    population += np.random.uniform(-1, 1, size=2)
    population = np.clip(population, bounds[0], bounds[1])
    return population

    def genetic_algorithm(pop_size=500, generations=500, bounds=(-10, 10)):
    population = initialize_population(pop_size, bounds)
    history = []

    for gen in range(generations):
    fitnesses = np.array([fitness_function(x, y) for x, y in population])
    parents = select(population, fitnesses)
    offspring_size = pop_size - len(parents)
    offspring = crossover(parents, offspring_size)
    population = np.vstack((parents, offspring))
    population = mutate(population, bounds)
    history.append(population.copy())

    if gen % 50 == 0:
    print(f"Generation {gen}: Best fitness = {fitnesses.min():.4f}")

    return history

    history = genetic_algorithm()

    fig, ax = plt.subplots(figsize=(8, 8))
    ax.set_xlim(-10, 10)
    ax.set_ylim(-10, 10)
    ax.set_title("Evolution of Genetic Algorithm Population")
    ax.set_xlabel("X")
    ax.set_ylabel("Y")

    colors = np.linspace(0, 1, len(history))

    scat = ax.scatter([], [], c=[], cmap='viridis', s=50, vmin=0, vmax=1)

    ax.plot([0, 0], [-10, 10], color='blue', linewidth=1)
    ax.plot([-10, 10], [0, 0], color='blue', linewidth=1)

    def update(frame):
    print(f"Frame: {frame}, History Length: {len(history)}")
    data = history[frame]
    scat.set_offsets(data)
    scat.set_array(np.full(len(data), colors[frame]))
    ax.set_title(f"Generation {frame+1}/{len(history)}")
    return scat,

    anim = FuncAnimation(fig, update, frames=len(history), interval=50, repeat=False)
    plt.show()
    print(plt.get_backend())

    print(f"Number of generations: {len(history)}")



    I've read a lot of similar questions, but none of the answers worked for me.

    For example, I ran the code that is marked as the required answer in this question, however I still only got one frame.

    If I just haven't found a question that has an answer to mine, I apologize in advance.

    Also, if you suddenly notice any mistakes in the algorithm, I would be grateful if you could point them out to me.

    I'm using:

    Python 3.9.13 matplotlib 3.9.3 numpy 2.0.2

    Continue reading...

Compartilhe esta Página