遗传算法生成代码

时间:2011-04-20 15:33:33

标签: algorithm code-generation genetic-algorithm genetic-programming evolutionary-algorithm

进化编程似乎是解决许多优化问题的好方法。这个想法非常简单,实施也不会产生问题。

我想知道是否有任何方法可以使用ruby / python脚本(或任何其他语言)进化创建程序?

这个想法很简单:

  1. 创建一系列程序
  2. 进行遗传操作(轮盘选择或任何其他选择),创建具有最佳程序继承的新程序等。
  3. 循环点2直到找到满足我们条件的程序
  4. 但问题仍然很少:

    1. 如何表示染色体?例如,染色体的一个细胞应该是一行代码吗?
    2. 如何生成染色体?如果它们是代码行,我们如何生成它们以确保它们在语法上是正确的等等?
    3. 可以生成的程序示例:

      创建脚本,将N个数字作为输入,并将其均值作为输出返回。

      如果有任何尝试创建此类算法,我会很高兴看到任何链接/来源。

8 个答案:

答案 0 :(得分:23)

如果您确定要这样做,则需要genetic programming,而不是遗传算法。 GP允许您发展树形结构的程序。你会做的是给它一堆原始操作(while($ register),read($ register),increment($ register),decrement($ register),divide($ result $ numerator $ denominator),print ,progn2(这是GP代表“顺序执行两个命令”))。

你可以产生这样的东西:

progn2(
  progn2(
    read($1)
    while($1
      progn2(
        while($1
          progn2( #add the input to the total
            increment($2)
            decrement($1)
          )
        )
        progn2( #increment number of values entered, read again
          increment($3)
          read($1)
        )
      )
    )
  )
  progn2( #calculate result
    divide($1 $2 $3)
    print($1)
  )
)  

作为您的健身功能,您将使用它与真实解决方案的接近程度。其中有一个问题,你必须在传统上计算*。然后有一些东西将其翻译成代码(您选择的语言)。请注意,由于你在那里有一个潜在的无限循环,你将不得不在一段时间后切断执行(没有办法解决暂停问题),它可能无法工作。哪里哪里。另请注意,我提供的代码将尝试除以零。

*有很多方法,但通常不太远。

答案 1 :(得分:15)

它可以完成,但对大多数应用程序都非常糟糕。

遗传算法仅在适应度函数是连续的时才起作用,即您可以确定当前群体中哪些候选者比其他候选者更接近解决方案,因为只有这样,您才能从一代到下一代获得改进。当我在健身功能中使用一个强加权非连续分量的遗传算法时,我学到了很多。它主宰了所有其他人,并且因为它是不连续的,所以没有逐步提高适应性,因为在这方面几乎正确的候选人被认为比完全不正确的候选人更合适。

不幸的是,程序的正确性是完全不连续的。 A行上的错误X停止的程序是否比停在B行的错误Y的程序更好?你的程序可能是一个字符远离正确,并仍然中止错误,而返回恒定硬编码结果的程序至少可以通过一个测试。

这甚至没有触及代码本身在修改时不连续的问题......

答案 2 :(得分:9)

嗯,这是非常可能的,@ Jivlain在他的(好的)答案中正确地指出遗传编程是你正在寻找的(而不是简单的遗传算法)。

遗传编程是一个尚未覆盖广泛受众的领域,部分原因是@MichaelBorgwardt在答案中指出的一些复杂因素。但那些仅仅是并发症,这是不可能做到的。关于这个主题的研究已经持续了20多年。

Andre Koza是这方面的主要研究人员之一(看看他的1992 work)并且他证明了as early as 1996遗传编程在某些情况下如何在一些典型的计算问题上胜过天真的GA(例如作为元胞自动机同步的不断发展的程序)。

这是来自Koza和Poli 2003年的好Genetic Programming tutorial

有关最近的参考资料,您可能需要查看A field guide to genetic programming(2008)。

答案 3 :(得分:4)

自从提出这个问题以来,遗传编程领域已经取得了一些进展,并且除了传统遗传编程的树结构之外,还有一些额外的尝试来发展代码。以下是其中几个:

  • PushGP - 旨在发展人类编码器使用的模块化功能的目标,该系统中的程序将所有变量和代码存储在不同的堆栈上(每个变量类型一个)。程序是通过从堆栈中推送和弹出命令和数据来编写的。
  • FINCH - 一个发展Java字节码的系统。这已经被用来发展游戏玩家。
  • 各种算法已经开始发展C ++代码,通常需要纠正编译器错误的步骤。这种情况好坏参半,但并非完全没有希望。 Here's an example
  • Avida - 一个系统,代理使用非常简单的汇编代码来演化程序(主要是布尔逻辑任务)。基于较旧(且不太通用)的Tierra

答案 4 :(得分:1)

语言不是问题。无论语言如何,你都必须定义一些更高级别的变异,否则需要永远学习。

例如,由于任何Ruby语言都可以根据文本字符串定义,因此您可以随机生成文本字符串并对其进行优化。更好的是只生成合法的Ruby程序。但是,它也需要永远。

