*All archives* |  *Admin*

<<10  2017/11  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  12>>
floodgate for mahjong へ参戦その17・シミュレーションパートの時間短縮と調整
前回に引き続き、麻雀AIの話です。
シミュレーションパートの大枠は大体できた(自分鳴きと点棒状況以外)ので、コードの中身を最適化して、より高速に計算できるように試みます。

一番計算時間がかかる部分が他家のツモ番で、切る牌を選択する関数です。
単純に3人いるので呼び出される回数が多いのと、毎順ごとに37種類の牌すべてについて、どの程度切られやすいかを各入力変数(現物か無筋かとか枚数とかカベ効果とか)ごとに倍率で掛けて計算する必要があるためです。

掛け算とかで時間を食うのはしょうがないのですが、本筋と関係ないところで無駄に時間を使っているところはなるべく回避していきます。
・再帰パートでは手牌とか見えてる枚数とか現物筋変数とかが頻繁に更新されるので、Long型を使っていたが、シミュレーションパートでは更新の頻度よりも枚数等を参照する頻度の方が多いので、いちいちLong型から枚数の情報を取り出す演算が余計にかかっている。よってこれら変数をInteger型配列に戻した。
・牌種類(端寄り中寄りとか役牌オタ風とか)を頻繁に関数を使って計算していたのが無駄だったので、各プレイヤーごと・37種類の牌ごとに牌種類を直接参照できるように配列でデータを置いておくことにした。

後は明らかに劣ってる打牌はシミュレーションパートを計算しないようにしました。再帰パートで1番目と2番目に局収支がいい打牌候補2つ+他家リーチがあるときはベタ降りの2択か3択でのみ考えることにしました。

テスト風景はこんな感じ。
(牌姿は6巡目1235m445r56p23457s ドラ5m)
170601-01.png
正直、まだ計算時間的には不満(1打牌候補につき2秒くらい)なんですが、高速化の手法のネタ切れなので今のところこれ以上の改善は無理そうです。

それで、計算時間の件はいったんおいておいて、正しく動作するかどうかを1試合分の牌譜を通しで計算させてみました。

今のところ出ている問題点はこちら。
・自分聴牌でリーチしたときを開始時点にすると、四人リーチ流局率が0.5%とやけに高い数値が出ている。
プログラムを途中で止めたりしながら見ていると、どうやら無筋の切られる頻度が感覚より高いような感じになっています。

170601-03.png
↑こちらはある捨て牌状況での、各牌が切られる率です。
一番左が牌番号(1~37)、中央がその牌が切られる率、右側がリーチ者の筋現物変数(0が現物、1が両筋・字牌、3が片無筋、4が両無筋)
一番下が現物が切られる確率の総和と無筋が切られる確率の総和です。

無筋が切られる確率が17%というのはかなり大きいような気がします。

↓が先制立直からの経過巡目別の、リーチを受けた側が先制立直に対して切った現物枚数・無筋枚数の分布(実測値)です。
170601-02.png
5巡以上経過しているケースでも半分以上は無筋を1枚も切っていない(無筋0現物2)の状態であることが分かります。

それに対してAIの計算では現物を切った場合と無筋を切った場合の時にコードをストップして切ってる無筋現物数を調べると明らかに無筋0現物2になってる頻度が半分以上はないです。
AIの計算の中では他家が無筋を切ってるケースが多いので、追っかけリーチの発生率が高い数値のところが参照されて、四人リーチが発生しやすいという構図だと思われます。

このようになってる原因として考えられるのは牌が切られる確率の計算は現状だと、
各牌ごとに独立して行っていて最後に総和が1になるように帳尻を合わせている方式になっています。
当然、現物の方が無筋よりも切られやすいというのは考慮されているのですが、ある現物牌は通常の2倍切られやすい、ある無筋牌は通常の切られる率の半分程度、などといったものの積み重ねなので、
特に現物の種類(見えてない枚数)が少なくて、無筋の種類(枚数)が多いようなケースだと半分の切られ率の無筋も多数種類あると塵も積もれば山となるみたいな感じで、各牌の数値を積み上げた結果、切られる率が過大評価されるということが考えられます。

これを防ぐ方策として考えられるのは、先に現物が切られる確率の総和(どの現物が切られるかは問わない)や無筋が切られる確率の総和(どの無筋が切られるかは問わない)を枠として確保しておいて、第一段階で現物が切られるか無筋が切られるかを乱数で判定する→仮に現物が切られると決定されたら、第二段階として現物の中から枚数等の情報からどの現物を実際に切るかを選択する、みたいな案があります。

別途パラメータの取得は必要になるし、計算ステップが増えることで計算時間が増えそうなのもちょっと気がかりです。
まぁでも明らかに変な挙動のまま、放っておくわけにもいかないし、やるしかないかー。

・何か↑でやったテスト牌姿で再帰パートが打7sより打2sの方を和了率・局収支が高いとおっしゃっておられる。
どう考えても25sのどっち引いてもいいように打7sだと思うのだが、中で何が起こっているんだろう。意味が分からないです。

・塔子がぎりぎり足りているヘッドレス2シャンテンで、浮き牌比較の時に中寄りの牌を切って、端寄りや字牌を残したがる傾向があるみたい。
手変わり0回なので、浮き牌にくっつくことを考慮していなくて、ヘッドになりやすさで中寄りの牌を切っていると思われる。
これは手替わり1回にすれば解決すると思われるが、計算時間がどの程度増えるかが未知数なので、まだ触ることができていない。


というわけで、けっこうあやしい挙動が多数あるので、しばらくはバグ潰しや調整に時間がかかりそうです。
スポンサーサイト

コメントの投稿

Secret
(非公開コメント受付中)

コメント

プロフィール

nisi5028

Author:nisi5028
FC2ブログへようこそ!

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
FC2カウンター
フリーエリア
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード