Idea of GA is pretty simple, we are trying to “grow” solution, using natural selection mechanism, similar to one used by nature to create better live beings. Sounds easy? In fact it is easy, especially in Swift.
Tip: aim of this post is not to introduce into the GA topic in general, so i can suggest to visit below sources to get some basic knowledge before going further (it will be much easier to understand what’s going on):
Time to show some code. I decided to build some kind of simple starter kit with implementation of the simplest version of genetic algorithm in Swift, it is trying to find out sequence of integers. Code is structured (i believe) in a pretty generic way, so you can fork/copy it and play with it.
Code is not so long, yet worth explaining to be clear, starting from the very beginning:
AVAILABLE_GENES is an array of all possible values of genes, you can put here nearly anything, chars, other arrays, even emojis, it’s just important to have every possible value here, as algorithm is unable to use other genes.
DNA_LENGTH, this is probably self-explanatory, it’s the length of sequence, which we are looking for.
TOURNAMENT_SIZE, in this implementation we are using tournament method to select “parents”. In a shortcut, we randomly select group of individuals and select one which is the fittest of them, this one will be the parent for next generation.
MUTATION_CHANCE, value between 0 and 1, which defines how particular gene is likely to mutate. 0.1 (which refers to 10%) is used by default in many implementations.
SAVE_FITTEST, this boolean defines if the fittest individual from current generation will survive to the next one without any changes.
Individual, this is core of this implementation. Each individual object represents potential solution to our problem, also defines every operation needed in GA.
randomize(), allows to create individual with random genes draw from the AVAILABLE_GENES pool.
calculatefitness(), this method returns integer value, which is interpreted as a distance between current solution and the one we are looking for, the closer to zero, the better. Zero means, the solution is as good as the optimal.
cross(), it gets one param, which is other individual object and returns new individual (children of received individual and the one, which was used to call the method on). This implementation is using single cross, but there also different methods, like multi cross, uniform cross and others.
mutate(), based on MUTATION_CHANCE is randomly changing value of particular genes in individual
Looks like this is it, all you need to know to start playing with genetic algorithms in Swift was explained above (hopefully), after few tests i noticed that in default configuration it takes ~80 generations to find the solution.
Population struct and runGeneticAlgorithm() method don’t need to be modified at all. If only individual struct will be properly defined, then it will work without any problems.
In case of any questions, suggestions, errors… feel free to let me know.