如果您正在尝试构建一个排序程序,并且您具有“交换”,“移动”等高级操作,那么您将有更高的成功机会。

理论上,一群猴子在打字机上敲打无限的时间会输出莎士比亚的所有作品。在实践中,它不是写文学的实用方法。仅仅因为遗传算法可以解决优化问题并不意味着它很容易,甚至不一定是一种很好的方法。

答案 5 :(得分:0)

遗传算法的最大卖点,就像你说的那样,就是它们很简单。他们没有最好的性能或数学背景,但即使你不知道如何解决你的问题,只要你可以将它定义为优化问题你就可以把它转过来进入GA。

程序并不适合GA,因为代码不是很好的染色体材料。我见过有人用(更简单的)机器代码而不是Python做了类似的东西(尽管它更像是一个ecossystem模拟然后是GA本身)如果你使用自动机/ LISP或类似的东西编写你的程序,你可能会有更好的运气这一点。


另一方面,考虑到GA的诱惑力以及看到它们的每个人基本上如何问同样的问题,我很确定已经有人在某个地方试过这个 - 我只是不知道他们是否有任何成功

答案 6 :(得分:0)

祝你好运。

当然,您可以编写一个“变异”程序来读取程序并随机添加,删除或更改一些字符。然后你可以编译结果,看看输出是否优于原始程序。 (但是我们定义并测量“更好”。)当然,99.9%的结果是编译错误:语法错误,未定义的变量等等。当然,其余的大部分都是非常不正确的。

尝试一些非常简单的问题。比如说,从一个读入两个数字的程序开始,将它们加在一起,然后输出总和。假设目标是一个读取三个数字并计算总和的程序。这样的程序当然有多长和复杂,当然取决于语言。假设我们有一些非常高级的语言,只需一行代码即可读取或写入数字。然后启动程序只有4行:

read x
read y
total=x+y
write total

达到预期目标的最简单程序就像是

read x
read y
read z
total=x+y+z
write total

因此,通过随机变异,我们必须添加“read z”和“+ z”,共有9个字符,包括空格和换行符。让我们在我们的突变程序上轻松一下,并说它总是插入9个随机字符,它们保证在正确的位置,并且它选择的字符集只有26个字母加10个数字加上14个特殊字符= 50个字符。选择正确的9个字符的几率是多少? 1在50 ^ 9 = 1在2.0e15。 (好吧,如果代替“读取z”和“+ z”它插入“读取w”和“+ w”,程序将起作用,但是我通过假设它神奇地插入了正确数量的字符来使其变得容易并且总是将它们插入到正确的位置。所以我认为这个估计仍然是慷慨的。)

在2.0e15中,

1是一个非常小的概率。即使程序每秒运行一千次,并且您可以快速测试输出,但仍然只有每秒2.0e12中的1或者每小时5.4e8中的1,每天2.3e7中的1。让它保持运行一年,成功的机会仍然只有62,000个。

即使是一个中等能干的程序员也应该能够在十分钟内做出这样的改变?

请注意,更改必须至少包含正确的“数据包”。也就是说,如果一个变异产生“reax z”,那只是远离“read z”的一个字符,但它仍会产生编译错误,因此会失败。

同样添加“read z”但将计算更改为“total = x + y + w”不起作用。根据语言的不同,您将获得未定义变量的错误,或者最多会有一些默认值,如零,并给出不正确的结果。

我想,你可以理论化增量解决方案。也许一个变异会添加新的read语句,然后未来的变异会更新计算。但是没有计算,额外的读取就毫无价值。如何评估程序以确定附加读取是“朝着正确方向迈出的一步”?我认为这样做的唯一方法是让每个突变后的智能读取代码并查看更改是否朝着预期目标前进。如果你有一个聪明的设计师能够做到这一点,那就必须意味着他知道所期望的目标是什么以及如何实现它。在这一点上,只做出所需的改变而不是等待它随机发生会更有效率。

这是一个非常容易用语言的非常简单的程序。大多数程序都是,数百或数千行,所有这些都必须协同工作。编写工作程序的任何随机过程的几率都是天文数字。

在一些非常专业的应用程序中,可能有一些方法可以做类似于此的事情,在这种应用程序中,您实际上并不是在进行随机突变,而是对解决方案的参数进行增量修改。就像,我们有一个公式,其中包含一些我们不知道的常量值。我们知道一些小输入的正确结果是什么。因此,我们对常量进行随机更改,如果结果更接近正确答案,则从那里更改,如果不是,则返回到先前的值。但即便如此,我认为随机变化也很少有效。尝试根据严格的公式更改常量可能会更有帮助,例如从更改1000开始,然后是100,然后是10,等等。

答案 7 :(得分:0)

我想给你一个建议。我不知道你会有多成功,但也许你可以尝试用遗传编程来发展core war机器人。你的健身功能很简单:让机器人在游戏中竞争。你可以从众所周知的机器人开始,也许还有一些随机的机器人然后等着看看会发生什么。