Before reading this you can have a look at my article on motivation behind writing this program (optional).
There are two words that sums up the definition of the word evolution:
- Descent with modicifation
- survival of the fittest
- Reproduce:
- Takes in a string
- Randomly mutate any one character of the string
- Repeatedly do this a number of times
- Return a list of mutated strings
- Natural selection:
- Takes in a list of strings
- Returns the fittest among them
import random import time def reproduce(string): children=[string] for i in range(100): mutant=list(string) mutant[int(random.uniform(0,1)*len(string))]=random.choice(all_char) mutant=reduce(lambda i,j : i+j,mutant) children+=[mutant] return children def natural_selection(children,final): err_list=dict() final=list(final) for i in children: i=list(i) err=0 for j in range(len(i)): err+=(ord(i[j])-ord(final[j]))**2 err_list[reduce(lambda a,b : a+b,i)] = err return [k for k,v in err_list.iteritems() if v== min(err_list.values())][0] main_str= 'i have just evolved from a random string' all_char='abcdefghijklmnopqrstuvwxyz ' total_len= len(main_str) temp=[] for i in range(total_len): temp+=random.sample(all_char,1) first_guess = reduce(lambda i,j : i+j, temp) select=first_guess print select count=0 while 1: progeny=reproduce(select) select=natural_selection(progeny,main_str) count+=1 time.sleep(.1) if select==main_str: break print select print '-----------------------------------------' print select print '-----------------------------------------\n\n' print 'initial guess : ' + first_guess print 'evolved string: ' + main_str + '\n' print 'number of generations = ' + str(count) raw_input()Reproduce takes the input "string" and splits it into a list of characters ['s','t','r','i','n','g']. Then randomly choose a character from the list and replace it by some other character (['s','t','r','i','a','g']). Then join the list back to form a mutated string: "striag" . Put this in the list of children and repeatedly do this to return a list (children) with 100 mutants and 1 progeny without mutation.
Natural selection takes the list of children and and the the final string i.e. the string that we need to evolve. It calculates the error for each child i.e. the difference between the the final string and the child string. To calculate this difference I have used the ord() function which returns the unicode of the character and squared it to get the absolute error. Eg.
>>> ord('a') 97 >>> ord('b') 98 >>> ord('c') 99 >>> ord('d') 100
Therefore, difference between 'abc' and 'acd' is:
>>> (ord('a')-ord('a'))**2+(ord('b')-ord('b'))**2+(ord('c')-ord('d'))**2 1
Natural selection then returns the child with the least error.
The programs starts with generating a random string (first_guess) and the taking its children and selecting the fittest progeny. Over the generations favourable mutations accumulate to give us the desired string ('i have just evolved from a random string').
That concludes our evolving string program in python. Feel free to ask me any doubts about the code.
No comments:
Post a Comment