Python 关于蒙特卡罗概率语法

Python 关于蒙特卡罗概率语法,python,probability,montecarlo,Python,Probability,Montecarlo,让20人,包括3名女性,随机坐在4张桌子上(表示为(A、B、C、D)),每个桌子5人,所有安排的可能性相同。设X为没有女性坐的桌子数。编写一个numpy Monte Carlo模拟来估计X的期望值,并估计没有女性坐在表a上的概率p。对3个案例进行模拟(100100010000) 我想定义一个函数,利用numpy的random.permutation函数来计算X的期望值,给定一个可变的试验次数,我知道如何在纸上和笔上进行,迭代我的概率集合并将它们相乘,这样我就可以计算出事件的总概率。这就是我目前所

让20人,包括3名女性,随机坐在4张桌子上(表示为(A、B、C、D)),每个桌子5人,所有安排的可能性相同。设X为没有女性坐的桌子数。编写一个numpy Monte Carlo模拟来估计X的期望值,并估计没有女性坐在表a上的概率p。对3个案例进行模拟(100100010000)

我想定义一个函数,利用numpy的random.permutation函数来计算X的期望值,给定一个可变的试验次数,我知道如何在纸上和笔上进行,迭代我的概率集合并将它们相乘,这样我就可以计算出事件的总概率。这就是我目前所拥有的

T = 4       # number of tables
N = 20      # number of persons. Assumption: N is a multiple of T.
K = 5       # capacity per table
W = 3       # number of women. Assumption: first W of N persons are women.
M =100      #number of trials

collection = []

for i in range(K):


    x = (((N-W)-i)/(N-i))

    collection.append(x)

如果我检查我的收藏,这是我的输出:[0.85,0.8421052631578947,0.8333334,0.8235294117647058,0.8125]

你必须显式模拟这些情景吗?如果没有,则只需随机抽取3次,替换为1..4,以模拟一次坐姿,即:

def one_experiment():
    return set(random.randint(1, 4) for _ in range(3))  # Distinct tables with women.
然后按如下方式获得所需值,其中N是任何情况下的实验次数

expectation_of_X = sum(4 - len(one_experiment()) for _ in range(N)) / float(N)
probability_no_women_table_1 = sum(1 not in one_experiment() for _ in range(N)) / float(N)

对于大N,您得到的值应该大约为p=(3/4)^3和E[X]=(3^3)/(4^2)。

您可以使用
functools.reduce
Python 3.X中对集合中的项进行乘法

from functools import reduce
event_probability = reduce(lambda x, y: x*y, collection)
因此,在您的代码中:

from functools import reduce

T = 4       # number of tables
N = 20      # number of persons. Assumption: N is a multiple of T.
K = 5       # capacity per table
W = 3       # number of women. Assumption: first W of N persons are women.
M = 100      #number of trials

collection = []

for i in range(K):
    x = (((N-W)-i)/(N-i))
    collection.append(x)

event_probability = reduce(lambda x, y: x*y, collection)

print(collection)
print(event_probability)
输出:

[0.85, 0.8421052631578947, 0.8333333333333334, 0.8235294117647058, 0.8125] # collection
0.3991228070175438 # event_probability
然后可以使用结果来完成代码。

实现 这是您的蒙特卡罗模拟的天真实现。它不是为性能而设计的,而是允许您交叉检查设置并查看详细信息:

import collections
import numpy as np

def runMonteCarlo(nw=3, nh=20, nt=4, N=20):
    """
    Run Monte Carlo Simulation
    """

    def countWomen(c, nt=4):
        """
        Count Number of Women per Table
        """
        x = np.array(c).reshape(nt, -1).T  # Split permutation into tables
        return np.sum(x, axis=0)           # Sum woman per table

    # Initialization:
    comp = np.array([1]*nw + [0]*(nh-nw)) # Composition: 1=woman, 0=man
    x = []                                # Counts of tables without any woman
    p = 0                                 # Probability of there is no woman at table A  

    for k in range(N):
        c = np.random.permutation(comp)   # Random permutation, table composition
        w = countWomen(c, nt=nt)          # Count Woman per table
        nc = np.sum(w!=0)                 # Count how many tables with women 
        x.append(nt - nc)                 # Store count of tables without any woman
        p += int(w[0]==0)                 # Is table A empty?
        #if k % 100 == 0:
            #print(c, w, nc, nt-nc, p)

    # Rationalize (count->frequency)
    r = collections.Counter(x)
    r = {k:r.get(k, 0)/N for k in range(nt+1)}
    p /= N
    return r, p
