Как запрограммировать симуляцию Монте-Карло парадокса Бертрана?


12

Следующая проблема была размещена на Mensa International на странице Facebook:

введите описание изображения здесь

Само сообщение получило более 1000 комментариев, но я не буду вдаваться в подробности о дебатах, поскольку знаю, что это парадокс Бертранда и ответ . Что меня здесь интересует, так это то, как можно решить эту проблему, используя подход Монте-Карло? Как работает алгоритм для решения этой проблемы?23

Вот моя попытка:

  1. Генерация равномерно распределенных случайных чисел от до .0 1N01
  2. Пусть событие коробки содержит 2 выбранных золотых шара (поле 1) меньше половины.
  3. Подсчитайте число , что меньше , чем и вызвать результат в виде .с0.5S
  4. Так как получение золотого шара является гарантией, если выбран ящик 1, и только 50% шанс получить золотой шар, если выбран ящик 2, следовательно, вероятность получения последовательности GG равна
    P(B2=G|B1=G)=SS+0.5(NS)

Реализуя алгоритм выше в R:

N <- 10000
S <- sum(runif(N)<0.5)
S/(S+0.5*(N-S))

Вывод программы выше составляет около что почти соответствует правильному ответу, но я не уверен, что это правильный путь. Есть ли правильный способ решить эту проблему программно?0.67

Ответы:


14

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

boxes <- list(
  c(0, 0),
  c(0, 1),
  c(1, 1)
)

count_successes = 0
count_valid_samples = 0

for (i in 1:5000) {
  sampled_box <- unlist(sample(boxes, 1)) # sample box
  sampled_balls <- sample(sampled_box)    # shuffle balls in the box

  if (sampled_balls[1] == 1) {            # if first ball is golden
    if (sampled_balls[2] == 1) {          # if second ball is golden
      count_successes = count_successes + 1
    }
    count_valid_samples = count_valid_samples + 1
  }
}
count_successes / count_valid_samples

или используя "векторизованный" код:

mean(replicate(5000, {       # repeat 5000 times, next calculate empirical probability
  x <- boxes[[sample(3, 1)]] # pick a box
  if (x[sample(2, 1)] == 1)  # pick a ball, check if it is golden
    return(sum(x) == 2)      # check if you have two golden balls in the box
  else
    return(NA)               # ignore if sampled ball is silver
  }), na.rm = TRUE)          # not count if silver

Обратите внимание на то, что если вы примите во внимание тот факт, что первый шарик уже нарисован, и он золотой, то приведенный выше код может просто использовать два поля, boxes <- list(c(0, 1), c(1, 1))а затем брать из них образцы x <- boxes[[sample(2, 1)]], поэтому код будет быстрее, так как он не получит 1/3 пустые пробеги, которые мы делаем скидку. Однако, поскольку проблема проста и код выполняется быстро, мы могли бы позволить себе явно смоделировать весь процесс генерации данных, «чтобы быть уверенным», что результат верен. Кроме того, этот шаг не нужен, поскольку он даст одинаковые результаты в обоих случаях.


Значит, x <- boxes[[sample(3, 1)]]вы берете коробку из 3 коробок? Если так, то почему это необходимо, поскольку мы знаем, что вы уже выбрали золотой шар?
Анастасия-Романова

7
@ Анастасия-Романова instead вы могли бы вместо этого сделать выборку из двух блоков, boxes <- list(c(0, 1), c(1, 1))а затем x <- boxes[[sample(2, 1)]], но так как это почти одно и то же время вычислений, почему бы не использовать дополнительный шаг, который точно напоминает процесс выборки? Это ничего не меняет в результате, но делает моделирование явным.
Тим

Хорошо, Тим, спасибо за ваш ответ. Дайте мне время, чтобы сначала понять ваш ответ, так как я довольно новичок в R. На данный момент +1 для вас и @Henry.
Анастасия-Романова

1
@ Анастасия-Романова 秀 да, именно так. Код сэмплирует коробку, затем сэмпл шара из коробки, если он золотой (= 1), тогда он проверяет, является ли другой шар из коробки также золотым (1 + 1 = 2), если да, то он считает его и в конце он делит сумму на общее количество (то есть использует mean).
Тим

1
@ Anastasiya-Romanova 秀return(NA)возвращает пропущенное значение и затем mean(, na.rm = TRUE)используется, где na.rm = TRUEаргумент указывает функции игнорировать пропущенные значения. В других языках программирования это можно сделать по-другому, например, используя continueили passключевые слова.
Тим

4

Я чувствую, что ваш S/(S+0.5*(N-S))расчет на самом деле не симуляция

Попробуйте что-то вроде этого

N <- 10^6
ballsinboxes <- c("G","G", "G","S", "S","S")
selectedbox <- sample(c(1,2,3), N, replace=TRUE)
selectedball <- sample(c(1,2), N, replace=TRUE)
selectedcolour <- ballsinboxes[(selectedbox-1)*2 + selectedball ]
othercolour <- ballsinboxes[(selectedbox-1)*2 + 3 - selectedball ]
sum(selectedcolour == "G" & othercolour == "G") / sum(selectedcolour == "G")

-2

Почему бы просто не перечислить дела?

Здесь: G для «золота», S для «серебра», капитал для первоначальной добычи:

Гг

Гг

Gs

... все остальные случаи предполагают начальное извлечение серебра (S) и не удовлетворяют условному (начальное извлечение G).

Таких, P (g | G) = 2/3.


7
Вопрос задается о решении Монте-Карло.
Тим

Ну, перечисление ВСЕХ возможностей - крайний случай Монте-Карло.
ghuezt

4
Нет, Монте-Карло занимается симуляцией / рандомизацией.
Тим

Тим, правильно разберись с математикой. С бесконечным количеством розыгрышей вы получите точно список всех случаев с равными вероятностями. Я грустный "крайний случай" и имел ввиду предел
ghuezt

1
Конечно, но перечисление всех дел не Монте-Карло. Квадрат - это прямоугольник, но прямоугольник - это не квадрат.
Тим
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.