2in1法の検証シミュレーション(c++)

  • このエントリーをはてなブックマークに追加

スポンサーリンク

※サイト運営にサーバーは必須です※
ロリポップ! はコスパのよい初心者向けサーバーです~

はじめに

※目次用の記事:ギャンブルの賭け方の種類をまとめてみた

賭け方にはいくつか種類がある。

そのうちの一つに、2in1法というのがある。

この記事では、2in1法とはなにかを説明した後、プログラムによるシミュレーション結果を示す。

2in1法とは

数列を用意する。最初は、数字の1だけ
(1)

数列の左端と右端を足し合わせた数だけ賭ける
※ただし、最初は数列の中身は1つしかないので、1だけ賭ける

負けた場合:賭け金額を数列の右端に加える
勝った場合:数列の右端と左端を消す

数列の大きさが1より小さくなった場合は、ゲームをリセット。数列は(1)から再びスタートする。

※数列の大きさが1以下だと、右端と左端を足し合わせて、賭け金額を算出するという操作ができなくなる。

※数列は、賭けた金額を記録することに対応する

2in1法の具体例

ルールだけ、説明してもイメージがつかめないと思うので、具体例を挙げる。

勝負 数列 賭け金額 勝敗 利益
初期 1 1 × -1
× 11 2 × -3
×× 112 3 × -6
××× 1123 4 -2
×××○ 12 3 × -5
×××○× 123 4 × -9
×××○×× 1234 5 -4
×××○××○ 23 5 1
×××○××○○ なし ゲーム終了  

1回目の勝負にかける金額は1。

※ここで、勝てば、数列はリセットされ、再び1を賭ける。

もしも、負けたら、賭けた金額を数列の右端に加える
(1,1)

2回目に賭ける金額は、一番右端と左端を足し合わせた1+1=2
2回目負けると、賭けた金額を数列の右端に加える
(1,1,2)

3回目に賭ける金額は、一番右端と左端を足し合わせた1+2=3
3回目負けると、賭けた金額を数列の右端に加える
(1,1,2,3)

3回目に賭ける金額は、一番右端と左端を足し合わせた1+3=4
4回目勝つと、数列の右端と左端を消す
1,1,2,3

このような操作を数列が、完全に消えるか、1つ残るまで続ける。

2in1法の特徴

賭け方の動きは、モンテカルロ法とほぼ同じ。

2in1法は、最初の数列が(1)でモンテカルロ法は(1,2,3)の違いであると言ってもほぼ間違いはない。

※2in1法は、最初の1回目の数列の大きさが1という所が、若干イレギュラーな感じがある。後で紹介するプログラムを見れば、気が付くかもしれないが、初期の賭ける金額は、m_bet(賭け金額)=vec[0]+vec[size-1](数列の両端)でなくm_bet=vec[0] (数列の左端)と書いている

モンテカルロ法で指摘したことと被るが……

負けた場合、賭け金額を右端に加える。
これは、負けた金額を記憶しておくことに対応する。

勝った場合、右端と左端を消す。
これは、負けた時の金額を帳消しすることを意味する。

負けた時に、数字を付け加えるスピードが1だとしたら、勝った時は、数字を消すスピードは2とえる。

そういう意味で、1回の勝ちで、2回分の負けを帳消ししている。(たぶんこれが、2in1の名前の由来だろう)

数列が全部消えて、ゲームのセッションが終わった場合、最初の数列である(1)の分だけ、利益がでる。つまり、数列が完全に消えた時に、最初に持っていた金額よりも+1多い金額になる。

しかし、既に気づいている方もいると思うが、2in1法は、数列に1つ数字が残っている場合もゲームがリセットされる。

その場合、
1-(最後に残った数列の数字)
が手持ちの金額として増減する。

もしも(最後に残った数列の数字)が大きいと、ゲームがリセットされてもする。

※2in1法を、払い戻し金が3倍の時に、適用したい場合は、モンテカルロ法に習って、数列の一番左と一番右合わせて計4つを一気に消せばよい。

