Индекс за пределами границ, итерация для связанного случайного блуждания

#r #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, вероятно, является более правильным способом сделать это, но мне интересно узнать, почему этот подход не работает.

Комментарии:

1. for (i in n) всегда будет повторяться ровно один раз со значением if i = 10 . Вы намерены seq(n) это сделать ? Кроме того, первый раз, когда вы запускаете for цикл, i равен 10 и new_loc содержит всего 1 строку, поэтому new_loc[10,] сбой должен быть очевиден.

2. Я вижу ошибку в том, что не использую seq_along, однако, если я попробую n <- 1: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_along(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[10,] , он все равно вернет ту же ошибку.

Ответ №1:

Некоторые мысли:

  • в то время как вы «исправили» проблему for (i in n) , канонический (более распространенный) метод, как правило, сохраняется n как счетчик одной длины и используется seq_len(n) или аналогичен в for вызове, например n <- 10; for (i in seq_len(n)) .
  • return ни в чем , кроме формального function(.){..} заявления, это неправильно; если вы хотите остановить a 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