如何在 Fortran 随机模拟器代码中更改种子数
How to change seed number in Fortran stochastic simulator code
我是 运行 Fortran 代码,它执行标记泊松簇过程的随机模拟。实际上,事件属性(例如发生时间)是通过反演方法生成的,即通过累积分布函数的随机抽样生成。
由于泊松随机性,我希望每个生成的序列都不同,但事实并非如此。我想原因是伪随机数生成器的种子在每次模拟中都是相同的。
我不懂 Fortran,所以我不知道如何解决这个问题。这是伪随机数生成器涉及的代码部分,知道吗?
subroutine pseud0(r)
c generation of pseudo-random numbers
c data ir/584287/
data ir/574289/
ir=ir*48828125
if(ir) 10,20,20
10 ir=(ir+2147483647)+1
20 r=float(ir)*0.4656613e-9
return
end
subroutine pseudo(random)
c wichmann+hill (1982) Appl. Statist 31
data ix,iy,iz /1992,1111,1151/
ix=171*mod(ix,177)-2*(ix/177)
iy=172*mod(iy,176)-35*(iy/176)
iz=170*mod(iz,178)-63*(iz/178)
if (ix.lt.0) ix=ix+30269
if (iy.lt.0) iy=iy+30307
if (iz.lt.0) iz=iz+30323
random=mod(float(ix)/30269.0+float(iy)/30307.0+
& float(iz)/30323.0,1.0)
return
end
首先,我会回顾 PRNG 的现代文献并选择一个现代实现。其次,我会用现代 Fortran 重写代码。
您需要遵循@francescalus 的建议并有更新种子的方法。在不尝试使您的代码现代化的情况下,这是 pseud0
prng
的一种方法
subroutine init0(i)
integer, intent(in) :: i
common /myseed0/iseed
iseed = i
end subroutine init0
subroutine pseud0(r)
common /myseed0/ir
ir = ir * 48828125
if (ir) 10,20,20
10 ir = (ir+2147483647)+1
20 r = ir*0.4656613e-9
end subroutine pseud0
program foo
integer i
real r1
call init0(574289) ! Original seed
do i = 1, 10
call pseud0(r1)
print *, r1
end do
print *
call init0(289574) ! New seed
do i = 1, 10
call pseud0(r1)
print *, r1
end do
print *
end program foo
我是 运行 Fortran 代码,它执行标记泊松簇过程的随机模拟。实际上,事件属性(例如发生时间)是通过反演方法生成的,即通过累积分布函数的随机抽样生成。 由于泊松随机性,我希望每个生成的序列都不同,但事实并非如此。我想原因是伪随机数生成器的种子在每次模拟中都是相同的。 我不懂 Fortran,所以我不知道如何解决这个问题。这是伪随机数生成器涉及的代码部分,知道吗?
subroutine pseud0(r)
c generation of pseudo-random numbers
c data ir/584287/
data ir/574289/
ir=ir*48828125
if(ir) 10,20,20
10 ir=(ir+2147483647)+1
20 r=float(ir)*0.4656613e-9
return
end
subroutine pseudo(random)
c wichmann+hill (1982) Appl. Statist 31
data ix,iy,iz /1992,1111,1151/
ix=171*mod(ix,177)-2*(ix/177)
iy=172*mod(iy,176)-35*(iy/176)
iz=170*mod(iz,178)-63*(iz/178)
if (ix.lt.0) ix=ix+30269
if (iy.lt.0) iy=iy+30307
if (iz.lt.0) iz=iz+30323
random=mod(float(ix)/30269.0+float(iy)/30307.0+
& float(iz)/30323.0,1.0)
return
end
首先,我会回顾 PRNG 的现代文献并选择一个现代实现。其次,我会用现代 Fortran 重写代码。
您需要遵循@francescalus 的建议并有更新种子的方法。在不尝试使您的代码现代化的情况下,这是 pseud0
prng
subroutine init0(i)
integer, intent(in) :: i
common /myseed0/iseed
iseed = i
end subroutine init0
subroutine pseud0(r)
common /myseed0/ir
ir = ir * 48828125
if (ir) 10,20,20
10 ir = (ir+2147483647)+1
20 r = ir*0.4656613e-9
end subroutine pseud0
program foo
integer i
real r1
call init0(574289) ! Original seed
do i = 1, 10
call pseud0(r1)
print *, r1
end do
print *
call init0(289574) ! New seed
do i = 1, 10
call pseud0(r1)
print *, r1
end do
print *
end program foo