サイコロを落とすための式(非ブルートフォース)


14

まず第一に、この質問をどこに投稿すべきかわからない。統計の問題がNP-Completeであるかどうか、およびプログラムでそれを解決しないかどうかを尋ねています。統計問題が中心点であるため、ここに掲載しています。

私は問題を解決するためのより良い式を見つけようとしています。問題は、4d6(通常の6面のサイコロ4枚)を持っている場合、それらを一度に振って、最も小さい数字(「ドロップ」と呼ばれる)のダイスを取り除き、残りの3を合計して、それぞれの可能な結果の確率です?私は答えがこれであることを知っています:

Sum (Frequency): Probability
3   (1):         0.0007716049
4   (4):         0.0030864198
5   (10):        0.0077160494
6   (21):        0.0162037037
7   (38):        0.0293209877
8   (62):        0.0478395062
9   (91):        0.0702160494
10  (122):       0.0941358025
11  (148):       0.1141975309
12  (167):       0.1288580247
13  (172):       0.1327160494
14  (160):       0.1234567901
15  (131):       0.1010802469
16  (94):        0.0725308642
17  (54):        0.0416666667
18  (21):        0.0162037037

平均は12.24で、標準偏差は2.847です。

私は上記の答えをブルートフォースで見つけましたが、どのように、または公式が存在するのかわかりません。この問題はNP完全であると思われるため、ブルートフォースによってのみ解決できます。3d6(3つの通常の6面のサイコロ)のすべての確率を取得し、それぞれを上に傾けることが可能です。私はすべてのサイコロが保持されているとき、私は高速式を持っているので、これはブルートフォースよりも速くなります。

私は大学ですべてのサイコロを保持するための式をプログラムしました。私は統計学の教授にそれについて尋ねたところ、彼はこのページを見つけました。このフォーミュラとブルートフォースには大きなパフォーマンスの違いがあります。50d6は20秒かかりましたが、8d6は40秒後に最低のクラッシュを落とします(クロームはメモリ不足になります)。

この問題はNP-Completeですか? はいの場合、証拠を提供してください、いいえの場合、それを解決するために非総当たり式を提供してください。

NP-Completeについてはあまり知らないので、NP、NP-Hard、または他の何かを考えているかもしれません。NP完全性の証明は役に立たない。私がそれを求める唯一の理由は、人々が推測するのを防ぐことだ。そして、私がこれに取り組んでから長い時間がかかっているので、私と一緒に裸にしてください:統計を覚えていないし、これを解決する必要があるかもしれません。

理想的には、N個のサイコロのN個がドロップされたときに、Y個のサイコロのX個のより一般的な式を探していますが、もっと単純なものから始めています。

編集:

また、周波数を出力するよりも数式を使用しますが、確率のみを出力することもできます。

興味がある人のために、私はGitHubでJavaScriptでwhuberの答えをプログラムしました(このコミットでは、テストでは実際に定義された関数を使用しています)。


1
これは興味深い質問です。ここで話題にすべきだと思います。ご検討をお願いいたします。
グング-モニカの復職

1
設定はおもしろいですが、答えられる質問はまだありません。NP完全性の考え方は、あるクラスの問題を抱えているかどうかにかかっていますが、1つだけを説明しました。正確にどのように一般化しますか?サイコロの数は異なる可能性があることを示唆しますが、さまざまな追加オプションが可能であり、異なる答えが得られる可能性があります。顔の数、顔の値、サイコロの数、およびドロップされたサイコロの数をすべて変更できますそれらの間のさまざまな関係を持つさまざまな方法で。
whuber

1
@whuber彼女は複雑さの理論を知りませんが、サイコロの数を変えることによって発生する問題のファミリーを求めていることは明らかだと思います。また、効率的なアルゴリズムを持っていると思います。
アンディジョーンズ14

2
@Andy私は最後に、彼女が「それらのNが落とされたときのY側のサイコロのX数のためのより一般的な式」を求めているのを見ます。
whuber

@whuberハァッ!どうやら私が当時考えていたほど明確ではないようです。すみません、私の悪い。
アンディジョーンズ14

回答:


5

解決

ことが聞かせての結果に等しいチャンスを与えるダイスそれぞれ1 2 ... D = 6。してみましょうKは、すべての値の最小値でn個のサイコロを独立にスローされます。n=41,2,,d=6Kn

Kを条件とするすべての値の合計の分布を考慮します。ましょXは、この合計になります。最小値が少なくともkである場合、Xの任意の値を形成するいくつかの方法の生成関数は、nKXXk

(1)f(n,d,k)(x)=xk+xk+1++xd=xk1xdk+11x.

サイコロは独立しているため、すべてのn個のサイコロがk以上の値を示す値を形成するいくつかの方法の生成関数は、Xnk

(2)f(n,d,k)(x)n=xkn(1xdk+11x)n.

この生成関数には、kを超えるイベントの項が含まれているため、それらを減算する必要があります。このための値を形成するための多くの方法のための生成機能Xを与え、K = kは、ありますKkXK=k

