Skip to content
Permalink
Newer
Older
100644 177 lines (155 sloc) 6.05 KB
Stephen
Feb 6, 2018
1
using StatsBase
Stephen
Feb 6, 2018
2
#=
3
Parents <— {randomly generated population}
4
While not (termination criterion)
5
Calculate the fitness of each parent in the population
6
Children <- 0
7
While | Children | < | Parents |
8
Use fitnesses to probabilistically select a pair of parents for mating
9
Mate the parents to create children c\ and c<i
10
Children <— Children U {ci,C2}
11
Loop
12
Randomly mutate some of the children
13
Parents <— Children
14
Next generation
15
16
Use continuous GA, not binary
17
18
include array of independent variables along with associated range
19
20
=#
21
22
function initialize_population(populationSize::Int, chromosomeSize::Int, bounds::Array{Tuple{Float64, Float64},1})
23
"""
Stephen
Feb 6, 2018
24
Initializes the population based on the given population size and chromosome size
Stephen
Feb 6, 2018
25
Values will be from lb to ub (lower to upper bound)
26
"""
27
28
# Check to see if we dont have enough bounds or have too many
29
if length(bounds) != chromosomeSize
30
println("Length of bounds ($(length(bounds))) not equal to specified chromosome size ($chromosomeSize)")
31
exit()
32
end
33
34
# Init population
Stephen
Feb 6, 2018
35
population = Array{Array{Float64}}(0)
Stephen
Feb 6, 2018
36
37
# Foreach member in population
38
for i = 1:populationSize
39
# Init the member
40
row = []
41
# Create member elements based on bounds
42
for bound in bounds
43
push!(row, rand(bound[1]:0.10:bound[2]))
44
end
45
# Add another element to the end to keep score
46
push!(row, 1.0)
47
48
# hcat row, append to 2D population matrix
Stephen
Feb 6, 2018
49
population = push!(population, row)
Stephen
Feb 6, 2018
50
end
51
return population
52
53
end
54
Stephen
Feb 6, 2018
55
function score_sort_population(population::Array{Array{Float64}}, fitness_function::Function)
Stephen
Feb 6, 2018
56
"""
57
Args
58
population: The population to score. Must be 2D array of Float64 elements
59
fitness_function: Function to score the population
60
Must be able to take array as argument
61
For example f(x,y) should be f(A) where A[1]=x, A[2]=y
62
Returns scored population. Score is the last element of each chromosome (row)
63
in population
64
"""
Stephen
Feb 6, 2018
65
# Enumerate through population, set last element of each chromosome to score
66
for (index,member) in enumerate(population)
67
population[index][end] = fitness_function(member)
Stephen
Feb 6, 2018
68
end
Stephen
Feb 6, 2018
69
sort!(population, by = x -> x[end])
70
return population
71
end
72
73
function create_next_generation(population::Array{Array{Float64}}, recombRate::Float64)
74
"""
75
Creates children given a population and recombination rate
76
Uses an elite selection of 0.10 (rounded up)
77
Creates random chance
78
TODO: Implement ranking
79
"""
80
81
popSize = length(population)
82
memberSize = length(population[1])
83
# Init children array
84
children = Array{Array{Float64}}(0)
85
# Elite selection
86
for i in 1:Int(ceil(popSize*0.10))
87
push!(children, population[i])
88
end
89
90
# Generate rest of population
91
while length(children) < popSize
92
# Two random children
93
choices = sample(1:popSize, 2, replace=false)
94
# Check for crossover
95
if rand() < recombRate
96
# Choose xover point
97
# Use -2 since last one is score, and last actual element cant be crossedover since that means there is none
98
xover = rand(1:memberSize-2)
99
child1 = cat(1,population[choices[1]][1:xover],population[choices[2]][xover+1:end])
100
child2 = cat(1,population[choices[2]][1:xover],population[choices[1]][xover+1:end])
101
else
102
# Else no crossover, just copy
103
child1 = population[choices[1]]
104
child2 = population[choices[2]]
105
end
106
# Push child 1 and 2 to children array
107
push!(children, child1, child2)
108
end
109
110
# We might have one extra due to rounding in the elite selection, let's check
111
if length(children) != popSize
112
pop!(children)
113
end
114
return children
115
end
116
117
function mutate(population::Array{Array{Float64}}, mutateRate::Float64, bounds::Array{Tuple{Float64, Float64},1})
118
"""
119
Iterates through each chromosome and mutates if needed
120
"""
121
122
for member in population
123
for i = 1:length(member)-1
124
if rand() < mutateRate
125
member[i] = rand(bounds[i][1]:0.10:bounds[i][2])
126
end
127
end
128
end
129
Stephen
Feb 6, 2018
130
return population
131
end
132
133
function GA(populationSize::Int, chromosomeSize::Int, fitness_function::Function, bounds::Array{Tuple{Float64, Float64},1})
134
"""
135
Args
136
populationSize: Total number of chromosomes
137
chromosomeSize: How long each chromosome should be (variables in fitness function)
138
fitness_function: Function to determine fitness of each solution
139
Should take an array as an arg
140
Example: f(x,y,z) = x+y+z
141
should be f(X) = X[1]+X[2]+X[3]
142
in order to allow GA to take in any function with any
143
amount of args to the fitness function
144
bounds: 1D array of tuples, each tuple is the (lower, upper) bounds
145
for each variable. Both lower and upper need to be Float64 types
146
Length should match chromosomeSize
147
e.g: [(1.0,2.0), (3.5,4.5)]
148
"""
149
150
# Set recombination and mutation rate, lower and upper bound
151
recombRate = 0.7
152
mutateRate = 0.05
Stephen
Feb 6, 2018
153
maxIterations = 1000
Stephen
Feb 6, 2018
154
# First initialize the population
155
population = initialize_population(populationSize, chromosomeSize, bounds)
Stephen
Feb 6, 2018
156
157
# Then loop for the required iterations
158
bestScores = Array{Float64}(0)
Stephen
Feb 6, 2018
159
i = 0
160
while i < maxIterations
Stephen
Feb 6, 2018
161
# Score and sort the population
162
population = score_sort_population(population, fitness_function)
163
push!(bestScores,population[1][end])
164
population = create_next_generation(population, recombRate)
165
population = mutate(population, mutateRate, bounds)
Stephen
Feb 6, 2018
166
i += 1
167
end
Stephen
Feb 6, 2018
168
println(bestScores)
169
println(population)
Stephen
Feb 6, 2018
170
end
171
172
function ackley(X)
Stephen
Feb 6, 2018
173
return e - 20*exp(-0.2*sqrt((X[1]^2 + X[2]^2)/2)) - exp((cos(2*pi*X[1]) + cos(2*pi*X[2]))/2)
Stephen
Feb 6, 2018
174
end
Stephen
Feb 6, 2018
175
Stephen
Feb 6, 2018
176
bounds = [(-2.0,2.0), (-2.0,2.0)]
177
GA(25,2,ackley,bounds)
You can’t perform that action at this time.