Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

AI: Evolution Simulation in the Physics World

0.00/5 (No votes)
8 Apr 2016 1  
Using Farseer Physics Library and Neural Networks, an example of behavioral evolution is simulated

Evolution

Bits and pieces of random parts don’t join together automatically to form machines that do a job, but in case of life, it seems like that’s not the case. Randomly generated traits are propagated if they are found fit for the environment. But how can this process of creation be visualized? For us to observe this change in natural environment, it takes observations of millions of generations of offspring. But luckily for us, computers can do the job quickly, for us to awe to this simple process which created all the glory of the natural world.

Problem

Here, we shall create a simple framework of life and a world which provides the environment for this artificial life to develop. We provide the basic structure, without a meaning, without a purpose, and we shall see that life finds a way.

So, for the basic structure of life, we use the simplest possible example, which is complex enough to make it seem closer to real life bacterium.

The structure for this life is as follows.

Base

A base contains nine nodes to which either an actuator or a sensor can be attached. A neural network controls these actuators with the help of input from the sensors. The node locations at which parts can be attached are given below:

Initially, the neural network is filled with random weights causing a very random behavior, also the location and number of sensors and actuators are randomly generated. This causes different behaviors in creatures.

Actuator

Actuator is a wheel, which can rotate clockwise or counter clockwise. It has an input with which it decides which direction to revolve. It uses Farseer Physics RevoluteJoint and a circular Body attached to it to achieve this.

Sensor

A sensor detects the presence of food in a field of view and sends single input to the attached neural network, either whether it can sense food or not. Color changes from red to grey accordingly.

Some examples of creatures randomly generated are given below, either a sensor or actuator are attached in random locations.

The environment has food generated in alternate locations and when the creature reaches the location, it consumes the food, and is generated next on the alternate location. The creature has to successfully change its direction, detecting the presence of food to be able to live in the environment. For this behavior to be generated in the creature, lots of chance and mutations in both the physical structure and neural network are required.

Locations at which food is generated are given below. Creature has to adapt successfully to be able to consume food at both the locations.

C# Setup

Here, we use the Farseer Physics Library based on Box2D to create the 2D physics environment. For the implementation of neural network, Parallel Neural Networks Library is used.

The first thing that comes to mind as the probable architecture of this system, will be to create a separate physics World for every Creature and its Food, because two different creatures are not supposed to collide with each other, nor consume other's food (which will ensure proper selection). But this was creating a huge memory bloat even for small number of instances. So, using a Box2D/Farseer Physics feature called 'Collision Filtering', in which we can create categories and groups of objects to lay out rules for collisions, a single World simulation for any number of instances was created. Upto 100 parallel instances of creatures have been run this way without a glitch. More about collision filtering is given here. For example, the creature's base, wheels and sensors are all given a 'category group' of -1, which means they never collide with each other. Remaining unwanted collisions are filtered out with CollisionCallback event.

The structure of the creature and the schema of neural network are managed by the DNA class, which also contains a method for mutating structure and the schema randomly.

An evolution instance contains a creature, food, and the count for the number of food it has consumed.

public EvolutionInstance(EvolutionWorld world, DNA dna)
{
    Creature = new Creature.Creature(world.World, dna);
    Food = new List<EvolutionCreature.Food>();
    NumFoodConsumed = 0;
    World = world;
    Died = false;

    FoodLocation = false;
    AddItemsToCanvas();

    GenerateFood();
}

The creature is made with the help of information in DNA, which is initially randomly generated. DNAElement describes the function of each node.

public class DNAElement
{
    public enum ElementType { ACTUATOR, SENSOR };
    public ElementType Type;
    public Dictionary<string, int> Attributes;
}

And DNA is made of a NetworkData which is a neural schema and a list of DNAElements.

public class DNA
{
        public List<DNAElement> DNAElements { get; set; }
        public NeuralNetworks.NetworkData NetworkData { get; set; }

        public DNA(DNA dna, int numJoints, bool mutate)
        {
            DNAElements = new List<DNAElement> ();
            foreach (DNAElement ele in dna.DNAElements)
            {
                DNAElement element = new DNAElement();
                element.Attributes["Joint"] = ele.Attributes["Joint"];
                element.Type = ele.Type;
                DNAElements.Add(element);
            }
            BackPropogationNetwork network = new BackPropogationNetwork(dna.NetworkData);
            NetworkData = network.GetNetworkData();

            if (mutate)
                Mutate(numJoints);
        }
}

Creature is created according to DNA.

public void CreateParts(World world)
{
    foreach(DNAElement element in DNA.DNAElements)
    {
        if (element.Type == DNAElement.ElementType.SENSOR)
        {
            Sensor s = new Sensor(world, this, element.Attributes["Joint"]);
            Shapes.Add(s.SensorBox);
        }
        else if (element.Type == DNAElement.ElementType.ACTUATOR)
        {
            Actuator a = new Actuator(world, this, element.Attributes["Joint"]);
            Shapes.Add(a.Wheel);
        }
    }
}

Mutations inside the DNA occur randomly.

public void Mutate(int maxJoints)
{
    switch (RandomProvider.random.Next(5))
    {
        case 0:
            MutateAddElement(maxJoints);
            break;
        case 1:
            MutateNetwork();
            break;
        case 2:
            MutateRemoveElement();
            break;
        case 3:
            MutateExistingType();
            break;
        case 4:
            // No change
             break;
    }
}

The Creature is initialized accordingly and the objects are created and added to WPF Canvas and Farseer Physics World after proper tweaking, for us to produce the creature described by DNA.

As the simulation proceeds, the next generation of instances are generated according to the ReSpawn() function after selecting the best creature and mutating its DNA by chance.

private void ReSpawn(DNA topDNA)
{
    Instances.ForEach(r => r.Die());
    Instances.Clear();
    CreateWorld();

    for (int i = 0; i < NumInstances; i++)
    {
        EvolutionInstance instance = new EvolutionInstance(this, new DNA(topDNA, 8, true));
        Instances.Add(instance);
    }
}

private void TimeOut()
{
    EvolutionInstance bestInstance = Instances.OrderBy(r => r.NumFoodConsumed).Last();
    ReSpawn(bestInstance.Creature.DNA);
}

Result

We can observe that the creature’s behavior is initially random and all of them either fall of the cliff or just stay where they are. As the simulation proceeds, mutations arise, generation after generation, the behavior which we are expecting, which is, the ability to change direction according to the location of food, is generated randomly inside the neural networks.

Many different kinds of behavior emerge in the simulation, according to the environment we provide, the creature which can consume more food in limited time has more chance to survive and propagate.

In real life, basic building blocks come from proteins taking complex shapes and making miniature machinery. Proteins also act as chemical messengers, transferring signals from one place to another in the organic world. These proteins somehow came together billions of years ago, by chance, to create self-replicating organic structures which eventually lead to life as we know it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here