骰子组合的标准偏差

时间:2016-10-29 20:56:42

标签: python algorithm numpy stdev

我试图找到一个数字序列的stdev,这些数字是从骰子(30)的总和为120的组合中提取的。我是Python的新手,所以这段代码会使控制台冻结,因为数字是无穷无尽的我不确定如何将它们全部放入更小,更有效的功能中。我做的是:

  • 找到了30个骰子的所有可能组合;
  • 过滤的总和达到120的组合;
  • 将结果列表中列表中的所有项目相乘;
  • 尝试提取标准差。

以下是代码:

import itertools
import numpy

dice = [1,2,3,4,5,6]
subset = itertools.product(dice, repeat = 30)

result = []
for x in subset:
    if sum(x) == 120:
        result.append(x)

my_result = numpy.product(result, axis = 1).tolist()
std = numpy.std(my_result)

print(std)

2 个答案:

答案 0 :(得分:1)

注意D(X^2) = E(X^2) - E(X)^2,你可以通过以下方程式解析地解决这个问题。

f[i][N] = sum(k*f[i-1][N-k])        (1<=k<=6)
g[i][N] = sum(k^2*g[i-1][N-k])
h[i][N] = sum(h[i-1][N-k])

f[1][k] = k ( 1<=k<=6)
g[1][k] = k^2 ( 1<=k<=6)
h[1][k] = 1 ( 1<=k<=6)

示例实施:

import numpy as np

Nmax = 120
nmax = 30
min_value = 1
max_value = 6
f = np.zeros((nmax+1, Nmax+1), dtype ='object')
g = np.zeros((nmax+1, Nmax+1), dtype ='object') # the intermediate results will be really huge, to keep them accurate we have to utilize python big-int
h = np.zeros((nmax+1, Nmax+1), dtype ='object')
for i in range(min_value, max_value+1):
    f[1][i] = i
    g[1][i] = i**2
    h[1][i] = 1

for i in range(2, nmax+1):
    for N in range(1, Nmax+1):
        f[i][N] = 0
        g[i][N] = 0
        h[i][N] = 0
        for k in range(min_value, max_value+1):
            f[i][N] += k*f[i-1][N-k]
            g[i][N] += (k**2)*g[i-1][N-k]
            h[i][N] += h[i-1][N-k]

result = np.sqrt(float(g[nmax][Nmax]) / h[nmax][Nmax] - (float(f[nmax][Nmax]) / h[nmax][Nmax]) ** 2)
# result = 32128174994365296.0

答案 1 :(得分:0)

你要求未经过滤的长度为6 30 = 2 * 10 23 的结果,不可能这样处理。

有两种可能的组合方式:

  1. 包括更多思考预先处理问题,例如:关于如何仅采样 那些总和120.
  2. 改为进行蒙特卡罗模拟,即不进行全部采样 组合,但只有随机的1000对才能获得代表 样本确定std足够准确。
  3. 现在,我只申请(2),给出强力代码:

    N = 30 # number of dices
    M = 100000 # number of samples
    S = 120 # required sum
    
    result = [[random.randint(1,6) for _ in xrange(N)] for _ in xrange(M)]
    result = [s for s in result if sum(s) == S]
    

    现在,在使用numpy.product之前,该结果应与您的结果相媲美...但我无法遵循的那部分,但是......

    好的,如果您在30个骰子产品的标准差之后,那就是您的代码所做的。然后我需要1 000 000个样本来获得std(1位数)的大致可重现值 - 使我的PC大约20秒,仍然远远少于100万年:-D。

    你想要的是一个像3.22 * 10 16 这样的数字吗?

    评论后修改: 那么,通过在约束中替换(sum = 120,总数= 30),对数字的频率进行采样仅产生6个独立变量 - 实际上只有4个变量。我目前的代码如下:

    def p2(b, s):
        return 2**b * 3**s[0] * 4**s[1] * 5**s[2] * 6**s[3]
    
    hits = range(31)
    subset = itertools.product(hits, repeat=4) # only 3,4,5,6 frequencies
    product = []
    permutations = []
    for s in subset:
        b = 90 - (2*s[0] + 3*s[1] + 4*s[2] + 5*s[3]) # 2 frequency
        a = 30 - (b + sum(s)) # 1 frequency
        if 0 <= b <= 30 and 0 <= a <= 30:
            product.append(p2(b, s))
            permutations.append(1) # TODO: Replace 1 with possible permutations
    print numpy.std(product)  # TODO: calculate std manually, considering permutations
    

    这计算大约1秒钟,但令人困惑的是我得到的结果是1.28737023733e + 17。无论我以前的方法还是这个方法都有错误 - 或两者都有。

    对不起 - 不那么容易:抽样概率不一样 - 这就是问题所在。每个样品具有不同数量的可能组合,给出其重量,在进行标准偏差之前必须考虑重量。我在上面的代码中草拟了它。