0

合計が 120 になるサイコロ (30) の組み合わせから抽出された一連の数字の stdev を見つけようとしています。私は 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)
4

2 に答える 2

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
于 2016-10-30T00:41:38.053 に答える
0

6 30 = 2*10 23のフィルタリングされていない長さの結果を要求しますが、そのように処理することは不可能です。

組み合わせることができる 2 つの可能性があります。

  1. たとえば、合計が 120 のものだけをサンプリングする方法など、問題を前処理するためのより多くの考えを含めます。
  2. 代わりにモンテカルロ シミュレーションを実行します。つまり、すべての組み合わせをサンプリングするのではなく、1000 のランダムなカップルのみをサンプリングして、十分に正確な std を決定する代表的なサンプルを取得します。

今、私はブルートフォースコードを与えて、(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 個のサイコロの積の標準偏差の後でアウトになった場合、それがコードの動作です。次に、std (1 桁) のほぼ再現可能な値を取得するには、1 000 000 サンプルが必要です。

探しているのは3.22*10 16のような数値ですか?

コメントの後に編集: 数の頻度をサンプリングすると、代わりに 6 つの独立変数のみが得られます。実際には、制約 (合計 = 120、合計数 = 30) を代入することにより、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 が得られることです。私の以前のアプローチまたはこれにはバグがあります-またはその両方です。

申し訳ありませんが、簡単ではありません。サンプリングの確率は同じではありません。これが問題です。各サンプルには異なる数の可能な組み合わせがあり、その重みを与えます。これは、標準偏差を取得する前に考慮する必要があります。上記のコードでそれを下書きしました。

于 2016-10-29T21:42:59.590 に答える