diff --git a/BestFitness.png b/BestFitness.png new file mode 100644 index 0000000..01c4aa3 Binary files /dev/null and b/BestFitness.png differ diff --git a/GA.jl b/GA.jl index dacc1f4..ff151fb 100644 --- a/GA.jl +++ b/GA.jl @@ -1,4 +1,5 @@ using StatsBase +using PyPlot #= Parents <— {randomly generated population} While not (termination criterion) @@ -40,7 +41,7 @@ function initialize_population(populationSize::Int, chromosomeSize::Int, bounds: row = [] # Create member elements based on bounds for bound in bounds - push!(row, rand(bound[1]:0.10:bound[2])) + push!(row, rand(bound[1]:0.01:bound[2])) end # Add another element to the end to keep score push!(row, 1.0) @@ -122,7 +123,7 @@ function mutate(population::Array{Array{Float64}}, mutateRate::Float64, bounds:: for member in population for i = 1:length(member)-1 if rand() < mutateRate - member[i] = rand(bounds[i][1]:0.10:bounds[i][2]) + member[i] = rand(bounds[i][1]:0.01:bounds[i][2]) end end end @@ -150,28 +151,103 @@ 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 = 1000 + maxIterations = 100 + runs = 20 # First initialize the population - population = initialize_population(populationSize, chromosomeSize, bounds) # Then loop for the required iterations - bestScores = Array{Float64}(0) + # Initialize iteration counter, run counter, and array to hold generations of best population i = 0 - while i < maxIterations - # 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 + run = 0 + bestGenerations = [[[0.0,0.0,Inf]]] + generations = Array{Array{Array{Float64}}}(0) + + # For each run + while run < runs + nextPopulation = initialize_population(populationSize, chromosomeSize, bounds) + # Iterate through max amount of generations + while i < maxIterations + # Score and sort the population + population = score_sort_population(nextPopulation, fitness_function) + # Push current population to generations array + push!(generations, deepcopy(population)) + # Create children + nextPopulation = create_next_generation(population, recombRate) + # Mutate children + nextPopulation = mutate(nextPopulation, mutateRate, bounds) + i += 1 + end + #= + At the end of the run, if the last generations best solution + # is better than that of the best of all runs so far + set new best run so we can graph later + =# + if generations[end][1][end] < bestGenerations[end][1][end] + bestGenerations = deepcopy(generations) + end + clear!(:generations) + clear!(:population) + clear!(:children) + run += 1 + end + + # Reporting and plotting + # Report best solution and value + bestVariables = bestGenerations[end][1][1:end-1] + bestScore = bestGenerations[end][1][end] + println("Best solution\nVariables: $bestVariables\nScore: $bestScore") + + # Generate best fitness vs. # generation + # Init score array + y = Array{Float64}(0) + # Get scores, push to array + for g in bestGenerations + push!(y,g[1][end]) + end + # Plot and label + PyPlot.plot(y) + xlabel("Generation #") + ylabel("Fitness") + # Save and close + PyPlot.savefig("BestFitness.png") + PyPlot.close() + + # Contour + # Check to make sure we only have two variables, otherwise exit + if length(bestGenerations[1][1]) > 3 + println("Plotting the 4th dimension currently disabled to avoid tearing the space-time continuum") + quit() end - println(bestScores) - println(population) + + # Init x and y z for contour plots + x = y = z = Array{Float64}(0) + for (index, gen) in enumerate(bestGenerations) + if (index == 1) || (mod(index,10) == 0) + for m in gen + push!(x,m[1]) + push!(y,m[2]) + end + size = length(x) + z = rand(size,size) + for i in 1:size + for j in 1:size + z[i,j] = fitness_function([x[i],y[j]]) + end + end + contour(x,y,z) + savefig("contour_gen$index.png") + close() + clear!(:x) + clear!(:y) + clear!(:z) + end + end + end -function ackley(X) +function fitness_function(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) end bounds = [(-2.0,2.0), (-2.0,2.0)] -GA(25,2,ackley,bounds) +GA(25,2,fitness_function,bounds) diff --git a/contour_gen1.png b/contour_gen1.png new file mode 100644 index 0000000..c4b7b2f Binary files /dev/null and b/contour_gen1.png differ diff --git a/contour_gen10.png b/contour_gen10.png new file mode 100644 index 0000000..5770b31 Binary files /dev/null and b/contour_gen10.png differ diff --git a/contour_gen100.png b/contour_gen100.png new file mode 100644 index 0000000..c3181e5 Binary files /dev/null and b/contour_gen100.png differ diff --git a/contour_gen20.png b/contour_gen20.png new file mode 100644 index 0000000..181a04a Binary files /dev/null and b/contour_gen20.png differ diff --git a/contour_gen30.png b/contour_gen30.png new file mode 100644 index 0000000..f43d2fe Binary files /dev/null and b/contour_gen30.png differ diff --git a/contour_gen40.png b/contour_gen40.png new file mode 100644 index 0000000..23e7a10 Binary files /dev/null and b/contour_gen40.png differ diff --git a/contour_gen50.png b/contour_gen50.png new file mode 100644 index 0000000..e484f9e Binary files /dev/null and b/contour_gen50.png differ diff --git a/contour_gen60.png b/contour_gen60.png new file mode 100644 index 0000000..4432866 Binary files /dev/null and b/contour_gen60.png differ diff --git a/contour_gen70.png b/contour_gen70.png new file mode 100644 index 0000000..fbc3441 Binary files /dev/null and b/contour_gen70.png differ diff --git a/contour_gen80.png b/contour_gen80.png new file mode 100644 index 0000000..8b375df Binary files /dev/null and b/contour_gen80.png differ diff --git a/contour_gen90.png b/contour_gen90.png new file mode 100644 index 0000000..b9bfbbb Binary files /dev/null and b/contour_gen90.png differ