Stefan van der Meer <stefanvanderm...@gmail.com> writes:
> On Aug 21, 12:05 pm, Jan Rychter <j...@rychter.com> wrote:
>> think crossover in genetic programming (this is actually what I need
>> this for).
> I've written a genetic programming framework in Clojure, it might
> be of interest if you're looking for some inspiration:
> http://bitbucket.org/svdm/clojuregp/src/

I didn't know about this -- thanks, I will definitely check it out.

> Though I experimented with using zippers initially, I ended up
> not using them for the fundamental tree operations like the one
> discussed here. I found zippers to be quite a bit slower than
> more low level approaches for traversing trees, which becomes
> significant in typical GP experiments where things like subtree
> replacement are used a large number of times.

Interesting. I don't see why zippers would be much slower than other
approaches, unless manipulating metadata in Clojure is excessively slow.

In my case, I don't much care, because my program spends most of the time
in fitness evaluations. Actual code manipulation takes only a small
percentage of the time and isn't worth worrying about (so far).

[...]
> So that's one way of doing it. Not the prettiest, but it does
> what I need it to. I'm not sure it does exactly what you want
> though, because:
> user> (tree-replace 3 '(7 8 (9 10)) '(1 2 (3 4 5) 6))
> (1 2 (3 (7 8 (9 10)) 5) 6)
>
> Compared to:
>> should produce => '(1 2 (3 7 8 (9 10) 6))
>
> I'm kind of wondering why you want the replacement subtree (tree2
> if you will) to be spliced "flat" into the original tree like
> that. It seems to me that such an operation would not actually do
> a subtree replacement in the typical genetic programming sense.

Flat splicing-in makes sense, because my GP is a stack-based one (a
concatenative language, inspired by PushGP and Forth). Programs are
really flat sequences of instructions and constants. Trees arise only
because I want the language to have loops and function/code generation
facilities. A subtree is a piece of code that gets pushed onto the code
stack, to be executed later.

For simple tasks, flat sequences of instructions would be enough and
indeed this is the primary mechanism.

Here are three examples that hopefully illustrate the concept:

(1 2 int+) => 3
(2 (1 int+) exec) => 3
(2 (1 int+) 3 dotimes) => 5

As you can see, I really do want the crossover operator to splice code
flat into the original tree. Adding a subtree has an entirely different
meaning.

You might want to look at stack-based GP. I think it is much more
flexible than code trees.

--J.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to