如何编写伯特兰盒子悖论的蒙特卡罗模拟?

机器算法验证 r 可能性 模拟 蒙特卡洛 悖论
2022-03-24 02:47:25

以下问题已发布在 Mensa International Facebook 页面上:

在此处输入图像描述

帖子本身收到了 1000 多条评论,但我不会详细讨论那里的辩论,因为我知道这是伯特兰的盒子悖论,答案是23. 让我感兴趣的是如何使用蒙特卡洛方法回答这个问题?算法如何解决这个问题?

这是我的尝试:

  1. 产生N之间均匀分布的随机数01.
  2. 让包含 2 个金球的盒子(盒子 1)被选中的事件少于一半。
  3. 数一下小于的数0.5并将结果称为S.
  4. 既然选择了盒子1就一定会得到一个金球,而如果选择了盒子2只有50%的几率得到一个金球,所以得到一个序列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这几乎与正确答案匹配,但我不确定这是正确的方法。是否有适当的方法以编程方式解决此问题?

3个回答

@Henry一样,我真的不觉得您的解决方案是蒙特卡洛。当然,您从分布中采样,但它与模仿数据生成过程没有太大关系。如果您想使用 Monte Carlo 让某人相信理论解决方案是正确的,则需要使用模拟数据生成过程的解决方案。我想它是这样的:

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我们打折的空运行。然而,由于问题很简单,代码运行速度很快,我们可以明确地模拟整个数据生成过程,“以确保”结果是正确的。除此之外,不需要此步骤,因为它会在两种情况下产生相同的结果。

我觉得你的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")

为什么不简单列出案例呢?

这里:G 代表“金”,S 代表“银”,大写代表初始提取:

GG

gG

GS

...所有其他情况都涉及初始银 (S) 提取并且不满足条件(初始提取 G)。

这样,P(g|G) = 2/3。