Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 增强梅森缠绕:如何使用多个值进行播种?_C++_Boost_Boost Random - Fatal编程技术网

C++ 增强梅森缠绕:如何使用多个值进行播种?

C++ 增强梅森缠绕:如何使用多个值进行播种?,c++,boost,boost-random,C++,Boost,Boost Random,我正在使用boost mt19937实现进行模拟 模拟需要是可复制的,这意味着以后要存储和潜在地重用RNG种子。我使用windows crypto api生成种子值,因为我需要种子的外部源,而不是因为任何特定的随机性保证。任何模拟运行的输出都会有一个注释,包括RNG种子-因此种子需要合理地短。另一方面,作为模拟分析的一部分,我将比较几次运行-但为了确保这些运行实际上是不同的,我需要使用不同的种子-因此种子需要足够长以避免意外碰撞 我已经确定64位的种子应该足够了;在大约2^32次运行后,碰撞的概

我正在使用boost mt19937实现进行模拟

模拟需要是可复制的,这意味着以后要存储和潜在地重用RNG种子。我使用windows crypto api生成种子值,因为我需要种子的外部源,而不是因为任何特定的随机性保证。任何模拟运行的输出都会有一个注释,包括RNG种子-因此种子需要合理地短。另一方面,作为模拟分析的一部分,我将比较几次运行-但为了确保这些运行实际上是不同的,我需要使用不同的种子-因此种子需要足够长以避免意外碰撞

我已经确定64位的种子应该足够了;在大约2^32次运行后,碰撞的概率将达到50%——这种概率足够低,以至于由碰撞引起的平均误差对我来说可以忽略不计。仅使用32位种子是很棘手的;在2^16次运行后,碰撞概率已达到50%;这对我的口味来说太可能了

不幸的是,boost实现要么使用一个完整的状态向量(太长了),要么使用一个32位无符号长的种子(不理想)。

如何使用超过32位但小于完整状态向量的生成器种子?我试着只填充向量或重复种子来填充状态向量,但即使粗略地看一眼结果,也会得出很差的结果。

查看:

void种子(UIntType值)
{
//一种新的种子算法
// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
//在以前的版本中,种子的MSB仅影响
//国家x[]。
const UIntType mask=~0u;
x[0]=值和掩码;
对于(i=1;i>(w-2))+i)和掩码;
}
}
对于mt19937
UIntType
uint32\u t
w
为32。对于64位seed,您可以使用该算法使用较低的32位计算状态的每个偶数索引(
x
),使用较高的32位计算状态的奇数索引


(这是一个很好的建议)

你的假设是错误的。对于模拟,您不需要加密强大的种子。事实上,使用种子1,2,3,4等往往是一个更好的主意。Mersenne Twister的输出值将是不相关的,但是没有人会质疑您是否通过樱桃采摘种子来获得所需的模拟输出

对于其他确实有实际需要的人,一个简单的方法是丢弃生成的第一个(seed>>32)值。这将为您提供关于log2(seed>>32)的额外状态位。然而,它只有在您需要一些额外的位时才能有效地工作。以这种方式添加32位可能太慢了


一个更快的算法是为好的随机发生器生成完整的状态向量。问题中提到的解决方案(重复或填充)不太好,因为结果状态向量的随机性有限。但是,如果您从
mersenne_twister(seed1)^mersenne_twister(seed2)
的输出填充初始状态向量,这根本不是问题。

您只需获取当前状态并对其进行修改……您的碰撞数学不太正确。例如,对于64位种子,77163!=65536运行。冲突数学只是一个简单的近似值-我想你是指32位种子,顺便说一句,不是64位种子?我不担心加密安全;我只需要从某处获取种子值。使用顺序种子的缺点是部分管理:如果我使用一些预定的种子序列,这意味着除非我以某种方式管理这些种子,否则每次运行都是相同的(即,在某个地方使用一个文件以确保我不会意外地重用种子)。
mersenne\u twister(seed1)^mersenne\u twister(seed2)存在问题
是指种子值可能相同,在这种情况下,输出为,在这种情况下,输出的XOR为0-用零填充整个状态向量会导致扭曲卡住(我不确定它是否可以逃逸,但肯定不会很快)。但是,如果我区分了单独可检查运行(32位种子可以)和聚合分析运行(顺序种子可以很好),我可以使用您使用顺序种子的想法。我不确定我是否真的可以将此标记为一个答案(尚未?),因为它实际上没有让我获得64位种子;但你确实解决了我的直接需求,+1,非常感谢!请注意,您可以自由选择这对32位种子;只是不要选择完全相同的密码源。当你的加密源给出两个完全相同的密码源时,丢弃一个,然后得到另一个。这意味着你失去了2^64个可能的种子中的2^32个-没什么大不了的。
  void seed(UIntType value)
  {
    // New seeding algorithm from 
    // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
    // In the previous versions, MSBs of the seed affected only MSBs of the
    // state x[].
    const UIntType mask = ~0u;
    x[0] = value & mask;
    for (i = 1; i < n; i++) {
      // See Knuth "The Art of Computer Programming" Vol. 2, 3rd ed., page 106
      x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask;
    }
  }