OK, you’ve been very patient.  All this talk of genetics, drift and populations and so far we haven’t seen any ‘survival of the fittest’.  Well, here goes.

The last version of the overlapping population model just randomly killed individuals with a 0.25 probability. By simply making this probability dependent on the trait on the individual we link survival to genetics which is the basis for Darwinian evolution.

So, I’ve slightly modified the mortality function in the ComplexPopulation<T> class to call a virtual method to calculate the probability that a specific individual dies:

        ///<summary> 
        /// Does one season of mortality. 
        ///</summary> 
        ///<remarks>Performs probability-based deletions of individuals in the population.</remarks> 
        public void DoOneSeasonOfMortality() 
        { 
            System.Random rand = new Random();   

            for (int i = 0; i < mPopulationSize; i++) 
            { 
                double chance = rand.NextDouble();   

                if (chance <= ProbabilityOfDeath(population[i])) 
                { 
                    // Push index into stack then delete individual. 
                    stackTop++; 
                    stack[stackTop] = i; 
                    population[i] = null; 
                } 
            } 
        }   

        ///<summary> 
        /// Calculates the probability that this individual dies 
        ///</summary> 
        ///<param name="individual">The individual.</param> 
        ///<returns>A value between 0 and 1</returns> 
        public virtual double ProbabilityOfDeath(IIndividual individual) 
        { 
            // 0.25 probability of death for each individual. 
            return 0.25; 
        }

 

This has no effect on the functionality of this class, but it enables us to create a new population class with a different mortality function:

///<summary> 
/// An overlapping population with trait-dependent mortality. 
///</summary> 
///<typeparam name="T">The <see cref="IIndividual"/>-based type in the population.</typeparam> 
class MortalityPopulation<T> : ComplexPopulation<T> where T : class, IIndividual, new() 
{ 
    public MortalityPopulation(int populationSize, int MaxTraitValue) 
        : base(populationSize, MaxTraitValue) 
    { 
    }   

    ///<summary> 
    /// Calculates mortality as a straight line relationship with trait value. 
    ///</summary> 
    ///<param name="individual">The <see cref="IIndividual"/>.</param> 
    ///<returns>A <see cref="double"/> between 0 and 1 representing the probability of mortality for this individual.</returns> 
    public override double ProbabilityOfDeath(IIndividual individual) 
    { 
        int traitValue = individual.TraitValue;   

        return ((double)traitValue / (double)base.mMaxTraitValue) / (double)10; 
    } 
}

 

All this derived class does is override the virtual method to provide a calculated survival probability.

The equation we’re using is charted as:

Chart of fitness functions.

We’ll come to the three ‘strength’ factors later – for the moment we’ll use the ‘default’ strength of 10. This means that individuals with a trait value of 20 (all AA alleles) have a 0.1 probability of death, while individual with a trait value of 0 (all aa alleles) have a probability of death of 0 (ie they live for ever!).

So what is the result of running a population through this simulation?

Average trait evolving over 1000 generations.

So there’s a marked drop in the average trait value and a gradual decrease in the standard deviation.  This is because the population’s distribution is being ‘squashed’ up against the edge of possible values.

If we look at the trait as a 3D chart of distribution over time we get:

3D image of trait evolving over time.

That’s a bit difficult to see, so here’s the distribution histograms over time:

TraitFitnessStandardHistogram

So you can see, firstly, that at generation 0 before any evolution has occurred, the trait is normally distributed in the population, but as our selective pressure takes hold (generation 50) the distribution stops being normal.

Imagine that the normal distribution is made of jelly.  Evolution is acting like a hand pushing the jelly to the left : while being pushed, the jelly distorts. This hand is the ‘selective pressure’ of evolution. The distribution is moving due to individuals dying and being born, not due to individuals changing while they live.

In this particular example, there is a wall in the way at trait value 0; there is nowhere left to evolve to.  Pushing the jelly against this wall makes it kind of go ‘splat’ against that wall, but the hand doesn’t stop pushing and it ends up holding the jelly against the wall.

If the wall wasn’t there and the hand stopped pushing, the jelly would return to it’s normal distribution shape.

From this we can draw the conclusion that measuring the distribution of a physical trait in a population might give us a clue as to whether it is under strong selective pressure – if the normal distribution is skewed it’s a clue that strong selective pressure is forcing the population to evolve.

Returning to our graph of mortality probability by trait value, we can turn the ‘strength’ of the selective pressure up or down.

In our code:

return ((double)traitValue / (double)base.mMaxTraitValue) / (double)10;

 

the value ’10’ is the strength of the selective pressure.  If we make it smaller, the selective pressure is stronger, if we make it larger the selective pressure is weaker.

Setting it to 1 gives the following change in mean trait:

TraitFitnessHighPressure

As you can see, the change in mean is sharper than before.  This is because more individuals are dying each year and so changes occur faster.

Setting the ‘strength’ factor to 25 gives the following:

TraitFitnessLowPressure

Which shows the changes taking place more slowly.

So there you have a simple evolutionary model based on ‘survival of the fittest’ Darwinian Evolution.

Next I shall show how Sexual Selection can also cause evolutionary change in place of survival of the fittest.

The code for this simulation can be found over in the Channel 9 sandbox.

 

If you’re interested in writing software, check out my other blog: Coding at The Coal Face