用于猜测字符串的进化算法,通过复制搞砸了

时间:2011-06-14 15:41:58

标签: algorithm code-generation

我正在研究一个python脚本来测试遗传编程。 作为一个练习,我做了一个试图猜测的简单脚本 没有整个人口部分的字符串。

我的代码是:

# acts as a gene
# it has three operations:
# Mutation   : One character is changed
# Replication: a sequencepart is duplicated
# Extinction : A sequencepart is lost
# Crossover  : the sequence is crossed with another Sequence
import random
class StringGene:
  def __init__(self, s):
    self.sequence = s
    self.allowedChars = "ABCDEFGHIJKLMOPQRSTUVWXYZ/{}[]*()+-"

  def __str__(self):
    return self.sequence

  def Mutation(self):
    x = random.randint(0, len(self.sequence)-1)
    r = random.randint(0, len(self.allowedChars)-1)
    d = self.sequence
    self.sequence =  d[:x-1]+ self.allowedChars[r] + d[x:]

  def Replication(self):
    x1 = random.randint(0, len(self.sequence)-1)
    x2 = random.randint(0, len(self.sequence)-1)
    self.sequence =self.sequence[:x1]+ self.sequence[x1:x2] + self.sequence[x2:]
    self.sequence = self.sequence[:32]

  def Extinction(self):
    x1 = random.randint(0, len(self.sequence)-1)
    x2 = random.randint(0, len(self.sequence)-1)
    self.sequence =     self.sequence[:x1] + self.sequence[x2:]

  def CrossOver(self, s):
    x1 = random.randint(0, len(self.sequence)-1)
    x2 = random.randint(0, len(s)-1)
    self.sequence = self.sequence[:x1+1]+ s[x2:]
    #x1 = random.randint(0, len(self.sequence)-1)
    #self.sequence = s[:x2             ] + self.sequence[x1+1:]

if __name__== "__main__":
  import itertools
  def hamdist(str1, str2):
    if (len(str2)>len(str1)):
      str1, str2 = str2, str1
    str2 = str2.ljust(len(str1))
    return  sum(itertools.imap(str.__ne__, str1, str2))


  g = StringGene("Hi there, Hello World !")
  g.Mutation()
  print "gm: " + str(g)
  g.Replication()
  print "gr: " + str(g)
  g.Extinction() 
  print "ge: " + str(g)
  h = StringGene("Hello there, partner")
  print "h: " + str(h)
  g.CrossOver(str(h))
  print "gc: " + str(g)
  change = 0
  oldres = 100
  solutionstring = "Hello Daniel. Nice to meet you."
  best = StringGene("")
  res = 100
  print solutionstring
  while (res > 0):
      g.Mutation()
      g.Replication()
      g.Extinction()
      res = hamdist(str(g), solutionstring)   
      if res<oldres:      
        print "'"+ str(g) + "'"
        print "'"+ str(best) + "'"
        best = g
        oldres = res
      else :
        g = best 

      change = change + 1
  print "Solution:" + str(g)+ " "  + str(hamdist(solutionstring, str(g))) + str (change)

我有一个粗糙的汉明距离作为衡量解决方案字符串的距离 与现在不同。但是我希望能够有所不同 在猜测的长度,所以我介绍了复制和删除部分 的字符串。

现在,字符串无限增长,解决方案字符串永远不会 找到。你能指出我错在哪里吗?

你能建议改进吗?

欢呼声

4 个答案:

答案 0 :(得分:1)

您的StringGene个对象是可变的,这意味着当您执行best = g之类的操作时,您正在使gbest引用相同的对象。由于在第一步之后你只有一个对象,每个变异都会被永久地应用,无论它是否成功,gbest之间的所有比较都是同一个对象之间的比较。

您需要实现复制运算符,或使实例不可变,并让每个变异运算符返回'基因'的修改版本。

此外,如果第一个突变无法改善字符串,则将g设置为best,这是一个空字符串,完全丢弃您的起始字符串。

最后,规范测试字符串是“Methinks它就像一个黄鼠狼”。

答案 1 :(得分:0)

最简单的方法可能是限制猜测字符串的持续时间。不要超过一定长度的猜测。

我查看了你的代码,我在Python中找不到任何错误,但是你可能只是错误地引用或索引数组,导致总是在猜测字符串中添加新字符,所以你的字符串总是在增加...我不知道这是不是错误,但之前发生过这样的事情,所以请仔细检查你的数组指标。 ;)

答案 2 :(得分:0)

我认为你的健身功能太简单了。我会玩两个变量,一个是大小距离,另一个是你的“hamdist”。尺寸差异越大,它对总体健康的影响就越大。所以将两者加在一起,加上一些百分比常数。

我对python也不是很熟悉,但我认为这不是你正在做的事情。

答案 3 :(得分:0)

首先,你所做的是遗传算法,而不是遗传编程(这是一个相关但不同的概念)。

我不懂Python,但看起来你的灭绝功能存在一个主要问题。据我所知,如果x1&gt; x2它导致字符串的大小增加而不是减少(x1和x2之间的部分实际上加倍)。当x1&gt;时,复制功能会发生什么? x2,我不知道如何不知道Python。

还要记住,维持人口是有效解决遗传算法问题的关键。交叉是算法的重要组成部分,如果它们不是在人口成员之间产生的话,它们几乎没有意义(同样,人口越多,越多越好,大部分时间)。您提供的代码取决于单个样本的突变以达到预期的结果,因此与简单的强力方法相比,极不可能产生任何有用的东西。