*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>>
高速シャンテン計算プログラムのソースコード2
昨日の記事(高速シャンテン計算プログラムのソースコード)で、ソースを晒してみたところ、かなり有益な情報を頂きました。

前のコードは配列の操作とかをいろいろやっていた分、計算時間的に損をしているらしく、ビット列で操作する方が計算時間が早くなるみたいです。

その発想はAI計算部分で部分的に取り入れてはいましたが、シャンテン計算の関数はけっこう前に作ったものをそのまま利用していたので、ビット列(もしくは長整数型)で計算時間短縮のギミックをまだ搭載していませんでした。
というわけで、前のコードをなるべくビット列計算をメインになるよう改造してみました。
ソースコード2
hashtable2.txt

normalshantenfunc_game関数の代わりにnormalshantenfunc_game2関数を面子手シャンテン数計算に使用します。

normalshantenfunc_game2関数の中で、まずは再帰計算をしない限り(必要になるのは相当レアで複雑な牌姿に限定される)、Integer型配列はいらないので、その部分は全部取っ払いました。
次にハッシュ関数を乗算や累乗で計算していたのをビット演算子に変えたのが、tehaitolongtaiou関数です。
この関数は引数がInteger型配列と始点と終点のインデックスで戻り値がLong型整数です。
次のようにハッシュ値を計算します。
'例 引数{1,1,0,2}→(2進数で)10101100→(10進数で)172
'1と1の間にある0の個数が手牌の枚数…最上位に1を置いて、先頭は1枚なので01、2番目が1枚なので01、3番目が0枚なので1、最後尾が2枚なので00、の順で2進数を並べる
ポイントは異なる牌姿であれば必ず異なる戻り値を返す、つまり入力の牌姿と戻り値の長整数型が完全に1対1対応しているという点です。
0の個数がすべての牌の枚数(max14枚)で、1の個数が始点から終点までの牌の種類数(max37種)というわけで、maxで51ビット使うので、ぎりぎり長整数型(64ビット)でおさまる範囲です。
計算式で用いているのは+1の加算と左シフト演算のみなので、従前の乗算、累乗よりは高速で計算できると思われます。
コードの中身も前のnormalshantenfunc_game関数より2の方がやや読みやすくなったかもしれません。

また、ハッシュ関数の計算式が変わったので、ハッシュテーブルの中身を置き換えることも必要です。
それがソースコード2.txtの下のhashtable2.txtとhashyomikomi2関数です。
hashtable2.txtも前のhashtable.txtと同じところに保存しておいてください。

また、従前よりもハッシュ値の数値が大きくなってるので、検索時間の速度を考慮して、普通の配列ではなく、Dictionaryクラスを使用します。(hashmentusu3、hashkouho3)
キーがLong型のハッシュ値、値が対応するメンツ数(メンツ候補数)です。

修正点は以上なので、実践してみます。

このコードをビルドしてそのまま実行すると、
"2m4m5m8m8m9m9m5P6p8p3s4s5s東"というてきとうな牌姿に対して、1000万回シャンテンチェックを繰り返します。(1万回終了ごとにコンソールに終わった回数が表示される。)
従前のtotalshantenfunc_game関数だと私の環境で100万回に20秒、毎秒5万回というスピードでした。
これが改造したtotalshantenfunc_game2関数に変えると1000万回終えるのに30秒、毎秒30万回となりました。
およそ6倍くらいにスピードアップしたので、まぁ上出来でしょう。
爆打のプログラムはこれよりもっと早いらしいです。

まだ改善できる点はあるにはあるのですが(一部配列参照が残っているところとか)、
ビット演算は処理速度的にはいいのですが、プログラムの保守というか可読性みたいなのがちょっとネックです。String型とかInteger型配列の方が頭の中では考えやすいです。
いったん正しいロジックで組めればいいのですけど、私のおつむでは正しく組んだ上で、それ以上の手直しとかができる自信がありません。なんとなく考えやすいInteger型配列でなれ合ってしまうあたり、トップクラスのプログラマーにはなれない感じです。
まぁ、無料で公開するレベルの話なので、このレベルでお許しください。

計算の正確性についてはちょっと前にfloodgate for mahjongで対局した試合のリプレイでAIに再計算させて、1試合分動かしたところ従前の関数と違う数値が出たところはなかったので、おそらくだいじょうぶのはずです。

一応、ソースコードの中には従前で使用しているものも残しているのですが、以下のものは新関数では使わないので削除してもらって構いません。
Dim hashmentusu2(1562500) As Integer 'ハッシュテーブルメンツ数
Dim hashkouho2(1562500) As Integer 'ハッシュテーブルメンツ候補数
Sub hashyomikomi() 'hashtable読み込み
Function normalshantenfunc_game(ByVal tehaifuroigaiakanasi() As Integer, ByVal furosu As Integer) As Integer 'メンツ手のシャンテン数を返す。(ハッシュテーブル+パーツで区切って高速化)
Function totalshantenfunc_game(ByVal tehaiakanasi() As Integer, ByVal furosu As Integer) As Integer() '現在のシャンテン数を返す(0-最小、1-国士、2-チートイ、3-メンツ手)
スポンサーサイト
高速シャンテン計算プログラムのソースコード
昨日の雑談で書いた、高速シャンテン計算関数について、
必要になる部分だけ抜き出して、各関数の説明書きとかを書いたので、ソースを公開します。

