由于问题的性质,我必须包括许多背景信息(因为我的问题是:如何缩小此范围?)也就是说,据我所知,可以总结为:
有哪些方法可以在极大的组合搜索空间中找到局部最优值?
背景
在工具辅助的超级游戏社区中,我们希望为视频游戏机或仿真器提供特制的(不是实时生成的)输入,以最大程度地减少成本(通常是完成时间)。这是目前做的方法是通过玩游戏帧一帧,并确定各帧的输入,经常重做多次运行的部分(例如,最近公布的运行塞尔达传说:时之笛有总共198,590次重试)。
使这些运行达到其目标通常可以归结为两个主要因素:路线规划和遍历。前者比后者更具“创造力”。
路线规划是确定玩家应该整体导航以完成游戏的方式,并且通常是奔跑过程中最重要的部分。例如,这类似于选择使用哪种排序方法。世界上最好的气泡排序根本不会胜过100万个元素的快速排序。
然而,在追求完美的过程中,遍历(路线的执行方式)也是一个巨大的因素。继续类推,这就是实现排序算法的方式。如果没有非常具体的输入帧,甚至无法执行某些路由。这是最繁琐的工具辅助过程,因此完成完整生产的过程要花费数月甚至数年。对于人类而言,这不是一个困难的过程,因为它可以尝试对同一想法进行不同的变体,直到被认为是最好的,但是人类只能在注意力范围上尝试如此多的变体。在这里,将计算机应用于此任务似乎是正确的。
我现在的目标是尝试使Nintendo 64系统的遍历过程自动化。对于这个问题的搜索空间是远远太大用蛮力的方法来攻击。N64运行的n帧段具有2个30n可能的输入,这意味着仅30帧输入(每秒30FPS)就有2 900个可能的输入;测试这些潜在的解决方案是不可能的,更不用说整整运行两个小时了。
但是,我对尝试(或者甚至不想尝试)完整的全局全局优化没有兴趣。相反,在给定初始输入的情况下,我想近似某个运行特定段的局部最优值(对于某种半全局优化,则近似为n个局部最优值)。也就是说,给定一条路线和该路线的初始遍历:搜索该遍历的邻居以最大程度地降低成本,但不要退化为尝试所有可以解决问题的情况。
因此,我的程序应采用启动状态,输入流,评估函数,并通过使评估结果最小化来输出局部最优值。
当前状态
目前,我已经处理了所有框架。这包括通过仿真器的操作,设置和拆卸,配置等评估输入流。作为各种占位符,优化器是一种非常基本的遗传算法。它只是评估输入流的总数,存储/替换获胜者,并通过更改获胜者流来生成新的总数。这个过程一直持续到满足一些任意标准,例如时间或世代号。
注意,到目前为止,该程序最慢的部分将是对输入流的评估。这是因为这涉及到模拟n帧游戏。(如果有时间,我要编写自己的仿真器来提供此类功能的钩子,但是现在,我剩下的工作是合成消息并为来自另一个进程的现有仿真器修改内存。)在我的主计算机上,相当现代,评估200帧大约需要14秒。因此,我更喜欢一种算法(给定的选择),该算法可以最大程度地减少函数求值的次数。
我在框架中创建了一个同时管理模拟器的系统。这样,我可以立即以线性性能尺度评估多个流,但是实际上,在系统性能下降之前,正在运行的仿真器的数量只能是8到32(并且实际上是在推动它)。这意味着(根据选择),可以在进行评估时执行处理的算法将非常有益,因为优化器可以在等待评估时进行一些繁重的工作。
作为测试,我的评估功能(对于游戏Banjo Kazooie)是每帧求出从玩家到目标点的距离之和。这意味着最佳解决方案是尽可能快地接近该点。仅将突变限制在模拟摇杆上,就花了一天的时间才得到一个好的解决方案。(这是在我实现并发之前。)
添加并发之后,我启用了A按钮按下的突变,并在需要跳转的区域执行了相同的评估功能。在运行24个仿真器的过程中,从最初空白的输入流中花费了大约1个小时才能达到目标,但可能要花几天时间才能达到接近最佳的水平。
问题
我面临的问题是,我对数学优化领域的了解不足,无法知道如何正确地对我的优化问题建模!例如,我可以大致遵循Wikipedia上描述的许多算法的概念,但是我不知道如何对问题进行分类或如何为该类别选择最新的算法。
据我所知,我在一个非常大的邻里中遇到一个组合问题。最重要的是,评估功能非常不连续,没有梯度,并且有很多平稳状态。而且,约束不多,但如果可以解决问题,我很乐意添加表达约束的能力;我想允许指定例如不应使用“开始”按钮,但这不是一般情况。
题
所以我的问题是:如何建模?我要解决哪种优化问题?我应该使用哪种算法?我不害怕阅读研究论文,所以让我知道我应该阅读什么!
直觉上,遗传算法不可能是最好的,因为它似乎并没有真正学习。例如,如果按Start(开始)似乎总是使评估变得更糟(因为它使游戏暂停),那么应该有一些设计师或大脑可以学习:“在任何时候按Start都是没有用的。” 但是,即使达到这个目标也不是那么简单,因为有时按启动是最佳选择,例如在Super Mario 64中所谓的“暂停向后跳远” !在这里,大脑必须学习一个更为复杂的模式:“按下开始是没有用的,除非玩家处于这种非常特定的状态,并且会继续进行某些按键组合。”
似乎我应该(或机器可以学习)以更适合修改的其他方式表示输入。每帧输入似乎太细粒度了,因为真正需要的是“动作”,它可能跨越多个帧...但是许多发现是逐帧进行的,因此我不能完全排除它(上述暂停向后长跳需要帧级精度)。似乎也可以串行处理输入,这是可以利用的事实,但我不确定如何使用。
目前,我正在阅读(反应式)禁忌搜索,超大规模邻域搜索,基于教学的优化以及蚁群优化。
除了随机遗传算法,这个问题是否真的很难解决?还是实际上是一个很久以前解决的琐碎问题?感谢您的阅读,并预先感谢您的任何答复。