2012-02-17 54 views
1

我不知道是不是这个正确的空间问这个问题。如果没有,我很抱歉。 我是Fortran的新用户,为以下内容花费大量时间。调用函数

我已经构建了一个名为“loglike”的函数,它根据两个参数返回一个实数。我想用这个函数来构造一个mcmc算法,它是这样的。

psi = min(0, loglike(propalpha,propbeta) - loglike(currentalpha,currentbeta)) 

其中propalpha = currentalpha + noise,和propbeta = currentbeta + noise,噪声是从一些分布的随机样本。

现在我想通过调用之前构造的函数“loglike”来使用这个算法。

1)我怎样才能调用函数'loglike'为主程序的新程序
2)我怎样才能使用这个子程序?

任何帮助对我来说都非常棒。 在此先感谢

编辑:

module mcmc 

implicit none 

contains 

    subroutine subru(A,B, alphaprop, betaprop) 
     real, intent(in)::A,B 
     real, intent(out)::alphaprop, betaprop 
    end subroutine subru 

    real function aloglike(A,B) 
     real:: A,B,U, aloglike 
     aloglike = U 
    end function aloglike 

end module mcmc 


program likelihood 
    use mcmc 

    implicit none 

    real :: alpha,beta,dist1,dist2,prob1,prob2 
    real:: psi,a(1000),b(1000), u1, u2,u, alphaprop, betaprop 
    real, dimension(1:1):: loglike 
    integer :: t,i,j,k,l 
    real, dimension(1:625):: x 
    real, dimension(1:625):: y 
    integer, dimension(1:625):: inftime 

    alpha = 0.5 
    beta = 2.0 

    open(10, file = 'epidemic.txt', form = 'formatted') 
    do l = 1,625 
     read(10,*,end = 200) x(l), y(l), inftime(l) 
    enddo 
200 continue 

    loglike = 0.0 
    do t=1,10 
     do i=1,625 
      if(inftime(i)==0 .or. t < (inftime(i)-1)) then 
       dist1 = 0.0 
       do j = 1, 625 
        if(t >= inftime(j) .and. inftime(j)/=0)then 
         dist1 = dist1 + sqrt((x(i) - x(j))**2 + (y(i) - y(j))**2)**(-beta) 
        endif 
       enddo 
       prob1 = 1 - exp(-alpha * dist1) 
       loglike = loglike + log(1 - prob1) 
      endif 

      if(inftime(i) .eq. (t+1)) then 
       dist2 = 0.0 
        do k=1, 625 
        if(t >= inftime(k) .and. inftime(k)/=0) then 
         dist2 = dist2 + sqrt((x(i) - x(k))**2 + (y(i) - y(k))**2)**(-beta) 
        endif 
       enddo 
       prob2 = 1 - exp(-alpha * dist2) 
       loglike = loglike + log(prob2) 
      endif 
     enddo 
    enddo 

    do i = 2, 1000 
     a(1)= 0.0 
     b(1) = 0.0 
     call subru(a(i),b(i), alphaprop, betaprop) 
     call random_number(u1) 
     call random_number(u2) 

     alphaprop = a(i-1) + (u1*0.4)-0.2 
     betaprop= b(i-1) + (u2*0.4)-0.2 

     if(alphaprop> 0 .and. alphaprop < 0.2 .and. betaprop > 0 .and. betaprop < 0.2)then 
      psi = min(0.0,aloglike(alphaprop,betaprop)- aloglike(a(i-1),b(i-1))) 
      call random_number(u) 

      if(u < psi)then 
       a(i)= alphaprop 
       b(i) = betaprop 
      else 
       a(i) = a(i-1) 
       b(i) = b(i-1) 
      endif 
     endif 
    enddo 

    do j = 1, 1000 
     print *, A(j), A(j), LOGLIKE 
    enddo 

end program 
+1

aloglike使用变量“u”,它没有在该函数中定义。它看起来在定义之前使用了变量“size”。两条建议:1)从片段开始,让它们工作,然后添加更多。 2)打开编译器的所有调试选项。例如,你的编译器应该告诉你,你已经声明了两次aloglike。你在用什么编译器? – 2012-02-18 18:33:14

+0

哪个厂商的f90编译器? gfortran,英特尔ifort等?哪个操作系统? – 2012-02-18 21:30:52

+0

如果您在不同的文件中有类似日志,你不需要在这个文件中使用aloglike。你可以将它移动到这个文件,以便它在同一个模块中?如果没有,那么把这两个文件名放在编译命令上:如:“gfortran loglike.f90 myprog.f90 -o myprog.exe”。我建议在gfortran中包含以下选项以帮助您找到程序问题:-O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file- fcheck = all -std = f2008 -pedantic -fbacktrace。 – 2012-02-18 22:57:29

回答

2

这是它看起来的一般方式。请注意,函数通过将结果分配给自己的名称来返回一个值。 A return声明是没有必要的。

C "loglike" is renamed "aloglike" so implicit typing uses REAL 
C A type declaration could be used instead 

    function aloglike (alpha, beta) 
     aloglike = ... (expression which computes value) 
    end 

    program whateveryouwanttocallit 
     ... 
     propalpha = ... 
     propbeta = ... 
     currentalpha = ... 
     currentbeta = ... 
     ... 
     psi = min(0, aloglike(propalpha,propbeta) - aloglike(currentalpha,currentbeta)) 
     print *, 'psi = ', psi 

    end 
+0

对不起,我无法正确上传我的代码。我遇到的问题是如何使用给定的程序启动主程序和子程序?所以,如果你给出了代码的外线,这对我来说会很好。谢谢 – David 2012-02-17 21:26:34

+0

@David:我确实给出了纲要。只需将所有这些行放在一个文件中,用适当的逻辑替换'...',编译并运行。 – wallyk 2012-02-17 21:52:03

4

最简单,最可靠的方法是把你的功能和子程序模块中和“使用”这个模块从你的主程序。这可以在一个文件中完成。此方法使过程(函数和子例程)的接口已知,以便编译器可以检查调用(实际参数)和调用(虚参数)中参数之间的一致性。示意图:

module mysubs 

implicit none 

contains 

subroutine sub1 (xyz) 
    declarations 
    code 
end subroutine sub1 

function func2 (u) 
    declarations 
    code 
    func2 = ... 
end func2 

end module mysubs 

program myprog 

use mysubs 

implicit none 

declarations... 

call sub1 (xyz) 

q = func2 (z) 

end program myprog 

ADDED:“隐式无”用于禁用隐式键入,这在我看来是危险的。所以你需要键入所有的变量,包括函数中的函数名。您可以从模块的其他过程调用子例程和函数 - 它们将自动被识别。所以如果你愿意,你可以使用“sub1”中的“func2”。对于模块之外的实体(例如主程序),您必须“使用”模块。

+0

我把你的代码示例放入问题中。你会想在函数fun的声明中使用“real :: fun”。可能最好在模块中包含loglike ......显然这些骨架中缺少很多部分。你还有问题吗? – 2012-02-18 04:52:49

+0

@ M.B.S你能通过编辑2的上面的示例代码,并告诉我什么是错误的? – David 2012-02-18 13:51:08