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 f5ecabb

Browse files
author
Ahmed Gad
committed
Edit gene_constraint callables
1 parent 079475f commit f5ecabb

File tree

8 files changed

+86
-12
lines changed

8 files changed

+86
-12
lines changed

‎.DS_Store

8 KB
Binary file not shown.

‎examples/example_gene_constraint.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ def fitness_func(ga_instance, solution, solution_idx):
2525
gene_type=int,
2626
sample_size=100,
2727
random_seed=10,
28-
gene_constraint=[lambda x,v: [val for val in v if val>=98],
29-
lambda x,v: [val for val in v if val>=98],
30-
lambda x,v: [val for val in v if 80<val<90],
28+
gene_constraint=[lambda x,v: [val for val in v if val>=98],
29+
lambda x,v: [val for val in v if val>=98],
30+
lambda x,v: [val for val in v if 80<val<90],
3131
None,
32-
lambda x,v: [val for val in v if 20<val<40],
32+
lambda x,v: [val for val in v if 20<val<40],
3333
None]
3434
)
3535

‎pygad/.DS_Store

10 KB
Binary file not shown.

‎pygad/helper/.DS_Store

6 KB
Binary file not shown.

‎pygad/pygad.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,8 +1434,15 @@ def initialize_population(self,
14341434
else:
14351435
raise Exception("The output from the gene_constraint callable/function must be a list or NumPy array that is subset of the passed values (second argument).")
14361436

1437-
# Check if the gene value satisfies the gene constraint.
1438-
if len(filtered_values) == 1 and filtered_values[0] == solution[gene_idx]:
1437+
if len(filtered_values) ==1 and filtered_values[0] != solution[gene_idx]:
1438+
# Error by the user's defined gene constraint callable.
1439+
raise Exception(f"It is expected to receive a list/numpy.ndarray from the gene_constraint callable with a single value equal to {values[0]}, but the value {filtered_values[0]} found.")
1440+
1441+
# Check if the gene value does not satisfy the gene constraint.
1442+
# Note that we already passed a list of a single value.
1443+
# It is expected to receive a list of either a single value or an empty list.
1444+
if len(filtered_values) < 1:
1445+
# Search for a value that satisfies the gene constraint.
14391446
range_min, range_max = self.get_initial_population_range(gene_index=gene_idx)
14401447
# While initializing the population, we follow a mutation by replacement approach. So, the original gene value is not needed.
14411448
values_filtered = self.get_valid_gene_constraint_values(range_min=range_min,
@@ -1450,6 +1457,12 @@ def initialize_population(self,
14501457
warnings.warn(f"No value satisfied the constraint for the gene at index {gene_idx} with value {solution[gene_idx]} while creating the initial population.")
14511458
else:
14521459
self.population[sol_idx, gene_idx] = random.choice(values_filtered)
1460+
elif len(filtered_values) == 1:
1461+
# The value already satisfied the gene constraint.
1462+
pass
1463+
else:
1464+
# Error by the user's defined gene constraint callable.
1465+
raise Exception(f"It is expected to receive a list/numpy.ndarray from the gene_constraint callable that is either empty or has a single value equal, but received a list/numpy.ndarray of length {len(filtered_values)}.")
14531466

14541467
# 4) Solve duplicate genes.
14551468
if allow_duplicate_genes == False:

‎pygad/utils/.DS_Store

6 KB
Binary file not shown.

‎pygad/visualize/.DS_Store

6 KB
Binary file not shown.

‎tests/test_gene_constraint.py

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,11 @@ def fitness_func_no_batch_multi(ga, solution, idx):
6969

7070
#### Single-Objective
7171
def test_initial_population_int_by_replacement():
72-
gene_constraint=[lambda x: x[0]>=8,lambda x: x[1]>=8,lambda x: 5>=x[2]>=1,lambda x: 5>x[3]>3,lambda x: x[4]<2]
72+
gene_constraint=[lambda x,v: [val for val in v if val>=8],
73+
lambda x,v: [val for val in v if val>=8],
74+
lambda x,v: [val for val in v if 5>=val>=1],
75+
lambda x,v: [val for val in v if 5>val>3],
76+
lambda x,v: [val for val in v if val<2]]
7377
ga_instance = population_gene_constraint(gene_constraint=gene_constraint,
7478
init_range_low=0,
7579
init_range_high=10,
@@ -79,17 +83,21 @@ def test_initial_population_int_by_replacement():
7983
gene_type=int,
8084
mutation_by_replacement=True)
8185
initial_population = ga_instance.initial_population
82-
# print(initial_population)
8386

8487
assert numpy.all(initial_population[:, 0] >= 8), "Not all values in column 0 are >= 8"
8588
assert numpy.all(initial_population[:, 1] >= 8), "Not all values in column 1 are >= 8"
8689
assert numpy.all(initial_population[:, 2] >= 1), "Not all values in column 2 are >= 1"
8790
assert numpy.all((initial_population[:, 2] >= 1) & (initial_population[:, 2] <= 5)), "Not all values in column 2 between 1 and 5 (inclusive)"
8891
assert numpy.all(initial_population[:, 3] == 4), "Not all values in column 3 between 3 and 5 (exclusive)"
8992
assert numpy.all(initial_population[:, 4] < 2), "Not all values in column 4 < 2"
93+
print("All constraints are met")
9094

9195
def test_initial_population_int_by_replacement_no_duplicates():
92-
gene_constraint=[lambda x: x[0]>=5,lambda x: x[1]>=5,lambda x: x[2]>=5,lambda x: x[3]>=5,lambda x: x[4]>=5]
96+
gene_constraint=[lambda x,v: [val for val in v if val>=5],
97+
lambda x,v: [val for val in v if val>=5],
98+
lambda x,v: [val for val in v if val>=5],
99+
lambda x,v: [val for val in v if val>=5],
100+
lambda x,v: [val for val in v if val>=5]]
93101
ga_instance = population_gene_constraint(gene_constraint=gene_constraint,
94102
init_range_low=1,
95103
init_range_high=10,
@@ -117,9 +125,15 @@ def test_initial_population_int_by_replacement_no_duplicates():
117125
assert numpy.all(initial_population[:, 2] >= 5), "Not all values in column 2 >= 5"
118126
assert numpy.all(initial_population[:, 3] >= 5), "Not all values in column 3 >= 5"
119127
assert numpy.all(initial_population[:, 4] >= 5), "Not all values in column 4 >= 5"
128+
print("All constraints are met")
120129

121130
def test_initial_population_int_by_replacement_no_duplicates2():
122-
gene_constraint=[lambda x: x[0]>=98,lambda x: x[1]>=98,lambda x: 20<x[2]<40,lambda x: x[3]<40,lambda x: x[4]<50,lambda x: x[5]<100]
131+
gene_constraint=[lambda x,v: [val for val in v if val>=98],
132+
lambda x,v: [val for val in v if val>=98],
133+
lambda x,v: [val for val in v if 20<val<40],
134+
lambda x,v: [val for val in v if val<40],
135+
lambda x,v: [val for val in v if val<50],
136+
lambda x,v: [val for val in v if val<100]]
123137
ga_instance = population_gene_constraint(gene_constraint=gene_constraint,
124138
random_mutation_min_val=1,
125139
random_mutation_max_val=100,
@@ -149,9 +163,14 @@ def test_initial_population_int_by_replacement_no_duplicates2():
149163
assert numpy.all(initial_population[:, 3] < 40), "Not all values in column 3 < 40"
150164
assert numpy.all(initial_population[:, 4] < 50), "Not all values in column 4 < 50"
151165
assert numpy.all(initial_population[:, 5] < 100), "Not all values in column 4 < 100"
166+
print("All constraints are met")
152167

153168
def test_initial_population_float_by_replacement_no_duplicates():
154-
gene_constraint=[lambda x: x[0]>=5,lambda x: x[1]>=5,lambda x: x[2]>=5,lambda x: x[3]>=5,lambda x: x[4]>=5]
169+
gene_constraint=[lambda x,v: [val for val in v if val>=5],
170+
lambda x,v: [val for val in v if val>=5],
171+
lambda x,v: [val for val in v if val>=5],
172+
lambda x,v: [val for val in v if val>=5],
173+
lambda x,v: [val for val in v if val>=5]]
155174
ga_instance = population_gene_constraint(gene_constraint=gene_constraint,
156175
init_range_low=1,
157176
init_range_high=10,
@@ -178,9 +197,48 @@ def test_initial_population_float_by_replacement_no_duplicates():
178197
assert numpy.all(initial_population[:, 2] >= 5), "Not all values in column 2 >= 5"
179198
assert numpy.all(initial_population[:, 3] >= 5), "Not all values in column 3 >= 5"
180199
assert numpy.all(initial_population[:, 4] >= 5), "Not all values in column 4 >= 5"
200+
print("All constraints are met")
181201

182202
def test_initial_population_float_by_replacement_no_duplicates2():
183-
gene_constraint=[lambda x: x[0]>=1,lambda x: x[1]>=1,lambda x: x[2]>=1,lambda x: x[3]>=1,lambda x: x[4]>=1]
203+
gene_constraint=[lambda x,v: [val for val in v if val>=1],
204+
lambda x,v: [val for val in v if val>=1],
205+
lambda x,v: [val for val in v if val>=1],
206+
lambda x,v: [val for val in v if val>=1],
207+
lambda x,v: [val for val in v if val>=1]]
208+
ga_instance = population_gene_constraint(gene_constraint=gene_constraint,
209+
init_range_low=1,
210+
init_range_high=2,
211+
gene_type=[float, 1],
212+
num_genes=5,
213+
crossover_type=None,
214+
mutation_by_replacement=False,
215+
allow_duplicate_genes=False)
216+
217+
num_duplicates = 0
218+
for idx, solution in enumerate(ga_instance.solutions):
219+
num = len(solution) - len(set(solution))
220+
if num != 0:
221+
print(solution, idx)
222+
num_duplicates += num
223+
224+
assert num_duplicates == 0
225+
226+
initial_population = ga_instance.initial_population
227+
# print(initial_population)
228+
229+
assert numpy.all(initial_population[:, 0] >= 1), "Not all values in column 0 >= 1"
230+
assert numpy.all(initial_population[:, 1] >= 1), "Not all values in column 1 >= 1"
231+
assert numpy.all(initial_population[:, 2] >= 1), "Not all values in column 2 >= 1"
232+
assert numpy.all(initial_population[:, 3] >= 1), "Not all values in column 3 >= 1"
233+
assert numpy.all(initial_population[:, 4] >= 1), "Not all values in column 4 >= 1"
234+
print("All constraints are met")
235+
236+
def test_initial_population_float_by_replacement_no_duplicates_None_constraints():
237+
gene_constraint=[lambda x,v: [val for val in v if val>=1],
238+
None,
239+
lambda x,v: [val for val in v if val>=1],
240+
None,
241+
lambda x,v: [val for val in v if val>=1]]
184242
ga_instance = population_gene_constraint(gene_constraint=gene_constraint,
185243
init_range_low=1,
186244
init_range_high=2,
@@ -207,6 +265,7 @@ def test_initial_population_float_by_replacement_no_duplicates2():
207265
assert numpy.all(initial_population[:, 2] >= 1), "Not all values in column 2 >= 1"
208266
assert numpy.all(initial_population[:, 3] >= 1), "Not all values in column 3 >= 1"
209267
assert numpy.all(initial_population[:, 4] >= 1), "Not all values in column 4 >= 1"
268+
print("All constraints are met")
210269

211270
if __name__ == "__main__":
212271
#### Single-objective
@@ -221,3 +280,5 @@ def test_initial_population_float_by_replacement_no_duplicates2():
221280
print()
222281
test_initial_population_float_by_replacement_no_duplicates2()
223282
print()
283+
test_initial_population_float_by_replacement_no_duplicates_None_constraints()
284+
print()

0 commit comments

Comments
(0)

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