Моделирование Монте-Карло с заменой на основе суммы столбца - PullRequest
0 голосов
/ 08 декабря 2018

Я пытаюсь смоделировать маловероятную ситуацию в видеоигре, используя симуляцию Монте-Карло.Я чрезвычайно новичок в кодировании и подумал, что это забавная ситуация для симуляции.

Есть 3 цели, и они атакованы 8 раз независимо друг от друга.Моя проблема заключается в том, как справиться с тем фактом, что один из столбцов не может быть атакован более 6 раз при 8 атаках.

Я хотел бы предпринять любую атаку, направленную на столбец 2, выберите один издругие 2 столбца наугад атаковать вместо этого, но только если столбец 2 уже атакован уже 6 раз .

Вот моя попытка смоделировать, например, с 5000 повторений.

#determine number of repeats
trial <- 5000

#create matrix with a row for each trial
m <- matrix(0, nrow = trial, ncol = 3)

#The first for loop is for each row
#The second for loop runs each attack independently, sampling 1:3 at random, then adding one to that position of the row.
#The function that is called by ifelse() when m[trial, 2] > 6 = TRUE is the issue.

for (trial in 1:trial){
  for (attack in 1:8) {
    target <- sample(1:3, 1)
    m[trial, target] <- m[trial, target] + 1
    ifelse(m[trial, 2] > 6, #determines if the value of column 2 is greater than 6 after each attack
           function(m){
             m[trial, 2] <- m[trial, 2] - 1 #subtract the value from the second column to return it to 6
             newtarget <- sample(c(1,3), 1) #select either column 1 or 3 as a new target at random
             m[trial, newtarget] <- m[trial, newtarget] + 1 #add 1 to indicate the new target has been selected
             m}, #return the matrix after modification
           m) #do nothing if the value of the second column is <= 6
  }
}

Например, если у меня есть матрица ниже:

> matrix(c(2,1,5,7,1,0), nrow = 2, ncol = 3)
     [,1] [,2] [,3]
[1,]    2    5    1
[2,]    1    7    0

Я бы хотел, чтобы функция посмотрела на вторую строку матрицы, вычтите 1 из 7, а затем добавьте 1 к любомустолбец 1 или 3 для создания c (2,6,0) или c (1,6,1). Я хотел бы узнать, как сделать это в цикле, но это можно было бы сделать и впоследствии.

Я думаю, что я делаю серьезную, фундаментальную ошибку с использованием function(x)или ifelse.

Спасибо.

1 Ответ

0 голосов
/ 08 декабря 2018

Вот улучшенная версия вашего кода:

set.seed(1)

trial <- 5000

#create matrix with a row for each trial
m <- matrix(0, nrow = trial, ncol = 3)

#The first for loop is for each row
#The second for loop runs each attack independently, sampling 1:3 at random, then adding one to that position of the row.
#The function that is called by ifelse() when m[trial, 2] > 6 = TRUE is the issue.

for (i in 1:trial){
    for (attack in 1:8) {
        target <- sample(1:3, 1)
        m[i, target] <- m[i, target] + 1 
        #determines if the value of column 2 is greater than 6 after each attack
        if(m[i, 2] > 6){ 
            #subtract the value from the second column to return it to 6
            m[i, 2] <- m[i, 2] - 1 
            #select either column 1 or 3 as a new target at random
            newtarget <- sample(c(1,3), 1)
            #add 1 to indicate the new target has been selected
            m[i, newtarget] <- m[i, newtarget] + 1 
            }   
        }   
    }   

# Notice the largest value in column 2 is no greater than 6.
apply(m, 2, max)

set.seed используется, чтобы сделать результаты воспроизводимыми (обычно просто используется для тестирования).Функция ifelse имеет другое назначение, чем обычный поток управления if-else.Вот пример:

x = runif(100)
ifelse(x < 0.5, 0, x)

Вы заметите, что любой элемент в x, который меньше 0.5, теперь равен нулю.Я изменил ваш код, чтобы иметь блок if.Обратите внимание, что m[i, 2] > 6 возвращает один TRUE или FALSE, тогда как в приведенном выше небольшом примере x < 0.5 возвращается вектор логики.Таким образом, ifelse может принимать вектор логики, но блок if требует, чтобы был только один логический элемент.

Вы были на правильном пути с использованием function, но это просто не нужнов этом случае.Часто, но не всегда, вы определяете функцию следующим образом:

f = function(x)
    x^2

Но просто возвращение значения не означает, что вы хотите изменить:

x = 5
f(5) # 25
x    # still 5

Для болеена этом посмотрите область действия функции в R.

Наконец, я изменил цикл на i in 1:trial вместо trial in 1:trial.Вы, вероятно, не заметите никаких проблем в вашем случае, но лучше использовать отдельную переменную, чем та, которая составляет диапазон цикла.

Надеюсь, это поможет.

PSR не очень известен своей скоростью при зацикливании.Если вы хотите, чтобы все шло быстрее, вам обычно нужно векторизовать ваш код.

...