Skip to content

Commit 2025468

Browse files
committed
Merge PR #375: select two random genes for swap mutation
2 parents 8c2cad6 + 6697509 commit 2025468

2 files changed

Lines changed: 27 additions & 5 deletions

File tree

‎pygad/utils/mutation.py‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,8 @@ def polynomial_mutation(self, offspring):
362362

363363
def swap_mutation(self, offspring):
364364
"""
365-
Swap the values of two genes inside each offspring. One gene is
366-
picked at random from the first half of the chromosome; the
367-
other is its mirror in the second half.
365+
Swap the values of two genes inside each offspring. The two
366+
genes are 2 different genes picked at random.
368367
369368
Parameters
370369
----------
@@ -378,8 +377,7 @@ def swap_mutation(self, offspring):
378377
"""
379378

380379
for idx in range(offspring.shape[0]):
381-
mutation_gene1 = numpy.random.randint(low=0, high=offspring.shape[1]/2, size=1)[0]
382-
mutation_gene2 = mutation_gene1 + int(offspring.shape[1]/2)
380+
mutation_gene1, mutation_gene2 = numpy.random.choice(offspring.shape[1], size=2, replace=False)
383381

384382
temp = offspring[idx, mutation_gene1]
385383
offspring[idx, mutation_gene1] = offspring[idx, mutation_gene2]

‎tests/test_crossover_mutation.py‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,27 @@ def test_two_points_crossover_manual_call():
267267

268268
assert segment_lengths == set(range(1, num_genes + 1))
269269

270+
271+
def test_swap_mutation_manual_call():
272+
# Any 2 different genes can be swapped.
273+
num_genes = 6
274+
result, ga_instance = output_crossover_mutation(gene_type=int,
275+
num_genes=num_genes,
276+
mutation_type="swap")
277+
278+
temp_offspring = numpy.array([list(range(num_genes))] * 1000)
279+
offspring = ga_instance.swap_mutation(offspring=temp_offspring.copy())
280+
281+
swapped_pairs = set()
282+
for solution in offspring:
283+
changed = numpy.flatnonzero(solution != numpy.arange(num_genes))
284+
# Exactly 2 genes exchange their values.
285+
assert len(changed) == 2
286+
assert solution[changed[0]] == changed[1] and solution[changed[1]] == changed[0]
287+
swapped_pairs.add(tuple(changed))
288+
289+
assert len(swapped_pairs) == num_genes * (num_genes - 1) // 2
290+
270291
if __name__ == "__main__":
271292
#### Single-objective
272293
print()
@@ -314,3 +335,6 @@ def test_two_points_crossover_manual_call():
314335

315336
test_two_points_crossover_manual_call()
316337
print()
338+
339+
test_swap_mutation_manual_call()
340+
print()

0 commit comments

Comments
 (0)