@@ -26,24 +26,26 @@ def single_point_crossover(self, parents, offspring_size):
2626 offspring = numpy .empty (offspring_size , dtype = object )
2727
2828 # 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.
2930 crossover_points = numpy .random .randint (low = 0 ,
3031 high = parents .shape [1 ],
3132 size = offspring_size [0 ])
33+
3234 for k in range (offspring_size [0 ]):
3335 # Check if the crossover_probability parameter is used.
3436 if not (self .crossover_probability is None ):
3537 probs = numpy .random .random (size = parents .shape [0 ])
36- indices = numpy .where (probs <= self .crossover_probability )[0 ]
38+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
3739
38- # 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 .
3941 if len (indices ) == 0 :
4042 offspring [k , :] = parents [k % parents .shape [0 ], :]
4143 continue
4244 elif len (indices ) == 1 :
4345 parent1_idx = indices [0 ]
4446 parent2_idx = parent1_idx
4547 else :
46- indices = random .sample (list ( set ( indices )) , 2 )
48+ indices = random .sample (indices , 2 )
4749 parent1_idx = indices [0 ]
4850 parent2_idx = indices [1 ]
4951 else :
@@ -88,17 +90,23 @@ def two_points_crossover(self, parents, offspring_size):
8890 else :
8991 offspring = numpy .empty (offspring_size , dtype = object )
9092
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+
91105 for k in range (offspring_size [0 ]):
92- if (parents .shape [1 ] == 1 ): # If the chromosome has only a single gene. In this case, this gene is copied from the second parent.
93- crossover_point1 = 0
94- else :
95- crossover_point1 = numpy .random .randint (low = 0 , high = numpy .ceil (parents .shape [1 ]/ 2 + 1 ), size = 1 )[0 ]
96-
97- crossover_point2 = crossover_point1 + int (parents .shape [1 ]/ 2 ) # The second point must always be greater than the first point.
98106
99107 if not (self .crossover_probability is None ):
100108 probs = numpy .random .random (size = parents .shape [0 ])
101- indices = numpy .where (probs <= self .crossover_probability )[0 ]
109+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
102110
103111 # If no parent satisfied the probability, no crossover is applied and a parent is selected.
104112 if len (indices ) == 0 :
@@ -108,7 +116,7 @@ def two_points_crossover(self, parents, offspring_size):
108116 parent1_idx = indices [0 ]
109117 parent2_idx = parent1_idx
110118 else :
111- indices = random .sample (list ( set ( indices )) , 2 )
119+ indices = random .sample (indices , 2 )
112120 parent1_idx = indices [0 ]
113121 parent2_idx = indices [1 ]
114122 else :
@@ -118,11 +126,11 @@ def two_points_crossover(self, parents, offspring_size):
118126 parent2_idx = (k + 1 ) % parents .shape [0 ]
119127
120128 # The genes from the beginning of the chromosome up to the first point are copied from the first parent.
121- 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 ] ]
122130 # The genes from the second point up to the end of the chromosome are copied from the first parent.
123- offspring [k , crossover_point2 :] = parents [parent1_idx , crossover_point2 :]
131+ offspring [k , crossover_points_2 [ k ] :] = parents [parent1_idx , crossover_points_2 [ k ] :]
124132 # The genes between the 2 points are copied from the second parent.
125- 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 ] ]
126134
127135 if self .allow_duplicate_genes == False :
128136 if self .gene_space is None :
@@ -153,10 +161,18 @@ def uniform_crossover(self, parents, offspring_size):
153161 else :
154162 offspring = numpy .empty (offspring_size , dtype = object )
155163
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+
156172 for k in range (offspring_size [0 ]):
157173 if not (self .crossover_probability is None ):
158174 probs = numpy .random .random (size = parents .shape [0 ])
159- indices = numpy .where (probs <= self .crossover_probability )[0 ]
175+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
160176
161177 # If no parent satisfied the probability, no crossover is applied and a parent is selected.
162178 if len (indices ) == 0 :
@@ -166,7 +182,7 @@ def uniform_crossover(self, parents, offspring_size):
166182 parent1_idx = indices [0 ]
167183 parent2_idx = parent1_idx
168184 else :
169- indices = random .sample (list ( set ( indices )) , 2 )
185+ indices = random .sample (indices , 2 )
170186 parent1_idx = indices [0 ]
171187 parent2_idx = indices [1 ]
172188 else :
@@ -175,12 +191,11 @@ def uniform_crossover(self, parents, offspring_size):
175191 # Index of the second parent to mate.
176192 parent2_idx = (k + 1 ) % parents .shape [0 ]
177193
178- genes_source = numpy .random .randint (low = 0 , high = 2 , size = offspring_size [1 ])
179194 for gene_idx in range (offspring_size [1 ]):
180- if (genes_source [ gene_idx ] == 0 ):
195+ if (genes_sources [ k , gene_idx ] == 0 ):
181196 # The gene will be copied from the first parent if the current gene index is 0.
182197 offspring [k , gene_idx ] = parents [parent1_idx , gene_idx ]
183- elif (genes_source [ gene_idx ] == 1 ):
198+ elif (genes_sources [ k , gene_idx ] == 1 ):
184199 # The gene will be copied from the second parent if the current gene index is 1.
185200 offspring [k , gene_idx ] = parents [parent2_idx , gene_idx ]
186201
@@ -214,10 +229,18 @@ def scattered_crossover(self, parents, offspring_size):
214229 else :
215230 offspring = numpy .empty (offspring_size , dtype = object )
216231
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+
217240 for k in range (offspring_size [0 ]):
218241 if not (self .crossover_probability is None ):
219242 probs = numpy .random .random (size = parents .shape [0 ])
220- indices = numpy .where (probs <= self .crossover_probability )[0 ]
243+ indices = list ( set ( numpy .where (probs <= self .crossover_probability )[0 ]))
221244
222245 # If no parent satisfied the probability, no crossover is applied and a parent is selected.
223246 if len (indices ) == 0 :
@@ -227,7 +250,7 @@ def scattered_crossover(self, parents, offspring_size):
227250 parent1_idx = indices [0 ]
228251 parent2_idx = parent1_idx
229252 else :
230- indices = random .sample (list ( set ( indices )) , 2 )
253+ indices = random .sample (indices , 2 )
231254 parent1_idx = indices [0 ]
232255 parent2_idx = indices [1 ]
233256 else :
@@ -236,9 +259,9 @@ def scattered_crossover(self, parents, offspring_size):
236259 # Index of the second parent to mate.
237260 parent2_idx = (k + 1 ) % parents .shape [0 ]
238261
239- # 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.
240- gene_sources = numpy . random . randint ( 0 , 2 , size = self . num_genes )
241- 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 , :])
242265
243266 if self .allow_duplicate_genes == False :
244267 if self .gene_space is None :
0 commit comments