Evolving Dawkins’ Weasels

In a previous post, I wrote about Richard Dawkins’ Weasel computer program that demonstrated how cumulative selection can generate something useful from pure random chance. I’ve included my version of the program in that post, which you can try out for yourself. Weasels are featured in the demo because the program generates Shakespeare’s famous line about weasels.

The problem with Richard Dawkins’ Weasel program is not that it doesn’t work; it’s that it works too well. Critics argue that because the program “knows” its target Shakespeare quote, it can’t truly demonstrate how evolution works without a predetermined goal.

The Problem with Dawkins’ Original

Naturally, critics from the Intelligent Design community had complaints about the program. One particularly challenging criticism is that the program has the target sentence from Shakespeare built into it. The concern is that while the program works towards recreating the target string, the process of biological evolution doesn’t have such an end goal to strive towards. So, the critics say, the Weasel program is not a valid demonstration of anything having to do with evolution.

This criticism has some merit. Real evolution doesn’t have a target; organisms don’t evolve “toward” anything specific. They simply survive and reproduce based on their current environment, with success measured only by survival and reproduction rates.

A Better Challenge: The Steiner Weasel

A few years ago, I decided to create a new, improved version of a Weasel program that does not have any end goal built into it. I chose a problem similar to the Traveling Salesman problem, where the computer program must determine the most efficient route between a large number of cities.

Why is this a better problem for a Weasel program? There is no closed solution one can figure out beforehand. It is more efficient to “evolve” the solution using random chance and cumulative selection than it is to generate every possible path between cities and evaluate them. More importantly, the program has no knowledge of what the optimal solution should look like—it can only evaluate paths based on their performance, not their similarity to a predetermined target.

My program is called the Steiner Weasel program because it not only finds a solution close to the optimum, but it also identifies shortcuts1 along the way. This connects to the famous Steiner tree problem in mathematics, which involves finding the shortest network connecting multiple points, sometimes by adding intermediate waypoints that create shortcuts.

In this program, the cities serve as different food sources that the Weasels must visit and eat from to acquire calories. The cost of doing that is the distance they travel, which determines how many calories they burn in the process. Since the various paths are generated by random mutation, the selection process can only evaluate the paths based on how many more calories are acquired than calories spent. A successful path might collect 1,200 calories while spending only 800 traveling, yielding a net gain of 400 calories.

Since the program lacks knowledge of the optimal path, it has no way of knowing if it succeeded. So it just keeps running, blindly trying to improve the path, which is exactly like biological evolution.

See It in Action

But enough theory—let’s see this goalless evolution in action. The demo below will show you how complex, efficient solutions can emerge from nothing but random mutations and survival pressure.

Just press the Run button to see the program in action. Notice that it is not trying every possible combination of routes to food sources. Instead, it converges on increasingly better solutions with every generation.

Also, notice that it slows down but never actually stops when it thinks it has found a good solution, because it doesn’t really know what the answer is supposed to be. It also seems to stop after a while at a solution that still has some outstanding opportunities for improvement. But if you go get a cup of coffee and come back ten minutes later you will see that it eventually found and fixed many of those opportunities. One way to confirm that is to write down the Net Calories number on a piece of paper and then see that it has increased a bit after running for ten minutes or so.

The apparent slowing down and stopping is not due to the program doing anything different. Each generation churns out the same algorithm over and over again, without regard for how close it might be to an optimal solution. Unless you press the stop button or leave the page, this process will continue indefinitely.

Under the Hood: How It Works

So, how does it work, and what does it have to do with evolution?

Think of it this way: imagine 5,000 weasels each carrying a genetic “map” that tells them where to go on the field. Each map is a series of connected waypoints (genes that specify locations and connections between them), creating a path through the food sources.

The elements of the program are the rectangular playing field and a randomly positioned set of circles that represent different food sources. What you don’t see is a population of 5,000 weasels that need to acquire calories by visiting each food source, as each source supplies a different type of food suitable for the weasels. Each food source spills out across the field in an amount that decreases with distance from the circle representing the source. Think of a bell-shaped pile of food centered on each circle.

Weasels must move through the field, acquiring calories from as many food sources as possible. They move in a series of straight-line segments, stopping at the end of each segment to sample a food source. The closer that stop is to a food source the more calories they can get from that source. The problem is that every time a weasel moves from one stop to the next, it consumes calories it has acquired. The longer the journey between stops, the more calories consumed.

That means that the healthiest weasel is the one who stops as close as possible to each of the food sources along the shortest total journey across the field.

The Genetic Algorithm

The program starts by creating a Weasel. This Weasel contains DNA that consists of a number of Genes. Each Gene specifies a position on the playing field and a possible connection to another gene in the same DNA. Any two connected genes describe a straight line path on the playing field. The end of each line segment is the “stop” mentioned above, where the Weasel can acquire calories from the closest food source. All the Genes in the Weasel’s DNA describe the entire wandering pathway, a connected series of straight lines across the field.

Then the program creates a population of 4999 child weasels with identical DNA using that first Weasel as the parent.

Then the program starts running Generation cycles over and over again, consisting of the following steps:

  1. Mutation: Ask all 5000 Weasels to self-mutate. Each weasel complies by making up to three (randomly chosen) types of random mutations to its DNA. A mutation can add a new gene in a random location and connection, delete a randomly chosen gene, make a small random change to the position specified by the gene, or alter a connection of a randomly chosen gene.
  2. Evaluation: At the end of one cycle, each of the 5000 weasels are interrogated for the number of calories they acquired and the number of calories they consumed.
  3. Selection: The weasel with the highest net calories (acquired calories – spent calories) is selected as the parent for the next generation.
  4. Display: Display the path of the parent weasel on the field.
  5. Reproduction: The remaining DNA of the parent weasel is copied into the remaining 4999 weasels.
  6. Repeat: Go back to step 1.

The important thing to note is that the selection process in step 3 knows nothing about any of the DNA in any of the weasels. All it can know is what it gets from each weasel when it asks for calories acquired and calories spent.

The other important thing to note is that the mutations that occur in each weasel’s DNA all happen randomly within the weasel without regard for consequences. Therefore, no information is available about the pathway in relation to the food sources in any of the mutations.

The Evolutionary Connection

This mirrors biological evolution perfectly: organisms don’t evolve “toward” anything—they simply survive and reproduce based on their current environment. The “goal” emerges from the process itself, not from any predetermined target. A giraffe’s neck didn’t evolve to reach high leaves; rather, giraffes with longer necks simply survived better in environments where high leaves were available.

By removing the built-in target, the Steiner Weasel demonstrates what Darwin actually proposed: that complexity and efficiency can emerge from simple rules (random variation and natural selection) without any guiding intelligence or predetermined goal. The program doesn’t know what a good solution looks like, yet it consistently finds increasingly better ones. Just like evolution itself.

Earthquakes!

For more fun with Steiner Weasels, while it is running close to a good solution, apress the Earthquake button. This causes the Food Source locations to be scrambled, which, in turn, causes the Weasels to adapt to a new solution by the same process as before.

Badgers!

Another fun thing to do is to activate the Predator switch in the demo and then press the Run button. This causes a Badger to drift through the playing field. As Weasels travel on their path near the Badger, they burn calories by fighting the badger. The consequence of this is that the mindless process of evolving paths ends up with paths that are trying to avoid the Badger. There is no special Badger code in the evolution part of the algorithm. It adapting new pathways is simply a consequence of evaluating calories acquired minus calories spent.

  1. More information about Steiner Trees. In our case, the Steiner shortcut through the playing field shows up as a branching stop that allows a path to two different nearby food sources. Please note that the software does not include special Steiner code. The Steiner shortcut is caused by just another gene that was randomly added to a weasel’s DNA during the mutation process. If it happened to improve the path, there is a higher chance that this weasel becomes the parent compared to a weasel with the same path but no shortcut. If you run enough examples and let them run long enough, you will eventually see a rare Steiner stop. ↩︎

Leave a Comment