GALib is a small C# library that provides scaffolding for genetic algorithm based functionalities. It's completely Open Source, and is available under the GNU General Public License.
I created this library while working on an application to solve the Travelling Salesman Problem. The idea for creating that application came to me after reading the first part of Bio-Inspired Artificial Intelligence by Dario Floreano and Claudio Mattiussi. I figured I needed to do an implementation of what I've read to test myself. All work was done in my free time.
Using the code
This section explains how to create your own GA implementations using GALib. If you are not familiar with how genetic algorithms work, you are advised to first have a good look at this Wikipedia article and related pages, or one of the many awesome articles here on CP. This section will first introduce you to how the actual evolution is done, and then how to create your own specific implementation by specifying an individual type.
Population class is the core of GALib. It is a collection of individuals of a type you specify on which evolution (selection and reproduction) can be done. The evolution of the population is done on a background thread, and can be done with rank based selection, truncated rank based selection, roulette wheel selection, and tournament selection. Events are fired every time a new generation is created, a new fittest individual has been found, or the evolution is complete.
The constructor allows you to specify some general properties that are likely to be different in multiple Use Cases. These are:
size - Optional.
Int32. The size of the population (# of individuals). Defaults to 100.
generations - Optional.
Int64. The maximum number of generations in the evolution. Defaults to 100000.
stagnationLimit - Optional.
Int64. The maximum number of generations with no fitness improvement. Defaults to 10000.
Population will automatically populate itself with
size amount of new individuals. Since Population is a list of individuals, you can add, remove, and manipulate members yourself. This is, however, highly discouraged once the evolution is running.
You can choose between several selection algorithms:
- Rank based selection
Rank based selection allocates reproduction slots to individuals based on their fitness rank. You can initiate rank based selection with the
DoRankBasedSelection method. Similarly, you can do truncated rank selection, a rank selection that only holds into account the first n individuals, by calling the
DoTruncatedRankSelection method, which accepts an
Int32 parameter indicating n.
- Roulette wheel based selection
Roulette wheel selection allocates reproduction slots to individuals proportional to their fitness. You can initiate roulette wheel selection with the
- Tournament based selection
Tournament based selection consists of allocating reproduction slots to the best individuals of a randomly chosen subset.
Population contains several overloaded
DoTournamentBasedSelection methods, allowing you to hold tournaments of a fixed size, or a variable size between two bounds, both specified either as the amount of individuals, or as a percentage of the population size.
You can stop the evolution by calling the
CancelEvolution method. The worker thread on which evolution is done will finish after the current generation has been completed.
After every generation, the individuals will be sorted according to their fitness, fittest first. This means that
populationInstance will yield you the fittest individual for that generation, and
populationInstance[populationInstance.Count - 1] will get you the least fit member. You can also use
GetFittest to get a range of fittest individuals. It accepts an
Int32 indicating the size of the range, and a boolean indicating whether elites should be included.
Population class contains three events that will be fired at various points through the evolutionary process:
GenerationComplete (Object sender, GenerationCompleteEventArgs<IndividualType> e)
Occurs every time a generation is complete. This means selection, reproduction, and fitness determination have happened, in that order.
GenerationCompleteEventArgs contains the current generation number and the fittest individual of the generation.
NewFittest (Object sender, NewFittestEventArgs<IndividualType> e)
Occurs when a new overall fittest individual is found.
NewFittestEventArgs contains the current generation number and the overall fittest individual.
EvolutionComplete (Object sender, EvolutionCompleteEventArgs<IndividualType> e)
The list below contains the most important properties of the
Population class, which allow you to drastically change the working of the algorithm.
For your own implementation, you need to specify your own individual type(s). The definitions for these types contain initialization, mutation, and crossover methods, as well as the genotype specification and fitness function. GALib provides scaffolding in the form of an
IIndividual interface and an
Individual abstract class. You must implement the interface in your individual type definition to be able to create a population of your type. You can (most likely should) inherit from
Individual, which will spare you some basic work, and implement
IIndividual for you.
Individual forces you to implement some abstract methods:
void doCrossover(IIndividual mother, IIndividual father)
For details on other work done by
Individual, see the source of the class itself.
Points of interest
Since my main motivation for creating this library was exercise, I learned a lot from building it. This is the first C# library I've ever written, as well as the first time I've done any GA programming (or AI in general). Abstracting the library in a way so that it can be used for GA in general was very interesting, and required me to expanded my knowledge of how to use interfaces and inheritance and use Generics in a non-basic way for the first time.
- Version 0.1: 2010-01-24: Initial release.