Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

delay_after_gen warning #283

Open
wassimj opened this issue Mar 21, 2024 · 3 comments
Open

delay_after_gen warning #283

wassimj opened this issue Mar 21, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@wassimj
Copy link

wassimj commented Mar 21, 2024

Hello,
I am using PyGAD version: 3.3.1 on Windows with python 3.10 within jupyter notebook.

When I run my GA, I am getting the following user warning. This is not something I am setting. It seems to emanate from the internal pygad code. How can I avoid having this warning displayed? Thank you

C:\Users\wassimj\AppData\Local\Programs\Python\Python310\lib\site-packages\pygad\pygad.py:1139: UserWarning:

The 'delay_after_gen' parameter is deprecated starting from PyGAD 3.3.0. To delay or pause the evolution after each generation, assign a callback function/method to the 'on_generation' parameter to adds some time delay.
@ahmedfgad ahmedfgad added the enhancement New feature or request label Mar 27, 2024
@ahmedfgad
Copy link
Owner

Thanks, @wassimj. This is a bug. This warning should only be printed if you used the delay_after_gen parameter.

It will be fixed soon.

ahmedfgad added a commit that referenced this issue Mar 27, 2024
@gnypit
Copy link

gnypit commented Jun 1, 2024

Hi all,

I've encountered this as well. What's interesting is that if I re-run the code, the warning disapears and the overall performance of the genetic algorithm improves. For example, the first time the warning comes out, the final result is correct, but the fitness history shows that fitness values varied quite strongly - sometimes fitness wasn't even a non-decreasing function, in spite of a non-zero value in the keep_parents parameter (keeping the so-called 'elite'). Since I haven't been able to reproduce it yet, that's probably for another time.

Back to the delay_after_gen issue; this is a simple code for a packaging problem - a thief has to choose what to steal with a limited maximum weight he can carry. Items at the house have different values and weights. The goal is to choose the most expensive things without surpassing the weight limit. The code is as follows:

import pygad
import matplotlib.pyplot as plt

house = {
    1: ['clock', 100, 7],
    2: ['landscape painting', 300, 7],
    3: ['portrait painting', 200, 6],
    4: ['radio', 40, 2],
    5: ['laptop', 500, 5],
    6: ['night lamp', 70, 6],
    7: ['silver cutlery', 100, 1],
    8: ['porcelain', 250, 3],
    9: ['bronze figurine', 300, 10],
    10: ['leather handbag', 280, 3],
    11: ['vacuum cleaner', 300, 15]
}

def fitness_function(genetic_algorithm_instance, solution, solution_index):
    weight = 0
    fitness = 0

    for i in range(len(solution)):
        if solution[i] == 1:
            fitness += domek[i+1][1]
            weight += domek[i+1][2]
            if weight > 25:
                fitness += -2000

    return fitness

ga_instance = pygad.GA(
    gene_space=[0, 1],
    num_generations=100,
    num_parents_mating=15,
    fitness_func=fitness_function,
    sol_per_pop=40,
    num_genes=11,
    parent_selection_type="tournament",
    keep_parents=5,
    crossover_type="single_point",
    mutation_type="random",
    mutation_probability=0.02
)

# At this point a UserWarning appears

ga_instance.run()

solution, solution_fitness, solution_idx = ga_instance.best_solution()
print("Parameters of the best solution : {solution}".format(solution=solution))
print("Fitness value of the best solution = {solution_fitness}".format(solution_fitness=solution_fitness))

prediction = []
money= 0
weight = 0
for i in range(len(solution)):
    if solution[i] == 1:
        prediction.append(domek[i+1][0])
        money += house[i+1][1]
        weight += house[i+1][2]

print("Predicted output based on the best solution : {prediction}".format(prediction=prediction))
print(money)
print(weight)

# Ensure any previous plots are cleared
plt.clf()

# Plot the fitness values vs. generations with proper labels (ga_instance.plot_fitness() gives two plots)
plt.plot(ga_instance.best_solutions_fitness, label='Best Fitness')
plt.xlabel("Generation")
plt.ylabel("Fitness")
plt.title("Fitness over Generations")
plt.legend()
plt.show()

The waring I get is this:

C:\Users\Jakub\AppData\Local\Programs\Python\Python311\Lib\site-packages\pygad\pygad.py:1139: UserWarning: The 'delay_after_gen' parameter is deprecated starting from PyGAD 3.3.0. To delay or pause the evolution after each generation, assign a callback function/method to the 'on_generation' parameter to adds some time delay.
warnings.warn("The 'delay_after_gen' parameter is deprecated starting from PyGAD 3.3.0. To delay or pause the evolution after each generation, assign a callback function/method to the 'on_generation' parameter to adds some time delay.")

If I re-run the code, result and overall performance improve, while 1the warnings disappear. Fitness plots:
output_thief_01
output_thief_02

Another matter altogether is that it seems to me that in spite of restarting the kernel, pygad somehow remembers something about previous runs, because while the file is open in PyCharm, the 'bad' fitness history doesn't actually repeat. To be more precise, only at the first run with the kernel still operating does the algorithm get stuck in a local maximum of the fitness function. So that's curious on it's own - I apologise, if my lack of understanding and knowledge is showing.

I debugged the 'ga_instance' initialisation with pydev debugger (build 241.14494.241). The 'delay_after_gen' was indeed set by default to 0.0; after a while I got to this section of the pygad.py file:

# Validate delay_after_gen
            if type(delay_after_gen) in GA.supported_int_float_types:
                if not self.suppress_warnings:
                    warnings.warn("The 'delay_after_gen' parameter is deprecated starting from PyGAD 3.3.0. To delay or pause the evolution after each generation, assign a callback function/method to the 'on_generation' parameter to adds some time delay.")
                if delay_after_gen >= 0.0:
                    self.delay_after_gen = delay_after_gen
                else:
                    self.valid_parameters = False
                    raise ValueError(f"The value passed to the 'delay_after_gen' parameter must be a non-negative number. The value passed is ({delay_after_gen}) of type {type(delay_after_gen)}.")
            else:
                self.valid_parameters = False
                raise TypeError(f"The value passed to the 'delay_after_gen' parameter must be of type int or float but {type(delay_after_gen)} found.")

Since delay_after_gen is by default set to 0.0, it is a float value and it passes the if type(delay_after_gen) in GA.supported_int_float_types: check. Then, since (again, by default) the self.suppress_warnings is set to False, the warning from the first nested conditional clause is run:
Zrzut ekranu 2024-06-01 152734
Zrzut ekranu 2024-06-01 152753
Zrzut ekranu 2024-06-01 152859

My idea is to change the default value of the delay_after_gen parameter to None. I guess (haven't checked that yet tbh) that it is not included in the supported types of variables for the parameter. What's the most interesting though, is that when I re-run the code with the same kernel operating, the same default values are assigned to both delay_after_gen and self.suppress_warnings, the waring doesn't show and while debugging I didn't get to the section of the code above ^ what else does it depend on? I didn't notice any other change, and the delay_after_gen falls under the try clause right in the __init__() constructor of the GA class. Since it is not nested in another conditional clause or anything else like that, what's the difference between the first run and the other runs?

Just in case: I'm using Python 3.12.3 and pygad 3.3.1.

@Kk-Ling
Copy link

Kk-Ling commented Jul 5, 2024

suppress_warnings=True

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants