このブログ内を検索可能

2017年10月14日土曜日

モンパレ 肉投げスカウトの確率2

以前の記事で、初期スカウト率をa、スカウト率上昇率をbとして、100回中n回スカウトできる確率はsum[product[1-a-kb,{k,0,98-A(n)}]×product[(a+A(k)-1)b×product[1-a-kb,{k,0,A(k)-A(k-1)-2}],{k,1,n}],)),{A(n),1,100},{A(n-1),1,A(n)-1},{A(n-2),1,A(n-1)-1},…{A(2),1,A(3)-1},{A(1),1,A(2)-1}]で(たぶん)表されることが分かった。が、これでは我でも全然値の見当がつかない。

よって、やはりここはプログラムで試行することにする。
さすがにプログラムは統計的に処理を行うので、一般のa,bに対して行うことはできない。

そこで、一応今回はa=0.001,b=0.001として話を進めることにする。
まず、みんなが取りそうな以下の作戦を考える。手持ちのしもふりにくは100個。
一応スカウトのチャンスは100回とする。
肉は100個投げることを前提とする。

このとき、どのように肉を投げればスカウトの成功数が上がるのか?ということである。

作戦1 スカウト上昇率が上がってくれば自然にスカウトできるかもしれない。
     よって最初の0.2%の時のみに全力、あるいは相当量のしもふりにくを投げる。
     それで次に0.2%であまったしもふりにく全投入。後98回は運だのみ。
作戦2 常に確率を上昇させるために100回中100回それぞれしもふりにくを1個ずつ投入。

その中で、もっともたくさんモンスタースカウト回数の期待値が多かった方法を採用しよう。

…だがこれ、普通のプログラミングより難しい。

この詳しいプログラムの記述については次の3つ目の記事を参照。
(まだ作成していない。ちょっと他にいろいろとやりたいことがあるので)

モンパレ 肉投げスカウトの確率1

たまにはウォーミングアップということで、通常パレや強敵パレで、肉をどんな感じに使えばモンスターを効率よく入手できるのか、ということについて考えてみる。

直感的に、おそらくみな10%の迷宮の門では肉など使わず、0.1%の場合だったら肉1個たして少し確率をあげてみようかな…?と思うだろう。

はたしてこの行為が正しいのか(効率的か)どうかをみていく。
おそらくこれが分かれば、しもふりにくが100個あった場合、1個ずつ100回挑戦するのがいいのか70個くらい投げてあと1回30個がいいのか、という問いにも答えられるようになる。

この問題は、そこそこの難易度だと予想しているが、最近新たにスカウト率上昇システムが加わったことにより、激ムズになることが予想される。

こういう問題が解けてこそ、医学部を目指したりや数学科を名乗れたり。
(計算ミスなどについては勘弁。後でわかり次第訂正する)

さて、とりあえず変数(文字)を定める。初期スカウト率をaとして、スカウト率上昇をbとする。
これによって、n回目まで失敗する確率は、
P(n)=(1-a)(1-a-b)(1-a-2b)…(1-a-(n-1)b)であることが容易に分かる。
(P(0)=1とする)

さて…。しもふりにくを使わず、これに100回挑戦したとしよう…。
では、100回挑戦して1回スカウト成功する確率は?といわれるとどうするか?
これはそう簡単に反復試行ではうまくいかない。
なぜなら、失敗時、次の確率が上昇する時点で「反復」ではないからである。

例として、1回目に成功するならば、確率aであり、以降は全て外れるので、
結局a(1-a)(1-a-b)(1-a-2b)…(1-a-98b)が求める確率になる。(99.9%にはまずならない範囲で考える。すなわち、a+nb<0.999の範囲で考える)
実際、モンパレでは、基本的にはスカウト率上昇はDランクでも1%なので、100回弱ならぎりぎり99.9%を超えない。
次。2回目に成功するならば、(1-a)(a+b)(1-a)(1-a-b)(1-a-2b)…(1-a-97b)となる。
これらはPを用いると、
1回目成功はあと99回失敗。よってaP(99)となる。
2回目成功は1回目失敗と2回目成功、98回失敗。よって、P(1)(a+b)P(98)である。
同様に、
3回目成功はP(2)(a+2b)P(97)となる。
これで法則性は読めた。100回スカウトチャンスがあればSum[(a+(k-1)b)P(k-1)P(100-k),{k,1,100}]
である。

