【问题标题】:Monte Carlo simulation of Birthday paradox in python 3python 3中生日悖论的蒙特卡罗模拟
【发布时间】:2021-11-27 12:33:26
【问题描述】:

生日悖论是每个人在任意给定的 365 天生日的概率都是相等的。我们开始在房间中添加人员。 2 个人在同一天过生日的概率是房间里人数的函数?我写的代码如下:

import numpy as np
import matplotlib.pyplot as plt

x=[0]
y=[0]
for j in range(1000):
    if j!=0:
        freq = []
        L1 = list(np.random.randint(low = 1, high=366, size = j))
        result = list((i, L1.count(i)) for i in L1)
        for a_tuple in result:
            freq.append(a_tuple[1])
            print(freq)
        rep = j - freq.count(1)
        prob = rep/j
        y = y + [prob]
        x = x + [j]
print(prob)
plt.plot(x,y)

L1 = list(np.random.randint(low = 1, high=366, size = j)) 中,我选择某人过生日的日期,在result = list((i, L1.count(i)) for i in L1) 中,我计算每天生日的频率。整个事情都是循环的,以解释越来越多的人。

在下面的 for 循环中,我隔离了唯一事件并找到重复并将值存储在 rep 中。 接下来,我将概率计算为共享生日的人的比例,并将它们绘制为数字的函数。 然而,这个问题需要我找出只有一个共同生日的概率。我该如何计算?我想我必须循环这整个事情来进行多次试验,但这只是给出了一个准确的解决方案,同一程序的变化更少。目前,我认为我的程序提供了共享生日的人的一小部分。

Birthday problem Wikipedia for better reference

【问题讨论】:

  • 所以,为了确保,你要计算以下;如果 i=1..1000 人在同一个房间,那么至少 2 个人生日相同的概率是多少(作为 i 的函数)?是否必须模拟,还是允许计算?
  • 我所做的是我发现 1000 人中有多少人共享生日。问题是给定 N,2 人生日相同的概率是多少。它没有说明哪个 2,所以如果做得正确,大约 n=23,有 50% 的机会 2 共享生日。它在 200 时接近 99%。分析解决方案是已知的,甚至在 wiki 链接中给出。它需要由 monte carlo
  • 如果房间里有超过 366 人,则概率为 1(因此模拟超过 366 人没有意义)。必须是正好两个人还是至少两个人?

标签: python montecarlo birthday-paradox


【解决方案1】:

您应该针对房间内不同数量的人运行多个实验。请注意,对于 N_people > 365,概率应该等于 1。

重构你的代码,并稍微改变一下逻辑,我想出了以下内容:

import numpy as np
import matplotlib.pyplot as plt


def random_birthdays(n_people):
    return list(np.random.randint(low=1, high=366, size=n_people))

def check_random_room(n_people):
    """
    Generates a random sample of `n_people` and checks if at least two of them
    have the same birthday
    """
    birthdays = random_birthdays(n_people)
    return len(birthdays) != len(set(birthdays))

def estimate_probability(n_people, n_experiments):
    results = [check_random_room(n_people) for _ in range(n_experiments)]

    return sum(results)/n_experiments


N_EXPERIMENTS = 1000
x = list(range(1, 400))

y = [estimate_probability(x_i, N_EXPERIMENTS) for x_i in x]

plt.plot(x, y)


plt.show()

【讨论】:

    【解决方案2】:

    注意

    我假设当n 人进入房间时,他们都被赶出房间,然后n+1 人进入房间。

    ==========================================

    我会这样想;

    首先,设置probs = [0]*365。现在,假设有 2 个人进入房间 - 然后我们将他们的生日写在一张纸上并检查这两个日期是否相等。如果是,我们将probs[2] 增加 1(是的,有一些我们不需要的索引,Python 是 0 索引等,但为了简单起见)。

    现在对 3 人、4 人、5 人执行相同的操作……一直到 365。 您的数组可能类似于 probs==[0,0,0,0,0,1,0,1,1,0,1,1,1,1,0,1....]

    您现在可以从 2 个人开始(仍然保持与以前相同的数组,即不要用 0 创建一个新数组!),然后是 3 个人等,并开始超过 1000 次。你的数组可能看起来像

    probs==[0,0,2,0,4,1,5,2,9,12,10,17....,967,998]

    如果您将该数组除以 1000(按元素),您现在将模拟概率作为 n 人的函数。

    import numpy as np
    import matplotlib.pyplot as plt
    
    N_TOTAL_PERS= 366
    N_SIM = 10000 #number of simulations
    counts = np.zeros(N_TOTAL_PERS)
    
    for _ in range(N_SIM): 
        for n in range(2,N_TOTAL_PERS):
            b_days = np.random.randint(1,366,size=n) #Get each persons birth-day
            counts [n] += len(b_days) != len(set(b_days)) #Increment if some birthdays are equal    
    
    
    total_probs = counts/N_SIM #convert to probabilities
    total_probs[70] #Get the probability when 70 persons are together (0.9988)
    plt.plot(range(N_TOTAL_PERS),total_probs)
    

    它会生成一个看起来像

    【讨论】:

      猜你喜欢
      • 2020-01-28
      • 2015-06-15
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 2012-04-26
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多