- こちらにself-avoiding pathのシミュレーションがある
- Rcppを使って比較してみる
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp ;
using namespace Rcpp;
IntegerMatrix selfAvoidingPathCpp2(int k,int past,int t,int maxt) {
IntegerMatrix x(t,k);
for(int i=0;i<k;++i){
for(int j=0;j<t;++j){
x(j,i) = 0;
}
}
RNGScope scope;
IntegerVector kv = seq_len(k);
IntegerVector s(2);
s[0] = -1;
s[1] = 1;
IntegerVector r = RcppArmadillo::sample(kv, maxt, TRUE);
IntegerVector rs = RcppArmadillo::sample(s, maxt, TRUE);
int cnt = 0;
for(int i=0;i<maxt;++i){
if(cnt==t-1){
break;
}
IntegerVector here(k);
for(int j=0;j<k;++j){
here[j] = x(cnt,j);
}
IntegerVector toward(k);
for(int j=0;j<k;++j){
toward[j] = here[j];
}
toward[r[i]-1] = toward[r[i]-1]+rs[i];
if(past == 0){
++cnt;
for(int j=0;j<k;++j){
x(cnt,j) = toward[j];
}
}else{
int tmppast = 0;
if(past == -1){
}else{
int tmp2 =cnt-past;
if(tmppast<tmp2){
tmppast = tmp2;
}
}
bool b = TRUE;
for(int j=tmppast;j<cnt+1;++j){
bool b2 = TRUE;
for(int jj=0;jj<k;++jj){
if(x(j,jj) != toward[jj]){
b2 = FALSE;
break;
}
}
if(b2){
b = FALSE;
break;
}
}
if(b){
++cnt;
for(int j=0;j<k;++j){
x(cnt,j) = toward[j];
}
}else{
++cnt;
for(int j=0;j<k;++j){
x(cnt,j) = here[j];
}
}
}
}
return x;
}
library(Rcpp)
library(RcppArmadillo)
library(rgl)
sourceCpp("selfAvoidingPathCpp2.cpp")
selfAvoidingWalkR <- function(k,past=-1,t=100,max.t=1000){
X <- matrix(0,t,k)
R <- sample(1:k,max.t,replace=TRUE)
R.sign <- sample(c(-1,1),max.t,replace=TRUE)
cnt <- 1
for(i in 1:(max.t-1)){
if(cnt==t){
break
}
here <- X[cnt,]
toward <- X[cnt,]
toward[R[i]] <- toward[R[i]] + R.sign[i]
if(past == 0){
cnt <- cnt+1
X <- X[cnt,] <- toward
}else{
if(past == -1){
tmp.past <- 1
}else{
tmp.past <- cnt-past+1
tmp.past <- max(1,tmp.past)
}
if(cnt==tmp.past){
tmp.X <- matrix(X[cnt,],nrow=1)
}else{
tmp.X <- X[tmp.past:cnt,]
}
tmp.d <- apply(abs(t(tmp.X)-toward),2,sum)
if(prod(tmp.d)!=0){
cnt <- cnt+1
X[cnt,] <- toward
}else{
cnt <- cnt+1
X[cnt,] <- here
}
}
}
X
}
-
- cppの方では、既通過点があるかないかの処理のところで、既通過点を順に調べて、あったらループを終了している(本当は近い過去から調べる方が効率的だが、今のソースは遠い過去から調べているので、さらに高速になるはず)のに対して、対象となるすべての過去の点を調べているところは、処理数の違いを生んでいるので、「対等な比較」ではないのだが、おそらくRの方では、既通過点を逐一調べると遅くなるだろうと予想するので、ここではそれは比較しないこととする)
> k<-2
> max.t<-10000
> past <- -1
> t <- 1000
> benchmark(
+ selfAvoidingPathCpp2(k,past,t,max.t),
+ selfAvoidingWalkR(k,past=past,t=t,max.t=max.t),
+ columns=c("test", "replications","elapsed", "relative"),
+ replications=100,
+ order="relative")
test replications
1 selfAvoidingPathCpp2(k, past, t, max.t) 100
2 selfAvoidingWalkR(k, past = past, t = t, max.t = max.t) 100
elapsed relative
1 0.06 1
2 100.68 1678