Shorelark

A simulation of evolution

Benjamin published on
4 min, 606 words

This is a project I started after my second year exams, after coming across this series of blog posts by Patryk27.

About

I was drawn to this as it was a combination of things I have rather little experience in: WebAssembly, Neural Networks and Machine Learning. It was also an opportunity to use Rust some more, this time in a completely different domain.

Neural Networks and Machine Learning

This is an area of computing that I've had very little exposure to. I couldn't to do a Machine Learning module in second year due to other module choices and in online tutorials I disliked how they seemed to always boil down to "here, use this pre-existing library".

The approach used in the blog posts attracted me as it involved building our own libraries, that we could then use in the simulation library. Of course, this meant that the resulting library is very simple compared to the established libraries out there, but I now have a much better understanding of how these crates work. Albeit this is only a theoretical understanding, I imagine the authors of these crates do a bunch of tricks and optimisations to make their implementation far better than mine.

The library for the genetic algorithm is the one I found most interesting from a "Rust features" perspective due to the use of traits to avoid hardcoding a particular crossover or selection algorithm.

The Simulation

The simulation is rather simple, it has a list of animals and a list of food items. Whenever an animal comes within a certain distance of a food item, the animal's "satiation" score increases, and the food items position is randomised.

Vision

The animals' vision uses a cone extending in front of each animal. This cone is subdivided into "cells" that each have an "energy" level. The energy level is calculated from the amount of food items in the cell's subdivision of the vison cone and the distance to each food item.

Brain

The brain of each animal uses a neural network from the library made as part of this project, which starts off with completely random weights. In each simulation step the brain's network is given the "energy" levels of the vision cells. The network then spits out two values, a new speed for the animal, and a rotation for the animal to make.

Evolution

Every few thousand simulation steps, the animal population are converted into "Individual"s which have a fitness score, the amount of food eaten, and a "Chromosome". This "Chromosome" is in fact just the weights of the neural network and is what is actually "evolved". The genetic algorithm takes these "Individuals" and evolves a new population of individuals using parent selection, crossover, and mutation methods defined when the simulation is initialised. Currently these are Roulette Wheel selection, Uniform crossover, and Gaussian mutation.

WebAssembly

The simulation library created cannot be simply built for the wasm target, as WebAssembly can only accept a small number of types at its interface. For this reason, there is also a simulation-wasm library which exposes a WebAssembly friendly interface that we can then interact with from JavaScript. It does reimplement a lot of struct definitions from simulation, but all the logic is still contained within simulation, and these structs are also pared down slightly.

Result

You can view the result of the project here, and the code is available on GitHub here.

Shorelark Screenshot