【问题标题】:What would be a good way to perform crossover with dependencies in GA?在 GA 中执行与依赖项交叉的好方法是什么?
【发布时间】:2015-03-13 05:14:33
【问题描述】:

我正在编写一个遗传算法来查找表达目标数字的表达式,即如果目标数字是10,则解决方案将是2*5。现在我使用的是固定大小的染色体,我想将其更改为随机长度,但只有在我找到执行交叉的方法之后。

以下是可能的染色体,遵循数字和运算符交替出现在字符串中的规则,以没有两个数字或两个运算符相邻的方式。合法字符串将以数字或+/- 运算符开头。表达式将按原样从左到右计算(忽略算术运算的顺序):

  • 1/2+3+5
  • -2+4+1+8
  • -7+6*2+8
  • +2/5-1+8 2+1*2-2
  • +2*7*7+3
  • +1/2/2/6 5/5*9*1
  • +3-1+1*8 3-8+7*1

尝试实现交叉我尝试了以下方法(在伪代码中):

crossover(chrom-a, chrom-b):
    min_length = min(length(chrom-a), length(chrom-b))
    locus = random(1, min_length-1)

    while (chrom-a[locus] & chrom-b[locus] aren't both digit or operator)
        ocus = random(1, min_length-1)

    chrom-a = chrom-a[:locus] + chrom-b[locus:]
    chrom-b = chrom-b[:locus] + chrom-a[locus:]

    return chrom-a, chrom-b

但该功能没有按预期工作,有时需要花费太多时间才能找到正确的轨迹。我必须找到一种方法使交叉与随机大小的染色体一起工作,但我不知道如何(当然要确保没有被零除)。

【问题讨论】:

    标签: algorithm artificial-intelligence genetic-algorithm arithmetic-expressions


    【解决方案1】:

    较长的处理时间很可能是因为两个染色体在同一位置具有不同类型(运算符或数字)字符的事件的可能性很小。请注意,对于 1 位数字,两条染色体将总是在同一位置具有相同的类型。解决方法是分别在每条染色体中寻找分裂点:

    find_loci(chrom-a, chrom-b):
        return pair(random(1, length(chrom-a)-1), random(1, length(chrom-b)-1))
    
    crossover(chrom-a, chrom-b):
        locus-a, locus-b = find_loci(chrom-a, chrom-b)
    
    while (chrom-a[locus-a] & chrom-b[locus-b] aren't both digit or operator)
        locus-a, locus-b = find_loci(chrom-a, chrom-b)
    
    chrom-a = chrom-a[:locus-a] + chrom-b[locus-b:]
    chrom-b = chrom-b[:locus-a] + chrom-a[:locus-b]
    chrom-c = chrom-a[locus-a:] + chrom-b[locus-b:]
    chrom-d = chrom-b[locus-a:] + chrom-a[:locus-b]
    
    return chrom-a, chrom-b, chrom-c, chrom-d
    

    结果当然是你会有四个可能的结果,而不是两个。您可以全部使用,也可以忽略其中的一半。

    另一个解决方法是首先枚举所有可能的分裂点:

    enumerate_possible_loci(chrom-a, chrom-b):
        for all indexes i in (1, chrom-a):
            for all indexes j in (1, chrom-b):
                if type(chrom-a[i]) != type(chrom-b[j]):
                    yield return pair(i, j)
    
    crossover(chrom-a, chrom-b):
       possible_loci = enumerate_possible_loci(chrom-a, chrom-b)
       locus_pair = possible_loci[random(0, length(possible_loci) - 1)]
    
       locus-a = locus_pair[0]
       locus-b = locus_pair[1]
    
        chrom-a = chrom-a[:locus-a] + chrom-b[locus-b:]
        chrom-b = chrom-b[:locus-a] + chrom-a[:locus-b]
        chrom-c = chrom-a[locus-a:] + chrom-b[locus-b:]
        chrom-d = chrom-b[locus-a:] + chrom-a[:locus-b]
    
        return chrom-a, chrom-b, chrom-c, chrom-d
    

    如果您总是只有 1 位数字,那么枚举可能位点的算法会更加简单,因为当一个索引是偶数而另一个索引是奇数时,它总是会返回所有可能的对,反之亦然。

    【讨论】:

    • @Quaker 干杯,祝你好运! :) 不要让 me 更新 :) 如果您还有其他问题 - 发布另一个问题。如果我有空,我一定会调查的。
    • @Quaker 不,不。这不是一个线程。 SO 是关于积累特定问题的答案,而不是讨论(讨论有时只需要澄清帖子)。在您发布了一个明确定义的问题并解决后,您不应该更改它,因为它可能会以当前形式帮助未来的读者。只需发布另一个定义明确的问题 :-) (example meta post on "chameleon questions" - 他们感到气馁,甚至皱眉头:) )。
    猜你喜欢
    • 2020-02-26
    • 2011-11-08
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2018-06-26
    • 2011-08-26
    • 2012-11-17
    • 1970-01-01
    相关资源
    最近更新 更多