【发布时间】:2017-08-25 13:36:01
【问题描述】:
我正在使用 OMNeT++ 5.1.1 模拟器。我从 bernoulli() 函数中看到了一些奇怪的行为,所以我构建了一个 MWE 来查看发生了什么。
MWE 通过创建具有单个节点的网络并在 t=0 设置一个计时器(自消息)来工作。当计时器关闭时,模拟运行一些 n 次伯努利试验,成功概率为 p。值 n 和 p 是通过我使用 Register_PerRunConfigOption() 宏定义的每次运行配置选项指定的。
这是我的代码:
#include <math.h>
#include <omnetpp.h>
using namespace omnetpp;
Register_PerRunConfigOption(CFGID_NUM_TRIALS, "num-trials", CFG_INT,
"0", "The number of Bernoulli trials to run");
Register_PerRunConfigOption(CFGID_BERNOULLI_MEAN, "bernoulli-mean",
CFG_DOUBLE, "0.0", "The mean of the Bernoulli experiments");
class Test : public cSimpleModule {
private:
int nTrials, nSuccess;
double p;
cMessage *timer;
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Test);
void Test::initialize()
{
nTrials = getEnvir()->getConfig()->getAsInt(CFGID_NUM_TRIALS);
p = getEnvir()->getConfig()->getAsDouble(CFGID_BERNOULLI_MEAN);
timer = new cMessage("timer");
scheduleAt(0.0, timer);
}
void Test::handleMessage(cMessage *msg)
{
int trial;
printf("\n\n");
for (int n = 0; n < nTrials; n++) {
trial = bernoulli(p);
if (trial)
nSuccess++;
}
double mean = nTrials * p;
double variance = mean * (1.0 - p);
double stddev = std::sqrt(variance);
printf("nTrials: %12d(%.3e)\n", nTrials, (double) nTrials);
printf("nSuccess: %12d(%.3e)\n", nSuccess, (double) nSuccess);
printf("Pct.: %12.5f\n", 100.0 * (double) nSuccess / nTrials);
printf("nStdDevs: %12.2f\n", (nSuccess - mean) / stddev);
printf("\n\n");
delete msg;
}
这段代码和我能想到的一样简单(我是 OMNeT++ 的新手)。这是 .ned 文件:
simple Test
{
gates:
}
network Bernoulli
{
submodules:
node: Test;
}
这里是 omnetpp.ini 文件:
[General]
network = Bernoulli
bernoulli-mean = 0.05
num-trials = 10000000
rng-class = "cMersenneTwister"
seed-0-mt = ${seed=0,1,2,3,4,5,6,7,8,9}
我正在使用以下命令运行代码:./exe_file -u Cmdenv -r 3(我有意选择第三次运行)。当我使用上面的 omnetpp.ini 文件执行此操作时,我获得了大约 532,006 次成功(尽管这个数字在每次运行时都会略有变化??)。对于 10^7 次运行,这大约是均值的 46 个标准差(使用二项分布的均值和方差计算)。
此外,如果我注释掉 rng-class="cMersenneTwister" 行,成功次数会跃升至大约 531,793 次,每次都略有变化(但不是根本性变化)。
此外,如果我注释掉 seed-0-mt=... 行,那么模拟突然开始产生 0.06 std 以内的值。开发。的意思!尽管事实上 OMNeT++ 手册确保使用 cMersenneTwister 算法意味着您可以随机选择种子,因为周期是如此之大。
为什么会这样??我希望(1)因为 cMersenneTwister 是默认设置,包括它在 omnetpp.ini 文件中不应该改变任何东西,并且(2)因为我每次都选择相同的种子(即种子 3),那我应该得到相同的结果。但我不是!这让我很困惑,因为 OMNeT++ 手册指出:
对于 cMersenneTwister 随机数生成器,由于 RNG 的序列非常长,因此选择种子以使生成的序列不重叠很容易。 RNG 从 32 位种子值 seed = runNumber*numRngs + rngNumber 初始化。
谢谢!
【问题讨论】:
标签: omnet++