4

我在尝试将遗传运算符应用于二叉树时遇到问题。

首先,我有为初始种群生成两种类型树的方法,即Grow(可变大小的树)和Full(平衡相同形状和大小的树)。

    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
} 

现在这是我难以理解如何实现遗传算子的地方,即MutationCrossover

从我的初始种群中随机选择一棵树,我该如何应用这些遗传算子?对于突变

  • 我需要在父树中随机选择一个点。
  • 删除该选定点下方的整个子树。
  • 生成与移除的子树深度相似的新子树。
  • 将其替换回原始父树和选定点。

这是现在的后代。

图形描述:

                             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);
        }
    }
4

2 回答 2

2

我将尝试简要解释一些步骤。

在父树中随机选择一个点

这样做的一种方法是选择一个随机数,例如k,介于 0 和树中非叶元素的数量之间。随机点将是第kth 个元素,同时按顺序遍历树

替换该选定点下方的整个子树。

只需将子树设置为新生成的树。像这样的东西:

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()方法返回直接父节点。

请注意,您还必须检查返回的随机子树是根本身的某些情况。

于 2015-08-14T12:10:37.250 回答
1
  1. 随机选择一个点: 从不平衡二叉树中随机选择一个节点

  2. 不需要从选定节点中删除子树,只需获取选定子树的深度,并保持对它的引用。http://www.geeksforgeeks.org/get-level-of-a-node-in-a-binary-tree/

  3. 使用您的“完整”方法生成具有保存的旧子树深度的新随机子树,并将此子树分配给您保存的旧子树引用,因此旧子树被垃圾收集器杀死。

于 2015-08-14T12:05:10.973 回答