Evolutionary TreeGP distribution version falls over

Hi folks - I am just learning Julia as I want to use TreeGP in Evolutionary. The code at SymbolicRegression.ipynb works fine right up to this bit ==>

res = Evolutionary.optimize(fitobj,
TreeGP(50, Terminal[syms…], funcs,
optimizer = GA(
selection = uniformranking(5),
ɛ = 0.1,
mutationRate = 0.95,
crossoverRate = 0.05,

which it pukes up as below. I don’t understand. How does this not work? - it’s the basic example code. It tells me “optimizer” is not an argument. Thanks for any help.

here’s the errors ==>

MethodError: no method matching TreeGP(; populationSize=50, terminals=Dict(:x => 1), functions=Dict{Function, Int64}((-) => 2, (/) => 2, (*) => 2, (+) => 2), mindepth=1, maxdepth=4, optimizer=GA[P=50,x=0.05,μ=0.95,ɛ=0.1])
Closest candidates are:
TreeGP(; populationSize, terminals, functions, mindepth, maxdepth, crossover, mutation, selection, crossoverRate, mutationRate, initialization, simplify, metrics) at util.jl:453 got unsupported keyword argument “optimizer”
TreeGP(::Integer, ::Vector{Union{Function, Real, Symbol}}, ::Vector{Function}; kwargs…) at /Users/sabel/.julia/packages/Evolutionary/65hL6/src/gp.jl:40
TreeGP(::Integer, ::Dict{Union{Function, Real, Symbol}, Int64}, ::Dict{Function, Int64}, ::Int64, ::Int64, ::Function, ::Function, ::Function, ::Real, ::Real, ::Symbol, ::Union{Nothing, Function}, ::Vector{ConvergenceMetric}) at /Users/sabel/.julia/packages/Evolutionary/65hL6/src/gp.jl:26 got unsupported keyword arguments “populationSize”, “terminals”, “functions”, “mindepth”, “maxdepth”, “optimizer”

[1] kwerr(kw::NamedTuple{(:populationSize, :terminals, :functions, :mindepth, :maxdepth, :optimizer), Tuple{Int64, Dict{Symbol, Int64}, Dict{Function, Int64}, Int64, Int64, GA{Evolutionary.var"#uniformrank#246"{Evolutionary.var"#uniformrank#245#247"{Int64}}, typeof(Evolutionary.genop), typeof(Evolutionary.genop)}}}, args::Type)
@ Base ./error.jl:157
[2] TreeGP(pop::Int64, term::Vector{Union{Function, Real, Symbol}}, func::Vector{Function}; kwargs::Base.Iterators.Pairs{Symbol, Any, Tuple{Symbol, Symbol, Symbol}, NamedTuple{(:mindepth, :maxdepth, :optimizer), Tuple{Int64, Int64, GA{Evolutionary.var"#uniformrank#246"{Evolutionary.var"#uniformrank#245#247"{Int64}}, typeof(Evolutionary.genop), typeof(Evolutionary.genop)}}}})
@ Evolutionary ~/.julia/packages/Evolutionary/65hL6/src/gp.jl:43
[3] top-level scope
@ In[15]:2
[4] eval
@ ./boot.jl:360 [inlined]
[5] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
@ Base ./loading.jl:1116

The example is outdated, TreeGP constructor has different parameters now. There is no optimizer parameter anymore. Mutation operators are specified as TreeGP parameters, see here.

You should run

julia> res = Evolutionary.optimize(fitobj,
           TreeGP(25, Terminal[syms...], funcs,
               selection = tournament(3),
               mutationRate = 0.5,
               crossoverRate = 0.05

 * Status: success

 * Candidate solution
    Minimizer:  (+)(x, (+)((*)(x, x), x))
    Minimum:    0.27305007890318983
    Iterations: 117

 * Found with
    Algorithm: TreeGP[P=25,Parameter[x],Function[-, *, /, +]]

 * Convergence measures
    |f(x) - f(x')| = 0.0 ≤ 1.0e-5

 * Work counters
    Seconds run:   0.5655 (vs limit Inf)
    Iterations:    117
    f(x) calls:    2950

Fantastic - thanks so much that worked perfectly. I am inspired to use this.!

Hi again - hmmm, it runs but doesn’t work. It never finds for example xxx+x but declares an early success with a function x (I pasted the output below). I have not yet got it to output x^3+x even if I increase maximum tree depth.

I am using Julia 1.6.5 - I assume this is OK? If so, is there code for your result so I can see if I am doing something wrong. Or a repository of other examples would be great!

By the way I defined data in like this …
d, n = 1, 20
Nguyen1(x) = xxx + x
xs = sort!(2*rand(n).-1)


here’s my output ==>

  • Status: success

  • Candidate solution
    Minimizer: (-)(x, (*)((-)(x, x), (/)(x, x)))
    Minimum: 0.41449217882225364
    Iterations: 700

  • Found with
    Algorithm: TreeGP[P=25,Parameter,Function[-, /, *, +]]

  • Convergence measures
    |f(x) - f(x’)| = 0.0 ≤ 1.0e-5

  • Work counters
    Seconds run: 1.83 (vs limit Inf)
    Iterations: 700
    f(x) calls: 17525

You need to play around with mutation operations rates. Usually, for GP, you would use a high crossover rate and a low mutation rate with a relatively sized random population. If the solution is still subpar, and optimization terminates earlier, try to increase mutation rate.

There is one caveat, the default (and only) crossover operation constantly increases depth of the expression tree (the tree depth parameter is not applied). You might want to use simplify parameter to counteract unchecked growth, but no guaranties. The better crossovers are needed.