GeneticString generates PopulationItem based on the imputed target string, and a set of possible runes to build a string with. In order to optimise string generation additional configurations can be provided with Conf instance. Empty instance of Conf (&Conf{}) can be provided, then default values wo
(target string, charmap []rune, conf *Conf)
| 69 | // Link to the same algorithm implemented in python: |
| 70 | // https://github.com/TheAlgorithms/Python/blob/master/genetic_algorithm/basic_string.py |
| 71 | func GeneticString(target string, charmap []rune, conf *Conf) (*Result, error) { |
| 72 | populationNum := conf.PopulationNum |
| 73 | if populationNum == 0 { |
| 74 | populationNum = 200 |
| 75 | } |
| 76 | |
| 77 | selectionNum := conf.SelectionNum |
| 78 | if selectionNum == 0 { |
| 79 | selectionNum = 50 |
| 80 | } |
| 81 | |
| 82 | // Verify if 'populationNum' s bigger than 'selectionNum' |
| 83 | if populationNum < selectionNum { |
| 84 | return nil, errors.New("populationNum must be bigger than selectionNum") |
| 85 | } |
| 86 | |
| 87 | mutationProb := conf.MutationProb |
| 88 | if mutationProb == .0 { |
| 89 | mutationProb = .4 |
| 90 | } |
| 91 | |
| 92 | debug := conf.Debug |
| 93 | |
| 94 | // Just a seed to improve randomness required by the algorithm |
| 95 | rnd := rand.New(rand.NewSource(time.Now().UnixNano())) |
| 96 | |
| 97 | // Verify that the target contains no genes besides the ones inside genes variable. |
| 98 | for position, r := range target { |
| 99 | invalid := true |
| 100 | for _, n := range charmap { |
| 101 | if n == r { |
| 102 | invalid = false |
| 103 | } |
| 104 | } |
| 105 | if invalid { |
| 106 | message := fmt.Sprintf("character not available in charmap at position: %v", position) |
| 107 | return nil, errors.New(message) |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // Generate random starting population |
| 112 | pop := make([]PopulationItem, populationNum) |
| 113 | for i := 0; i < populationNum; i++ { |
| 114 | key := "" |
| 115 | for x := 0; x < utf8.RuneCountInString(target); x++ { |
| 116 | choice := rnd.Intn(len(charmap)) |
| 117 | key += string(charmap[choice]) |
| 118 | } |
| 119 | pop[i] = PopulationItem{key, 0} |
| 120 | } |
| 121 | |
| 122 | // Just some logs to know what the algorithms is doing |
| 123 | gen, generatedPop := 0, 0 |
| 124 | |
| 125 | // This loop will end when we will find a perfect match for our target |
| 126 | for { |
| 127 | gen++ |
| 128 | generatedPop += len(pop) |