diff --git a/cfg/parity.yaml b/cfg/parity.yaml new file mode 100644 index 0000000..b7f92fa --- /dev/null +++ b/cfg/parity.yaml @@ -0,0 +1,21 @@ +# Cambrian.jl settings +seed: 0 +d_fitness: 1 +n_population: 5 +n_elite: 1 +n_gen: 3000 +log_gen: 10 +save_gen: 10 +m_rate: 0.1 +# CartesianGeneticProgramming.jl settings +rows: 2 +columns: 16 +recur: 0.0 +n_in: 8 +n_out: 1 +out_m_rate: 0.3 +functions: + - f_and + - f_or + - f_xor + - f_not diff --git a/graphing/graph_utils.jl b/graphing/graph_utils.jl index ed85328..7fc4ebb 100644 --- a/graphing/graph_utils.jl +++ b/graphing/graph_utils.jl @@ -1,10 +1,11 @@ -using CGP +using CartesianGeneticProgramming using LightGraphs using MetaGraphs using TikzGraphs using TikzPictures using LaTeXStrings -using Base.Test +using Printf +#using Base.Test function to_graph(c::Chromosome; active_outputs=trues(c.nout)) actives = [n.active for n in c.nodes] diff --git a/graphing/to_dot.jl b/graphing/to_dot.jl new file mode 100644 index 0000000..c4c1563 --- /dev/null +++ b/graphing/to_dot.jl @@ -0,0 +1,29 @@ +function walk_nodes(ind::CGPInd) + dot_strs = [] + push!(dot_strs, "digraph cgpgraph {\n") + function visit(node_num, current_nd) + if current_nd.active + fname = String(Symbol(current_nd.f)) + visit(current_nd.x, ind.nodes[current_nd.x]) + if(CGPFunctions.arity[fname] > 1) + visit(current_nd.y, ind.nodes[current_nd.y]) + + end + @show (node_num, current_nd) + + xdotline = "N$(current_nd.x)-> N$node_num ;" + push!(dot_strs, "N$node_num [label=\"$fname:$node_num\"];") + push!(dot_strs, xdotline) + if(CGPFunctions.arity[fname] > 1) + ydotline = "N$(current_nd.y)-> N$node_num ;" + push!(dot_strs, ydotline) + end + end + end + for current_node_num in ind.outputs + current_node = ind.nodes[current_node_num] + visit(current_node_num, current_node) + end + push!(dot_strs, "}") + dot_strs +end diff --git a/scripts/parity.jl b/scripts/parity.jl new file mode 100644 index 0000000..aaf7c87 --- /dev/null +++ b/scripts/parity.jl @@ -0,0 +1,78 @@ +using CartesianGeneticProgramming +using Cambrian +import Cambrian.mutate +using StatsBase +using Base.Iterators: repeated +include("../graphing/to_dot.jl") +""" +A simple example for calculating parity +""" + + #bitArray parity + parity(x) = isodd(sum(x)) + + function create_testcases(sz) + train_cases = [] + for i in 0:(2^sz-1) + bin = digits(i, base=2, pad=sz) + push!(train_cases, (bin, parity(bin))) + @show (bin, parity(bin)) + end + return train_cases + end + + NUMCLASSES = 10 + WIDTH = 8 #60 + + train = create_testcases(WIDTH) + trainX = [ x[1] for x in train ] + trainX = hcat(trainX...) + trainY = [ x[2] for x in train ] + + +X, Y = trainX, trainY + +function evaluate(ind::CGPInd, X::AbstractArray, Y::AbstractArray) + accuracy = 0.0 + for i in 1:size(X, 2) + out = process(ind, float(X[:, i])) + if out[1] == Int(Y[i]) + accuracy += 1 + end + end + [accuracy / size(X, 1)] +end + +function error_count(e, X::AbstractArray, Y::AbstractArray) + failed = 0 + for i in 1:size(X,2) + y_hat = process(e.population[5], float(X[:,i])) + if y_hat[1] != Int(Y[i]) + failed += 1 + end + end + failed +end + +cfg = get_config("cfg/parity.yaml") +fit(i::CGPInd) = evaluate(i, X, Y) +mutate(i::CGPInd) = goldman_mutate(cfg, i) +e = CGPEvolution(cfg, fit) +println("run!") +run!(e) + +@show e.population[end].nodes +errors = error_count(e,X,Y ) +println("$errors errors out of $(size(X,2)) entries") + +#generate dot file +dot_array = walk_nodes(e.population[5]) +dot_file = "parity_graph.dot" +open(dot_file, "w") do f + for i in dot_array + println(f, i) + end +end +# to view from commandline: +# $ dot -Tpng parity_graph.dot -o parity_graph.png +# $ display parity_graph.png \ No newline at end of file