8000 PyGAD 2.16.0 · SiJason/GeneticAlgorithmPython@c4564ec · GitHub
[go: up one dir, main page]

Skip to content
65E3

Commit c4564ec

Browse files
authored
PyGAD 2.16.0
A user-defined function can be passed to the mutation_type, crossover_type, and parent_selection_type parameters in the pygad.GA class to create a custom mutation, crossover, and parent selection operators. Check the User-Defined Crossover, Mutation, and Parent Selection Operators section in the documentation: https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#user-defined-crossover-mutation-and-parent-selection-operators The example_custom_operators.py script gives an example of building and using custom functions for the 3 operators. ahmedfgad#50
1 parent 3349dea commit c4564ec

File tree

3 files changed

+149
-39
lines changed

3 files changed

+149
-39
lines changed

__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from .pygad import * # Relative import.
22

3-
__version__ = "2.15.1"
3+
__version__ = "2.16.0"

example_custom_operators.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import pygad
2+
import numpy
3+
4+
"""
5+
This script gives an example of using custom user-defined functions for the 3 operators:
6+
1) Parent selection.
7+
2) Crossover.
8+
3) Mutation.
9+
For more information, check the User-Defined Crossover, Mutation, and Parent Selection Operators section in the documentation:
10+
https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#user-defined-crossover-mutation-and-parent-selection-operators
11+
"""
12+
13+
equation_inputs = [4,-2,3.5]
14+
desired_output = 44
15+
16+
def fitness_func(solution, solution_idx):
17+
output = numpy.sum(solution * equation_inputs)
18+
19+
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
20+
21+
return fitness
22+
23+
def parent_selection_func(fitness, num_parents, ga_instance):
24+
# Selects the best {num_parents} parents. Works as steady-state selection.
25+
26+
fitness_sorted = sorted(range(len(fitness)), key=lambda k: fitness[k])
27+
fitness_sorted.reverse()
28+
29+
parents = numpy.empty((num_parents, ga_instance.population.shape[1]))
30+
31+
for parent_num in range(num_parents):
32+
parents[parent_num, :] = ga_instance.population[fitness_sorted[parent_num], :].copy()
33+
34+
return parents, fitness_sorted[:num_parents]
35+
36+
def crossover_func(parents, offspring_size, ga_instance):
37+
# This is single-point crossover.
38+
offspring = []
39+
idx = 0
40+
while len(offspring) != offspring_size[0]:
41+
parent1 = parents[idx % parents.shape[0], :].copy()
42+
parent2 = parents[(idx + 1) % parents.shape[0], :].copy()
43+
44+
random_split_point = numpy.random.choice(range(offspring_size[0]))
45+
46+
parent1[random_split_point:] = parent2[random_split_point:]
47+
48+
offspring.append(parent1)
49+
50+
idx += 1
51+
52+
return numpy.array(offspring)
53+
54+
def mutation_func(offspring, ga_instance):
55+
# This is random mutation that mutates a single gene.
56+
for chromosome_idx in range(offspring.shape[0]):
57+
# Make some random changes in 1 or more genes.
58+
random_gene_idx = numpy.random.choice(range(offspring.shape[0]))
59+
60+
offspring[chromosome_idx, random_gene_idx] += numpy.random.random()
61+
62+
return offspring
63+
64+
ga_instance = pygad.GA(num_generations=10,
65+
sol_per_pop=5,
66+
num_parents_mating=2,
67+
num_genes=len(equation_inputs),
68+
fitness_func=fitness_func,
69+
parent_selection_type=parent_selection_func,
70+
crossover_type=crossover_func,
71+
mutation_type=mutation_func)
72+
73+
ga_instance.run()
74+
ga_instance.plot_fitness()

0 commit comments

Comments
 (0)
0