Skip to content

Here is my toolbox #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
48 changes: 37 additions & 11 deletions evolve_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def __init__(self, starting_string=None, min_length=4, max_length=30):
"""
# Want to minimize a single objective: distance from the goal message
self.fitness = FitnessMinimizeSingle()

random.seed(9)
# Populate Message using starting_string, if given
if starting_string:
self.extend(list(starting_string))
Expand Down Expand Up @@ -92,16 +92,35 @@ 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):

""" Computes the Levenshtein
distance between two input strings """
if len(s1) == 0:
return len(s2)
if len(s2) == 0:
return len(s1)
if (s1, s2) not in memo:
memo[(s1, s2)] = min([int(s1[0] != s2[0]) +
levenshtein_distance(s1[1:],s2[1:], memo),
1+levenshtein_distance(s1[1:],s2,memo),
1+levenshtein_distance(s1,s2[1:], memo)])
return memo[(s1, s2)]

else:
return memo[(s1, s2)]


def evaluate_text(message, goal_text, verbose=VERBOSE):
"""
Given a Message and a goal_text string, return the Levenshtein distance
between the Message and the goal_text as a length 1 tuple.
If verbose is True, print each Message as it is evaluated.
"""
distance = levenshtein_distance(message.get_text(), goal_text)
memo = {}
distance = levenshtein_distance(message.get_text(), goal_text, memo)
if verbose:
print "{msg:60}\t[Distance: {dst}]".format(msg=message, dst=distance)
return (distance, ) # Length 1 tuple, required by DEAP
Expand All @@ -122,12 +141,18 @@ 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
randchar = random.choice(list(VALID_CHARS))
index_ins = random.randint(0, len(message))
message.insert(index_ins, randchar)

# 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
if random.random() < prob_del:
index_del = random.randint(0, len(message)-1)
del message[index_del]

if random.random() < prob_sub:
randchar = random.choice(list(VALID_CHARS))
index_sub = random.randint(0, len(message)-1)
message[index_sub] = randchar

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

Expand All @@ -154,8 +179,8 @@ def get_toolbox(text):
toolbox.register("select", tools.selTournament, tournsize=3)

# NOTE: You can also pass function arguments as you define aliases, e.g.
# toolbox.register("individual", Message, max_length=200)
# toolbox.register("mutate", mutate_text, prob_sub=0.18)
# toolbox.register("individual", Message, max_length=200)
# toolbox.register("mutate", mutate_text, prob_sub=0.18)

return toolbox

Expand Down Expand Up @@ -216,3 +241,4 @@ def evolve_string(text):

# Run evolutionary algorithm
pop, log = evolve_string(goal)

Loading