SingleNodeCrossover extends TreeCrossover<G, C> { static <A> int swap(final TreeNode<A> that, final TreeNode<A> other) { assert that != null; assert other != null; final Random random = RandomRegistry.random(); final ISeq<TreeNode<A>> seq1 = that.breadthFirstStream() .collect(ISeq.toISeq()); final ISeq<TreeNode<A>> seq2 = other.breadthFirstStream() .collect(ISeq.toISeq()); final int changed; if (seq1.length() > 1 && seq2.length() > 1) { final TreeNode<A> n1 = seq1.get(random.nextInt(seq1.length() - 1) + 1); final TreeNode<A> p1 = n1.parent().orElseThrow(AssertionError::new); final TreeNode<A> n2 = seq2.get(random.nextInt(seq2.length() - 1) + 1); final TreeNode<A> p2 = n2.parent().orElseThrow(AssertionError::new); final int i1 = p1.indexOf(n1); final int i2 = p2.indexOf(n2); p1.insert(i1, n2.detach()); p2.insert(i2, n1.detach()); changed = 2; } else { changed = 0; } return changed; } SingleNodeCrossover(double probability);  SingleNodeCrossover(); @Override String toString();  }
@Test(dataProvider = "treeLevels") public void crossover1(final int level1, final int level2) { final Random random = new Random(); final TreeNode<Integer> tree1 = newTree(level1, random); final TreeNode<Integer> tree2 = newTree(level2, random); final int size1 = tree1.size(); final int size2 = tree2.size(); SingleNodeCrossover.swap(tree1, tree2); Assert.assertEquals(tree1.size() + tree2.size(), size1 + size2); }