Skip to content

Commit 25bee39

Browse files
committed
Update all crossover operators to clone the genes, thus avoiding
potential problems with referencing.
1 parent 069b0a7 commit 25bee39

6 files changed

Lines changed: 41 additions & 26 deletions

File tree

pygenalgo/operators/crossover/mutli_point_crossover.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
9797

9898
# Check the flag value.
9999
if reset_flag:
100-
genome_1[i] = parent1.genome[i]
101-
genome_2[i] = parent2.genome[i]
100+
genome_1[i] = parent1.genome[i].clone()
101+
genome_2[i] = parent2.genome[i].clone()
102102
else:
103-
genome_1[i] = parent2.genome[i]
104-
genome_2[i] = parent1.genome[i]
103+
genome_1[i] = parent2.genome[i].clone()
104+
genome_2[i] = parent1.genome[i].clone()
105105
# _end_if_
106106

107107
# _end_for_

pygenalgo/operators/crossover/order_crossover.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,19 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
4646
used_parent1 = set(parent1.genome[:locus])
4747
used_parent2 = set(parent2.genome[:locus])
4848

49+
# Preallocate 1st genome.
50+
genome_1 = [gene.clone() for gene in parent1.genome[:locus] +
51+
[x for x in parent2 if x not in used_parent1]]
52+
53+
# Preallocate 2nd genome.
54+
genome_2 = [gene.clone() for gene in parent2.genome[:locus] +
55+
[y for y in parent1 if y not in used_parent2]]
56+
4957
# Create the 1st NEW offspring at locus.
50-
child1 = Chromosome(parent1.genome[:locus] +
51-
[x for x in parent2 if x not in used_parent1])
58+
child1 = Chromosome(genome_1)
5259

5360
# Create the 2nd NEW offspring at locus.
54-
child2 = Chromosome(parent2.genome[:locus] +
55-
[y for y in parent1 if y not in used_parent2])
61+
child2 = Chromosome(genome_2)
5662

5763
# Increase the crossover counter.
5864
self.inc_counter()

pygenalgo/operators/crossover/partially_mapped_crossover.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
6060

6161
# Copy the relevant part of the segment.
6262
for k in id_segment:
63-
genome_1[k] = parent1.genome[k]
64-
genome_2[k] = parent2.genome[k]
63+
genome_1[k] = parent1.genome[k].clone()
64+
genome_2[k] = parent2.genome[k].clone()
6565
# _end_for_
6666

6767
# Create auxiliary Sets for faster membership check.
@@ -92,7 +92,7 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
9292
else:
9393

9494
# Copy the gene.
95-
genome_1[x_pos] = gene_x
95+
genome_1[x_pos] = gene_x.clone()
9696

9797
# Break the loop.
9898
found = True
@@ -126,7 +126,7 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
126126
else:
127127

128128
# Copy the gene.
129-
genome_2[y_pos] = gene_y
129+
genome_2[y_pos] = gene_y.clone()
130130

131131
# Break the loop.
132132
found = True
@@ -141,12 +141,12 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
141141
parent2.genome)):
142142
# Check if the gene exists.
143143
if gene_a not in genome_2:
144-
genome_2[k] = gene_a
144+
genome_2[k] = gene_a.clone()
145145
# _end_if_
146146

147147
# Check if the gene exists.
148148
if gene_b not in genome_1:
149-
genome_1[k] = gene_b
149+
genome_1[k] = gene_b.clone()
150150
# _end_if_
151151

152152
# _end_for_

pygenalgo/operators/crossover/position_based_crossover.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
4646
number_of_points = self.rng.integers(1, high=number_of_genes-1)
4747

4848
# Select randomly the crossover points.
49-
cross_points = sorted(self.rng.choice(number_of_genes, size=number_of_points,
49+
cross_points = sorted(self.rng.choice(number_of_genes,
50+
size=number_of_points,
5051
replace=False, shuffle=False))
5152

5253
# Initialize the genome of the new chromosomes to 'None'.
@@ -56,8 +57,8 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
5657
# Copy the genes of the parents at
5758
# the preselected gene cross points.
5859
for i in cross_points:
59-
genome_1[i] = parent2.genome[i]
60-
genome_2[i] = parent1.genome[i]
60+
genome_1[i] = parent2.genome[i].clone()
61+
genome_2[i] = parent1.genome[i].clone()
6162
# _end_for_
6263

6364
# Fill the rest of the positions in both offsprings.
@@ -69,7 +70,7 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
6970
j = genome_1.index(None)
7071

7172
# Assign the current gene value.
72-
genome_1[j] = gene1
73+
genome_1[j] = gene1.clone()
7374
# _end_if_
7475

7576
# Check if 'gene2' exists in 2nd offspring.
@@ -78,7 +79,7 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
7879
k = genome_2.index(None)
7980

8081
# Assign the current gene value.
81-
genome_2[k] = gene2
82+
genome_2[k] = gene2.clone()
8283
# _end_if_
8384

8485
# _end_for_

pygenalgo/operators/crossover/single_point_crossover.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,17 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
4444
# Select randomly the crossover point.
4545
locus = self.rng.integers(1, high=len(parent1))
4646

47-
# Create the two NEW offsprings at locus.
48-
child1 = Chromosome(parent1.genome[:locus] + parent2.genome[locus:])
49-
child2 = Chromosome(parent2.genome[:locus] + parent1.genome[locus:])
47+
# Preallocate 1st genome at locus.
48+
genome_1 = [x.clone() for x in parent1.genome[:locus] +
49+
parent2.genome[locus:]]
50+
51+
# Preallocate 2nd genome at locus.
52+
genome_2 = [y.clone() for y in parent2.genome[:locus] +
53+
parent1.genome[locus:]]
54+
55+
# Create the two NEW offsprings.
56+
child1 = Chromosome(genome_1)
57+
child2 = Chromosome(genome_2)
5058

5159
# Increase the crossover counter.
5260
self.inc_counter()

pygenalgo/operators/crossover/uniform_crossover.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ def crossover(self, parent1: Chromosome, parent2: Chromosome):
5757
for i, (flag, p1, p2) in enumerate(zip(swap_probability.tolist(),
5858
parent1.genome, parent2.genome)):
5959
if flag:
60-
genome_1[i] = p1
61-
genome_2[i] = p2
60+
genome_1[i] = p1.clone()
61+
genome_2[i] = p2.clone()
6262
else:
63-
genome_1[i] = p2
64-
genome_2[i] = p1
63+
genome_1[i] = p2.clone()
64+
genome_2[i] = p1.clone()
6565
# _end_if_
6666

6767
# _end_for_

0 commit comments

Comments
 (0)