2013-04-09 4 views
3

랜덤 워크 메트로폴리스를 수행하기 위해 작은 C 코드를 작성했습니다.이 코드는 실행시 R이 동결됩니다. 코드의 어느 부분이 정확하지 않은지 잘 모르겠습니다. 나는이 Peng and Leeuw tutorial (6 페이지)을 따른다. 부인으로 : 나는 C와 많은 경험이없는, 그것을 컴파일 후 C++C 코드를 호출하면 R이 동결됩니다.

#----C code -------- 
#include <R.h> 
#include <Rmath.h> 

void mcmc(int *niter, double *mean, double *sd, double *lo_bound, 
      double *hi_bound, double *normal) 
{ 
    int i, j; 
    double x, x1, h, p; 
    x = runif(-5, 5); 
    for(i=0; i < *niter; i++) { 
     x1 = runif(*lo_bound, *hi_bound); 
     while((x1 + x) > 5 || (x1 + x) < -5) 
      x1 = runif(*lo_bound, *hi_bound); 
     h = dnorm(x+x1, *mean, *sd, 0)/dnorm(x, *mean, *sd, 0); 
     if(h >= 1) 
      h = 1; 
     p = runif(0, 1); 
     if(p < h) 
      x += x1; 
     normal[i] = x; 
    } 
} 


#-----R code --------- 
foo_C<-function(mean, sd, lo_bound, hi_bound, niter) 
{ 
    result <- .C("mcmc", as.integer(niter), as.double(mean), as.double(sd), 
       as.double(lo_bound), as.double(hi_bound), normal=double(niter)) 
    result[["normal"]] 
} 

의 몇 가지 기본적인 지식을 가지고 :

dyn.load("foo_C.so") 
foo_C(0, 1, -0.5, 0.5, 100) 

FOLLOW UP :while 루프는 문제가있는 곳. 그러나이 문제의 근본 원인은 lower bound와 upper bound 사이의 무작위 변수를 생성하는 함수 runif과 관련이있는 것 같습니다. 그러나 함수가 실제로하는 것은 무작위로 상한값 (5) 또는 하한값 (-5) 중 하나를 선택하는 것입니다.

+3

@ 알렉스, 내가 defintely 이런 종류의 일을 수행하는'Rcpp'를 사용하는 것이 좋습니다 것입니다. 이 패키지를 사용하여'R'과'C \ C++ '를 통합하는 데는 두통이 적다. –

+0

@PaulHiemstra 제안에 감사드립니다! Dirk Eddelbuettel의 PowerPoint 자습서를 살펴 보았습니다. 하지만 불행히도 작동하지 않는 코드를 이미 작성 했으므로 적어도 문제가 무엇인지 파악해야한다고 생각했습니다. :) – Alex

+2

문제의 원인이되는 행을 찾기 위해 C 코드를 단순화하려고 시도 했습니까? 어쩌면 모든 것을 주석 처리하고 라인별로 추가 할 수 있습니다. 어쩌면 당신은 그런 식으로 문제를 좁힐 수 있을까요?! –

답변

4

Writing R Extensions, 6.3 Random number generation 섹션의 지침에 따라 R의 난수 생성 루틴을 호출하기 전에 GetRNGstate();으로 전화해야합니다. 완료되면 PutRNGstate();으로 전화해야합니다.

코드가 작동하기 시작한 이유는 mcmc C 함수를 호출하기 전에 R 세션에서 set.seed을 호출했기 때문일 수 있습니다.

그래서 C 코드는 다음과 같아야합니다

#include <R.h> 
#include <Rmath.h> 

void mcmc(int *niter, double *mean, double *sd, double *lo_bound, 
      double *hi_bound, double *normal) 
{ 
    int i; 
    double x, x1, h, p; 
    GetRNGstate(); 
    x = runif(-5.0, 5.0); 
    for(i=0; i < *niter; i++) { 
     x1 = runif(*lo_bound, *hi_bound); 
     while((x1 + x) > 5.0 || (x1 + x) < -5.0) { 
      x1 = runif(*lo_bound, *hi_bound); 
      //R_CheckUserInterrupt(); 
     } 
     h = dnorm(x+x1, *mean, *sd, 0)/dnorm(x, *mean, *sd, 0); 
     if(h >= 1) 
      h = 1; 
     p = runif(0, 1); 
     if(p < h) 
      x += x1; 
     normal[i] = x; 
    } 
    PutRNGstate(); 
} 
+0

... Rcpp를 사용할 때'RNGScope' 클래스를 통해 훨씬 쉽게 접근 할 수 있는데'sourceCpp)'도 자동으로 추가됩니다. –

+0

@DirkEddelbuettel : Rccp는 "학습"목록에서 다음 일입니다. D. 그리고 여호수아 : 설명 해줘서 고마워. 매우 감사. – Alex

관련 문제