Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions evolve_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down Expand Up @@ -121,13 +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

# 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
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)

return (message, ) # Length 1 tuple, required by DEAP

Expand Down Expand Up @@ -181,8 +195,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
Expand Down
5 changes: 5 additions & 0 deletions results.txt
Original file line number Diff line number Diff line change
@@ -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.