GeneticAlgorithmPython
GeneticAlgorithmPython copied to clipboard
FEATURE REQUEST: args to pass parameter to fitness function
First of all, thank you for the great repository.
The thing we need to improve about pygad is args for fitness function. Currently, fitness function takes only two inputs: solution and solution index. However, sometimes we also need to take extra inputs for the fitness function.
In the example of diff_evol from scipy, it has "args" to pass parameters. https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.differential_evolution.html
If you think this is a good feature, I will try to implement this by myself.
Are there any plans to merge this in pygad
?
Also *args
for mutation functions would be really useful :)
The pull request https://github.com/ahmedfgad/GeneticAlgorithmPython/pull/73 suggests creating a new parameter called args
. Then the library just passes this parameter to each call to the fitness function without changes.
Since the passed args
are static, I prefer using this solution instead of asking the library to do such stuff.
It just creates a wrapper function for the fitness function. The fitness function accepts args
without having to define it as a global variable.
import pygad
import numpy
function_inputs = [4,-2,3.5,5,-11,-4.7]
desired_output = 44
def fitness_func_wrapper(ga_instanse, solution, solution_idx):
def fitness_func(ga_instanse, solution, solution_idx, *args):
print("args", args)
output = numpy.sum(solution*function_inputs)
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
return fitness
args = [4, 6, 10]
fitness = fitness_func(ga_instanse, solution, solution_idx, *args)
return fitness
def on_generation(ga_instance):
ga_instance.population[4:] = numpy.ones((6, num_genes))
num_genes = len(function_inputs)
sol_per_pop = 10
ga_instance = pygad.GA(num_generations=3,
num_parents_mating=5,
fitness_func=fitness_func_wrapper,
sol_per_pop=sol_per_pop,
num_genes=num_genes,
on_generation=on_generation,
suppress_warnings=True)
ga_instance.run()
I would also be in favor of implementing this feature. In my case, the definition of the optimization case contains one integer gene, which correlates with several other parameters that have specific values for each integer value of the gene. For this case it would be great to be able to pass these correlated values into ga_instance
, e.g., as a dictionary, to have access to them from fitness_func
. I understand that the args
argument could be used to achieve this goal.
I also tried using the fitness_func_wrapper
setup proposed by you, @ahmedfgad, but it does not seem work for this specific case, since I also need to refer to dynamically updated global variables to achieve this goal, which I would prefer to circumvent.
@timorichert,
So, your args
are dynamic. You can simply create a new instance attribute to ga_instance
and fetch it inside the fitness function.
If the args
change after each generation, then you can edit them inside the on_generation()
calback function.
def fitness_func_wrapper(ga_instanse, solution, solution_idx):
# Access args using ga_instance.args
fitness = ...
return fitness
def on_generation(ga_instance):
ga_instance.args = [...]
ga_instance = pygad.GA(...)
ga_instance.args = None
ga_instance.run()
@ahmedfgad, thanks a lot for that, that did the job!