执行工作:

for n in [100, 1000, 10000]:
    s = runMonteCarlo(N=n)
    E = sum([k*v for k,v in s[0].items()])
    print('N=%d, P(X=k) = %s, p=%s, E[X]=%s' % (n, *s, E))
返回:

N=100, P(X=k) = {0: 0.0, 1: 0.43, 2: 0.54, 3: 0.03, 4: 0.0}, p=0.38, E[X]=1.6
N=1000, P(X=k) = {0: 0.0, 1: 0.428, 2: 0.543, 3: 0.029, 4: 0.0}, p=0.376, E[X]=1.601
N=10000, P(X=k) = {0: 0.0, 1: 0.442, 2: 0.5235, 3: 0.0345, 4: 0.0}, p=0.4011, E[X]=1.5924999999999998
通过绘制分布图,可以得出:

import pandas as pd
axe = pd.DataFrame.from_dict(s[0], orient='index').plot(kind='bar')
axe.set_title("Monte Carlo Simulation")
axe.set_xlabel('Random Variable, $X$')
axe.set_ylabel('Frequency, $F(X=k)$')
axe.grid()

与替代版本的分歧 注意:此方法无法解决所述问题

如果我们实施另一个版本的模拟,我们改变随机实验的执行方式如下:

import random
import collections

def runMonteCarlo2(nw=3, nh=20, nt=4, N=20):
    """
    Run Monte Carlo Simulation
    """

    def one_experiment(nt, nw):
        """
        Table setup (suggested by @Inon Peled)
        """
        return set(random.randint(0, nt-1) for _ in range(nw)) # Sample nw times from 0 <= k <= nt-1

    c = collections.Counter()             # Empty Table counter
    p = 0                                 # Probability of there is no woman at table A  

    for k in range(N):
        exp = one_experiment(nt, nw)      # Select table with at least one woman
        c.update([nt - len(exp)])         # Update Counter X distribution
        p += int(0 not in exp)            # There is no woman at table A (table 0)

    # Rationalize:
    r = {k:c.get(k, 0)/N for k in range(nt+1)}
    p /= N

    return r, p
第二个版本收敛于另一个值,它显然不等同于第一个版本,它没有回答相同的问题

讨论 为了区分哪种实现是两种实现的正确实现。第一个版本似乎是正确的,因为它考虑到女性在餐桌上就座的概率取决于之前被选中的人。第二个版本没有考虑到这一点,这就是为什么它不需要知道有多少人以及每张桌子可以坐多少人的原因


这是一个很好的问题,因为两个答案都提供了接近的结果。工作的一个重要部分是很好地设置Monte Carlo输入。

您正在每个周期清除收集<代码>集合=[]应该在循环之外。计数=0时相同。为什么要使用count而不是
i
?我对python相当陌生,希望确保我的计数为0。我不确定我是否为0编制了索引。但是你的建议极大地改进了我的代码。是的,python是0-indexedfurtmore,现在我有了我的独立概率,我如何遍历我的集合并将每个值相乘?更新你的问题,添加你的新代码以及你在集合中遇到的问题。如果您能给我们展示一个示例输出,那就太好了!我确实需要显式地模拟坐着,在那里我可以传递试验次数。你确定你的
E[x]
p
公式吗?有4个表,而不是5个。我不认为下面代码的输出是正确的。我的计算表明,5名男性坐在一张桌子旁的概率为(91/228),E(x)为(91/57)。我在起草一个函数时遇到了麻烦,这个函数接受了不同数量的试验并输出了这个输出。是的,这种类型的输入错误经常发生。无论如何,我一直在考虑你的实现,我发现它与我的不同。做一些数学,我知道为什么,它可能会指出,你的答案并不完全解决所述的问题。细节是正确的。我喜欢调查这个问题。有趣的是,答案是相对紧密的,所以很容易说服自己答案可能是正确的,直到你发现根本原因。很好的锻炼。
N=100, P(X=k) = {0: 0.0, 1: 0.41, 2: 0.51, 3: 0.08, 4: 0.0}, p=0.4, E[X]=1.67
N=1000, P(X=k) = {0: 0.0, 1: 0.366, 2: 0.577, 3: 0.057, 4: 0.0}, p=0.426, E[X]=1.691
N=1000000, P(X=k) = {0: 0.0, 1: 0.37462, 2: 0.562787, 3: 0.062593, 4: 0.0}, p=0.42231, E[X]=1.687973