diff --git a/.evolve_text.py.swp b/.evolve_text.py.swp new file mode 100644 index 0000000..0bcb7bf Binary files /dev/null and b/.evolve_text.py.swp differ diff --git a/evolve_text.py b/evolve_text.py index e0202d2..e0a25fc 100644 --- a/evolve_text.py +++ b/evolve_text.py @@ -95,6 +95,37 @@ 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={}): + #base cases + if b=="": + return len(a) + elif a=="": + return len(b) + + #check dictionaray + elif (a,b) in d: + return d[(a,b)] + + #Option 1, first character is same + elif a[0]==b[0]: + option1 = levenshtein_distance(a[1:],b[1:],d) + else: + option1 = 1+levenshtein_distance(a[1:],b[1:],d) + + #Option 2, insert character + option2 = 1+levenshtein_distance(a,b[1:],d) + + #option 3, delete character + option3 = 1+levenshtein_distance(a[1:],b,d) + + #find minimum distance + minimum = min(option1, option2, option3) + + #add to dictionary + d[(a,b)] = minimum + + return minimum + def evaluate_text(message, goal_text, verbose=VERBOSE): """ Given a Message and a goal_text string, return the Levenshtein distance @@ -121,8 +152,21 @@ 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 + #Insertion-type mutation + randIndex = random.randint(0,len(message)-1) + message.insert(randIndex,random.choice(VALID_CHARS)) + + if random.random() < prob_ins: + # Deletion-type mutation + randIndex = random.randint(0,len(message)-1) + message.pop(randIndex) + + + if random.random() < prob_ins: + # Substitution-type mutation + randIndex = random.randint(0,len(message)-1) + message.pop(randIndex) + message.insert(randIndex,random.choice(VALID_CHARS)) # TODO: Also implement deletion and substitution mutations # HINT: Message objects inherit from list, so they also inherit @@ -202,7 +246,7 @@ 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 = "CLAP YOUR HANDS" else: goal = " ".join(sys.argv[1:]) diff --git a/results.txt b/results.txt new file mode 100644 index 0000000..d5ebb85 --- /dev/null +++ b/results.txt @@ -0,0 +1,3 @@ +This toolbox has provided me with a basic understanding of what are and how to use genetic algorithms. Even though the cost function contains the target string, we can still learn how cost functions work. + +In terms of the mutation, given a small number of generations, it is very difficult to evolve past a certain number of letters. For example, let's look at at 26 character string, the alphabet, "ABCDEFGHIJKLMNOPQRSTUVWXYZ". If we run for 500 generations, we can only get a levenshtein distance of 2-5. If we run 1000 generations, we can get a levenshtein distance of 1-2. If we run 1500 generations, we almost always a levenshtein distance of 0, a the exact copy of the targe string.