2012-02-17 52 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