在 Javascript 中实现 Zobrist 散列
Posted
技术标签:
【中文标题】在 Javascript 中实现 Zobrist 散列【英文标题】:Implementing Zobrist hashing in Javascript 【发布时间】:2014-09-08 21:53:12 【问题描述】:我需要在 javascript 中为国际象棋引擎实现 Zobrist 散列,我想知道实现这一点的最佳方法是什么。现在,我不是计算机科学家,也从来没有正式的算法和数据结构类,所以如果我在这方面有点偏离,我很抱歉......
据我了解,我需要一个 64 位散列函数来将位置编码为低于该位置的位置会引发太多冲突。现在在 javascript 中,我只能访问 32 位数字。还有一个问题是我如何实现哈希表以及它是如何由节点中的 V8 引擎“在幕后”实现的。
我可以将它作为长度为 TABLESIZE 的 javascript 数组,然后执行以下操作:
var table = new Array();
table[hashCodeLo % TABLESIZE] =
hashCodeLo: hashCodeLo,
hashCodeHi: hashCodeHi,
someProperty: someValue
;
其中 hashCodeLo 和 hashCodeHi 表示代码的高 32 位和低 32 位,TABLESIZE
var table = ;
table[hashCode] =
someProperty: someValue
这里的 hashCode 只是我的 64 位 hashCode 的字符串表示。由于我不确定“字典模式”如何在幕后工作,我不确定哪个更好。另外我不知道我是否通过使用“1983981918391”之类的键而不是更紧凑的表示形式来使用更多内存:
hashCode = String.fromCharCode(FIRST_16BITS, SECOND_16BITS, THIRD_16BITS, FOURTH_16BITS)
我什至不确定这是否符合我的预期......
由于这是引擎的关键部分,因此我希望尽可能多地发挥性能,因此不胜感激。
【问题讨论】:
你在哪个环境下运行 v8 怎么样? 【参考方案1】:据我了解,我需要一个 64 位散列函数来将位置编码为低于该位置会引发太多冲突。
至少不适用于transposition table - 它几乎不会有 264 的大小。
如果您要实现此功能来对位置本身进行编码(并通过比较 64 位哈希来检测一些冲突),那么是的,如果这是文献推荐的,您可以使用 64 位(尽管您可能想尝试52 位也是如此)。
现在在 javascript 中我只能访问 32 位数字。
没有。 JavaScript 中的数字是 64 位浮点数,您最多可以在其中精确存储 52 位整数。只有位运算符仅限于 32 位整数(如有必要,数字将被强制转换为整数)。
但是,数组本身的长度限制为 232;但即使这样也应该绰绰有余。
还有一个问题是我如何实现哈希表以及它是如何由节点中的 V8 引擎“在幕后”实现的。
只需将其实现为数组。尝试用 null
值填充它以进行初始化,并查看非稀疏数组是否表现更好。如果您关心性能,请测试一下。
hashCodeLo 和 hashCodeHi 分别表示代码的高低 32 位,TABLESIZE
我会使用 Uint32Array
而不是对象数组。根据someProperty
和someValue
是什么,您可能只想将对象的索引存储在普通数组或标量本身(可能使用DataView
)中。代码可能如下所示:
var zobrist = new Uint32Array(13 * 2 * 64 * 2) // pieces * colors * fields * 64/32
for (var i=0; i<zobrist.length; i++)
zobrist[i] = Math.random() * 4294967296;
var table = new Uint32Array(3 * tablesize);
function hash(hi, lo, piece, color, field)
hi ^= zobrist[piece * 128 + color * 64 + field];
lo ^= zobrist[piece * 128 + color * 64 + field + 1];
var i = lo % tablesize;
if (table[i] == hi && table[i+1] == lo)
// collision
else
table[i] = hi; table[i+1] = lo;
// do what you want with table[i+2]
【讨论】:
>没有。你是怎么得出这个结论的?有超过 264 个可能的国际象棋位置,您几乎不会尝试存储(甚至枚举)它们。 这似乎是我读过的国际象棋文献中的共识。我知道有超过 2^64 个可能的国际象棋位置,但我再次需要 64 位的密钥来检测合理数量的碰撞。将完整位置存储在转置表中似乎很浪费,而且我还没有看到任何引擎可以做到这一点。通过将其减少到 64 位,我假设您在哈希表大小和未检测到的冲突数之间取得了不错的折衷。我没有对此进行数学计算,我只是按照其他人所做的... 啊,我现在看到您将使用散列来编码实际位置,而不仅仅是转置表索引。我认为 2^64 的哈希表大小会有点大……以上是关于在 Javascript 中实现 Zobrist 散列的主要内容,如果未能解决你的问题,请参考以下文章