diff --git a/evolve_text.py b/evolve_text.py index cb29dc8..3949d4a 100644 --- a/evolve_text.py +++ b/evolve_text.py @@ -92,7 +92,28 @@ def get_text(self): # Genetic operators # ----------------------------------------------------------------------------- -# TODO: Implement levenshtein_distance function (see Day 9 in-class exercises) +def levenshtein_distance(message, goal): + if len(message) < len(goal): + return levenshtein_distance(goal, message) + #always uses the shorter string as the indicator for how many + #steps it will take to get from one to another + if len(goal) == 0: + return len(message) + #if the length of the goal is = 0, then we just have to see + #how long the message is and delete every letter 1 at a time + previous_row = range(len(goal) + 1) + for index, counter in enumerate(message): + current_row = [index + 1] + for index2, counter2 in enumerate(goal): + dels = current_row[index2] + 1 + ins = previous_row[index2 + 1] + 1 + subs = previous_row[index2] + (counter != counter2) + current_row.append(min(dels, ins, subs)) + #finds the minimum amount of steps to the goal. + previous_row = current_row + + return previous_row[-1] + # HINT: Now would be a great time to implement memoization if you haven't def evaluate_text(message, goal_text, verbose=VERBOSE): @@ -121,15 +142,41 @@ 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 + r = random.randint(1, len(message)-1) + message = message[:r] + random.choice(VALID_CHARS) + message[r:] + #cuts the string randomly and inserts a random valid character + if random.random() < prob_del: + r2 = random.randint(1, len(message)-1) + message = message[:r2 - 1] + message[r2:] + #gets a random number between the string and removes that letter + if random.random() < prob_sub: + r3 = random.randint(1, len(message)-1) + message = message[:r3 - 1] + random.choice(VALID_CHARS) + message[r3:] + #finds a random character within the string and replaces that character + #with a random character + - # 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 + return (Message("".join(message)), ) # Length 1 tuple, required by DEAP + +def mate_text(parent1, parent2): + newstring1 = [] + newstring2 = [] + index = 0 + crossover_prob = 0.50 + # 1/2 chance of characters swapping + while index < len(parent1) and index < len(parent2): + if random.random() > crossover_prob: + newstring1.append(parent2[index]) + newstring2.append(parent1[index]) + else: + newstring1.append(parent1[index]) + newstring2.append(parent2[index]) + index = index + 1 + return (Message("".join(newstring1)), Message("".join(newstring2))) # ----------------------------------------------------------------------------- @@ -149,7 +196,7 @@ def get_toolbox(text): # Genetic operators toolbox.register("evaluate", evaluate_text, goal_text=text) - toolbox.register("mate", tools.cxTwoPoint) + toolbox.register("mate", mate_text) toolbox.register("mutate", mutate_text) toolbox.register("select", tools.selTournament, tournsize=3) diff --git a/results.txt b/results.txt new file mode 100644 index 0000000..b2ff755 --- /dev/null +++ b/results.txt @@ -0,0 +1,5 @@ +I apologize in advance for not being able to completely debug my code. I could not find the error within +the sections that I was supposed to implement. Maybe I modified the the Message class in my code when I wasn't supposed to. +Because the submission date is tonight, I won't be able to debug my code, but each independent section works as implied and +I will revise this for the future. +