Use a genetic algorithm to evolve populations of bit strings.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
4.5 KiB

  1. # Mike's Genetic Bit String Evolver
  2. This library is intended to help you apply a genetic algorithm to any number of your own projects.
  3. ## License
  4. This software is licensed under [GPLv3](./LICENSE)
  5. ## How to Use
  6. The general process is quite simple:
  7. 1. Decide what *thing* of your own you'd like to evolve. This could be anything that can be represented with a binary string:
  8. * Simple floating point numbers or integers
  9. * Neural networks
  10. * Instructions that come together to make a program of some sort (ie LISP)
  11. * Anything you can imagine you'd like to evolve using a genetic algorothm
  12. 2. Write an *encoder* function which will convert your *thing* into a string of bits
  13. 3. Write a *decoder* function which will convert a string of bits into your *thing*
  14. 4. Write a *fitness* function that will give your *thing* a score based on how well it performs (using whatever arbitrary rules and tests you care to).
  15. 5. Include this library in your program; Use the Population classes to manage and evolve your Chromosome classes.
  16. 6. A typical workflow where you repeatedly evolve your *things* could be something like:
  17. 1. Create a population using the Population class
  18. 2. Use the Population class to grab individuals of the Chromosome class
  19. 3. Grab each Chromosome's bit string with the method Chromosome::ToString()
  20. 4. Decode each bit string to an instance of one of your *things*, keeping track of which Chromosome it was decoded from
  21. 5. Run whatever tests you want, in order to determine the *fitness* of each of your *thing* instances (fitness is just a number; the higher the better).
  22. 6. Iterate over all your *thing* instances and tell their linked Chromosome about the fitness you just calculated
  23. 7. Use the Population class to perform an evolution of all the Chromosome classes at once with the method Population::Evolve()
  24. 8. Delete all your *thing* instances, since they now refer to the previous generation of Chromosome instances that no longer exist
  25. 9. Go back to Step 2 and keep repeating as long as you're seeing improvement.
  26. Note that you don't actually need to write an encoder if you decide to do it this way.
  27. ### Encoder / Decoder Examples
  28. **Simple Example**
  29. Suppose you wanted to evolve an unsigned integer using only one byte (ranging from 0 to 255). Suppose at some point your unsigned integer is the number 11. Your *encoder* should produce the bit string **00001011**, since that's just 11 in binary. Your **decoder** should be able to turn **00001011** back into the number 11.
  30. **Slightly Less Simple Example**
  31. Suppose you wanted to evolve a program. For simplicity, we'll start by saying this is a simple language that can only *print* and *exit*. You might represent this by saying an instruction starts with four bits, followed by an eight bit number. Suppose we assign *0000* to the instruction *exit*, and *0001* to the instruction *print*. Now take the following simple program:
  32. ```
  33. print 5
  34. exit 0
  35. ```
  36. Our encoder would then represent this program with the following bit string:
  37. ```000100000101000000000000```
  38. ## Features
  39. The following features have been implemented thus far:
  40. * **Sexual Reproduction**
  41. Two parent Chromosomes are selected, and a simple crossover operator is used to combine their bits into a single child Chromosome, before applying mutation.
  42. * **Asexual Reproduction**
  43. One parent Chromosome duplicates itself exactly into a child Chromosome, before applying mutation
  44. * **Roulette Wheel Selection**
  45. When choosing parent Chromosomes to produce offspring, a method is used to allow Chromosomes that have higher fitness to reproduce more often, yet without guaranteeing any fit Chromosome will reproduce. Less fit Chromosomes will have less chance to reproduce, but aren't guaranteed *not* to reproduce.
  46. * **Elitism**
  47. Before evolving a population of Chromosomes, a few of the *most fit* Chromosomes are copied directly into the next population without modification, in an attempt to ensure that a population's *Champions* (most fit Chromosomes) never get worse as a result of evolution. Elitism has two modes, currently:
  48. * *Rate* : The number of *champions* is determined by taking a percentage of the total population. A rate of 2% with a population size of 200 would result in 4 *champions*
  49. * *Absolute* : The number of *champions* can be set to any whole number manually
  50. ## Special Thank You
  51. I would like to thank my old professor, Christopher Ryu, Ph.D., for teaching a great Artificial Intelligence class and inspiring me to create this project while taking his class.