8000 PyGAD 2.13.0 · SKakar13/GeneticAlgorithmPython@05c5d27 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 05c5d27

Browse files
authored
PyGAD 2.13.0
1. A new `bool` parameter called allow_duplicate_genes is supported. If True, which is the default, then a solution/chromosome may have duplicate gene values. If False, then each gene will have a unique value in its solution. Check the [Prevent Duplicates in Gene Values](https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#prevent-duplicates-in-gene-values) section for more details. 2. The last_generation_fitness is updated at the end of each generation not at the beginning. This keeps the fitness values of the most up-to-date population assigned to the last_generation_fitness parameter.
1 parent 3391808 commit 05c5d27

File tree

2 files changed

+55
-52
lines changed

2 files changed

+55
-52
lines changed

__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11

2-
__version__ = "2.12.0"
2+
__version__ = "2.13.0"

pygad.py

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,45 +1868,10 @@ def adaptive_mutation_probs_randomly(self, offspring):
18681868
num_trials=10)
18691869
return offspring
18701870

1871-
def unique_int_gene_from_range(self, solution, gene_index, min_val, max_val, mutation_by_replacement, gene_type):
1872-
1873-
"""
1874-
Finds a unique integer value for the gene.
1875-
1876-
solution: A solution with duplicate values.
1877-
gene_index: Index of the gene to find a unique value.
1878-
min_val: Identical to the self.random_mutation_min_val attribute.
1879-
max_val: Identical to the self.random_mutation_max_val attribute.
1880-
mutation_by_replacement: Identical to the self.mutation_by_replacement attribute.
1881-
gene_type: Exactly the same as the self.gene_type attribute.
1882-
1883-
Returns:
1884-
selected_value: The new value of the gene. It may be identical to the original gene value in case there are no possible unique values for the gene.
1885-
"""
1886-
1887-
all_gene_values = numpy.arange(min_val, max_val, dtype=gene_type)
1888-
1889-
if mutation_by_replacement:
1890-
pass
1891-
else:
1892-
all_gene_values = all_gene_values + solution[gene_index]
1893-
1894-
values_to_select_from = list(set(all_gene_values) - set(solution))
1895-
1896-
if len(values_to_select_from) == 0:
1897-
if not self.suppress_warnings: warnings.warn("You set 'allow_duplicate_genes=False' but there is no enough values to prevent duplicates.")
1898-
selected_value = solution[gene_index]
1899-
else:
1900-
selected_value = random.choice(values_to_select_from)
1901-
1902-
selected_value = gene_type(selected_value)
1903-
1904-
return selected_value
1905-
19061871
def solve_duplicate_genes_randomly(self, solution, min_val, max_val, mutation_by_replacement, gene_type, num_trials=10):
19071872

