Recently, I implemented a Mathematica 6 version of the Weasel program by Richard Dawkins. It is a simple demonstration of the power of the process of cumulative natural selection as compared to random process.
The usual implementation starts with a random string of 28 characters. Then in each generation, it makes say 100 copies of the string, with a small chance (say 5%) per character of that character being replaced by a random character. Then it selects the string that is closest to the target sequence (the highest number of correct characters with correct positions)
METHINKS IT IS LIKE A WEASEL
and repeats the process until one of the copies exactly matches the target sequence.
The program is not supposed to model any real biological system. But when one allows for insertions and deletions of random letters, this simple modification of the algorithm moves it somewhat closer to how DNA mutates. It turns out that an implementation of such modification is straightforward in Mathematica 6.
Implementation
alphabet = CharacterRange["a", "z"]~Join~{" "}; source = Characters[""]; target = Characters["methinks it is like a weasel"]; numindividuals = 50; maxgenerations = 500; (* Mutation rates: {deletion, insertion, replacement} *) mutationrates = {0.02, 0.02, 0.02}; With[{mr = Join[#, {1 - Total[#]}] &[mutationrates]}, mutate[l_] := Flatten[ If[RandomReal[] < mr[[2]], {RandomChoice[alphabet], #}, #] &[ RandomChoice[ Unevaluated[ mr -> {{}, {#, RandomChoice[alphabet]}, RandomChoice[alphabet], #}]] & /@ l ] ] ] Timing[res = NestWhileList[ SortBy[Table[mutate[#], {numindividuals}], EditDistance[target, #] &][[1]] &, source, (# != target) &, 1, maxgenerations]; ] (* Printout *) Column[StringJoin /@ res[[;; ;; 10]]] ListPlot[EditDistance[target, #] & /@ res, PlotRange -> All, Filling -> Axis, AxesOrigin -> {0, 0}]
In this code, we start with an empty string “”. In each generation, we produce a pool of 50 individuals (copies). While creating a copy, each letter in the parent string has a 2% chance to be erased, 2% chance to be changed to a random letter and 2% chance that a random letter will be inserted next to it. Then we sort the pool with respect to the Levenshtein edit distance from the target string. We select the string with the first string with the smallest distance and use it as the parent string for the copies in the next generation. We repeat the process until one of the copies exactly matches the target string or when we achieve the maximal number of generations, whichever comes first.
Output
The following is a sample output of the program:
h ee il eal es i lie weael etn i s lie aweael eth i is lie aweael ethns i is lie a eael ethns i is lie a eael ethns i is lie a weael ethns i is lie a weael ethnk i is lie a weasel ethnks i is lie a weasel ethnks i is lie a weasel ethnks i is like a weasel ethnks i is like a weasel ethnks i is like a weasel ethnks i is like a weasel ethnks i is like a weasel ethnks i is like a weasel methnks i is like a weasel methnks i is like a weasel methnks i is like a weasel methnks i is like a weasel methnks i is like a weasel methiks i is like a weasel methiks it is like a weasel methiks it is like a weasel methiks it is like a weasel methiks it is like a weasel methiks it is like a weasel
Note that the printout shows only every 10th generation. You can see that there is no locking of correct letter, for example w was removed and replaced by a space from line 5 to line 6, even though it was in the correct spot. The following figure show the evolution of the edit distance of the best string in each generation:
And this is a sample output for an initial string “anything is possible for this weasel code”:
anything is possible for this weasel code aptaink zs fukr t wasel taink s k wasel think s k wasel thinks is lk easel mhinks is ike weasel meinki is ike a weasel meink i is ike a weasel meink i is ike a weasel meink i i like a weasel meink i i like a weasel meink i is like a weasel meink i is like a weasel meink i is like a weasel meink i is like a weasel meink i is like a weasel meink i is like a weasel meink i is like a weasel mehnk i is like a weasel methnk it is like a weasel methnk it is like a weasel methnk it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel methink it is like a weasel
Levenshtein distance