言語はVB.NETで書いています。そんなに難しい文法は使ってない(配列と繰り返しとテキストファイル読み込みと再帰関数程度)ので、他言語を使う方は適宜置き換えて使ってください。(必要な部分だけとはいえ、そこそこの分量があるので、大変かとは思いますが。)
ソースの本体は「ソースコード.txt」、それの説明文が「使用説明.txt」です。
また、「hashtable.txt」も計算に必要なテキストファイルになるので、指定の場所に名前を付けて保存してください。
ソースコード
使用説明
hashtable.txt

詳しくは「使用説明.txt」をご覧下さい。
質問等があればブログのコメントなりツイッターなりでしてください。

それでは、現在、もしくは将来の麻雀研究者に向けて、このソースが少しでも足しになることをお祈りしております。
麻雀研究しない方も「普段の研究ではこういうことを書いてるんだなー」と横目で見ながらお楽しみ?ください。
鳳凰卓用シミュレータの公開
染め副露に関するパラメータにちょっと疑問があるので、今取り直してるところですが、
とりあえず一回現状できてるものを上げときます。

http://www1.axfc.net/u/3521842

上のURLからダウンロードしてください。

前回の分からファイルが2個増えてます。(hououtakupara.txtと鳳凰卓パラメータ表(見る用).xls)
新たに取った鳳凰卓のパラメータを載せています。

東風荘パラメータと同じ形式なので、エクセルファイルの同じ行のところを見れば、両者のパラメータを見比べることができます。

150822-01.png

シミュレータの見た目の変更点は右下の赤丸で囲ったところ

・使用パラメータ
「鳳凰卓」が選択されてる時はhououtakupara.txtから、「東風荘」が選択されてる時はhousimyu.txtからパラメータを読み込みます。

・シミュレーション回数
モンテカルロシミュレーションの繰り返し回数を指定できます。

・局結果別得失点表記
ここにチェックを入れると結果表示の時に、
ツモ和了時平均得点・ロン和了時平均得点・放銃時平均失点・被ツモ時平均失点・横移動時平均失点・聴牌流局時平均得点・不聴流局時平均失点を、
各巡目の結果の末尾に表示されます。
平均得失点にはリーチ棒・積み棒・親連荘時利益650点の影響も含みます。

シミュレーション回数と局結果別得失点はデバッグ・テストに便利なので、置いときました。


染め副露のパラメータを取り直したらそこだけ直してもう一回上げようと思います。

そろそろチェックボックスとかコンボボックスを置くスペースがなくなってきた。
新たな要素を入れようと思ったら画面サイズをでかくしないといけなさそう。
いろいろと変更した局収支シミュレータの公開
局収支シミュレータについて、前回に公開したものから結構多くの点を修正したので改めてアップします。

http://www1.axfc.net/u/3485603
からダウンロードしてください。

150614-03.png


主な変更点

・リーチ経過巡目の導入(経過巡目が少ないと追っかけリーチ発生率が上がり、多いと追っかけリーチ発生率が下がる。)
・親子別のリーチ発生率の導入
・ポンチー発生率の変更(喰いタンありベースへ)
・副露聴牌率の変更(手出し数を考慮から外し、対リーチに無筋・現物を切ってる枚数を考慮する。)
・副露聴牌者がリーチに対して降りることがあることも想定。
・他家和了時ハン数符数の決め方を変更(一発裏赤ナシの分布から一発裏赤を後付けする。)
・祝儀ルールに対応(チップ収支は半荘収支に増減させる。現局チップ数・次局以降チップ数も出力される。)
・自分副露(orダマ)聴牌時、自分の副露数もロン和了率に考慮する。
・自分チートイダマ時、手変わってもリーチに行かないよう変更。
・自分降り、他家降り時、現物が増える数調整(降り者から増える現物数導入。)
・次局以降上がり方について、順位別・残り局数別の数値を導入。
・雀荘ルールの初期値を「25000点持ち30000点返しウマ10-30」に変更。

見た目の大きな変更点は赤丸で囲ったところです。
・副露聴牌まわり(他家「不聴面前」、「副露」の場合、手出し数に変えて無筋数現物数を入力する。)
・先制リーチからの経過巡目を設定する。
・自分の赤枚数、4人の捨て牌の赤枚数を入力
・他家に赤の情報があるときそれを入力
・雀荘の祝儀ルールの場合、「祝儀ルール」にチェックを入れてチップ1枚の価値を入力

特に赤ドラに関しては入力の手間が増えました。そこはご了承ください。(祝儀ルールでない場合も他家和了時のハン数にかかわってくるので入力の必要があります。)

詳しくは同梱の操作説明.txtをご覧ください。
到達段位のシミュレータの公開
昨日から遊んでる到達段位に関するシミュレータについて公開したいと思います。

150223-04.png

各順位率と卓レベルと東風戦東南戦と現段位と現ptと試合数とシミュレーション回数を入力して、集計ボタンをクリック。

しばらく待つと下のリストボックスに結果(最終段位と最終ptと最高到達段と平均段位)が表示されます。(試合数が多かったりシミュレーション回数が多かったりすると表示に時間がかかるかも)
「書き込み」にチェックを入れて集計するか、「書き込み」ボタンを押すとテキストファイルに排出されます。
とっても単純。

http://www1.axfc.net/u/3418282

多分、例のごとく実行ファイルを開こうとすると「PCの危険性が~」みたいな警告が出てきます。
単に計算して、テキストファイルに排出するだけなんで、問題はないはずです。

↓コード本文はこんな感じ。
dani_source.txt

かなりあっさりした感じのプログラム。
プロフィール

nisi5028

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

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

この人とブロともになる

QRコード
QRコード