From 1c5af3e4a998cf25fe18a4bb0255684699d3bac1 Mon Sep 17 00:00:00 2001 From: ClaireKincaid Date: Thu, 14 Apr 2016 21:40:50 -0400 Subject: [PATCH] Turning in my Evolutionary Algorithms Toolbox --- evolve_text.py | 41 ++++++++++++++++++++++++++++++----------- results.txt | 26 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 results.txt diff --git a/evolve_text.py b/evolve_text.py index e0202d2..b26e261 100644 --- a/evolve_text.py +++ b/evolve_text.py @@ -95,12 +95,32 @@ 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(message, goal_text, dicts = {}): + """Computes the levenshtein distance between two input strings by memoizing with d, an empty dictionary""" + if (message, goal_text) in dicts.keys(): + return dicts[message, goal_text] + else: + if len(message)== 0: + return len(goal_text) + elif len(goal_text) ==0: + return len(message) + elif message[0] == goal_text[0]: + option1 = levenshtein_distance(message[1:], goal_text[1:], dicts) + else: + option1 = 1 + levenshtein_distance(message[1:], goal_text[1:], dicts) + option2 = 1 + levenshtein_distance(message[1:], goal_text, dicts) + option3 = 1 + levenshtein_distance(message, goal_text[1:], dicts) + minimum = min(option1, option2, option3) + dicts[message, goal_text] = minimum + return minimum + 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. """ + dicts = {} distance = levenshtein_distance(message.get_text(), goal_text) if verbose: print "{msg:60}\t[Distance: {dst}]".format(msg=message, dst=distance) @@ -119,19 +139,16 @@ def mutate_text(message, prob_ins=0.05, prob_del=0.05, prob_sub=0.05): Substitution: Replace one character of the Message with a random (legal) character """ - 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.append(random.choice(VALID_CHARS)) + if random.random() < prob_del: + message = message[0:] + if random.random() < prob_sub: + i = random.randint(0, len(message)) + message[i] = random.choice(VALID_CHARS) return (message, ) # Length 1 tuple, required by DEAP - #----------------------------------------------------------------------------- # DEAP Toolbox and Algorithm setup #----------------------------------------------------------------------------- @@ -181,8 +198,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 = 5, + lambda_ = 5, cxpb=0.5, # Prob. of crossover (mating) mutpb=0.2, # Probability of mutation ngen=500, # Num. of generations to run @@ -215,4 +234,4 @@ def evolve_string(text): raise ValueError(msg.format(goal=goal, char=char, val=VALID_CHARS)) # Run evolutionary algorithm - pop, log = evolve_string(goal) + pop, log = evolve_string(goal) \ No newline at end of file diff --git a/results.txt b/results.txt new file mode 100644 index 0000000..563eaba --- /dev/null +++ b/results.txt @@ -0,0 +1,26 @@ +###Experimentation Results for ToolBox-EvolutionaryAlgorithms +###Claire Kincaid +###April 14, 2016 + +I chose to change the DEAP evolutionary algorithm the code uses from eaSimple to eaMuPlusLambda to examine how it affects the run time and the generation results of the evolutionary algorithm software. + +RESULTS +- it still takes forever to run +- after lots of debugging I discovered that the levenshtein distance function was just recursive forever so it never stopped running, invalidating the change made by the use of eaMuPlusLambda +- now it's running great +- it starts running very quickly and slows down after a bit of time +- lets see how many generations it takes, I think we're on 50 right now +- btw the message code here is "THIS IS MY EXPERIMENT" +- mu is set to 5 +- lambda_ is set to 5 +- its getting closish +- levenshtein distance started at around 22 average now its down to 17 +- this still takes forever but is much more efficient than eaSimple for long message codes +- this is taking forever--- I'm going to do a smaller message and that should take less time (?) +- smaller message = EVOLUTION +- already going much faster +- it's slowed down but has an average levenshtein of about 12 +- bogged down around randint, had to debug +- rerunning at message = EVOLUTION +- its pretty efficient but still running fairly slow-- I think it's that my lambda_ is too high, I should add fewer new instances each time and keep more of the optemized ones +- took about 200 generations to get it, but I didn't have them officially count it so I don't know for sure