Skip to content

Commit

Permalink
Exchanging the actual subtrees (crossover.subtree)
Browse files Browse the repository at this point in the history
# The problem
crossover.subtree.do_crossover looked for the exchanging subtrees by means of method index (lines 279, 293, 307, and 308). However, the instruction pX.children.index(tX) returned the index of the subtree with the same content (I suppose that for which Tree.__eq__ returns True), but perhaps that is not the right subtree.

## Example:
p0.children = ['whatever_1', 'Yes', 'whatever_2', 'Yes']
t0 = p0.children[3] # i.e. str(0) == 'Yes'

p0.children.index(t0)  # this returns 1, but the actual index of t0 is 3


# Implications
Since the trees are not exchanging the right subtrees, the new trees share nodes. But not nodes with the same content, but actually the same objects in memory. The problem is that subsequent modification in Tree A may produce modifications in another expected independent Tree B, because they share the same node-objects.


# Final comment
I am not sure if this is significant in other problems (/ grammars / linear operators / ...). It was in my case, since I am using some operators for prunning the trees in the context of classification with decision trees (a grammar similar to the if_else_classifier.bnf). In particular, due to the interaction between my prunning operators and the aforementioned fact, I was getting some trees that did not point to their parents, which actually contained them in property children, and viceversa, some trees pointing to parent nodes that did not contained them in property children. In case it was interesting, I noticed that Tree B changed when changing A, afterwards I noticed that there were trees sharing the same objects, and finally, I detected that behaviour in the method index.

Best regards.
  • Loading branch information
cgarcia-UCO authored Oct 17, 2022
1 parent 8ee2bd1 commit 1c7f6f4
Showing 1 changed file with 4 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/operators/crossover.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ def do_crossover(tree0, tree1, shared_nodes):
tree0 = t1

# Swap over the subtrees between parents.
i1 = p1.children.index(t1)
i1 = [id(i) for i in p1.children].index(id(t1))
p1.children[i1] = t0

# Set the parents of the crossed-over subtrees as their new
Expand All @@ -290,7 +290,7 @@ def do_crossover(tree0, tree1, shared_nodes):
tree1 = t0

# Swap over the subtrees between parents.
i0 = p0.children.index(t0)
i0 = [id(i) for i in p0.children].index(id(t0))
p0.children[i0] = t1

# Set the parents of the crossed-over subtrees as their new
Expand All @@ -304,8 +304,8 @@ def do_crossover(tree0, tree1, shared_nodes):

# For the parent nodes of the original subtrees, get the indexes
# of the original subtrees.
i0 = p0.children.index(t0)
i1 = p1.children.index(t1)
i0 = [id(i) for i in p0.children].index(id(t0))
i1 = [id(i) for i in p1.children].index(id(t1))

# Swap over the subtrees between parents.
p0.children[i0] = t1
Expand Down

0 comments on commit 1c7f6f4

Please sign in to comment.