※もしも、ゲームがリセットされても、損することのない手法にしたいのなら、数列の大きさが1になっても、一番左に、新たに数字(例えば1)を加えて、ゲームを続行させるルールを加えれば可能である。例えば、最後の数列の数字が(7)だったら、左に1を加え、(1,7)にしてゲームを続けるようにする。もしくは、数列に何も加えず、最初の1回目のようにゲームを進める。つまり、(7)のままで、次の勝負7を賭ける。もしも、賭ける金額が膨らむのを嫌うのなら、モンテカルロ法(賭け)の欠点&改良手法の提案(c++)で指摘したように、数字を分解すればよい。7→(3,4)

2in1法の検証

以下では2種類のプログラムを紹介する。

言語はC++で作った。

※C言語では動かない。大きさの変わる配列を扱う必要があり、vectorという動的配列を取り扱っている。vector はC言語では使用できないので注意。

※このプログラムを組んだ人間は、大学時代に少しプログラムをかじった程度の戦闘能力しかない。

2in1法個別シミュレーション

 

プログラムで使用している変数の説明

マーチンゲール法(2倍賭け)の破綻までのシミュレーションで紹介したプログラムと同じ変数の置き方をしている

i_max:勝負の回数
w:賭けたお金の戻る倍率を指定。ここでは2倍を指定
p:勝率を指定。ここでは1/2の確率なので50を指定。

m_min:かけ金を指定
m_ini:最初の資金を指定

※ここではm_min=1でm_ini=1000と、最小の賭け金の1000倍を所持していると考えている。

例えば、最小の賭け金が1000円(千円)だとするなら、手元の軍資金は、1000000円(百万円)。割と現実的な設定だと思われる。

r:乱数(0~100の乱数)

※乱数rが勝率pより下の数で収まるなら勝ちの判定がでる。

そして、勝負を続けていくうちに、負け続けることもあるだろう。
そしてついに、賭けしようにも手持ちのお金が足りなくなるかもしれない。
この場合、これ以上勝負ができなくなり、プログラムは終了する。(破綻判定)

つまり、借金はNG

c:トータルの勝ち負けの差がどのくらいあるか調べる用 。

実際にプログラムを走らせると以下のような結果となる
勝負回数i_maxは100000(10万回)までとする

#倍率は2.000000 勝率は50.000000 最小の賭け金は1.000000 手持ちのお金は1000.000000
1回目 賭け金は1.000000 数列:1/ win 勝敗差1 手持ちのお金は1001.000000 数列リセット
(省略)
28回目 賭け金は1.000000 数列:1/ win 勝敗差8 手持ちのお金は1016.000000 数列リセット
29回目 賭け金は1.000000 数列:1/ lose 勝敗差7 手持ちのお金は1015.000000
30回目 賭け金は2.000000 数列:1/1/ lose 勝敗差6 手持ちのお金は1013.000000
31回目 賭け金は3.000000 数列:1/1/2/ lose 勝敗差5 手持ちのお金は1010.000000
32回目 賭け金は4.000000 数列:1/1/2/3/ lose 勝敗差4 手持ちのお金は1006.000000
33回目 賭け金は5.000000 数列:1/1/2/3/4/ lose 勝敗差3 手持ちのお金は1001.000000
34回目 賭け金は6.000000 数列:1/1/2/3/4/5/ win 勝敗差4 手持ちのお金は1007.000000
35回目 賭け金は5.000000 数列:1/2/3/4/ lose 勝敗差3 手持ちのお金は1002.000000
36回目 賭け金は6.000000 数列:1/2/3/4/5/ lose 勝敗差2 手持ちのお金は996.000000
37回目 賭け金は7.000000 数列:1/2/3/4/5/6/ lose 勝敗差1 手持ちのお金は989.000000
38回目 賭け金は8.000000 数列:1/2/3/4/5/6/7/ lose 勝敗差0 手持ちのお金は981.000000
39回目 賭け金は9.000000 数列:1/2/3/4/5/6/7/8/ win 勝敗差1 手持ちのお金は990.000000
40回目 賭け金は9.000000 数列:2/3/4/5/6/7/ lose 勝敗差0 手持ちのお金は981.000000
41回目 賭け金は11.000000 数列:2/3/4/5/6/7/9/ win 勝敗差1 手持ちのお金は992.000000
42回目 賭け金は10.000000 数列:3/4/5/6/7/ lose 勝敗差0 手持ちのお金は982.000000
43回目 賭け金は13.000000 数列:3/4/5/6/7/10/ win 勝敗差1 手持ちのお金は995.000000
44回目 賭け金は11.000000 数列:4/5/6/7/ win 勝敗差2 手持ちのお金は1006.000000
45回目 賭け金は11.000000 数列:5/6/ win 勝敗差3 手持ちのお金は1017.000000 数列リセット
(省略)
17529回目 賭け金は551.000000 数列:43/56/69/92/115/138/161/184/207/250/293/336/379/422/465/508/ lose 勝敗差-3 手持ちのお金は106.000000
次の勝負に必要な金額は594.000000です。17529回目でゲームを終了します

