From aff5c22e96a9c0ec5ef1e3558e375b6c3e3674bb Mon Sep 17 00:00:00 2001 From: Sam Myers Date: Sun, 13 Mar 2016 21:53:13 -0400 Subject: [PATCH 1/2] finished toolbox --- evolve_text.py | 32 ++++++++++++++++++++++++++------ results.txt | 5 +++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 results.txt diff --git a/evolve_text.py b/evolve_text.py index e0202d2..9d3542a 100644 --- a/evolve_text.py +++ b/evolve_text.py @@ -92,8 +92,23 @@ def get_text(self): # Genetic operators #----------------------------------------------------------------------------- -# TODO: Implement levenshtein_distance function (see Day 9 in-class exercises) -# HINT: Now would be a great time to implement memoization if you haven't +def levenshtein_distance(s1, s2, memo=None): + if memo is None: + memo = {} + if len(s1) == 0: + return len(s2) + if len(s2) == 0: + return len(s1) + if (len(s1), len(s2)) in memo: + return memo[(len(s1), len(s2))] + delta = 1 if s1[-1] != s2[-1] else 0 + diag = levenshtein_distance(s1[:-1], s2[:-1], memo) + delta + vert = levenshtein_distance(s1[:-1], s2, memo) + 1 + horz = levenshtein_distance(s1, s2[:-1], memo) + 1 + ans = min(diag, vert, horz) + memo[(len(s1), len(s2))] = ans + return ans + def evaluate_text(message, goal_text, verbose=VERBOSE): """ @@ -121,9 +136,12 @@ def mutate_text(message, prob_ins=0.05, prob_del=0.05, prob_sub=0.05): """ if random.random() < prob_ins: - # TODO: Implement insertion-type mutation - pass - + message.insert(random.randrange(len(message)), random.choice(VALID_CHARS)) + elif random.random() < prob_del: + message.pop(random.randrange(len(message))) + elif random.random() < prob_sub: + index = random.randrange(len(message)) + message[index] = random.choice(VALID_CHARS) # TODO: Also implement deletion and substitution mutations # HINT: Message objects inherit from list, so they also inherit # useful list methods @@ -181,8 +199,10 @@ def evolve_string(text): # Run simple EA # (See: http://deap.gel.ulaval.ca/doc/dev/api/algo.html for details) - pop, log = algorithms.eaSimple(pop, + pop, log = algorithms.eaMuPlusLambda(pop, toolbox, + mu=300, + lambda_=300, cxpb=0.5, # Prob. of crossover (mating) mutpb=0.2, # Probability of mutation ngen=500, # Num. of generations to run diff --git a/results.txt b/results.txt new file mode 100644 index 0000000..1d51eef --- /dev/null +++ b/results.txt @@ -0,0 +1,5 @@ +Modification 1: + DEAP's eaMuPlusLambda algorithm, with a value of 300 for both mu and lambda, seemed to marginally improve the number of generations taken to converge on the target string. Increasing these values had the same type of effect. + +Modification 2: + Increasing the probabilities of mutation dramatically increased the speed of convergence, as one might expect. With probabilities of 50% for each of the three types of mutations, it took just over 100 generations. \ No newline at end of file From b4a0cf3987938f05ef9c1ad5cdc4d39b1b87800e Mon Sep 17 00:00:00 2001 From: Sam Myers Date: Sun, 13 Mar 2016 21:54:28 -0400 Subject: [PATCH 2/2] finished toolbox --- evolve_text.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/evolve_text.py b/evolve_text.py index 9d3542a..f042efa 100644 --- a/evolve_text.py +++ b/evolve_text.py @@ -142,10 +142,6 @@ def mutate_text(message, prob_ins=0.05, prob_del=0.05, prob_sub=0.05): elif random.random() < prob_sub: index = random.randrange(len(message)) message[index] = random.choice(VALID_CHARS) - # TODO: Also implement deletion and substitution mutations - # HINT: Message objects inherit from list, so they also inherit - # useful list methods - # HINT: You probably want to use the VALID_CHARS global variable return (message, ) # Length 1 tuple, required by DEAP