@@ -25,23 +25,27 @@ def single_point_crossover(self, parents, offspring_size):
25
25
else :
26
26
offspring = numpy .empty (offspring_size , dtype = object )
27
27
28
- for k in range (offspring_size [0 ]):
29
- # The point at which crossover takes place between two parents. Usually, it is at the center.
30
- crossover_point = numpy .random .randint (low = 0 , high = parents .shape [1 ], size = 1 )[0 ]
28
+ # Randomly generate all the K points at which crossover takes place between each two parents. The point does not have to be always at the center of the solutions.
29
+ # This saves time by calling the numpy.random.randint() function only once.
30
+ crossover_points = numpy .random .randint (low = 0 ,
31
+ high = parents .shape [1 ],
32
+ size = offspring_size [0 ])
31
33
34
+ for k in range (offspring_size [0 ]):
35
+ # Check if the crossover_probability parameter is used.
32
36
if not (self .crossover_probability is None ):
33
37
probs = numpy .random .random (size = parents .shape [0 ])
34
- indices = numpy .where (probs <= self .crossover_probability )[0 ]
38
+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
35
39
36
- # If no parent satisfied the probability, no crossover is applied and a parent is selected.
40
+ # If no parent satisfied the probability, no crossover is applied and a parent is selected as is .
37
41
if len (indices ) == 0 :
38
42
offspring [k , :] = parents [k % parents .shape [0 ], :]
39
43
continue
40
44
elif len (indices ) == 1 :
41
45
parent1_idx = indices [0 ]
42
46
parent2_idx = parent1_idx
43
47
else :
44
- indices = random .sample (list ( set ( indices )) , 2 )
48
+ indices = random .sample (indices , 2 )
45
49
parent1_idx = indices [0 ]
46
50
parent2_idx = indices [1 ]
47
51
else :
@@ -51,9 +55,9 @@ def single_point_crossover(self, parents, offspring_size):
51
55
parent2_idx = (k + 1 ) % parents .shape [0 ]
52
56
53
57
# The new offspring has its first half of its genes from the first parent.
54
- offspring [k , 0 :crossover_point ] = parents [parent1_idx , 0 :crossover_point ]
58
+ offspring [k , 0 :crossover_points [ k ]] = parents [parent1_idx , 0 :crossover_points [ k ] ]
55
59
# The new offspring has its second half of its genes from the second parent.
56
- offspring [k , crossover_point :] = parents [parent2_idx , crossover_point :]
60
+ offspring [k , crossover_points [ k ] :] = parents [parent2_idx , crossover_points [ k ] :]
57
61
58
62
if self .allow_duplicate_genes == False :
59
63
if self .gene_space is None :
@@ -86,17 +90,23 @@ def two_points_crossover(self, parents, offspring_size):
86
90
else :
87
91
offspring = numpy .empty (offspring_size , dtype = object )
88
92
93
+ # Randomly generate all the first K points at which crossover takes place between each two parents.
94
+ # This saves time by calling the numpy.random.randint() function only once.
95
+ if (parents .shape [1 ] == 1 ): # If the chromosome has only a single gene. In this case, this gene is copied from the second parent.
96
+ crossover_points_1 = numpy .zeros (offspring_size [0 ])
97
+ else :
98
+ crossover_points_1 = numpy .random .randint (low = 0 ,
99
+ high = numpy .ceil (parents .shape [1 ]/ 2 + 1 ),
100
+ size = offspring_size [0 ])
101
+
102
+ # The second point must always be greater than the first point.
103
+ crossover_points_2 = crossover_points_1 + int (parents .shape [1 ]/ 2 )
104
+
89
105
for k in range (offspring_size [0 ]):
90
- if (parents .shape [1 ] == 1 ): # If the chromosome has only a single gene. In this case, this gene is copied from the second parent.
91
- crossover_point1 = 0
92
- else :
93
- crossover_point1 = numpy .random .randint (low = 0 , high = numpy .ceil (parents .shape [1 ]/ 2 + 1 ), size = 1 )[0 ]
94
-
95
- crossover_point2 = crossover_point1 + int (parents .shape [1 ]/ 2 ) # The second point must always be greater than the first point.
96
106
97
107
if not (self .crossover_probability is None ):
98
108
probs = numpy .random .random (size = parents .shape [0 ])
99
- indices = numpy .where (probs <= self .crossover_probability )[0 ]
109
+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
100
110
101
111
# If no parent satisfied the probability, no crossover is applied and a parent is selected.
102
112
if len (indices ) == 0 :
@@ -106,7 +116,7 @@ def two_points_crossover(self, parents, offspring_size):
106
116
parent1_idx = indices [0 ]
107
117
parent2_idx = parent1_idx
108
118
else :
109
- indices = random .sample (list ( set ( indices )) , 2 )
119
+ indices = random .sample (indices , 2 )
110
120
parent1_idx = indices [0 ]
111
121
parent2_idx = indices [1 ]
112
122
else :
@@ -116,11 +126,11 @@ def two_points_crossover(self, parents, offspring_size):
116
126
parent2_idx = (k + 1 ) % parents .shape [0 ]
117
127
118
128
# The genes from the beginning of the chromosome up to the first point are copied from the first parent.
119
- offspring [k , 0 :crossover_point1 ] = parents [parent1_idx , 0 :crossover_point1 ]
129
+ offspring [k , 0 :crossover_points_1 [ k ]] = parents [parent1_idx , 0 :crossover_points_1 [ k ] ]
120
130
# The genes from the second point up to the end of the chromosome are copied from the first parent.
121
- offspring [k , crossover_point2 :] = parents [parent1_idx , crossover_point2 :]
131
+ offspring [k , crossover_points_2 [ k ] :] = parents [parent1_idx , crossover_points_2 [ k ] :]
122
132
# The genes between the 2 points are copied from the second parent.
123
- offspring [k , crossover_point1 : crossover_point2 ] = parents [parent2_idx , crossover_point1 : crossover_point2 ]
133
+ offspring [k , crossover_points_1 [ k ]: crossover_points_2 [ k ]] = parents [parent2_idx , crossover_points_1 [ k ]: crossover_points_2 [ k ] ]
124
134
125
135
if self .allow_duplicate_genes == False :
126
136
if self .gene_space is None :
@@ -151,10 +161,18 @@ def uniform_crossover(self, parents, offspring_size):
151
161
else :
152
162
offspring = numpy .empty (offspring_size , dtype = object )
153
163
164
+ # Randomly generate all the genes sources at which crossover takes place between each two parents.
165
+ # This saves time by calling the numpy.random.randint() function only once.
166
+ # There is a list of 0 and 1 for each offspring.
167
+ # [0, 1, 0, 0, 1, 1]: If the value is 0, then take the gene from the first parent. If 1, take it from the second parent.
168
+ genes_sources = numpy .random .randint (low = 0 ,
169
+ high = 2 ,
170
+ size = offspring_size )
171
+
154
172
for k in range (offspring_size [0 ]):
155
173
if not (self .crossover_probability is None ):
156
174
probs = numpy .random .random (size = parents .shape [0 ])
157
- indices = numpy .where (probs <= self .crossover_probability )[0 ]
175
+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
158
176
159
177
# If no parent satisfied the probability, no crossover is applied and a parent is selected.
160
178
if len (indices ) == 0 :
@@ -164,7 +182,7 @@ def uniform_crossover(self, parents, offspring_size):
164
182
parent1_idx = indices [0 ]
165
183
parent2_idx = parent1_idx
166
184
else :
167
- indices = random .sample (list ( set ( indices )) , 2 )
185
+ indices = random .sample (indices , 2 )
168
186
parent1_idx = indices [0 ]
169
187
parent2_idx = indices [1 ]
170
188
else :
@@ -173,12 +191,11 @@ def uniform_crossover(self, parents, offspring_size):
173
191
# Index of the second parent to mate.
174
192
parent2_idx = (k + 1 ) % parents .shape [0 ]
175
193
176
- genes_source = numpy .random .randint (low = 0 , high = 2 , size = offspring_size [1 ])
177
194
for gene_idx in range (offspring_size [1 ]):
178
- if (genes_source [ gene_idx ] == 0 ):
195
+ if (genes_sources [ k , gene_idx ] == 0 ):
179
196
# The gene will be copied from the first parent if the current gene index is 0.
180
197
offspring [k , gene_idx ] = parents [parent1_idx , gene_idx ]
181
- elif (genes_source [ gene_idx ] == 1 ):
198
+ elif (genes_sources [ k , gene_idx ] == 1 ):
182
199
# The gene will be copied from the second parent if the current gene index is 1.
183
200
offspring [k , gene_idx ] = parents [parent2_idx , gene_idx ]
184
201
@@ -212,10 +229,18 @@ def scattered_crossover(self, parents, offspring_size):
212
229
else :
213
230
offspring = numpy .empty (offspring_size , dtype = object )
214
231
232
+ # Randomly generate all the genes sources at which crossover takes place between each two parents.
233
+ # This saves time by calling the numpy.random.randint() function only once.
234
+ # There is a list of 0 and 1 for each offspring.
235
+ # [0, 1, 0, 0, 1, 1]: If the value is 0, then take the gene from the first parent. If 1, take it from the second parent.
236
+ genes_sources = numpy .random .randint (low = 0 ,
237
+ high = 2 ,
238
+ size = offspring_size )
239
+
215
240
for k in range (offspring_size [0 ]):
216
241
if not (self .crossover_probability is None ):
217
242
probs = numpy .random .random (size = parents .shape [0 ])
218
- indices = numpy .where (probs <= self .crossover_probability )[0 ]
243
+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
219
244
220
245
# If no parent satisfied the probability, no crossover is applied and a parent is selected.
221
246
if len (indices ) == 0 :
@@ -225,7 +250,7 @@ def scattered_crossover(self, parents, offspring_size):
225
250
parent1_idx = indices [0 ]
226
251
parent2_idx = parent1_idx
227
252
else :
228
- indices = random .sample (list ( set ( indices )) , 2 )
253
+ indices = random .sample (indices , 2 )
229
254
parent1_idx = indices [0 ]
230
255
parent2_idx = indices [1 ]
231
256
else :
@@ -234,9 +259,9 @@ def scattered_crossover(self, parents, offspring_size):
234
259
# Index of the second parent to mate.
235
260
parent2_idx = (k + 1 ) % parents .shape [0 ]
236
261
237
- # A 0/1 vector where 0 means the gene is taken from the first parent and 1 means the gene is taken from the second parent.
238
- gene_sources = numpy . random . randint ( 0 , 2 , size = self . num_genes )
239
- offspring [ k , :] = numpy . where ( gene_sources == 0 , parents [ parent1_idx , :], parents [parent2_idx , :])
262
+ offspring [ k , :] = numpy . where ( genes_sources [ k ] == 0 ,
263
+ parents [ parent1_idx , :],
264
+ parents [parent2_idx , :])
240
265
241
266
if self .allow_duplicate_genes == False :
242
267
if self .gene_space is None :
0 commit comments