祝你好运。
当然,您可以编写一个“突变”程序来读取程序并随机添加、删除或更改一些字符。然后你可以编译结果,看看输出是否比原来的程序好。(但是我们定义和衡量“更好”。)当然,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 个字符的几率是多少?50^9 中的 1 = 2.0e15 中的 1。(好吧,如果不是“read z”和“+z”,而是插入“read 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”是行不通的。根据语言的不同,您会得到未定义变量的错误,或者充其量它会有一些默认值,如零,并给出不正确的结果。
我想,你可以对增量解决方案进行理论化。也许一个突变添加了新的读取语句,然后一个未来的突变更新了计算。但如果没有计算,额外的阅读是毫无价值的。如何评估程序以确定额外的读取是“朝着正确方向迈出的一步”?我认为做到这一点的唯一方法是让智能体在每次突变后读取代码,看看变化是否朝着预期目标前进。如果你有一个聪明的设计师可以做到这一点,那一定意味着他知道期望的目标是什么以及如何实现它。在这一点上,只进行所需的更改而不是等待它随机发生会更有效率。
这是一个非常简单的程序,语言非常简单。大多数程序是什么,成百上千行,所有这些都必须协同工作。编写工作程序的任何随机过程的几率都是天文数字。
在一些非常专业的应用程序中,可能有一些方法可以做类似的事情,在这些应用程序中,您并不是真正进行随机突变,而是对解决方案的参数进行增量修改。就像,我们有一个公式,其中包含一些我们不知道其值的常数。我们知道对于一小部分输入的正确结果是什么。所以我们对常数进行随机更改,如果结果更接近正确答案,则从那里更改,如果不是,则返回之前的值。但即便如此,我认为进行随机更改很少有成效。尝试根据严格的公式更改常数可能会更有帮助,例如从 1000 开始更改,然后 100 和 10 等。