【问题标题】:Generating a set of pseudorandom numbers satisfying following xor-property?生成一组满足以下异或属性的伪随机数?
【发布时间】: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


【解决方案1】:

该集合应该具有每个子集的 XOR 组合不应导致值 0 的属性。

恕我直言,这会将子集的最大数量限制为 64(Pigeonhole 原则);对于 >64 个子集,总会有一个(非空)子集异或为零。对于较小的子集,可以满足该属性。

为了进一步说明我的观点:考虑一个包含 64 个未知变量的 64 个方程的系统。然后,添加一个额外的方程。方程和变量是布尔值这一事实并没有使问题有所不同。

--EDIT/UPDATE--: 由于应用程序似乎是游戏“connect-four”,因此您可以枚举所有可能 配置。无法对不可能的电路板配置进行编码将节省足够的编码空间以适应 64 位中的任何有效电路板位置:

将彩色宝石编码为 {A,B},与 {X} 无关,(hight=6)列的配置可以是以下之一:

                   X
                X  X
             X  X  X
          X  X  X  X
       X  X  X  X  X
_   A  A  A  A  A  A   <<-- possible configurations for one pile
--+--+--+--+--+--+--+ 
1   1  2  4  8 16 32   <<-- number of combinations of the Xs
               -2 -5   <<-- number of impossible Xs

(对于 B 而不是 A 类似)。堆下面的数字是顶部 X 的可能性数量,负数是禁止/不可能配置的数量。对于一个 A 和 4 个 X 的列,X 的每个值都是有效的,*除了 3*A(游戏已经结束)。最右边的那堆也一样:下面的3个X不能全是A,X不能全是X。

这导致总共 1 + 2 * (63-7) := 113。 (1 为空板,2 为颜色数)。所以:113 是一列的配置数,非常适合 7 位。对于 7 列,我们需要 7*7:=49 位。 (我们可能会为 L/R 镜像对称节省一点,甚至可能为颜色对称节省一点,但这只会使事情复杂化,恕我直言)。

还有很多编码空间被浪费了(列不是独立的,板上As的数量等于B的数量,或者多一个,等等),但是我不要认为避免它们很容易。幸运的是,这不是必需的。

【讨论】:

  • 我不太确定我是否可以关注你。在我看来,一列应该有 2^0 + 2^1 + ... + 2^6 - 3 = 127 种可能性(3 是无效列,其中连续 6 或 5 列)。毕竟,这 7 列仍然适合 64 位变量,其中一位保留用于我的目的(因此感谢您的想法) ant 将列映射到 7 位值,查找表(具有 127 列)可能是用过的。您能否解释一下如何将鸽巢原理应用于我的问题?
  • 不仅连续5个或6个无效;连续 4 个 + XX 也是无效的(不可能/无法到达),因为游戏已经结束了。鸽巢原理有点夸大了。在我的第一次编辑中,我使用 64 个方程和 64 个未知数重新陈述了它。关键是:如果不让某些矩阵行/列成为其他矩阵的函数,您不能拥有超过 64 个(正交)方程。
  • 啊,我明白了,没有必要记住连续 4 个板。但我不确定方程式部分。我们有一个包含 84 个数字的集合和一个包含 2^64 个数字的集合以及 XOR 操作。现在应该有 84*83*...*2*1 建立其他数字的方程。好的,我的计算器显示 84!大约是 3.3*10^126 而 2^64 只有大约 1.8*10^19 因此数字 0 肯定可以通过多种方式生成(鸽笼原理?),还是我错了?
  • 在纸上使用 4 位(16 个可能的哈希)并尝试创建一组超过 4 个正交哈希。 (在这种情况下正交意味着:使得不存在(非空)散列集 XOR 为零)您可以尝试所有 1 位的集或 2 位散列的集。 BTW:导致 113 的计算可能有一些错误,但案例数肯定
  • 我认为,我对可能方程的数量(XOR 组合的数量,给定一组 84 个数字)有误。我必须总结组合!现在我得到 1.93E+025,它仍然比 1.84E+019(64 位范围)大得多。
【解决方案2】:

为了放大 wildplasser:每个 用于区分每个 n 位字符串和每个其他 n 位字符串的散列函数的输出不能短于 n 位。较短的哈希函数是可用的,因为我们只需要避免实际到达的字符串中的冲突,但我们不能希望离线做出明智的选择。只需使用加密安全的 RNG,就会发生以下两种情况之一:(i)您的代码将像 RNG 是真正随机的一样工作,或者(ii,不太可能)您的代码会中断并且(如果它没有被窃听)它将充当加密 RNG 和真正随机性之间的区别,为您带来名声和恶名。

【讨论】:

    【解决方案3】:

    通过 wildplasser 进一步扩大答案,这是一个如何实现 propertyIsNotFullfilled 的想法。

    将一组伪随机数表示为 {0,1} 矩阵。执行Gaussian elimination(使用 XOR 而不是通常的乘法/减法运算)。如果得到最后一行为零的矩阵,则返回true,否则返回false

    当然,当集合的大小接近64时,这个函数会非常频繁地返回true。所以OP中的算法只对相对较小的大小有效。

    为了优化这个算法,你可以保留最后一次高斯消元的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-20
      • 2023-01-03
      • 2015-08-07
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      相关资源
      最近更新 更多