You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* now using new `random` API from the Swift collection protocols, instead of creating a new function that uses `arc4random`
* updates code to Swift 4.2
* fixes some inconsistencies between terms begin used - such as `MAX_GENERATIONS` and `GENERATIONS`
Copy file name to clipboardExpand all lines: Genetic/README.markdown
+23-37
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@
5
5
A genetic algorithm (GA) is process inspired by natural selection to find high quality solutions. Most commonly used for optimization. GAs rely on the bio-inspired processes of natural selection, more specifically the process of selection (fitness), crossover and mutation. To understand more, let's walk through these processes in terms of biology:
6
6
7
7
### Selection
8
-
>**Selection**, in biology, the preferential survival and reproduction or preferential elimination of individuals with certain genotypes (genetic compositions), by means of natural or artificial controlling factors.[Britannica](britannica)
8
+
>**Selection**, in biology, the preferential survival and reproduction or preferential elimination of individuals with certain genotypes (genetic compositions), by means of natural or artificial controlling factors.
9
9
10
10
In other words, survival of the fittest. Organisms that survive in their environment tend to reproduce more. With GAs we generate a fitness model that will rank individuals and give them a better chance for reproduction.
11
11
@@ -60,35 +60,23 @@ extension String {
60
60
let OPTIMAL:[UInt8] ="Hello, World".unicodeArray
61
61
let DNA_SIZE = OPTIMAL.count
62
62
let POP_SIZE =50
63
-
letMAX_GENERATIONS=5000
63
+
letGENERATIONS=5000
64
64
let MUTATION_CHANCE =100
65
65
```
66
66
67
-
The last piece we need for set up is a function to give us a random unicode value from our lexicon:
68
-
69
-
```swift
70
-
funcrandomChar(fromlexicon: [UInt8]) ->UInt8 {
71
-
let len =UInt32(lexicon.count-1)
72
-
let rand =Int(arc4random_uniform(len))
73
-
return lexicon[rand]
74
-
}
75
-
```
76
-
77
-
**Note**: `arc4random_uniform` is strictly used in this example. It would be fun to play around with some of the [randomization in GameKit](https://developer.apple.com/library/content/documentation/General/Conceptual/GameplayKit_Guide/RandomSources.html)
78
-
79
67
### Population Zero
80
68
81
69
Before selecting, crossover and mutation, we need a population to start with. Now that we have the universe defined we can write that function:
let char = lexicon.randomElement()!// guaranteed to be non-nil by initial guard statement
92
80
dna.append(char)
93
81
}
94
82
pop.append(dna)
@@ -102,10 +90,11 @@ Before selecting, crossover and mutation, we need a population to start with. No
102
90
There are two parts to the selection process, the first is calculating the fitness, which will assign a rating to a individual. We do this by simply calculating how close the individual is to the optimal string using unicode values:
The above function takes a list of individuals with their calculated fitness. Then selects one at random offset by their fitness value. The horrible 1,000,000 multiplication and division is to insure precision by calculating decimals. `arc4random` only uses integers so this is required to convert to a precise Double, it's not perfect, but enough for our example.
127
+
128
+
The above function takes a list of individuals with their calculated fitness. Then selects one at random offset by their fitness value. The horrible 1,000,000 multiplication and division is to insure precision by calculating decimals. `Double.random` only uses integers so this is required to convert to a precise Double, it's not perfect, but enough for our example.
142
129
143
130
## Mutation
144
131
145
132
The all powerful mutation, the thing that introduces otherwise non existent fitness variance. It can either hurt of improve a individuals fitness but over time it will cause evolution towards more fit populations. Imagine if our initial random population was missing the charachter `H`, in that case we need to rely on mutation to introduce that character into the population in order to achieve the optimal solution.
let rand =Int(arc4random_uniform(UInt32(mutationChance)))
138
+
let rand =Int.random(in: 0..<mutationChance)
153
139
if rand ==1 {
154
-
outputDna[i] =randomChar(from: lexicon)
140
+
outputDna[i] = lexicon.randomElement()!
155
141
}
156
142
}
157
-
143
+
158
144
return outputDna
159
145
}
160
146
```
@@ -168,12 +154,12 @@ This allows for a population to explore all the possibilities of it's building b
168
154
Crossover, the sexy part of a GA, is how offspring are created from 2 selected individuals in the current population. This is done by splitting the parents into 2 parts, then combining 1 part from each parent to create the offspring. To promote diversity, we randomly select a index to split the parents.
0 commit comments