我想有效地模拟漂移d> 0的布朗运动,其中漂移的方向改变,如果超过一些障碍b或-b(没有反射,只是改变漂移方向!)。
for
- 循环是这样做的简单方法
step<-0.1 #step size
sig<-1 #sign of drift
T<-10^4 #length of process
b<-300; d<-0.5#barrier and drift
W<-rep(NA,(T/step))
W[1]<-0
for (i in 2:(T/step))
{
if (W[i-1]>b) {sig<- -1} #change drift to -1
if (W[i-1]< -b) {sig<-1} #change drift to +1
W[i]<-W[i-1]+rnorm(1,d*sig*step,sqrt(step))
}
当然,这个循环在R中需要很长时间,特别是对于小步长。
因此,我对使用矢量运算或apply()
- 命令的更有效的解决方案感兴趣。 (如果是简单的布朗运动,我可以使用cumsum(rnorm())
,这里是否有类似的解决方案?)
非常感谢!!
答案 0 :(得分:1)
您对W[i]
和sig
进行了递归计算,这在每一步都有一些逻辑。在R中可能没有太多可以减少执行时间的因素,但有几件事情会使时间减少近50%。特别是,而不是在每个步骤上调用rnorm
,通过rnorm
调用mean=0
来计算num_step
以计算sig
值并存储结果,从而对此计算进行矢量化。在循环的每个步骤中,此向量的值将添加到该步骤的平均值。确定 step<-0.1 #step size
T<-10^4 #length of process
b<-300; d<-0.5 #barrier and drift
print(system.time({
sig <- 1 #sign of drift
set.seed(123) # set seed
W<-rep(NA,(T/step))
W[1]<-0
for (i in 2:(T/step))
{
if (W[i-1]>b) {sig<- -1} #change drift to -1
if (W[i-1]< -b) {sig<-1} #change drift to +1
W[i]<-W[i-1]+rnorm(1,d*sig*step,sqrt(step))
}
}))
print(system.time({
sig <- 1 # reset value of sig
set.seed(123) # reset seed
num_steps <- trunc(T/step)
W1 <- numeric(num_steps)
ep <- rnorm(num_steps, 0, sqrt(step))
for (i in 2:num_steps) {
if(abs(W1[i-1]) > b) sig <- ifelse( W1[i-1] >b, -1, 1)
W1[i] <- W1[i-1]+d*sig*step +ep[i-1]
}
}))
的值的逻辑也可以简化一点。具有发布方法和新代码的时间的代码是:
W
两项计算W1
和function move(touchDown)
{
if(touchDown)
{
touchMoves = setTimeout(function(){
if (Math.floor(touchX) < Math.floor(player.x + player.width))
{
if ((Math.floor(player.x + player.width) - Math.floor(touchX)) <= 10 )
{
touchDown = false;
clearTimeout(touchMoves);
}
else
{
player.x -= Math.floor(CANVAS_WIDTH / player.width);
}
}
else if ((Math.floor(touchX) == Math.floor(player.x + player.width)) || (player.x == (CANVAS_WIDTH - player.width)))
{
touchDown = false;
clearTimeout(touchMoves);
}
else
{
if ((Math.floor(touchX) - Math.floor(player.x + player.width)) <= 10 )
{
touchDown = false;
clearTimeout(touchMoves);
}
else
{
player.x += Math.floor(CANVAS_WIDTH / player.width);
}
}
if (touchDown)
{
move(touchDown);
}
}, 100);
}
}
mc.on("press", function(ev) {
if (gameIsActive)
{
touchDown = true;
touchX = ev.center.x;
move(touchDown);
}
});
mc.on("pressup", function(ev) {
if (gameIsActive)
{
touchDown = false;
}
});
的结果应该相同。