设置随机种子的问题

时间:2016-08-09 16:52:32

标签: random fortran fortran90

我正在尝试编写蒙特卡罗算法来模拟人口中代理之间的交互。该算法需要在每次迭代时调用两个随机数(例如,10 ^ 9次迭代)。

我的问题在于,每当我更改种子(以获得不同的实现)时,RNG都会给我相同的输出(相同的蒙特卡洛事件)。我尝试了不同的方法来实现它,但无济于事。

我是Fortran的新手,并从MATLAB复制此代码。我在实施此代码的方式上做错了吗?

以下是我的尝试:

program Gillespie

  implicit none

  integer*8, parameter :: n_max = 10.0**8 ! max. number of iterations
  integer*8 :: t_ext, I_init, S_init, jump, S_now, I_now, i, u
  real*8 :: t, N, a0, tau, st, r1, r2

  real, parameter :: beta = 1000
  real, parameter :: gammma = 99.98
  real, parameter :: mu = 0.02
  real, parameter :: R0 = beta/(gammma+mu)
  integer :: seed = 11

  real, dimension(n_max) :: S_new ! susceptible pop. array
  real, dimension(n_max) :: I_new ! infected pop. array
  real, dimension(n_max) :: t_new ! time array
  real, dimension(5) :: events    ! events array

  open(unit=3, file='SIS_output.dat')

  t = 0                     ! initial time
  N = 40                    ! initial population size

  jump = 1                  ! time increment (save in uniform increments)
  u = 2

  t_ext = 0                 ! extiction time
  I_init = 2                ! initial infected pop.
  S_init = N-I_init         ! initial susceptible pop.

  S_now = S_init
  I_now = I_init

  S_new(1) = S_init         ! initialize susceptibles array
  I_new(1) = I_init         ! initialize infected array
  t_new(1) = t              ! initialize time array

  write(3,*) t_new(1), S_new(1), I_new(1) ! write i.c. to array 

  call random_seed(seed)

  do i=2, n_max
     call random_number(r1)
     call random_number(r2)

     events(1) = mu*N       ! Birth(S)
     events(2) = mu*S_now   ! Death(S)
     events(3) = mu*I_now   ! Death(I)
     events(4) = (beta*S_now*I_now)/N ! Infection
     events(5) = gammma*I_now ! Recovery

     a0 = events(1)+events(2)+events(3)+events(4)+events(5)

     tau = LOG(1/r1)*(1/a0) ! time increment
     t = t + tau            ! update time
     st = r2*a0             ! stochastic time???

     ! update the populations
     if (st .le. events(1)) then
        S_now = S_now + 1
     else if (st .gt. events(1) .AND. st .le. 
 #(events(1) + events(2)))  then
        S_now = S_now - 1
     else if (st .gt. (events(1) + events(2)) .AND. st .le. 
 #(events(1) + events(2) + events(3))) then
        I_now = I_now - 1
     else if (st .gt. (events(1) + events(2) + events(3)) .AND. 
 #st .le. (events(1) + events(2) + events(3) + events(4))) then
        S_now = S_now - 1
        I_now = I_now + 1
     else
        S_now = S_now + 1
        I_now = I_now - 1
     end if

     ! save time in uniform increments
     if(t .ge. jump) then
         t_new(u) = floor(t)
         S_new(u) = S_now
         I_new(u) = I_now

         write(3,*) t_new(u), S_new(u), I_new(u)

         jump = jump+1
         u = u+1
     end if

    ! write(3,*) t_new(i), S_new(i), I_new(i)

    !N = S_now + I_now   ! update population post event

     if(I_now .le. 0) then  ! if extinct, terminate
        print *, "extinct"
        goto 2
     end if 

   end do

 2     end program Gillespie

我感谢所有的投入。感谢。

1 个答案:

答案 0 :(得分:0)

您的电话

call random_seed(seed)

很奇怪。我认为不应该没有关键字参数,但它实际上是在询问随机种子数组的大小。

有关初始化种子的正确方法,请参阅

中的示例

https://gcc.gnu.org/onlinedocs/gfortran/RANDOM_005fSEED.html