【问题标题】:Converting an evolutionary algorithm to genetic将进化算法转换为遗传算法
【发布时间】:2013-12-21 06:57:23
【问题描述】:

据我所知,进化算法和遗传算法之间最大的区别之一是进化使用变异函数来生成新种群,而遗传算法使用交叉函数。

我发现了一个evolutionary algorithm,它试图通过这样的突变来生成目标字符串:

  private static double newMutateRate(){
    return (((double)perfectFitness - fitness(parent)) / perfectFitness * (1 - minMutateRate));
  }

  private static String mutate(String parent, double rate){
    String retVal = "";
    for(int i = 0;i < parent.length(); i++){
      retVal += (rand.nextDouble() <= rate) ?
        possibilities[rand.nextInt(possibilities.length)]:
        parent.charAt(i);
    }
    return retVal;
  }

我写了这个交叉函数来代替变异函数:

private static String crossOver(String parent)
{
    String newChild = "";
    for(int i = 0;  i < parent.length(); i++)
    {
        if(parent.charAt(i) != target.charAt(i))
            newChild += possibilities[rand.nextInt(possibilities.length)];
        else
            newChild += parent.charAt(i);
    }
    return newChild;
}

效果很好。 但我想知道它是否是一个有效的交叉函数。我觉得,根据我在遗传算法方面的经验,交叉函数应该产生比我所写的更多的随机种群,换句话说,确切地知道哪一点不改变似乎几乎是作弊。

【问题讨论】:

  • 您第一段中的假设(“进化使用变异函数来产生新种群,而遗传使用交叉函数”)是错误的。不同之处在于遗传算法是进化算法的一个子类型,它明确使用“基因”来模拟个体的特征。阅读 this Wikipedia section 了解 EA 的比较。
  • @Junuxx 这个问题不是GA要解决的最实际的问题,而只是学习目的之一,因为您已经知道用于计算适应度的最佳目标字符串。

标签: java algorithm genetic-algorithm evolutionary-algorithm


【解决方案1】:

不,您的交叉函数不符合该术语的传统含义。交叉应该从两个父母那里获取基因。你现在拥有的更像是一个变异函数。

统一交叉是两个基因组的常见交叉实现,其中孩子获得每个父母大约 50% 的基因。这里我假设基因组长度是固定的。

private String crossover(String parent1, String parent2){

    String child = "";
    for(int i = 0; i < parent1.length(); i++){
        if (rand.nextFloat() >= 0.5){
            child += parent1[i];
        }
        else {
            child += parent2[i];
        }
    }
}

【讨论】:

  • 您能否提供一些关于有效交叉的伪代码。过去,我们使用轮盘赌的方法来确定哪些基因更有利,但对于如何实现这一点并不是 100%。
  • @Nick:见上面的编辑。不要将交叉与选择混淆;交叉只是产生新的基因组,应该关注哪些基因更有利。通过消除最弱的个体,您会获得自然选择,从而随着时间的推移而改进。
【解决方案2】:

我认为用目标来构造交叉函数是不合适的,但应该使用当前种群中最好的两个字符串进行交叉。

这是一个这样的交叉的伪代码:-

Crossover(String parent1,String parent2) {

 for(i=0;i<parent1.length;i++) {

       if(parent1[i]==target[i]) {
              child[i] = parent1[i]
       }
       else if(parent2[i]==target[i]) {
            child[i] = parent2[i]
       }
 } 

 insert remaining elements into child randomly

}

上述方法称为贪心交叉

【讨论】:

  • “两个最佳字符串”听起来像是elitism 的一种。这通常是一种很好的方法,但对于交叉原理来说不是必需的。
  • @Junuxx 上面的方法总是会从任何两个 parent 产生更好的字符串,它们不一定是最好的。如果你使用最好的字符串,它在很多情况下会收敛得更快。
  • 完全同意第二部分(我在之前的评论中说过同样的话),但仅在查看目标时才同意第一部分。这是一种作弊,@Nick,因为它在 EA 的实际应用中应该是未知的。
  • @Junuxx 但是在不知道目标字符串的情况下评估适应度函数是不可能的。这不是应用遗传算法的理想问题。
  • 不,这不是不可能的。例如考虑learning how to control a racing car 的目标。适应性不能通过比较基因组与理想基因组(我们不知道它是什么样子)来测量,而是通过测量实际性能来测量:汽车在撞车前开了多远,或者花了多长时间跑完一圈?
【解决方案3】:

我同意 Junuxx,我只想补充一件事。碰巧遗传算法比其他进化算法更倾向于使用交叉算子,但并不是繁殖算子使算法具有遗传性!我发现割草机的例子解释的很好(不用担心实现代码,看解释就行了):

Lawnmower Problem Solver

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-01
    • 2015-02-18
    • 2013-07-02
    • 2022-01-25
    • 2011-02-22
    • 2011-01-11
    • 1970-01-01
    相关资源
    最近更新 更多