Skip to content
Open
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
47 changes: 36 additions & 11 deletions evolve_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
VALID_CHARS = string.ascii_uppercase + " "

# Control whether all Messages are printed as they are evaluated
VERBOSE = True
VERBOSE = False


#-----------------------------------------------------------------------------
Expand Down Expand Up @@ -94,14 +94,35 @@ def get_text(self):

# 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(a,b,d):
"""returns the levenshtein distance between two strings a and b. Memoized.
>>> levenshtein_distance('linnea', 'lauren', {})
4
"""
if b=="":
return len(a)
elif a=="":
return len(b)
elif (a,b) in d:
return d[(a,b)]
elif a[0]==b[0]:
lev_skip_sub = levenshtein_distance(a[1:],b[1:],d)
else:
lev_skip_sub = 1+levenshtein_distance(a[1:],b[1:],d)
lev_insert = 1+levenshtein_distance(a,b[1:],d)
lev_delete = 1+levenshtein_distance(a[1:],b,d)
minLev = min(lev_skip_sub, lev_insert, lev_delete)
d[(a,b)] = minLev
return minLev


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)
distance = levenshtein_distance(message.get_text(), goal_text, {})
if verbose:
print "{msg:60}\t[Distance: {dst}]".format(msg=message, dst=distance)
return (distance, ) # Length 1 tuple, required by DEAP
Expand All @@ -121,13 +142,16 @@ 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
index = random.randint(0, len(message)-1)
char = random.choice(VALID_CHARS)
message.insert(index,char)
if random.random() < prob_del:
index = random.randint(0, len(message)-1)
message.pop(index)
if random.random() < prob_sub:
index = random.randint(0, len(message)-1)
char = random.choice(VALID_CHARS)
message[index] = char

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

Expand Down Expand Up @@ -185,7 +209,7 @@ def evolve_string(text):
toolbox,
cxpb=0.5, # Prob. of crossover (mating)
mutpb=0.2, # Probability of mutation
ngen=500, # Num. of generations to run
ngen=800, # Num. of generations to run
stats=stats)

return pop, log
Expand All @@ -202,7 +226,8 @@ def evolve_string(text):
if len(sys.argv) == 1:
# Default goal of the evolutionary algorithm if not specified.
# Pretty much the opposite of http://xkcd.com/534
goal = "SKYNET IS NOW ONLINE"
#goal = "SKYNET IS NOW ONLINE"
goal = 'PROGRAM TEST THREE'
else:
goal = " ".join(sys.argv[1:])

Expand Down