だが問題は2回以上成功するときである。
2回成功するとするなら、1回目と2回目、1回目と3回目、2回目と3回目、などが挙げられるが、
これら個々について確率を求めると、P(m,n)をm回目とn回目に成功するとすると、(m<n)
m-1回目まで失敗し、m回目に成功、そしてn回目に成功するので、m+1回目からn-1回目までは失敗。Pは失敗の連続数のみに依存するので、これは(n-1)-(m+1)+1でn-m-1回の失敗となる。これはP(n-m-1)である。それでn+1回目から100回目まで失敗。
ゆえに、sum[P(m-1)(a+(m-1)b)P(n-m-1)(a+(n-1)b)P(99-n)…と続く。
(n=100のときは、P(-1)となるがこれを0と定めておくなぜなら-1回目は存在しないので、失敗もしないので。…結構強引だが…。)

しかしここで問題となるのが、mとnをどのようにたし合わせるか、ということになる。
結論的には1<=m<n<=100であるような(m,n)の組全体なんだが、sumの書式でどう書くか。
とりあえずnを固定してkとし、mを1からk-1までたし合わせ、nをたし合わせるという方式をとることになる.これは大学入試の格子点の問題と一緒の考え方。
そうすると、たとえばn=1ではmはとれない。
n=2ではmは1を取れる。
これにより、mathematicaの多重総和の書式を参考にすると、nはkに置き換わり
sum[P(m-1)(a+(m-1)b)P(k-m-1)(a+(k-1)b)P(99-k),{k,1,100}{m,1,k-1}]となる。

すでにこの段階でもう普通の大学入試と同じくらいのレベルになっている。
ではこれが3回分の成功となると…?
そしてしもふりにくを投げるとなると…?
とんでもない事態になるのはいうまでもない。

これまでは計算とプログラムの両方で答えを求めてきたが、すでに2回分成功の式でも多重総和sumの中に総乗Pが入っているので、苦戦必至。

ちなみに3回分ならば、変数がまた1個増えて、L,m,n回目成功とすると、
範囲は1<=L<m<n<=100であって、
L回目に成功し、m回目に成功し、n回目に成功するので、
L-1回目まで失敗、L回目成功、L+1回目からm-1回目まで失敗、m回目に成功、m+1回目からn-1回目まで失敗、n回目成功、n+1回目から100回目まで失敗、ということになる。
すると、P(L-1)(a+(L-1)b)P(m-L-1)(a+(m-1)b)P(n-m-1)(a+(n-1)b)P(99-n)となる。
それで、nを固定すると、1<=L<m<nということで、さらにmを固定すると、
Lを1からm-1までたし合わせる。
するとsum[P(L-1)(a+(L-1)b)P(m-L-1)(a+(m-1)b)P(n-m-1)(a+(n-1)b)P(99-n),{n,1,100},{m,1,n-1},{L,1,m-1}]になる。

これらから、100回中n回成功するというものが、n回分の多重総和によってあらわせることが判明。
A(1),A(2),A(3),…A(n)回目に成功する、という仮定の元では、(Aは順序を保つ)
sum[P(A(1)-1)(a+(A(1)-1)b)P(A(2)-A(1)-1)…P(A(n)-A(n-1)-1)(a+(A(n)-1)b)P(99-A(n)),{A(n),1,100},{A(n-1),1,A(n)-1},{A(n-2),1,A(n-1)-1},…{A(2),1,A(3)-1},{A(1),1,A(2)-1}]となる。

なおこれは多重総和sum内に総乗で表せるので、式はもうちょっと簡単になる。
P(A(k)-A(k-1)-1)(a+(A(k)-1)b)がその組として考えられる。
これを、k=1からnまで掛け合わせればよい。それで最後にP(99-A(n))をかける。
すると、総乗を返す関数productを用いると、
P(99-A(n))product[P(A(k)-A(k-1)-1)(a+(A(k)-1)b),{k,1,n}]となる。ー※
(P(99-n)はkに関係ないので、kに関しては定数とみなして前に出せる)
ところで、簡略のためPで扱っていたが、これはproductで記述すると
P(n)=(1-a)(1-a-b)(1-a-2b)…(1-a-(n-1)b)は1-a-kbをk=0からk=n-1まで掛け合わせているので、
P(n)=product[1-a-kb,{k,0,n-1}]ということになる。
これらを全て組み合わせると、
100回挑戦してn回スカウト成功する確率、というのは、次の式で表される…はず。つまり
product[1-a-kb,{k,0,98-A(n)}]×product[(a+A(k)-1)b×product[1-a-kb,{k,0,A(k)-A(k-1)-2}],{k,1,n}]が※の示すところとなる(関数Pをproduct表記した)
そして、いよいよこれの多重総和をとることになる。
よって、sum[product[1-a-kb,{k,0,98-A(n)}]×product[(a+A(k)-1)b×product[1-a-kb,{k,0,A(k)-A(k-1)-2}],{k,1,n}],)),{A(n),1,100},{A(n-1),1,A(n)-1},{A(n-2),1,A(n-1)-1},…{A(2),1,A(3)-1},{A(1),1,A(2)-1}]で表されることがついに分かった。

…たぶんこれで考え方は間違っていないはず…だが、どうしてもこの式を求めることはできない。
なぜなら、多重総和をn回とっているから、計算量が尋常でない。
しかもその多重総和1回に対し、総乗処理を2回行っていて、さらにうち1回の処理の中にはさらに総乗が入るというカオスっぷり。

確率とは総和と総乗の世界であるといっても過言でないかも。なぜならもともと確率が和と積の法則から成り立っているので。
言い換えれば、基礎さえ分かっていればこれくらいの問題は余裕で解ける…はずなんだが、我でもやっぱり難しめに感じるのはたぶん総和などの扱いがややこしいからだろう。

では次にプログラムを用いた統計的に確率を出す手法でも説明してみる。
我はRPGを作成するにあたり、自然とプログラミング能力を身につけた。
このくらいは余裕。なぜなら、自分でモンパレのモンスタースカウトシステムを作ったり、RPG内で次が何駅、今停車中かどうかの電車の処理、アニマロッタ(メダルゲーム)のプログラムすら考えるくらいなので。

まあこれくらいのスペックなら、唐突に長期休暇中の空き時間を利用して医学部にいってみようかとか言っても虚言でないのが分かるだろう。ただし国語はどうにもならないっぽいが…。

次の記事で、RPGエディターを用いてこのプログラムを考える。もちろん、しもふりにく投げを考慮したものについても考えたい。