@@ -33,15 +33,25 @@ def evaluate(item: str, main_target: str) -> tuple[str, float]:
33
33
34
34
35
35
def crossover (parent_1 : str , parent_2 : str ) -> tuple [str , str ]:
36
- """Slice and combine two string at a random point."""
36
+ """
37
+ Slice and combine two strings at a random point.
38
+ >>> random.seed(42)
39
+ >>> crossover("123456", "abcdef")
40
+ ('12345f', 'abcde6')
41
+ """
37
42
random_slice = random .randint (0 , len (parent_1 ) - 1 )
38
43
child_1 = parent_1 [:random_slice ] + parent_2 [random_slice :]
39
44
child_2 = parent_2 [:random_slice ] + parent_1 [random_slice :]
40
45
return (child_1 , child_2 )
41
46
42
47
43
48
def mutate (child : str , genes : list [str ]) -> str :
44
- """Mutate a random gene of a child with another one from the list."""
49
+ """
50
+ Mutate a random gene of a child with another one from the list.
51
+ >>> random.seed(42)
52
+ >>> mutate("123456", list("ABCDEF"))
53
+ '123456'
54
+ """
45
55
child_list = list (child )
46
56
if random .uniform (0 , 1 ) < MUTATION_PROBABILITY :
47
57
child_list [random .randint (0 , len (child )) - 1 ] = random .choice (genes )
@@ -54,19 +64,27 @@ def select(
54
64
population_score : list [tuple [str , float ]],
55
65
genes : list [str ],
56
66
) -> list [str ]:
57
- """Select the second parent and generate new population"""
67
+ """
68
+ Select the second parent and generate new population.
69
+ >>> random.seed(42)
70
+ >>> select(("123456", 8), [("abcdef", 4), ("ghijkl", 5)], list("ABCDEF"))
71
+ ['ghijkl', '1234B6']
72
+ """
58
73
pop = []
59
74
# Generate more children proportionally to the fitness score.
60
75
child_n = int (parent_1 [1 ] * 100 ) + 1
61
76
child_n = 10 if child_n >= 10 else child_n
62
77
for _ in range (child_n ):
63
- parent_2 = population_score [random .randint (0 , N_SELECTED )][0 ]
64
-
65
- child_1 , child_2 = crossover (parent_1 [0 ], parent_2 )
66
- # Append new string to the population list.
67
- pop .append (mutate (child_1 , genes ))
68
- pop .append (mutate (child_2 , genes ))
69
- return pop
78
+ # Randomly select the second parent from the population.
79
+ if population_score :
80
+ parent_2 = random .choices (
81
+ population_score , k = 1 , weights = [score for _ , score in population_score ]
82
+ )[0 ][0 ]
83
+ child_1 , child_2 = crossover (parent_1 [0 ], parent_2 )
84
+ # Append new strings to the population list.
85
+ pop .append (mutate (child_1 , genes ))
86
+ pop .append (mutate (child_2 , genes ))
87
+ return pop [:2 ] # Ensure population size does not exceed N_POPULATION
70
88
71
89
72
90
def basic (target : str , genes : list [str ], debug : bool = True ) -> tuple [int , int , str ]:
0 commit comments