|
| 1 | +# Genetic algorithm. |
| 2 | +A genetic algorithm is a metaheuristic inspired by the process of natural selection that belongs to |
| 3 | +the larger class of evolutionary algorithms. Genetic algorithms are commonly used to generate high-quality |
| 4 | +solutions to optimization and search problems by relying on biologically inspired operators such as mutation, |
| 5 | +crossover and selection. John Holland introduced genetic algorithms in 1960 based on the concept of Darwin’s theory |
| 6 | +of evolution; his student David E. Goldberg further extended genetic algorithm in 1989. |
| 7 | + |
| 8 | +You can read more about this algorithm in [wikipedia](https://en.wikipedia.org/wiki/Genetic_algorithm) |
| 9 | + |
| 10 | +# Disclaimer. |
| 11 | +First of all, it is a training project. The main goal is to understand the genetic algorithm a bit more and to have a little fun. |
| 12 | +So, I did not seek to make it super optimal or something like that. Anyway, I am open to your suggestions :) |
| 13 | + |
| 14 | +This moment there are two ways to use this implementation: |
| 15 | +* Canonical example of evolution from a random set of characters to the target string. |
| 16 | +* More useful example is finding extremes of functions. |
| 17 | + |
| 18 | +The good piece of news is - you can use the algorithm for your own goals implementing AbstractDNA and AbstractGene |
| 19 | + |
| 20 | +# Usage. |
| 21 | +1. String evolution. |
| 22 | + |
| 23 | +Suppose you want to get the `Where is the money, Lebowski?`. Lets define it: |
| 24 | +```php |
| 25 | + $goal = 'Where is the money, Lebowski?'; |
| 26 | +``` |
| 27 | +Then, you need to instantiate Population object with StringDNA. |
| 28 | +Feel free to pick population number and mutation rate parameters. |
| 29 | +It's very interesting to see how the result will change depending on these parameters. |
| 30 | + |
| 31 | +```php |
| 32 | + $DNA = new ASCIIStringDNA($goal); |
| 33 | + $population = new Population($DNA, $populationNumber = 200, $mutationRate = 0.1); |
| 34 | +``` |
| 35 | + |
| 36 | +The main process takes place here. You need to evaluate a fitness of population and create new generation until you get your goal. |
| 37 | + |
| 38 | +```php |
| 39 | + $bestOfEveryGeneration = [] |
| 40 | + while ($population->getBest()->getValue() !== $goal) { |
| 41 | + $population->evaluateFitness(); |
| 42 | + $population->createNewGeneration(); |
| 43 | + $bestOfeveryGeneration[] = $population->getBest()->getValue(); |
| 44 | + } |
| 45 | + ``` |
| 46 | + |
| 47 | +Then you can analyse the result: |
| 48 | +```php |
| 49 | +$epoch = $population->getEpoch(); |
| 50 | +$yourGoal = $population->getBest()->getValue(); |
| 51 | +$evolutionString = implode(", " $bestOfeveryGeneration); |
| 52 | +``` |
| 53 | + |
| 54 | +2. Find extreme of a function. |
| 55 | + |
| 56 | +Suppose you want to find a max of following function: `5 + 3x - 4y - x^2 + x y - y^2`. |
| 57 | +Where x in [-2; 2] and y in [-2, 2]. |
| 58 | + |
| 59 | + |
| 60 | +Firstly you need to implement a callable function that will evaluate your equation. |
| 61 | +This callable should return the calculation result. |
| 62 | + |
| 63 | +```php |
| 64 | + $function = function (...$args) { |
| 65 | + $x = func_get_arg(0); |
| 66 | + $y = func_get_arg(1); |
| 67 | + |
| 68 | + $equation = 5 + 3 * $x - 4 * $y - $x ** 2 + $x * $y - $y ** 2; |
| 69 | + |
| 70 | + return $equation; |
| 71 | + } |
| 72 | +``` |
| 73 | + |
| 74 | +Then, let's wrap this function to Equation instance: |
| 75 | +```php |
| 76 | +$equation = new Equation($function); |
| 77 | +``` |
| 78 | + |
| 79 | +And finally, you need to instantiate a Math DNA. |
| 80 | +* The first argument is $equation object itself. |
| 81 | +* The second argument is an array of math genes where every gene corresponds to an equation variable. |
| 82 | +In turn, every variable has its own boundaries. |
| 83 | +* Bool value indicates max or min of the equation is interesting for you. |
| 84 | +```php |
| 85 | + $mathDNA = new MathDNA($equation, [new MathGene(-2, 2), new MathGene(-2, 2)], true); |
| 86 | +``` |
| 87 | +And then again you need to evaluate a fitness of population and create new generations. |
| 88 | +Feel free to experiment here. |
| 89 | + |
| 90 | +```php |
| 91 | + $population = new Population($DNA, $populationNumber = 200, $mutationRate = 0.1); |
| 92 | + |
| 93 | + for ($i = 0; $i < 100; $i++) { |
| 94 | + $population->evaluateFitness(); |
| 95 | + $population->createNewGeneration(); |
| 96 | + } |
| 97 | + |
| 98 | + /** @var MathGene[] $bestValue */ |
| 99 | + $bestValue = $population->getBest()->getValue(); |
| 100 | +``` |
| 101 | + |
| 102 | +Then you can analyze the result. |
| 103 | +The "bestValue" will contain array with math genes where every gene is an answer of your equation |
| 104 | +```php |
| 105 | +/** @var MathGene[] $bestValue */ |
| 106 | +$bestValue = $population->getBest()->getValue(); |
| 107 | +``` |
| 108 | +You can find more detailed examples in the tests directory of this repository. |
| 109 | + |
| 110 | +# Credits |
| 111 | +Feel free to ask any questions or make suggestions in issue. |
| 112 | +I hope this repository will be useful for you. |
0 commit comments