From 92709636a5634b4cdab7fc33fcb71547bb35cf83 Mon Sep 17 00:00:00 2001 From: KelvinPuyam Date: Sat, 20 Apr 2024 08:47:17 +0530 Subject: [PATCH 1/6] Add doctests in all functions in basic_string.py --- genetic_algorithm/basic_string.py | 38 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 089c5c99a1ec..5102ee6f30e5 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -33,7 +33,12 @@ def evaluate(item: str, main_target: str) -> tuple[str, float]: def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: - """Slice and combine two string at a random point.""" + """ + Slice and combine two strings at a random point. + >>> random.seed(42) + >>> crossover("123456", "abcdef") + ('12345f', 'abcde6') + """ random_slice = random.randint(0, len(parent_1) - 1) child_1 = parent_1[:random_slice] + parent_2[random_slice:] child_2 = parent_2[:random_slice] + parent_1[random_slice:] @@ -41,7 +46,12 @@ def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: def mutate(child: str, genes: list[str]) -> str: - """Mutate a random gene of a child with another one from the list.""" + """ + Mutate a random gene of a child with another one from the list. + >>> random.seed(42) + >>> mutate("123456", list("ABCDEF")) + '123456' + """ child_list = list(child) if random.uniform(0, 1) < MUTATION_PROBABILITY: child_list[random.randint(0, len(child)) - 1] = random.choice(genes) @@ -54,19 +64,27 @@ def select( population_score: list[tuple[str, float]], genes: list[str], ) -> list[str]: - """Select the second parent and generate new population""" + """ + Select the second parent and generate new population. + >>> random.seed(42) + >>> select(("123456", 8), [("abcdef", 4), ("ghijkl", 5)], list("ABCDEF")) + ['ghijkl', '1234B6'] + """ pop = [] # Generate more children proportionally to the fitness score. child_n = int(parent_1[1] * 100) + 1 child_n = 10 if child_n >= 10 else child_n for _ in range(child_n): - parent_2 = population_score[random.randint(0, N_SELECTED)][0] - - child_1, child_2 = crossover(parent_1[0], parent_2) - # Append new string to the population list. - pop.append(mutate(child_1, genes)) - pop.append(mutate(child_2, genes)) - return pop + # Randomly select the second parent from the population. + if population_score: + parent_2 = random.choices( + population_score, k=1, weights=[score for _, score in population_score] + )[0][0] + child_1, child_2 = crossover(parent_1[0], parent_2) + # Append new strings to the population list. + pop.append(mutate(child_1, genes)) + pop.append(mutate(child_2, genes)) + return pop[:2] # Ensure population size does not exceed N_POPULATION def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, str]: From e94e46206341bda1841a84c2a722c93142098ecf Mon Sep 17 00:00:00 2001 From: KelvinPuyam Date: Sat, 20 Apr 2024 13:31:40 +0530 Subject: [PATCH 2/6] Revert back to original basic_string.py --- genetic_algorithm/basic_string.py | 38 ++++++++----------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 5102ee6f30e5..089c5c99a1ec 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -33,12 +33,7 @@ def evaluate(item: str, main_target: str) -> tuple[str, float]: def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: - """ - Slice and combine two strings at a random point. - >>> random.seed(42) - >>> crossover("123456", "abcdef") - ('12345f', 'abcde6') - """ + """Slice and combine two string at a random point.""" random_slice = random.randint(0, len(parent_1) - 1) child_1 = parent_1[:random_slice] + parent_2[random_slice:] child_2 = parent_2[:random_slice] + parent_1[random_slice:] @@ -46,12 +41,7 @@ def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: def mutate(child: str, genes: list[str]) -> str: - """ - Mutate a random gene of a child with another one from the list. - >>> random.seed(42) - >>> mutate("123456", list("ABCDEF")) - '123456' - """ + """Mutate a random gene of a child with another one from the list.""" child_list = list(child) if random.uniform(0, 1) < MUTATION_PROBABILITY: child_list[random.randint(0, len(child)) - 1] = random.choice(genes) @@ -64,27 +54,19 @@ def select( population_score: list[tuple[str, float]], genes: list[str], ) -> list[str]: - """ - Select the second parent and generate new population. - >>> random.seed(42) - >>> select(("123456", 8), [("abcdef", 4), ("ghijkl", 5)], list("ABCDEF")) - ['ghijkl', '1234B6'] - """ + """Select the second parent and generate new population""" pop = [] # Generate more children proportionally to the fitness score. child_n = int(parent_1[1] * 100) + 1 child_n = 10 if child_n >= 10 else child_n for _ in range(child_n): - # Randomly select the second parent from the population. - if population_score: - parent_2 = random.choices( - population_score, k=1, weights=[score for _, score in population_score] - )[0][0] - child_1, child_2 = crossover(parent_1[0], parent_2) - # Append new strings to the population list. - pop.append(mutate(child_1, genes)) - pop.append(mutate(child_2, genes)) - return pop[:2] # Ensure population size does not exceed N_POPULATION + parent_2 = population_score[random.randint(0, N_SELECTED)][0] + + child_1, child_2 = crossover(parent_1[0], parent_2) + # Append new string to the population list. + pop.append(mutate(child_1, genes)) + pop.append(mutate(child_2, genes)) + return pop def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, str]: From deaa3ed144871636e81fe20ad1bbf2f6779e3e30 Mon Sep 17 00:00:00 2001 From: KelvinPuyam Date: Sat, 20 Apr 2024 13:34:41 +0530 Subject: [PATCH 3/6] Add doctest in basic_string.py --- genetic_algorithm/basic_string.py | 34 ++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 089c5c99a1ec..243376a9c18a 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -33,7 +33,12 @@ def evaluate(item: str, main_target: str) -> tuple[str, float]: def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: - """Slice and combine two string at a random point.""" + """ + Slice and combine two strings at a random point. + >>> random.seed(42) + >>> crossover("123456", "abcdef") + ('12345f', 'abcde6') + """ random_slice = random.randint(0, len(parent_1) - 1) child_1 = parent_1[:random_slice] + parent_2[random_slice:] child_2 = parent_2[:random_slice] + parent_1[random_slice:] @@ -41,7 +46,12 @@ def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: def mutate(child: str, genes: list[str]) -> str: - """Mutate a random gene of a child with another one from the list.""" + """ + Mutate a random gene of a child with another one from the list. + >>> random.seed(123) + >>> mutate("123456", list("ABCDEF")) + '12345A' + """ child_list = list(child) if random.uniform(0, 1) < MUTATION_PROBABILITY: child_list[random.randint(0, len(child)) - 1] = random.choice(genes) @@ -54,7 +64,25 @@ def select( population_score: list[tuple[str, float]], genes: list[str], ) -> list[str]: - """Select the second parent and generate new population""" + """ + Select the second parent and generate new population + + >>> import random + >>> random.seed(42) + >>> parent_1 = ("123456", 8.0) + >>> population_score = [("abcdef", 4.0), ("ghijkl", 5.0), ("mnopqr", 7.0)] + >>> genes = list("ABCDEF") + >>> pop = [] + >>> child_n = int(parent_1[1]) + 1 + >>> child_n = 10 if child_n >= 10 else child_n + >>> for _ in range(child_n): + ... parent_2 = population_score[random.randint(0, len(population_score) - 1)][0] + ... child_1, child_2 = crossover(parent_1[0], parent_2) + ... pop.append(mutate(child_1, genes)) + ... pop.append(mutate(child_2, genes)) + >>> len(pop) == (int(parent_1[1]) + 1) * 2 + True + """ pop = [] # Generate more children proportionally to the fitness score. child_n = int(parent_1[1] * 100) + 1 From b16674e157f45df45378d93859d766e978f80999 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 08:05:06 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- genetic_algorithm/basic_string.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 243376a9c18a..b7c8ca5393f7 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -66,7 +66,7 @@ def select( ) -> list[str]: """ Select the second parent and generate new population - + >>> import random >>> random.seed(42) >>> parent_1 = ("123456", 8.0) From 561e5a070b39eddd4eebdfee7996fe552f2efb22 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 20 Apr 2024 12:40:16 +0200 Subject: [PATCH 5/6] Update genetic_algorithm/basic_string.py --- genetic_algorithm/basic_string.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index b7c8ca5393f7..8aca8b778524 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -67,20 +67,17 @@ def select( """ Select the second parent and generate new population - >>> import random >>> random.seed(42) >>> parent_1 = ("123456", 8.0) >>> population_score = [("abcdef", 4.0), ("ghijkl", 5.0), ("mnopqr", 7.0)] >>> genes = list("ABCDEF") - >>> pop = [] - >>> child_n = int(parent_1[1]) + 1 - >>> child_n = 10 if child_n >= 10 else child_n + >>> child_n = int(min(parent_1[1]) + 1, 10)) + >>> population = [] >>> for _ in range(child_n): - ... parent_2 = population_score[random.randint(0, len(population_score) - 1)][0] + ... parent_2 = population_score[random.randrange(len(population_score))][0] ... child_1, child_2 = crossover(parent_1[0], parent_2) - ... pop.append(mutate(child_1, genes)) - ... pop.append(mutate(child_2, genes)) - >>> len(pop) == (int(parent_1[1]) + 1) * 2 + ... population.extend((mutate(child_1, genes), mutate(child_2, genes))) + >>> len(population) == (int(parent_1[1]) + 1) * 2 True """ pop = [] From c8e2982ee26295e7a884350a4a0d8d6f17d662a8 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 20 Apr 2024 12:45:00 +0200 Subject: [PATCH 6/6] Update basic_string.py --- genetic_algorithm/basic_string.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 8aca8b778524..a906ce85a779 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -71,7 +71,7 @@ def select( >>> parent_1 = ("123456", 8.0) >>> population_score = [("abcdef", 4.0), ("ghijkl", 5.0), ("mnopqr", 7.0)] >>> genes = list("ABCDEF") - >>> child_n = int(min(parent_1[1]) + 1, 10)) + >>> child_n = int(min(parent_1[1] + 1, 10)) >>> population = [] >>> for _ in range(child_n): ... parent_2 = population_score[random.randrange(len(population_score))][0]