(3)f(n,d,k)(x)nf(n,d,k+1)(x)n.

和と指摘の最高値はすべての値の和であるマイナス最小に等しいX - K。したがって、生成関数はkで割る必要があります。これは、サイコロの任意の組み合わせの一般的な確率1 / d nを掛けると、確率生成関数になります。n1XKk(1/d)n

(4)dnk=1dxk(f(n,d,k)(x)nf(n,d,k+1)(x)n).

すべての多項式の積と累乗は演算で計算できるため(畳み込みであり、したがって離散高速フーリエ変換で実行できます)、総計算量はO kO(nlogn)。特に、それは多項式時間アルゴリズムです。O(knlogn)


d = 6の質問の例を見てみましょう。n=4d=6

のPGFのためにXを条件K kが得られます(1)XKk

f(4,6,1)(x)=x+x2+x3+x4+x5+x6f(4,6,2)(x)=x2+x3+x4+x5+x6f(4,6,5)(x)=x5+x6f(4,6,6)(x)=x6f(4,6,7)(x)=0.

それらを上げ式のように電源2 生成しますn=4(2)

f(4,6,1)(x)4=x4+4x5+10x6++4x23+x24f(4,6,2)(x)4=x8+4x9+10x10++4x23+x24f(4,6,5)(x)4=x20+4x21+6x22+4x23+x24f(4,6,6)(x)4=x24f(4,6,7)(x)4=0

における連続した違いは(3)

f(4,6,1)(x)4f(4,6,2)(x)4=x4+4x5+10x6++12x18+4x19f(4,6,2)(x)4f(4,6,3)(x)4=x8+4x9+10x10++4x20f(4,6,5)(x)4f(4,6,6)(x)4=x20+4x21+6x22+4x23f(4,6,6)(x)4f(4,6,7)(x)4=x24.

の結果の合計は(4)

64(x3+4x4+10x5+21x6+38x7+62x8+91x9+122x10+148x11+167x12+172x13+160x14+131x15+94x16+54x17+21x18).

例えば、上部に3つのサイコロの合計可能性の係数であり、X 14は、に等しいです14x14

64×160=10/81=0.123456790123456.

それは質問で引用された確率と完全に一致しています。

ところで、平均(この結果から計算される)であると標準偏差である15869/129612.24459876513612487/16796162.8468444

n = 4の代わりにダイスの同様の(最適化されていない)計算に0.5秒もかかりませんでした。分布の主要部分のプロットは次のとおりです。n=400n=4

図

最小ので、可能性が高いに等しいで1Xは非常に近い通常有するであろう400 × 7 / 2 400 × 35 / 12 (その平均で分布1400及び標準偏差はおよそ34.1565を)、平均は1400 1 = 1399に極めて近く、標準偏差は34.16に極めて近くなければなりません。これはプロットをうまく説明しており、おそらく正しいことを示しています。実際、正確な計算は約の平均を与えますK1X(400×7/2,400×35/12)140034.156514001=139934.16 1399より大きく、標準偏差が 1.24 × 10 31より小さいより小さい2.13×103213991.24×1031400×35/12


1
あなたの答えは速くて正しいので、答えとしてマークしました。また、編集の中で、可能であれば周波数を持つこともいいと言いました。その6^-4ため、周波数から確率への変換に乗数が使用されていることがわかりますので、回答を編集する必要はありません。
SkySpiral7 16

6

編集:@SkySpiralは、以下の式を機能させるのに問題がありました。現在、私は問題が何であるかを解決する時間がないので、あなたがこれを読んでいるならば、それが間違っているという仮定の下で進めることが最善です。


サイコロ、サイド、ドロップの数が変化するという一般的な問題についてはわかりませんが、ドロップ1の場合の効率的なアルゴリズムを見ることができると思います。修飾子は、それが正しいことを完全に確信しているわけではないということですが、現時点では欠陥は見られません。

サイコロを落とさないことから始めましょう。仮定を表し、N番目のダイ、及び仮定Yをn個の総和を表し、n個のサイコロを。それからXnnYnn

p(Yn=a)=kp(Yn1=ak)p(Xn=k)

ここで、が1つのダイスがドロップされたときのn個のダイスの合計であるとします。それからZnn

p(Zn=a)=p(nth die is the smallest)p(Yn1=a)+p(nth die is not the smallest)kp(Zn1=ak)p(Xn=k)

を最小のn個のダイの分布として定義すると、Mnn

p(Zn=a)=p(XnMn1)p(Yn1=a|XnMn1)+p(Xn>Mn1)kp(Zn1=ak)p(Xn=k|Xn>Mn1)

を使用してを計算できますMn

p(Mn=a)=p(XnMn1)p(Xn=a|XnMn1)+p(Xn>Mn1)p(Mn1=a|Xn>Mn1)

とにかく、これはすべて、およびM nに基づく動的プログラミングアルゴリズムを示唆しています。nは 2次でなければなりません。Yn,ZnMnn

編集:コメントにはどのように計算するのに提起された。以来X nはM のn - 1は、それぞれ6つの値のいずれかにだけ取ることができ、私たちはあらゆる可能性を超える合計することができます:p(XnMn1)Xn,Mn1

