下标越界,有界随机游走的迭代

Subscript out of bounds, iteration for a bound random walk

我正在尝试编写一个函数来生成受单位球体约束的随机游走,从而产生由向量给出的随机游走的最后位置。为了弄清楚我的功能在哪里中断,我试过这样拼凑它:

norm_vec <- function(x) sqrt(sum(x^2))
sphere_start_checker <- function() {
        repeat {
        start_loc <- runif(3, min = -1, max = 1)
        if (norm_vec(start_loc) < 1) return(start_loc)
        }
}

n <- 10
set.seed(1)
new_loc <- as.matrix(t(sphere_start_checker()))
temp_loc <- as.matrix(t(c(0, 0, 0)))
for(i in n) {
repeat {
        temp_loc <- new_loc[i, ] + runif(3, min = -.01, max = .01)
        if (norm_vec(temp_loc) < 1) {
                return(new_loc <- rbind(new_loc, temp_loc))
        }
}
}
new_loc

我收到错误:new_loc[i, ] 中的错误:下标越界

但是,当我在 for 循环之外手动迭代代码时,一切正常。我认为这与 R 的作用域规则有关,我曾尝试将 rbind 的结果分配给全局环境,但这不起作用。

最初,我尝试这样编写函数:

randomwalk_sphere <- function(n, radius, stepmax) {
        # initialize sphere bounds
        sphere_radius <- as.double(radius)
        # initialize random starting vector
        # while loop that adds a random vector to our start_loc n times, repeating once boundary condition is met
        loop <- 0
        new_loc <- sphere_start_checker()
        while(loop <= n) {
                repeat {
                        temp_loc <- new_loc + runif(3, min = -stepmax, max = stepmax)
                        if (norm_vec(temp_loc) < sphere_radius) {
                                return(assign("new_loc", temp_loc, env = .GlobalEnv))
                        } 
                }
                loop <- loop + 1
        }
        new_loc
}

但是当我这样做时,while 循环似乎不起作用,我只是从均匀分布而不是随机游走中获得初始 new_loc 坐标。我意识到使用 rbind 可能是一种更正确的方法,但我有兴趣了解为什么这种方法不起作用。

一些想法:

  • 虽然您“修复”了 for (i in n) 的问题,但规范(更常见)的方法通常是将 n 保留为单一长度计数,并使用seq_len(n)for 调用中的类似内容,例如 n <- 10; for (i in seq_len(n)).

  • return 在正式 function(.){..} 声明之外的任何地方都是不正确的;如果你想停止repeat,使用break。如此处所示,重新分配的范围不正确,因此 new_loc 从未真正重新分配所有迭代结果。

最终,一旦您停止尝试从非函数 return,它就会起作用。

n <- 10
set.seed(1)
new_loc <- as.matrix(t(sphere_start_checker()))
temp_loc <- as.matrix(t(c(0, 0, 0)))
for (i in seq_len(n)) {
  repeat {
    temp_loc <- new_loc[i, ] + runif(3, min = -.01, max = .01)
    if (norm_vec(temp_loc) < 1) {
      new_loc <- rbind(new_loc, temp_loc)
      break
    }
  }
}
new_loc
#                [,1]       [,2]      [,3]
#          -0.4689827 -0.2557522 0.1457067
# temp_loc -0.4608185 -0.2617186 0.1536745
# temp_loc -0.4519250 -0.2585026 0.1562568
# temp_loc -0.4606893 -0.2643831 0.1497879
# temp_loc -0.4569488 -0.2667010 0.1551848
# temp_loc -0.4569948 -0.2623487 0.1650229
# temp_loc -0.4593941 -0.2567998 0.1737170
# temp_loc -0.4651513 -0.2537663 0.1662281
# temp_loc -0.4698069 -0.2560440 0.1564959
# temp_loc -0.4721591 -0.2486502 0.1533029
# temp_loc -0.4725175 -0.2466589 0.1531737