21 | | |
22 | | Another related issue concerns the actual way crossover was coded, looking at `SubtreeCrossover.cs` lines 112-127: |
23 | | {{{#!C# |
24 | | var selectedBranch = SelectRandomBranch(random, allowedBranches, internalCrossoverPointProbability); |
25 | | if (crossoverPoint0.Child != null) { |
26 | | // manipulate the tree of parent0 in place |
27 | | // replace the branch in tree0 with the selected branch from tree1 |
28 | | crossoverPoint0.Parent.RemoveSubtree(crossoverPoint0.ChildIndex); |
29 | | if (selectedBranch != null) { |
30 | | crossoverPoint0.Parent.InsertSubtree(crossoverPoint0.ChildIndex, selectedBranch); |
31 | | } |
32 | | } else { |
33 | | // child is null (additional child should be added under the parent) |
34 | | if (selectedBranch != null) { |
35 | | crossoverPoint0.Parent.AddSubtree(selectedBranch); |
36 | | } |
37 | | } |
38 | | return parent0; |
39 | | }}} |
40 | | |
41 | | In the snippet above, we see that when `crossoverPoint0.Child != null && selectedBranch == null`, a subtree is removed from the root parent without any replacement. This behavior is not consistent with the concept of crossover, but fixing this second issue is likely to change crossover behavior and affect reproducibility of saved experiments. |