人工蚂蚁问题¶
人工蚂蚁问题是更为复杂但经典的遗传编程问题,其中进化的个体必须控制一只人工蚂蚁,使其能够吃掉给定环境中所有的食物。这个例子展示了DEAP如何轻松处理更复杂的问题,包括一个复杂的功能和资源系统(包括一个小型模拟器)。
关于此问题的更多信息,请参阅 参考。
使用的基本集合¶
我们使用标准的基本操作集来解决人工蚂蚁问题:
pset = gp.PrimitiveSet("MAIN", 0)
pset.addPrimitive(ant.if_food_ahead, 2)
pset.addPrimitive(prog2, 2)
pset.addPrimitive(prog3, 3)
pset.addTerminal(ant.move_forward)
pset.addTerminal(ant.turn_left)
pset.addTerminal(ant.turn_right)
if_food_ahead
是一个原语,如果蚂蚁前方有食物,则执行其第一个参数;否则,执行其第二个参数。prog2()
和prog3()
相当于 lisp 的 PROGN2 和 PROGN3 函数。它们按顺序执行其子节点,从第一个到最后一个。例如,prog2 将首先执行其第一个参数,然后执行其第二个参数。move_forward()
使人工蚂蚁向前移动一步。这是一个终端。turn_right()
和turn_left()
使人工蚂蚁顺时针和逆时针转动,而不改变其位置。这些也是终端。
备注
与符号回归或奇偶校验不同,这里没有外部输入。
尽管这些功能显然不是Python内置的,但定义它们非常容易:
def progn(*args):
for arg in args:
arg()
def prog2(out1, out2):
return partial(progn,out1,out2)
def prog3(out1, out2, out3):
return partial(progn,out1,out2,out3)
def if_then_else(condition, out1, out2):
out1() if condition() else out2()
class AntSimulator(object):
def if_food_ahead(self, out1, out2):
return partial(if_then_else, self.sense_food, out1, out2)
部分函数是 Python 的一个强大功能,它允许动态创建函数。如需更详细的信息,请参阅 Python 文档中的 functools.partial()
。
评估函数¶
评估函数使用模拟器类的一个实例来评估个体。每个个体在模拟器地图上被给予600次移动(地图从外部文件获取)。每个个体的适应度对应于拾取的食物数量。在这个例子中,我们使用的是经典的轨迹,即*Santa Fe轨迹*,其中有89块食物。因此,一个完美的个体会达到89的适应度。
def evalArtificialAnt(individual):
# Transform the tree expression to functional Python code
routine = gp.compile(individual, pset)
# Run the generated routine
ant.run(routine)
return ant.eaten,
其中 ant 是使用的模拟器实例。evaluate()
函数是 DEAP 提供的一个便利函数,它从 GP 个体及其原始函数集中返回一个可执行的 Python 程序。
完整示例¶
除了模拟器代码(约75行),代码在本质上与 符号回归示例 没有根本区别。请注意,由于问题更复杂,通过将锦标赛规模增加到7来提高选择压力,可以实现更好的性能。
完整的 examples/gp/ant
参考¶
John R. Koza, “遗传编程I:通过自然选择对计算机进行编程”, MIT Press, 1992, 第147-161页.