我正在使用ifort 18.0.2编译器,在Fortran 90/95中编写Monte Carlo模拟程序的checkpoint功能。在详细说明之前,我想澄清一下我正在使用的伪随机生成器版本:
A C-program for MT19937, with initialization, improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Code converted to Fortran 95 by Josi Rui Faustino de Sousa
Date: 2002-02-01
请参考mt19937获取源代码。
我的蒙特卡罗模拟代码的一般结构如下:
program montecarlo
call read_iseed(...)
call mc_subroutine(...)
end
在read_iseed
函数中
subroutine read_iseed(...)
use mt19937
if (Restart == 'n') then
call system('od -vAn -N4 -td4 < /dev/urandom > '//trim(IN_ISEED)
open(unit=7,file=trim(IN_ISEED),status='old')
read(7,*) i
close(7)
!This is only used to initialise the PRNG sequence
iseed = abs(i)
else if (Restart == 'y') then
!Taking seed value from the latest iteration of previous simulation
iseed = RestartSeed
endif
call init_genrand(iseed)
print *, 'first pseudo-random value ',genrand_real3(), 'iseed ',iseed
return
end subroutine
根据我的理解,如果种子值保持不变,伪随机数生成器应该能够每次重现相同的伪随机序列?
为了证明这一点,我使用相同的种子值运行了两个独立的模拟,它们能够重现完全相同的序列。到目前为止一切都很好!
基于之前的测试,我进一步假设无论在一个单独的模拟中调用多少次init_genrand()
,PRNG也应该能够重现伪随机值序列?所以我对我的read_iseed()
子程序进行了一些修改。
subroutine read_iseed(...)
use mt19937
if (Restart == 'n') then
call system('od -vAn -N4 -td4 < /dev/urandom > '//trim(IN_ISEED)
open(unit=7,file=trim(IN_ISEED),status='old')
read(7,*) i
close(7)
!This is only used to initialise the PRNG sequence
iseed = abs(i)
else if (Restart == 'y') then
!Taking seed value from the latest iteration of the previous simulation
iseed = RestartSeed
endif
call init_genrand(iseed)
print *, 'first time initialisation ',genrand_real3(), 'iseed ',iseed
call init_genrand(iseed)
print *, 'second time initialisation ',genrand_real3(), 'iseed ',iseed
return
end subroutine
输出结果与我的预期不同,尽管在两次初始化之间
iseed
的输出是相同的,但genrand_real3()
的输出却不同。由于这个意外的结果,我很难在系统的任意状态下恢复模拟,因为模拟无法再现我正在模拟的系统的最新配置状态。我不确定是否提供了足够的信息,请让我知道如果这个问题的任何部分需要更具体的说明。
init_genrand
如何填充完整的 PRNG 状态? - francescalus