Level function returns different results depending on whether the iterator is iterating through a ProgramGene or TreeNode #475
Description
The following code displays my finding:
public class TestingLevel {
public static double fitness(final Genotype<ProgramGene<Double>> gene) {
return 0.0;
}
public static void main(String [] args) {
//functions
final Op<Double> add2 = Op.of("add2",2, v-> v[0]+v[1]);
final Op<Double> neg = Op.of("neg",1, v-> -v[0]);
//terminals
final Var<Double> x1 = Var.of("x1", 0);
final Var<Double> x2 = Var.of("x2", 1);
final ISeq<Op<Double>> Terminals = ISeq.of(x1, x2);
final ISeq<Op<Double>> Operations = ISeq.of(add2, neg);
//create tree
TreeNode<Op<Double>> tree = TreeNode.of(add2)
.attach(x1)
.attach(TreeNode.of(neg).attach(x1));
//create phenotype
ProgramChromosome<Double> chromosome = ProgramChromosome.of(tree, ch->ch.getRoot().size()<=20, Operations, Terminals);
Genotype<ProgramGene<Double>> mismatchTreeOneGenotype = Genotype.of(chromosome);
Phenotype<ProgramGene<Double>, Double> p1 = Phenotype.of(mismatchTreeOneGenotype, 0, TestingLevel::fitness).withFitness(0.3);
//convert back to traverse through
System.out.println("------------------Convert to Program--------------------");
ProgramGene<Double> program1 = (ProgramGene<Double>) p1.getGenotype().getChromosome().getGene();
Iterator<ProgramGene<Double>> iterator1 = program1.breadthFirstIterator();
while(iterator1.hasNext()) {
ProgramGene<Double> node = iterator1.next();
System.out.println(node.toParenthesesString().split("\\(")[0] + " | level: " + node.level());
}
System.out.println("------------------Convert to Tree--------------------");
TreeNode<Op<Double>> convertedTree = TreeNode.ofTree(program1);
Iterator<TreeNode<Op<Double>>> iterator = convertedTree.breadthFirstIterator();
while(iterator.hasNext()) {
TreeNode<Op<Double>> node = iterator.next();
System.out.println(node.toParenthesesString().split("\\(")[0] + " | level: " + node.level());
}
}
}
The output is:
------------------Convert to Program--------------------
add2 | level: 0
x1 | level: 1
neg | level: 1
x1 | level: 1
------------------Convert to Tree--------------------
add2 | level: 0
x1 | level: 1
neg | level: 1
x1 | level: 2
As can be seen x1 in the ProgramGene structure is at level 1, whereas in TreeNode it is at level 2.
I'm wondering if this is expected behavior? It was causing some of my code to fail, until I looked into it to find this difference.
If I replace the Var in neg to x2, then the output is as follows:
------------------Convert to Program--------------------
add2 | level: 0
x1 | level: 1
neg | level: 1
x2 | level: 2
------------------Convert to Tree--------------------
add2 | level: 0
x1 | level: 1
neg | level: 1
x2 | level: 2
In this case because the x2 isn't used further up in the programGene, it's level is outputting correctly.