diff --git a/gp.jl b/gp.jl index 34f5339..92c0a15 100644 --- a/gp.jl +++ b/gp.jl @@ -1,3 +1,5 @@ +using StatsBase + function GT(a,b) """ GT function to be used in AST @@ -71,6 +73,43 @@ function create_grow_tree(depth, fs, ts) end end +function tournament(scores, size) + """ + Does tournament selection for parents of next population + Inputs + scores Ordered dict of solution number and score + size Size of tournament population + Output + parent1 First parent to copy or crossover + parent2 Second parent to copy or crossover + """ + println(length(scores)) + choices = sample(1:length(scores), size, replace=false) + p = [] + for c in choices + push!(p, scores[c][2]) + end + p = p / sum(p) + + return sample(choices, WeightVec(p), 2, replace=false) + +end + +function crossover(parent1, parent2, max_depth) + """ + Crossover to generate next children + Inputs + parent1 Expression for parent1 + parent2 Expression for parent2 + max_depth Maximum depth of tree allowed + Output + child1 Child #1 of crossover + child2 Child #2 of crossover + """ + println(dump(parent1)) + + +end #= @@ -97,24 +136,24 @@ Selection: Tournament # around creating expressions and not being able to plug # x and v into them for the past week # Init everything -pop_size = 500 +pop_size = 10 max_iterations = 1 max_initial_depth = 6 max_depth = 17 xover_prob = 0.9 fs = [:+, :-, :DIV, :GT] ts = [:x,:v,-1] +tournament_size = 5 points = [rand(-0.75:0.05:.75,2) for i in 1:20] -println(points) elites = 2 tau = 0.02 max_time = 5 # Create initial population -pop0 = [] +population = [] for i in 1:pop_size/2 - push!(pop0, create_full_tree(max_initial_depth, fs, ts)) - push!(pop0, create_grow_tree(max_initial_depth, fs, ts)) + push!(population, create_full_tree(max_initial_depth, fs, ts)) + push!(population, create_grow_tree(max_initial_depth, fs, ts)) end # Init iterations, scores @@ -122,7 +161,7 @@ iteration = 0 scores = Dict(string(i) => Float64(i) for i in 1:pop_size) while iteration < max_iterations # For each member in the population - for (index, member) in enumerate(pop0) + for (index, member) in enumerate(population) # For each x,v pair times = [] for point in points @@ -130,12 +169,14 @@ while iteration < max_iterations x = point[1] v = point[2] t = 0 + # Evaluate solution while we arent at max time or x,v~=0 while (t <= max_time) && (abs(x) > 0.01 && abs(v) > 0.01) if eval(member) >=0 u = 1 else u = 0 end + # Update x,v,t values vk = v + tau*u xk = x + tau*(v+vk)/2 v = vk @@ -146,8 +187,32 @@ while iteration < max_iterations end scores[string(index)] = mean(times) end + # return list of sorted scores sorted_scores = sort(collect(scores), by=x->x[2]) - println(sorted_scores) + # Init next generation + next_population = [] + # copy number of elites to next gen + for i in 1:elites + push!(next_population, population[Int(parse(Float64,sorted_scores[i][1]))]) + end + println(next_population) + # Crossover + while length(next_population) < pop_size + # Choose parents with tournament selection + parents = tournament(sorted_scores, tournament_size) + parent1 = population[Int(parse(Float64,sorted_scores[parents[1]][1]))] + parent2 = population[Int(parse(Float64,sorted_scores[parents[2]][1]))] + println(parent1) + # See if we should crossover, if not copy + if rand() < xover_prob + child1,child2 = crossover(parent1, parent2, max_depth) + else + child1=parent1 + child2=parent2 + end + + + end iteration += 1 end diff --git a/test.jl b/test.jl index c4b025a..9d90c82 100644 --- a/test.jl +++ b/test.jl @@ -1,31 +1,18 @@ -function create_full_tree(depth, fs, ts) - """ - Creates a single AST with full depth - Inputs - depth Current depth of tree. Initially called from main() with max depth - fs Function Set - Array of allowed functions - ts Terminal Set - Array of allowed terminal values - Output - Full AST of typeof()==Expr - """ +function create_expression() + return Expr(:call, :*, :x, :y) +end - # If we are at the bottom - if depth == 1 - # End of tree, return function with two terminal nodes - return Expr(:call, fs[rand(1:length(fs))], ts[rand(1:length(ts))], ts[rand(1:length(ts))]) - else - # Not end of expression, recurively go back through and create functions for each new node - return Expr(:call, fs[rand(1:length(fs))], create_full_tree(depth-1, fs, ts), create_full_tree(depth-1, fs, ts)) - end +function create_function(expr) + return eval(Expr(:->,:(x,y), Expr(:block, expr))) end function main() - fs = [:+, :-, :DIV, :GT] - ts = [:x,:v,-1] - - expr = create_full_tree(6, fs, ts) - println(expr.args[2].args) + tst = create_expression() + f = create_function(tst) + x = 5 + y = 6 + println(f(x,y)) end main()