N元树的最佳数据结构

时间:2019-05-30 14:43:47

标签: c++ c++11 tree artificial-intelligence chess

我需要代表每个节点具有多个分支的树。我应该使用什么结构?用于计算国际象棋比赛状态。它呈指数级爆炸,因此内存将成为一个问题。我正在使用C ++ 11,但可以接受其他标准。另外,修剪应为O(1)。

EDIT1 为了扩大规模,我将举行国际象棋AI比赛。主要的PvP游戏已经完成,接下来我要编写AI API。参赛者将编写自己的AI,然后让他们参加比赛。获胜者的AI将用于玩家对战计算机游戏。我只是在考虑存储我的游戏状态和AI思想的最佳结构。

我正在阅读《深蓝》,它认为从5到25前进。我可以想象,大多数能够使用BFS进行5步移动的计算机,但是任何更深层次的操作,我相信我都必须使用DFS。

AI将会定时,而竞争性AI只会在本地播放,以免在CPU功耗方面带来优势。

我现在正在阅读Monte Carlo和Alpha Beta搜索。

我对数据结构的最初想法如下:

@Effect()
UpdateDashboardConfiguration$ = this.actions$.pipe(
  ofType<UpdateDashboardConfiguration>.(DashboardActionTypes.UpdateDashboardWidget),
  withLatestFrom(this.store.select(selectDashboardLayoutStateConfig)),
  switchMap(action => {
    return this.dashboardService.updateDashboardConfiguration(action).pipe(
      map(data => (new UpdateDashboardConfigurationSuccess(data))),
    );
  }
  ),
);

可以通过串联从根到叶子的路径来随时计算木板。尽管重新计算板可能会随着时间的流逝而变得非常昂贵。有想法吗?我应该存放板子吗?该板存储为64个字符索引的数组,其中包含件号。因此,与2相比,它是16字节,但是内存使用将节省大量的电路板状态重新计算。

对于我自己的个人AI,我将实现对游戏状态进行排名的棋盘得分功能,然后将丢弃所有非最大游戏状态,以及通过选择举动而无效的修剪游戏状态。< / p>

1 个答案:

答案 0 :(得分:0)

一种适用于蒙特卡洛树搜索(MCTS)的简单方法是使用某个自定义类的vector。在班级内部,除了子级信息外,您还需要任何状态信息-子级数及其在向量中的索引。这样可以避免为每个孩子存储单独的指针,这可能会导致大量开销。

因此,根在索引0处。在该索引内将有两个整数,指示子代从索引1开始,并且有k个子代。 (从索引1k。)在索引1处,子项将从索引k+1开始,共有l个子项,依此类推。

基于以下假设,这确实很好用:(1)子代的数目是固定的,(2)一次将所有子代添加,并且(3)不会从树中删除状态。

如果您尝试从树中修剪状态,则此方法也不起作用,因为如果删除树中的空隙,则会在树中留下空白。使用显式指针存储每个孩子非常昂贵,因此在实践中还需要做其他事情。

首先,通过alpha-beta搜索,您通常使用DFS搜索树,并且不存储分支。但是,您使用哈希表来存储状态并检查重复项。可以根据状态隐式计算树的分支,因此您可以在不显式存储所有内容的情况下重建树。

但是,请注意,哈希表(在游戏树搜索的上下文中称为换位表)通常不会在树的深处使用,因为存在许多状态,并且存储成本在增加,而删除重复项的好处却在缩小。 / p>

总结,假设您正在做类似alpha-beta的事情,并且您有充分的理由明确地存储树,则建议将状态存储在哈希表中,并保留从移动生成函数隐式计算的边。 (将应用移动并获取结果状态的哈希值以在哈希表中找到它们。如果不存在,则将它们修剪掉。)