p(XnMn1)=a,bp(Xn=a,Mn1=b,ab)

同様に、は、ベイズ規則を適用し、X nの可能な値M n 1を合計することで計算できます。p(Xn=k|Xn>Mn1)Xn,Mn1


1
+1これは正しいように見え、あなたはそれが二次的だと言った。しかし、統計を取り始めてから数年が経ちました(私は主にプログラマーです)。したがって、答えとしてマークする前に、これを完全に理解したいと思います。また、私はあなたがp(nthが最小のダイである)を持っているのを見ます。すべての3をローリングするなど。
SkySpiral7 14

良いキャッチ。ロールされた番目のサイコロが現在の最小サイコロと同じ場合、そのサイコロをドロップするサイコロと見なすことができます。その場合、分布はY n 1です。これを反映するために、いくつかの< )に入れ替えました。nYn1(<)()
アンディジョーンズ14

ありがとうございました。これを正しく理解すれば、あなたの式が答えだと思います。しかし、p(X(n)> M(n-1))(またはその否定)またはp(X(n)= k | X(n)> M(n-1)の計算方法がわかりません))この回答はまだ使用できません。これを回答としてマークしますが、詳細情報が必要です。これらを説明するために回答を編集できますか、または別の質問として投稿する必要がありますか?
SkySpiral7 14

私の答えを編集しました。
アンディジョーンズ14

1
申し訳ありませんが、1年半が経ちましたが、ついにこの式をコードに実装することになりました。ただし、p(Z(n)= a)の式は正しくありません。サイコロが2面(最低のドロップ)で、結果が1になる可能性はどれくらいですか?X(n)が最小またはタイになる確率は3/4であり、p(Y(n-1)= 1)は1/2であるため、Z(n)は少なくとも3/8を返しますが、正しい答えは1/4。Z式は私には正しいように見えますが、それを修正する方法がわかりません。質問するのが多すぎないなら、あなたはどう思いますか?
SkySpiral7

1

これには合理的な効率のアルゴリズムがあり、テストでは、すべての可能性を列挙することにあまり依存せずに、純粋なブルートフォースの結果と一致するようです。実際には、上記の4d6のドロップ1よりも一般化されています。

XNdYXY1YN43d63,4,51,3,4,54つのサイコロで。(私はそれを「シーケンス」と呼んでいますが、ここで順序は重要ではありません。特に最後に気にするのはシーケンスの合計ですから)

P(XNdY=S) (or more specifically, P(43d6=S)) is a simplified version of the original problem, where we are only considering a specific set of dice, and not all possible sets that add up to a given sum.

Suppose S has k distinct values, s0,s1,...,sk, such that si>si+1, and each si has a count of ci. For example, if S=3,4,4,5, then (s0,c0)=(5,1), (s1,c1)=(4,2), and (s2,c2)=(3,1).

You can calculate P(XNdY=S) in the following way:

P(XNdY=S)=(i=0k1(Xh=0i1chci))(j=0XN(ck+XNck+XNj)(sk1)j)YX

That's pretty messy, I know.

The product expression i=0k1 is iterating through all but the lowest of the values in S, and calculating all the ways those values may be distributed among the dice. For s0, that's just (Xci), but for s1, we have to remove the c0 dice that have already been set aside for s0, and likewise for si you must remove h=0i1ch.

The sum expression j=0XN is iterating through all the possibilities of how many of the dropped dice were equal to sk, since that affects the possible combinations for the un-dropped dice with sk as their value.

By example, let's consider P[43d6=(5,4,4)]:

(s1,c1)=(5,1)
(s2,c2)=(4,2)

So using the formula above:

P[43d6=(5,4,4)]=(41)((33)30+(32)31)64=5162=0.0308641975¯

The formula breaks down on a domain issue when sk=1 and j=0 in the summation, leading to a first term of 00, which is indeterminate and needs to be treated as 1. In such a case, a summation is not actually necessary at all, and can be omitted, since all the dropped dice will also have a value of sk=1.

Now here's where I do need to rely on some brute force. The original problem was to calculate the probability of the sum being some value, and XNdY represents the individual dice left after dropping. This means you must add up the probabilities for all possible sequences S (ignoring ordering) whose sum is the given value. Perhaps there is a formula to calculate this across all such values of S at once, but I haven't even tried broaching that yet.

I've implemented this in Python first, and the above is an attempt to express it mathematically. My Python algorithm is accurate and reasonably efficient. There are some optimizations that could be made for the case of calculating the entire distribution of XNdY, and maybe I'll do that later.


As a programmer it might be easier for me to understand your Python code (although I've never used Python so it might be the same). Posting the code here is off topic but you could post a link to github etc.
SkySpiral7

1
Your answer may be correct and it seems to reduce the complexity from O(Y^X) to O((Y+X-1)!/(X!*(Y-1)!)) but it still isn't as efficient as whuber's answer of O(c*X*log(X)). Thanks for your answer though +1.
SkySpiral7
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.