我在尝试将遗传算子应用于二叉树时遇到了问题。
首先,我有一些方法可以为初始种群生成两种类型的树,即成长(可变大小的树)和完整(平衡相同的形状和大小树)
FULL GROW
(*) (*)
(+) (-) (5) (-)
(1)(2) (3)(4) (6) (7)
每棵树的类看起来像这样:
public class Tree<E>{
E element;
Tree<E> left, right;
double rawFit;
int hitRat;
public Tree(E element)
{
this.element=element;
}
public Tree (E element, Tree left, Tree right)
{
this.element = element;
this.left = left;
this.right = right;
}
//MORE
//CODE
}
现在,我正在理解如何实施遗传算子,即突变和交叉
从我的初始人群中随机选择一棵树,我该如何应用这些遗传算子呢? 对于突变:
这是现在的后代。
图形描述:
PARENT
(*)
randomly chosen point --> (+) (-)
(1)(2) (3)(4)
OFFSPRING RANDOM SUBTREE
(*)
(NULL) (-) + (*)
(3) (4) (5) (6)
NEW OFFSPRING
(*)
(*) (-)
(5)(6) (3) (4)
我也需要为Crossover做类似的事情。
理论上似乎很容易,但我不知道如何编写这个(Java)。任何帮助将不胜感激。
编辑:我用于生成完整树的方法如下所示:
private static final String[] OPERATORS = {"+", "-", "/", "*"};
private static final int MAX_OPERAND = 100;
public static Tree full(int depth) {
if (depth > 1) {
String operator = OPERATORS[random.nextInt(OPERATORS.length)];
return new Tree(operator, full(depth - 1), full(depth - 1));
} else {
return new Tree(random.nextInt(MAX_OPERAND) + 1);
}
}
答案 0 :(得分:1)
我将尝试简要解释一些步骤。
这样做的一种方法是在0和树中非叶元素的数量之间选择一个随机数,比如k
。随机点将是k
元素traversing the tree in order。
只需将子树设置为新生成的树。像这样:
public class Tree<E> {
public void mutate() {
Tree tree = this.getRandomSubtree();
tree.replace(NEW_RANDOM_TREE);
}
public void replace(Tree<E> newTree) {
if(this.isLeftChild()) this.getParent().setLeft(newTree);
else this.getParent().setRight(newTree);
}
...
}
getRandomSubtree()
方法返回树中的随机点
树的getParent()
方法返回直接父节点。
请注意,您还必须检查返回的随机子树是根本身的一些情况。
答案 1 :(得分:0)
随机选择一个点: Select a Node at Random from Unbalanced Binary Tree
不需要从所选节点中删除子树,只需获取所选子树的深度,并保持对它的引用。 http://www.geeksforgeeks.org/get-level-of-a-node-in-a-binary-tree/
使用“完整”方法生成一个新的随机子树,其中保存了旧子树的深度,并将此子树分配给旧子树的已保存引用,因此旧子树被垃圾收集器杀死。