Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 33f443e

Browse files
Merge pull request #324 from ahmedfgad/master
Update the code
2 parents 1070ae7 + 44a9070 commit 33f443e

File tree

2 files changed

+123
-145
lines changed

2 files changed

+123
-145
lines changed

‎pygad/pygad.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def __init__(self,
4949
random_mutation_min_val=-1.0,
5050
random_mutation_max_val=1.0,
5151
gene_space=None,
52+
gene_constraint=None,
5253
allow_duplicate_genes=True,
5354
on_start=None,
5455
on_fitness=None,
@@ -104,6 +105,8 @@ def __init__(self,
104105
105106
gene_space: It accepts a list of all possible values of the gene. This list is used in the mutation step. Should be used only if the gene space is a set of discrete values. No need for the 2 parameters (random_mutation_min_val and random_mutation_max_val) if the parameter gene_space exists. Added in PyGAD 2.5.0. In PyGAD 2.11.0, the gene_space can be assigned a dict.
106107
108+
gene_constraint: It accepts a list of constraints for the genes. Each constraint is a Python function. Added in PyGAD 3.5.0.
109+
107110
on_start: Accepts a function/method to be called only once before the genetic algorithm starts its evolution. If function, then it must accept a single parameter representing the instance of the genetic algorithm. If method, then it must accept 2 parameters where the second one refers to the method's object. Added in PyGAD 2.6.0.
108111
on_fitness: Accepts a function/method to be called after calculating the fitness values of all solutions in the population. If function, then it must accept 2 parameters: 1) a list of all solutions' fitness values 2) the instance of the genetic algorithm. If method, then it must accept 3 parameters where the third one refers to the method's object. Added in PyGAD 2.6.0.
109112
on_parents: Accepts a function/method to be called after selecting the parents that mates. If function, then it must accept 2 parameters: the first one represents the instance of the genetic algorithm and the second one represents the selected parents. If method, then it must accept 3 parameters where the third one refers to the method's object. Added in PyGAD 2.6.0.
@@ -558,33 +561,58 @@ def __init__(self,
558561
self.random_mutation_min_val = random_mutation_min_val
559562
self.random_mutation_max_val = random_mutation_max_val
560563

564+
# Validate that gene_constraint is a list or tuple and every element inside it is either None or callable.
565+
if gene_constraint:
566+
if type(gene_constraint) in [list, tuple]:
567+
for constraint_idx, item in enumerate(gene_constraint):
568+
# Check whether the element is None or a callable.
569+
if item and callable(item):
570+
if item.__code__.co_argcount == 1:
571+
# Every callable is valid if it receives a single argument.
572+
# This argument represents the solution.
573+
pass
574+
else:
575+
self.valid_parameters = False
576+
raise ValueError(f"Every callable inside the gene_constraint parameter must accept a single argument representing the solution/chromosome. But the callable at index {constraint_idx} named '{item.__code__.co_name}' accepts {item.__code__.co_argcount} argument(s).")
577+
else:
578+
self.valid_parameters = False
579+
raise TypeError(f"The expected type of an element in the 'gene_constraint' parameter is None or a callable (e.g. function). But {item} at index {constraint_idx} of type {type(item)} found.")
580+
else:
581+
self.valid_parameters = False
582+
raise TypeError(f"The expected type of the 'gene_constraint' parameter is either list or tuple. But the value {gene_constraint} of type {type(gene_constraint)} found.")
583+
else:
584+
# It is None.
585+
pass
586+
587+
self.gene_constraint = gene_constraint
588+
561589
# Validating the number of parents to be selected for mating (num_parents_mating)
562590
if num_parents_mating <= 0:
563591
self.valid_parameters = False
564592
raise ValueError(f"The number of parents mating (num_parents_mating) parameter must be > 0 but ({num_parents_mating}) found. \nThe following parameters must be > 0: \n1) Population size (i.e. number of solutions per population) (sol_per_pop).\n2) Number of selected parents in the mating pool (num_parents_mating).\n")
565593

566594
# Validating the number of parents to be selected for mating: num_parents_mating
567-
if (num_parents_mating > self.sol_per_pop):
595+
if num_parents_mating > self.sol_per_pop:
568596
self.valid_parameters = False
569597
raise ValueError(f"The number of parents to select for mating ({num_parents_mating}) cannot be greater than the number of solutions in the population ({self.sol_per_pop}) (i.e., num_parents_mating must always be <= sol_per_pop).\n")
570598

571599
self.num_parents_mating = num_parents_mating
572600

573601
# crossover: Refers to the method that applies the crossover operator based on the selected type of crossover in the crossover_type property.
574602
# Validating the crossover type: crossover_type
575-
if (crossover_type is None):
603+
if crossover_type is None:
576604
self.crossover = None
577605
elif inspect.ismethod(crossover_type):
578606
# Check if the crossover_type is a method that accepts 4 paramaters.
579-
if (crossover_type.__code__.co_argcount == 4):
607+
if crossover_type.__code__.co_argcount == 4:
580608
# The crossover method assigned to the crossover_type parameter is validated.
581609
self.crossover = crossover_type
582610
else:
583611
self.valid_parameters = False
584612
raise ValueError(f"When 'crossover_type' is assigned to a method, then this crossover method must accept 4 parameters:\n1) Expected to be the 'self' object.\n2) The selected parents.\n3) The size of the offspring to be produced.\n4) The instance from the pygad.GA class.\n\nThe passed crossover method named '{crossover_type.__code__.co_name}' accepts {crossover_type.__code__.co_argcount} parameter(s).")
585613
elif callable(crossover_type):
586614
# Check if the crossover_type is a function that accepts 2 paramaters.
587-
if (crossover_type.__code__.co_argcount == 3):
615+
if crossover_type.__code__.co_argcount == 3:
588616
# The crossover function assigned to the crossover_type parameter is validated.
589617
self.crossover = crossover_type
590618
else:

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /