Balancing genes

24 Jan 2021 Code on Github


In the previous simulation we gave our creatures a single, simple gene to control its size and found that they just grew and grew. In the real world all attributes have downsides as well as benefits. We'll make this simulation more realistic by adding a cost to growing bigger: the bigger creatures are the slower they move.

The code for this simulation and all the others in this series is here.


At the start of the simulation creatures there are 50 creatures, each with a random size from 1 to 100 (so the radii are from 1 to 10). The speed of each creature is $(101 - size) \times 0.005$ pixels per tick, so between 0.005 and 0.5 pixels per tick.

The chart below shows how creature size changes over time. The red line in the mean creature size, while the grey area shows the range of creature sizes from largest to smallest.

Time (minutes) Gene value 0 10 20 30 40 50 60 70 80 90 100 0 10 20 30 40 50 60 70 80 90 100

The graph shows how the population starts with a wide range of creatures sizes, but the range quickly reduces, so after about 15 minutes, the minimum and maximum creature size are within 10 of each other. After about 20 minutes, the mean creature size settles down to somewhere in the range 20 - 30.

Predicting evolution

The system is so simple, it's possible to calculate the optimum creature size (with a few approximations). To survive and reproduce creatures want to maximise the area of land they cover each tick as this determines the chance they hit some food. (I'll ignore for now that food can be generated on top of creatures, adding slight additional pressure to be larger).

Consider a creature with a gene of value $x$. It has a radius of $\sqrt{x}$ pixels, so will hit any food whose center is along a line $2(\sqrt{x} + 1)$ pixels (because the radius of food is one pixel.

The speed of this creature is $\dfrac{100 - x}{200}$ pixels/tick.

So it covers an area of $\dfrac{(\sqrt{x} + 1)(100 - x)}{100}$ pixels$^2$/tick.

We can ignore the $\frac{1}{100}$ factor as it's the same for all creatures and depends on the units. So we have an expression for the area:

$\begin{align} A &= (\sqrt{x} + 1)(100 - x) \\ &= 100x^{\frac{1}{2}} + 100 - x^{\frac{3}{2}} -x \end{align}$.

To find the maximum area as $x$, we differentiate with respect to $x$:

$\dfrac{dA}{dx} = -\frac{3}{2}x^{\frac{1}{2}} + 50x^{-\frac{1}{2}} -1$

We then set that to 0 and solve the quadratic with a substitution of $u = x^{\frac{1}{2}}$, or plug it into Wolfram Alpha.

That gives a solution of roughly 26.5, which is in pretty good agreement with what we see.


In this simulation we made the gene for size a bit more realistic by giving it a cost - the bigger creatures get, the slower they move. This makes the simulation more interesting as rather than the value for the gene getting larger and larger, creature evolve to find the optimum value. However, it's still not that interesting since there is an optimum value.

In the real world, while people sometimes talk about "survival of the fittest", there is no such thing as "the fittest". The fitness of a creature is context dependent and depends on what other organisms live in the environment - there's no point being perfectly adapted to get the nectar of a particular long-necked flower is that flower doesn't exist in your environment.

In later simulations I hope to get something more similar to reality so there is no one perfect solution for the environment and species diverge to solve the problem of surviving and reproducing in different ways.