19081873
"""
1909-
Solves the duplicates in a solution randomly.
1874+
Solves the duplicates in a solution by randomly selecting new values for the duplicating genes.
19101875
19111876
solution: A solution with duplicate values.
19121877
min_val: Identical to the self.random_mutation_min_val attribute.
@@ -1965,7 +1930,7 @@ def solve_duplicate_genes_randomly(self, solution, min_val, max_val, mutation_by
19651930
def solve_duplicate_genes_by_space(self, solution, gene_type, num_trials=10):
19661931

19671932
"""
1968-
Solves the duplicates in a solution.
1933+
Solves the duplicates in a solution by selecting values for the duplicating genes from the gene space.
19691934
19701935
solution: A solution with duplicate values.
19711936
gene_type: Exactly the same as the self.gene_type attribute.
@@ -1987,8 +1952,8 @@ def solve_duplicate_genes_by_space(self, solution, gene_type, num_trials=10):
19871952
# For a solution like [3 2 0 0], the indices of the 2 duplicating genes are 2 and 3.
19881953
# The next call to the find_unique_value() method tries to change the value of the gene with index 3 to solve the duplicate.
19891954
if len(not_unique_indices) > 0:
1990-
new_solution, not_unique_indices, num_unsolved_duplicates = self.find_unique_values_by_space(new_solution=new_solution,
1991-
gene_type=gene_type,
1955+
new_solution, not_unique_indices, num_unsolved_duplicates = self.unique_genes_by_space(new_solution=new_solution,
1956+
gene_type=gene_type,
19921957
not_unique_indices=not_unique_indices,
19931958
num_trials=10)
19941959
else:
@@ -1998,10 +1963,10 @@ def solve_duplicate_genes_by_space(self, solution, gene_type, num_trials=10):
19981963
# If there are no possible values for the gene 3 with index 3 to solve the duplicate, try to change the value of the other gene with index 2.
19991964
if len(not_unique_indices) > 0:
20001965
not_unique_indices = set(numpy.where(new_solution == new_solution[list(not_unique_indices)[0]])[0]) - set([list(not_unique_indices)[0]])
2001-
new_solution, not_unique_indices, num_unsolved_duplicates = self.find_unique_values_by_space(new_solution=new_solution,
2002-
gene_type=gene_type,
2003-
not_unique_indices=not_unique_indices,
2004-
num_trials=10)
1966+
new_solution, not_unique_indices, num_unsolved_duplicates = self.unique_genes_by_space(new_solution=new_solution,
1967+
gene_type=gene_type,
1968+
not_unique_indices=not_unique_indices,
1969+
num_trials=10)
20051970
else:
20061971
# If there exist duplicate genes, then changing either of the 2 duplicating genes (with indices 2 and 3) will not solve the problem.
20071972
# This problem can be solved by randomly changing one of the non-duplicating genes that may make a room for a unique value in one the 2 duplicating genes.
@@ -2027,7 +1992,9 @@ def solve_duplicate_genes_by_space_OLD(self, solution, gene_type, num_trials=10)
20271992
if len(not_unique_indices) > 0:
20281993
for duplicate_index in not_unique_indices:
20291994
for trial_index in range(num_trials):
2030-
temp_val = self.get_gene_value_from_space(solution, duplicate_index, gene_type)
1995+
temp_val = self.unique_gene_by_space(solution=solution,
1996+
gene_idx=duplicate_index,
1997+
gene_type=gene_type)
20311998

20321999
if temp_val in new_solution and trial_index == (num_trials - 1):
20332000
# print("temp_val, duplicate_index", temp_val, duplicate_index, new_solution)
@@ -2047,11 +2014,47 @@ def solve_duplicate_genes_by_space_OLD(self, solution, gene_type, num_trials=10)
20472014

20482015
return new_solution, not_unique_indices, num_unsolved_duplicates
20492016

2050-
def find_unique_values_by_space(self, new_solution, gene_type, not_unique_indices, num_trials=10):
2017+
def unique_int_gene_from_range(self, solution, gene_index, min_val, max_val, mutation_by_replacement, gene_type):
20512018

20522019
"""
2053-
Loops through all the duplicating genes to find a unique value that from their gene space to solve the duplicates.
2054-
2020+
Finds a unique integer value for the gene.
2021+
2022+
solution: A solution with duplicate values.
2023+
gene_index: Index of the gene to find a unique value.
2024+
min_val: Identical to the self.random_mutation_min_val attribute.
2025+
max_val: Identical to the self.random_mutation_max_val attribute.
2026+
mutation_by_replacement: Identical to the self.mutation_by_replacement attribute.
2027+
gene_type: Exactly the same as the self.gene_type attribute.
2028+
2029+
Returns:
2030+
selected_value: The new value of the gene. It may be identical to the original gene value in case there are no possible unique values for the gene.
2031+
"""
2032+
2033+
all_gene_values = numpy.arange(min_val, max_val, dtype=gene_type)
2034+
2035+
if mutation_by_replacement:
2036+
pass
2037+
else:
2038+
all_gene_values = all_gene_values + solution[gene_index]
2039+
2040+
values_to_select_from = list(set(all_gene_values) - set(solution))
2041+
2042+
if len(values_to_select_from) == 0:
2043+
if not self.suppress_warnings: warnings.warn("You set 'allow_duplicate_genes=False' but there is no enough values to prevent duplicates.")
2044+
selected_value = solution[gene_index]
2045+
else:
2046+
selected_value = random.choice(values_to_select_from)
2047+
2048+
selected_value = gene_type(selected_value)
2049+
2050+
return selected_value
2051+
2052+
def unique_genes_by_space(self, new_solution, gene_type, not_unique_indices, num_trials=10):
2053+
2054+
"""
2055+
Loops through all the duplicating genes to find unique values that from their gene spaces to solve the duplicates.
2056+
For each duplicating gene, a call to the unique_gene_by_space() is made.
2057+
20552058
new_solution: A solution with duplicate values.
20562059
gene_type: Exactly the same as the self.gene_type attribute.
20572060
not_unique_indices: Indices with duplicating values.
@@ -2066,9 +2069,9 @@ def find_unique_values_by_space(self, new_solution, gene_type, not_unique_indice
20662069
num_unsolved_duplicates = 0
20672070
for duplicate_index in not_unique_indices:
20682071
for trial_index in range(num_trials):
2069-
temp_val = self.get_gene_value_from_space(new_solution,
2070-
duplicate_index,
2071-
gene_type)
2072+
temp_val = self.unique_gene_by_space(solution=new_solution,
2073+
gene_idx=duplicate_index,
2074+
gene_type=gene_type)
20722075

20732076
if temp_val in new_solution and trial_index == (num_trials - 1):
20742077
# print("temp_val, duplicate_index", temp_val, duplicate_index, new_solution)
@@ -2088,7 +2091,7 @@ def find_unique_values_by_space(self, new_solution, gene_type, not_unique_indice
20882091

20892092
return new_solution, not_unique_indices, num_unsolved_duplicates
20902093

2091-
def get_gene_value_from_space(self, solution, gene_idx, gene_type):
2094+
def unique_gene_by_space(self, solution, gene_idx, gene_type):
20922095

20932096
"""
20942097
Returns a unique gene value for a single gene based on its value space to solve the duplicates.

0 commit comments

Comments
 (0)
0