【发布时间】:2012-03-05 11:40:58
【问题描述】:
给定一个伪随机数生成器int64 rand64(),我想构建一组伪随机数。该集合应具有每个子集的 XOR 组合不应导致值 0 的属性。
我正在考虑以下算法:
count = 0
set = {}
while (count < desiredSetSize)
set[count] = rand64()
if propertyIsNotFullfilled(set[0] to set[count])
continue
count = count + 1
问题是:propertyIsNotFullfilled如何实现?
注意事项: 我喜欢生成这样一个集合的原因如下:我有一个哈希表,其中的哈希值是通过Zobrist hashing 生成的。我没有为每个哈希表条目保留一个布尔值来指示该条目是否已填充,而是认为哈希值(与每个条目一起存储)足以满足此信息(0 ... empty, != 0 ... set )。将此信息作为标记值携带到散列键表中还有另一个原因。我正在尝试从 AoS(结构数组)切换到 SoA(数组结构)内存布局。我正在尝试这样做以避免填充并测试是否存在较少的缓存未命中。我希望在大多数情况下,对 hash-key-table 的访问就足够了(暗示如果条目为空,哈希值会提供信息)。
我还考虑过为这些信息保留哈希值的最重要位,但这会减少可能的哈希值区域,而不是必要的。理论上,该区域将从 264(减去 seninal 0 值)减少到 263。
人们可以用另一种方式阅读这个问题:给定一组 84 个伪随机数,是否有任何数字不能通过对这个集合的任何子集进行异或生成,以及如何得到它?这个数字可以作为哨兵值。
现在,我需要它:我开发了一个连接四游戏引擎。玩家 A 和玩家 B 可能有 6 x 7 的移动。因此有 84 种可能的移动(因此需要 84 个随机值)。棋盘状态的哈希值由预先计算的随机值以下列方式生成:hash(board) = randomset[move1] XOR randomset[move2] XOR randomset[move3] ...
【问题讨论】:
-
这个已经试过了。问题是总有超过 5 层或 6 层的哈希冲突。以这样一种方式组成 Zobrist 表,使得任何一对条目之间的汉明距离最大是唯一可以做的事情。您可以首先将人口计数设置为位数的 1/2 左右,例如32/64。但是一旦超出了神奇的 n 层限制,就会发生碰撞。 (甚至更重)
-
@wildplasser:感谢您的评论,但我不会试图避免冲突,我会尝试将哈希键与其他表条目信息分开。之后,我有一个带有哈希值的
int64数组和一个带有其余部分的allOtherInfo数组。如果int64数组包含信息,如果条目为空,那就太好了。因此我的问题。 -
如果您的唯一目标是避免所有有效状态的
hash(state) == zero,并使用 hash==zero 作为“无效”的标记值:通常只需多花一点点即可表示“is_valid”条件。在某些游戏(围棋)中,空棋盘(大部分)的哈希值为零,但棋盘状态完全合法。不允许零哈希值将花费大量极端情况代码。在表中存储一个额外的“有效”位更便宜、更清洁。你的“有效载荷”到底有多大? -
@wildplasser:我已经用更多信息更新了这个问题。
-
如果游戏是四连接,则只有 3^42 种可能性(其中大多数是无法到达/不可能的。我的直觉是你甚至可以枚举所有有效的棋盘位置。顺便说一句:你不应该散列移动,而是位置。添加移动相当于 HASH(new_position) = HASH(previous_position) @@ hash( added_stone),带有@@ some operator,可能是 xor。BTW2 如果通过是不允许到达的位置数量更少。
标签: algorithm hash bit-manipulation xor