
在本文中,我将分享使用遗传算法发展简单人工智能(AI)的经验,还将讨论形成任何行为所需的最少命令集。
这项工作的结果是,不了解规则的AI独立掌握了井字游戏,并发现了与之对抗的机器人的弱点。 但是我从一个更简单的任务开始。
指令集
一切始于准备一套AI可能具有的命令。 高级语言包含数百种不同的运算符。 为了突出显示必要的最低限度,我决定转向汇编语言。 但是,事实证明它包含许多命令。
我需要AI读取和输出数据,使用内存,执行计算和逻辑运算,进行转换和循环。 我遇到了Brainfuck语言,该语言仅包含8条命令,可以执行任何计算(即Turing完成)。 原则上,它适合于基因编程,但我走得更远。
我想知道:实现任何算法所需的最少命令数量是多少? 事实证明-一个!
URISC处理器仅包含一个命令:如果相减的结果大于减量的结果,则减去并跳过下一条指令。 这足以构建任何算法。
Oleg Mazonka走得更远,他开发了
BitBitJump团队,并根据Turing证明了它的完成。 该命令包含三个地址,将一个位从第一个地址复制到第二个地址,并将控制权转移到第三个地址。
借用了Oleg的想法,以简化工作,我建立了SumIfJump团队。 该命令包含四个操作数:A,B,C,D并执行以下操作:将单元格中的数据添加到地址A到地址B,如果该值大于指定的*,它将到达地址C,否则将到达地址D。
注意事项*在这种情况下,使用了128个-基因组长度的一半。
当操作数A访问存储单元N0时,正在输入数据,而当操作数A进入存储单元N1时,则输出数据。
以下是FreePascal(Delphi的免费类似物)上的SumIfJump代码。
procedure RunProg(s: TData); var a, b, c, d: TData; begin Inc(NStep); if NStep > MaxStep then begin ProgResult := 'MaxStep'; Exit; end; a := s; b := s + 1; c := s + 2; d := s + 3; a := Prog[a]; b := Prog[b]; c := Prog[c]; d := Prog[d]; if a = 0 then begin ProgResult := 'Input'; Exit; end; if a = 1 then begin ProgResult := 'Output'; Exit; end; Prog[b] := Prog[b] + Prog[a]; if Prog[b] < ProgLength div 2 then RunProg(c) else RunProg(d); end;
SumIfJump实现自修改代码。 它可以执行常规编程语言中可用的任何算法。 该代码易于修改,并且可以承受任何操作。
简单的任务
因此,我们的AI只有一支团队。 虽然井字游戏对他来说是非常困难的游戏,但我还是从一个简单的游戏开始。

机器人给出一个随机数,而AI应该读取数据并给出答案。 如果数字大于平均值(在随机数范围内),则AI给出的数字应小于平均值,反之亦然。
我们AI的基因组由256个细胞组成,值从0到255。每个值是一个内存,一个代码和一个地址。 代码执行步骤的数量限制为256。操作数一个接一个地读取。
最初,基因组是由一组随机数组成的,因此AI不知道它需要发挥什么作用。 而且,他不知道自己需要按顺序输入和输出数据,以响应机器人。
人口与选择
第一批人口包括开始使用该机器人的256个AI。 如果AI执行正确的操作(例如,请求输入数据,然后显示某些内容),则AI会收到积分。 正确的动作越多,得分就越高。
得分最高的16个AI提供了15个后代,并继续参与游戏。 后代是突变体。 通过用随机值替换父副本中的一个随机单元格来发生突变。

如果在第一个总体中没有AI得分,则形成下一个总体。 依此类推,直到某些AI开始执行正确的操作并提供“正确的”后代。
发展历程
ñ | 大事记 |
---|
1个 | AI什么也没做。 该程序需要256个步骤并结束。 |
2 | 开始请求数据。 |
3 | 他开始请求数据并输出一些东西。 请求和响应的顺序很混乱。 |
4 | 数据输入和输出顺序发生,有时会发生错误。 在一半的情况下,人工智能给出了正确的答案。 |
5 | 定期给出正确答案,但有时会发生错误。 |
6 | 在3万次迭代中给出正确的答案。 选择已上传。 |
在重大事件之间,数千代人过去了。 该程序在Core i7的多个线程中启动。 计算耗时约15分钟。

有趣的地方
- 当AI“领导者”犯了一个随机错误并且没有获得足够的分数时,人口开始下降,因为 由“次生”父母组成的后代。
- 碰巧的是,在外部人在打发时间的流中,成功进行了一次突变,从而使累积的积分急剧增加。 此后,此流程成为领导者。
- 有时很长一段时间没有成功的突变发生,甚至50万代都不足以完成选择。
结论
总之,我在井字游戏中也这样做。 与第一种情况一样,使用基因组大小。 步骤数增加到1024,而总体大小增加到64(以便进行更快的计算)。 计算花费了更长的时间。 一切都根据相同的情况发生。
最初,AI与“随机化器”对抗。 我称它为随机行走的机器人。 很快,AI开始打败他,排成一列。 此外,我通过给随机化器添加一些理由来使任务复杂化:如果可能的话,占据优势或者保卫。 但是,在这种情况下,人工智能发现了机器人的弱点并开始击败他。 也许有关此的故事是另一篇文章的主题。
儿子要求我编写一个程序,以便AI相互之间而不是与机器人一起玩。 有一些想法可以玩跳棋或走棋,但是为此,我已经没有足够的时间了。
我用来获得新个体的唯一方法是突变。 您还可以使用交叉和反转。 也许这些方法将加快获得所需结果的速度。
最终,这个想法诞生了:使AI能够管理PC上的所有进程并争夺计算机资源。 将PC连接到Internet,并将旧的比特币农场池用作计算能力...
如前所述,博客作者
Mikhail Tsarkov进行了类似的实验:
也许他们会接管世界,但是如果呢?
参考文献
- 遗传算法
- 复制位-最简单的计算机/ Oleg Mazonka
- URISC-维基百科
- 图灵完整性-维基百科