ChrisTimperley / Wallace.jl

High-performance evolutionary computation in Julia.
http://christimperley.co.uk/Wallace.jl/
MIT License
21 stars 12 forks source link

Example for using grammatical evolution #23

Open rcnlee opened 8 years ago

rcnlee commented 8 years ago

Hello, I can't seem to find an example in the docs showing how to use Wallace for grammatical evolution. For example, how do you specify the grammar (And rules, Or rules, etc.) Does it produce an Expr at the end? Thanks!

ChrisTimperley commented 8 years ago

Hi,

I've been going through, re-doing the documentation over the last week or so, so I haven't quite had time to cover GE yet, but I shall get onto that next.

Grammars can be specified as a string, which is interpreted as a BNF and parsed accordingly. I don't think it's as pretty as Abe Schneider's code at the moment, but I'll see what I can do to improve that (https://github.com/abeschneider/GrammaticalEvolution).

Wallace produces an Expr along the way, but leaves the user with an anonymous function.

I've done a lot of work on optimising the performance of tree-based GP, not so quite so much on GE, so I'll have a look into that next.

I think the interesting differences in Wallace are:

If you have any thoughts or ideas, I would love to hear them.

Thanks,

Chris

ChrisTimperley commented 8 years ago

Okay dokay, I've nearly finished re-implementing GE, adding support for some of the nicer EBNF rules (AND, OR, ?, +, *). Like Abe's code, the new version operates directly on Expr objects, rather than deriving strings and later parsing them (which takes up a lot of the evaluation time).

There are a few other tricks in there which speed things up, and also, you can write actual Julia code, without having to specify Expr objects directly, which makes evolving more complex code much easier.

Expr(:call, :+, Expr(:call, :*, number, 3), 10)

becomes...

<number> * 3 + 10

Annoyingly, Julia doesn't perform any of its excellent type-specific optimisations on dynamically evaluated lambda functions, and so the functions that result from an @eval call are significantly slower than their static counterparts. Apparently support for optimised lambda functions is on the way, but in the mean time, Tim Holy has a faster (but rather limited) way of implementing anonymous functions, which I need to get round to extending: https://github.com/timholy/FastAnonymous.jl.

What kind of thing are you thinking of evolving with this, if you don't mind me asking?

rcnlee commented 8 years ago

Wow, thanks for the quick response (and moving the code forward so quickly)! I'm interested in using GE to evolve temporal rules for time-series machine learning. Actually, I am currently using Abe's GrammaticalEvolution.jl package, and it is definitely quite nice! The reason I found Wallace is because of an issue I encountered when I tried to scale it up. I filed this issue with the package. It turns out though, that the issue has nothing to do with the package as I was able to construct an MWE without using the package at all. I eventually filed an issue with JuliaLang here and found that if you @eval expressions with hardcoded constants (e.g., floats like 0.12345) too many times, it'll start to yield corrupted results. Unfortunately I expect this to affect Wallace.jl as well as you are repeatedly @eval'ing expressions.