下标越界,有界随机游走的迭代
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
我正在尝试编写一个函数来生成受单位球体约束的随机游走,从而产生由向量给出的随机游走的最后位置。为了弄清楚我的功能在哪里中断,我试过这样拼凑它:
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