【问题标题】:Connect Four Hash Function: Map close elements to close hash keys连接四个哈希函数:映射关闭元素以关闭哈希键
【发布时间】:2011-05-06 12:22:45
【问题描述】:

我正在编写一个Connect Four 游戏引擎。目前我正在使用Zobrist hashing 为不同的连接四个棋盘位置生成哈希键(为了不做同样的事情两次,评估的棋盘位置存储在哈希表中)。评估的棋盘位置(极小极大树中的节点)总是彼此靠近。不幸的是,关闭的棋盘位置被映射到均匀分布的哈希键,导致大量 cpu 缓存未命中。

是否可以构建一个哈希函数,将关闭的棋盘位置映射到关闭的哈希键?

一个玩家的棋盘位置由以下结构的位板表示:

.  .  .  .  .  .  .  TOP
5 12 19 26 33 40 47
4 11 18 25 32 39 46
3 10 17 24 31 38 45
2  9 16 23 30 37 44
1  8 15 22 29 36 43
0  7 14 21 28 35 42

我不知道这是否可能。 感谢您的帮助!

【问题讨论】:

    标签: algorithm hash


    【解决方案1】:

    我认为这是不可能的。一个好的散列键(如用于棋盘游戏的 zobrist 散列)很可能具有伪随机属性,以实现转置表中键的均匀分布。将“关闭”位置的键在表中彼此靠近与此相矛盾。

    考虑一下:即使您将棋盘位置一对一映射到具有 (2^7-1)^7 个位置的表格,您也无法将“关闭”棋盘位置映射到关闭内存位置:如果低索引的片段会发生变化,位置会很近,但是片段索引越高,每次位置差异都会加倍,而高的片段将相隔数 TB ;-)

    作为国际象棋引擎的作者,我知道这个问题。 AFAIK 还没有人解决这个问题,每个人都使用 zobrist 散列,也许有一些小的修改。

    不管怎样,祝你解决Connect-4好运……我知道以前做过,但还是自己做比较满意;-)

    【讨论】:

      【解决方案2】:

      这里是如何修改您的大概几乎是均匀随机的哈希函数,以使类似的棋盘位置在一定程度上可能出现在附近的哈希中。

      让 hash(gamestate) 成为你现有的函数。我们将创建一个 newhash(gamestate),它使用散列来表示随机行为,但有相当高的概率为密切相关的游戏状态生成彼此接近的散列。

      让棋盘状态的“颜色”成为下一个移动的玩家。如果想找到白玩家的哈希键,请使用 newhash(board) = hash(board)。如果您想找到黑色位置的哈希,请根据您的顺序找到具有最大数量的黑色块,例如在位置 i。从游戏状态中移除棋子 i 并调用修改后的状态 probableparent 然后使用 newhash(board) = hash(probableparent) + i。如果您按可能的放置顺序对位置进行排序(较高的事物作为第一顺序标准出现,也许中间位置作为第二标准出现较早?我真的不知道 connect4 的好策略),那么它很可能在黑转之前的白转可能是父项,因此很好地在您的缓存中,因此我在附近。此外,8 个可能的黑棋走法可能会共享相同的 prev_board 状态,因此具有邻近的散列位置。

      您可以将此想法扩展为一次回滚多个层。假设当前回合 % 3 == 2,移除棋盘位置 i 和 j 的最大两步,然后使用 newhash(board) = hash(board-two-removals-ago) + i*48 + j。

      【讨论】:

      • 这里是凌晨 1 点,所以我现在不明白 ;-) 在您的文本中,hash() 是一个随机散列函数吗? newhash() 是基于前一个hash的增量hash函数,有什么区别?你如何确保 hash() == newhash() 一直都是?
      • 我试图澄清。你不希望 hash() == newhash() 一直(因为 hash() 的局部性很差)。关键思想是利用游戏状态的结构,使得 newhash(g) = hash(g') + 相关游戏状态 g 和 g' 的小偏移量。
      • 但不是一直要求 hash() == newhash() 吗?想象一下,您有一个通过 newhash() 生成的位置散列,并且想要检查该位置散列是否已经通过不同的移动顺序达到(这实际上是转置表的要点)。存储的位置现在可能具有不同的哈希值,因此您将找不到它。
      • 假设你有一个位置 p1 和一个移动 m1 和一个 p2,m2 导致相同的位置 p。现在,如果您想在哈希中找到 p,则需要 hash(p1)+i(m1) == hash(p2)+i(m2) (同样,这就是转置表的目的)。如果 hash() 是伪随机的(根据密钥的平均分配所要求的)并且 i() 是一些“近”函数,那怎么能实现呢?请举一些hash()和i()的例子,我很感兴趣
      • 如果g = g*,则要求newhash(g) = newhash(g*),无论生成g和g*的轮次顺序如何。 newhash() 具有此属性。仔细阅读,我没有提到任何关于玩家行动的顺序,只有游戏的状态。最大编号的棋子只是棋盘的一个属性,而不是回合顺序。
      猜你喜欢
      • 2013-07-29
      • 2018-04-14
      • 2015-08-31
      • 1970-01-01
      • 2013-12-11
      • 1970-01-01
      • 2013-08-05
      • 2016-04-17
      • 1970-01-01
      相关资源
      最近更新 更多