Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Finished basic GA
  • Loading branch information
Stephen committed Feb 6, 2018
1 parent 19d3157 commit 1bb94ac
Showing 1 changed file with 82 additions and 20 deletions.
102 changes: 82 additions & 20 deletions GA.jl
@@ -1,3 +1,4 @@
using StatsBase
#=
Parents <— {randomly generated population}
While not (termination criterion)
Expand All @@ -20,7 +21,7 @@ include array of independent variables along with associated range

function initialize_population(populationSize::Int, chromosomeSize::Int, bounds::Array{Tuple{Float64, Float64},1})
"""
Initializes the population based on the given population and chromosome size
Initializes the population based on the given population size and chromosome size
Values will be from lb to ub (lower to upper bound)
"""

Expand All @@ -31,7 +32,7 @@ function initialize_population(populationSize::Int, chromosomeSize::Int, bounds:
end

# Init population
population = Array{Float64}(0,chromosomeSize+1)
population = Array{Array{Float64}}(0)

# Foreach member in population
for i = 1:populationSize
Expand All @@ -45,14 +46,13 @@ function initialize_population(populationSize::Int, chromosomeSize::Int, bounds:
push!(row, 1.0)

# hcat row, append to 2D population matrix
population = cat(1, population, hcat(row...))
population = push!(population, row)
end

return population

end

function score_population(population::Array{Float64}, fitness_function::Function, populationSize::Int, chromosomeSize::Int)
function score_sort_population(population::Array{Array{Float64}}, fitness_function::Function)
"""
Args
population: The population to score. Must be 2D array of Float64 elements
Expand All @@ -62,17 +62,71 @@ function score_population(population::Array{Float64}, fitness_function::Function
Returns scored population. Score is the last element of each chromosome (row)
in population
"""
#= 1-3, 4-6, 7-9, 10-12
1 2 3 4
=#
population = population'
for i in 0:populationSize-1
println(i)
member = population[(chromosomeSize+1)*i+1:(chromosomeSize+1)*(i+1)]
println(member)
population[(chromosomeSize+1)*(i+1)] = fitness_function(member)
# Enumerate through population, set last element of each chromosome to score
for (index,member) in enumerate(population)
population[index][end] = fitness_function(member)
end
println(population)
sort!(population, by = x -> x[end])
return population
end

function create_next_generation(population::Array{Array{Float64}}, recombRate::Float64)
"""
Creates children given a population and recombination rate
Uses an elite selection of 0.10 (rounded up)
Creates random chance
TODO: Implement ranking
"""

popSize = length(population)
memberSize = length(population[1])
# Init children array
children = Array{Array{Float64}}(0)
# Elite selection
for i in 1:Int(ceil(popSize*0.10))
push!(children, population[i])
end

# Generate rest of population
while length(children) < popSize
# Two random children
choices = sample(1:popSize, 2, replace=false)
# Check for crossover
if rand() < recombRate
# Choose xover point
# Use -2 since last one is score, and last actual element cant be crossedover since that means there is none
xover = rand(1:memberSize-2)
child1 = cat(1,population[choices[1]][1:xover],population[choices[2]][xover+1:end])
child2 = cat(1,population[choices[2]][1:xover],population[choices[1]][xover+1:end])
else
# Else no crossover, just copy
child1 = population[choices[1]]
child2 = population[choices[2]]
end
# Push child 1 and 2 to children array
push!(children, child1, child2)
end

# We might have one extra due to rounding in the elite selection, let's check
if length(children) != popSize
pop!(children)
end
return children
end

function mutate(population::Array{Array{Float64}}, mutateRate::Float64, bounds::Array{Tuple{Float64, Float64},1})
"""
Iterates through each chromosome and mutates if needed
"""

for member in population
for i = 1:length(member)-1
if rand() < mutateRate
member[i] = rand(bounds[i][1]:0.10:bounds[i][2])
end
end
end

return population
end

Expand All @@ -96,20 +150,28 @@ function GA(populationSize::Int, chromosomeSize::Int, fitness_function::Function
# Set recombination and mutation rate, lower and upper bound
recombRate = 0.7
mutateRate = 0.05
maxIterations = 1
maxIterations = 1000
# First initialize the population
population = initialize_population(populationSize, chromosomeSize, bounds)

# Then loop for the required iterations
bestScores = Array{Float64}(0)
i = 0
while i < maxIterations
scoredPopulation = score_population(population, fitness_function, populationSize, chromosomeSize)

# Score and sort the population
population = score_sort_population(population, fitness_function)
push!(bestScores,population[1][end])
population = create_next_generation(population, recombRate)
population = mutate(population, mutateRate, bounds)
i += 1

end
println(bestScores)
println(population)
end

function ackley(X)
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))
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)
end

bounds = [(-2.0,2.0), (-2.0,2.0)]
GA(25,2,ackley,bounds)

0 comments on commit 1bb94ac

Please sign in to comment.