28-45回目までの流れが、2in1法を理解するのにちょうどいいかなと思って、切り取っている。

28回目終了して、29回目最初の段階で持っている金額は1016。45回目で勝利して、数列がぴったり消えて、45回目が終わった段階で持っている金額は1017。最初の段階より+1される

※srand((unsigned)time(NULL));の部分で時間を参照した上で乱数を発生させている。そのため、実行するタイミングで結果が変化する。

2in1法の期待値シミュレーション

上のプログラムを何度も走らせて期待値や破綻する率をもとめたい

そのためのプログラムは以下のようになる

 

プログラムで使用している変数の説明

b_pro:破綻率
※ここでいう破綻率とは手持ちのお金が、賭けに耐えられない状況を意味する。借金してお金を用意することはできないとする。

i_exp: 破綻するまで何回勝負ができるかの期待値
m_exp: 勝負が終わった段階で持っているお金の期待値
k_max:試行回数。
※k_maxを大きくすればするほど、正確な期待値が求まる。

c_exp:勝敗差の期待値

以下では、k_max=100000、i_max=100000で指定。
試行回数10万回、勝負回数10万回。

勝負回数は100000
試行回数は100000
破たん回数は96618
破たん率は96.618000%
破たんするまでに行える勝負回数の期待値(i_exp)は12551.335270
破たんする直前で持っているお金の期待値(m_exp)は991.885580
破たんした時の勝負差の期待値は-0.452730

破綻率96.618%は、高いように見えるが、マーチンゲール法などの99%越えと比べるとだいぶましな数字である。

破綻するまでに行える勝負回数の期待値(i_exp)も12551回と1万回を超えしている。単純なモンテカルロ法よりは、破綻しにくく、長くゲームができる。

モンテカルロ法より破綻率が小さくなるのは、はっきりわからないが、以下の2つが原因の候補

  • モンテカルロ法と比べて、数列がリセットされた時に、2in1法は、最終的な収支において損が出やすい(損が出やすいというのは、逆に考えると、損が出ることに対して、寛容であるという意味だ。損が出ることに対して寛容でない手法ほど、破綻しやすい)
  • 最初に賭ける金額が、モンテカルロ法だと4(1+3)で、2in1法だと、1である。より小さな額から勝負ができる

ちなみに、2in1法の破綻率にもっとも近いのは、モンテカルロ法(賭け)の欠点&改良手法の提案(c++)の記事で提案した手法だ。

※その記事で提案した手法は、2in1法の初めの数列が(1)でなく(0,1)。また、数字が1個残った時に、分解する手順を加えただけの手法といえる。似たような結果になるのは、納得がいく。

まとめ

  • 2in1法は、払い戻し2倍で使用されることを想定されている
  • モンテカルロ法と似ている手法で、最初の数列が違うだけと捉えることができる
  • 数列が1つも残らず、リセットされると、最終的な収支は+1される。ただし、数列の数字が1つ残ってゲームを終えた場合は、損をだすことがある。
  • モンテカルロ法より、長くゲームが楽しめる

関連記事

※目次用の記事:ギャンブルの賭け方の種類をまとめてみた

~Webサイトを自分で作ってみませんか?~

Webサイトを運営するにはサーバーが必須です。
このサイトは、エックスサーバー のサーバーを使用しています。
エックスサーバーは無料で10日間お試しができます。

  • このエントリーをはてなブックマークに追加

スポンサーリンク


コメント

コメントを残す

*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)