正如Koza here所描述的那样,我正在研究能够利用遗传编程实现食物觅食行为的蚂蚁。每一步,我循环遍历每个蚂蚁,执行其计算机程序(同一程序由殖民地的所有蚂蚁使用)。目前,我已经定义了简单的指令,例如MOVE-ONE-STEP
,TURN-LEFT
,TURN-RIGHT
等。但我还有一个函数PROGN
,它按顺序执行参数。我遇到的问题是因为PROGN
可以按顺序执行指令,这意味着一个蚂蚁可以在一个时间步骤中执行多个操作。与大自然不同,我无法并行运行蚂蚁,这意味着一只蚂蚁可能会去做几个动作,操纵环境,而所有其他蚂蚁都在等待轮到他们。
我只是想知道,这是通常的做法,还是有更好的方法? Koza似乎没有提及它的任何内容。事实上,我想扩展场景以拥有其他代理(例如敌人),这可能依赖于在一个时间步骤中只发生一次的事情。
答案 0 :(得分:2)
我不熟悉Koza的工作,但我认为合理的方法是给每个蚂蚁自己的指令队列,这些队列在时间步骤中持续存在。通过这样做,您可以让蚂蚁每个时间步执行PROGN
个函数一个指令。例如,蚂蚁时间步长的高级逻辑可以是:
Do-Time-Step(ant):
1. if ant.Q is empty: // then put the next instruction(s) into the queue
2. instructions <- ant.Get-Next-Instructions()
3. for instruction in instructions:
4. ant.Q.enqueue(instruction)
5. end for
6. end if
7. instruction <- ant.Q.dequeue() // get the next instruction in the queue
8. ant.execute(instruction) // have that ant do its job
答案 1 :(得分:0)
排队指令的另一种类似方法是预处理指令集,将PROGN的扩展实例扩展到组件指令集。如果允许PROGN调用其他PROGN,则必须以递归方式完成此操作。这样做的缺点是候选程序有点臃肿,但这只是在运行时。另一方面,它易于,快速且易于调试。
实施例: 说PROGN1 = {inst-p1 inst-p2}
然后候选程序将以{inst1 PROGN1 inst2}开始,并且当准备好在模拟中进行评估时,将扩展到{inst1 inst-p1 inst-p2 inst2}。
答案 2 :(得分:0)
这完全取决于您的特定GP实施。
在我的GP内核程序中,要么重复评估,要么并行评估 - 整体而言,即此场景中的“原子”操作是单个程序评估。 因此,在评估下一个程序之前,人口中的所有个体都会重复执行n次,或者所有个体只执行一次,然后再执行n次。
我使用这种并发级别的虚拟代理获得了相当不错的结果。 绝对有可能将其分解得更多,但是在这一点上你会降低算法的可扩展性:
虽然很容易在多个CPU或核心之间分配程序评估,但由于所有程序之间需要同步的数量,因此每个节点的评估也会毫无价值地做同样的事情。
鉴于现代系统(甚至是智能手机)中CPU /核心的数量迅速增加以及GP的“CPU饥饿”,您可能想重新考虑一下您的方法 - 您真的想在程序中包含移动/转向指令吗?
为什么不重新设计它以在程序评估期间使用在一些寄存器/变量中存储方向和速度参数的基元? 然后,模拟步骤将根据程序存储的指令实际移动/转动代理。
干杯, 杰