我有一个Java模拟,我需要使用Uniform
,Exponential
,Poisson
和Gamma
分布 - 我需要使用相同的种子初始化随机流和/或这些分布中的每一个(这样我就可以准确地重现给定固定种子的轨迹)。
我正在使用并行柯尔特(这是柯尔特的多线程版本)。
对于Uniform
,我可以正确地将DoubleUniform
对象播种(从cern.jet.random.tdouble.DoubleUniform
导入后)为:
int fixedSeed = 12345;
doubleUniformDist = new DoubleUniform (0.0, 1.0, fixedSeed);
但是,对于Exponential
、Poisson
和Gamma
分布(全部在cern.jet.random.tdouble
中),我不能通过传递fixedSeed
来做同样的事情 - 因为它们期望传递一个DoubleRandomEngine
对象:
构造函数摘要
Exponential(double lambda, DoubleRandomEngine randomGenerator)
构造负指数分布。
Poisson(double mean, DoubleRandomEngine randomGenerator)
构造泊松分布。
Gamma(double alpha, double lambda, DoubleRandomEngine randomGenerator)
构造一个伽马分布。
有没有办法初始化这些(Exponential
、Poisson
和Gamma
),就像我对Uniform
所做的那样?或者我应该实例化一个父/基类(如果是这样,如何?)cern.jet.random.tdouble
所有这些类都已从中扩展?
笔记:
- 同样,我想要一个随机流(这样我所有的 发行版可以使用来自该流的随机数) - 这是 对于可重复性非常重要。
- 示例仿真可能需要对这些分布进行数百万次采样(总计),因此性能/速度始终是一个问题。
看起来DoubleMersenneTwister
扩展了 DoubleRandomEngine,允许您在其构造函数中设置种子。
各种随机变量生成都以 Uniform(0,1) 随机数开头。Exponential
、Poisson
和Gamma
的构造函数中的最后一个参数是让你提供一个扩展DoubleRandomEngine
抽象类的 Uniform(0,1) 的源。 看起来Parallel Colt提供了六个这样的实现。 您需要选择其中之一,为要生成的每个分配创建一个单独但种子相同的实例,然后使用您创建的DoubleRandomEngine
实例之一构造每个分配对象。 这样,基础的统一价值流将是相同的,并且可以适当地转换为您想要的分布。
这是一个相当简约的实现:
import cern.jet.random.tdouble.*;
import cern.jet.random.tdouble.engine.*;
public class RNG {
public static void main(String[] args) {
// create two instances of Mersenne Twister, seeded identically
DoubleRandomEngine twister1 = new DoubleMersenneTwister(42);
DoubleRandomEngine twister2 = new DoubleMersenneTwister(42);
// print ten values from each, to show they produce identical U(0,1)'s'
for(int i = 0; i < 10; ++i) {
System.out.println(twister1.nextDouble() + ", " + twister2.nextDouble());
}
System.out.println("nNow for some exponentials...n");
// instantiate two exponentials using our two twisters as the
// underlying random engine
Exponential exp1 = new Exponential(3, twister1);
Exponential exp2 = new Exponential(3, twister2);
// and print 10 of 'em to show they're synchronized.
for(int i = 0; i < 10; ++i) {
System.out.println(exp1.nextDouble() + ", " + exp2.nextDouble());
}
}
}
由于Exponential
级将"发动机"产生的制服流转换为指数RV,并且制服的种子相同,因此指数实际上是相同的种子。
所有,谢谢 - 我修好了。看起来我之前得到的不同数字是由于我使用了staticNextDouble()
方法 - 这不适合我的目的,因为staticNextDouble()
使用随机数生成器的内部/默认种子,绕过了我提供的固定外部种子。
在用nextDouble()
替换staticNextDouble()
调用后,我现在可以准确地重现给定固定外部种子的轨迹。