波理論を科学する

お世話になっております、スログラミングです。

波理論」。パチンコ・スロット好きな方なら一度は聞いたことがありますよね。
例えば、こんな感じで過去のスランプグラフから未来のスランプグラフを予想するオカルトです。


とはいえ、パチンコ・スロットが完全確率である限り予想は不可能なわけですが、楽しみ方の一つとして個人的には好きなオカルトです。
※怪しい情報教材にはくれぐれもご注意ください。

では早速Pythonでコーディングしていきましょう。

今回のアジェンダはこちら。
1. 波理論とは?
2. 波理論部分のコード
3. 今回作成したコード
4. 結果の確認


1. 波理論とは?

冒頭でちらっと記載しましたが、もう少し具体的に波理論の中身を考えてみます。
おそらく波理論をやるときの頭の中はこうなっていると思います。
1.スランプグラフを見る
2.頭の中にある過去のスランプグラフと照合
3.今のと似たスランプグラフをピックアップ
4.ピックアップしたスランプグラフをパターン分類
5.頻出するパターンになると予想


ここまでの流れを元に、プログラミングを行うためのフローチャートを作成したものがこちら。
実戦データベースは、過去に作成したマイジャグのシミュレータをちょっといじってcsv出力してます。
csvの中身は1列だけで、1回転ごとの差枚数をひたすら出力してます。


今回の評価方法は以下の形としています。
1.3000G分のスランプグラフを作成
2.その内、2000G分のデータから波理論で残りの1000Gの推移を予測
3.機種はマイジャグ、設定は1
想定としては、「軽く回されて判別やめされた設定1のマイジャグを1時間超くらいでさくっと出したい!」という感じです。


2. 波理論部分のコード

ここから実際のコーディングを行っていきます。
(フローチャートのスランプグラフ作成の部分はいつもと同じなので割愛。)

必要なデータの読み込み

まずは、必要なデータを読み込んでいきます。
csvデータの読み込みは、numpy(今回使用)とpandasがありますが、numpyに入っている相互相関(corrcoef)を使いたいのでnumpyで読み込んでいます。
また、コメントに記載しましたが、以下のようにデータを入れてます。
ResultData:2000Gまでのデータ
ResultData_full:3000Gまでのデータ
ResultDatabase:100万G分のデータ

    # データベースファイルの読み込み
    ResultData = np.loadtxt("D:\Test\data_mjg.csv", delimiter= ",") # 2000Gまでのデータ
    ResultData_full = np.loadtxt("D:\Test\data_mjg_full.csv", delimiter= ",")   # 3000Gまでのデータ
    ResultDatabase = np.loadtxt("D:\Test\database_mjg.csv", delimiter= ",") # 100万G分のデータ

類似データを抽出

先ほど読み込んだ2000Gまでのデータの類似データを100万G分のデータベースから抽出していきます。
用いるのは先ほどちらっと記載した相互相関(numpy.corrcoef)です。
簡単な説明は↑の記事に記載しているので、そちらをご覧ください。
この関数を使うと、「-1(正反対)~0(全く似てない)~1(そっくり)」まで)の値を出力してくれます。
抽出したデータは、corr_list内に[相関係数, 類似データの開始点, 類似データの終了点]の順に格納しています。
今回は一般的に類似データの基準となる相関係数=0.7を閾値に設定してます。

    # 類似と判定する閾値の設定
    corr_th = 0.7

    # 類似した箇所のカウント用変数
    count1 = 0
    corr_list = []

    # ビッグデータを少しづつずらしながら、当日のデータと比較
    for i in range(0, len(ResultDatabase) - len(ResultData), 500):
        corr = np.corrcoef(ResultDatabase[i : i + len(ResultData)], ResultData[:])[0,1]
        # 相関係数の高いデータの位置を記録する
        if corr_th < corr:
            count1 = count1 + 1
            corr_list.append([corr, i, i + len(ResultData)])

類似データをパターン分類

抽出した類似データから、頻出するパターンを見つけていきます。
for文がwhile文になったりしていますが、やってることはさっきとほぼ同じです。
違いとしては、さっきは他人から自分(データベースから当日のデータ)に類似するものを探していたのに対して、今回は自分から自分(抽出した類似データから抽出した類似データ)に類似するものを探しています。

抽出したリストは複数のデータなので、複数から複数を総当たりで処理する2重ループ処理が必要となります。
for文で処理しても問題ありませんが、抽出したリストのいらない部分を削除しながらwhile文で処理していくことで、処理時間の短縮を行っています。

最後に抽出したリストを類似データの個数が多い順にソートすれば、波理論の処理は完成です。

    # 相関係数の高いデータの集まりから、よく出現するパターンを取得する
    corr_res = []
    i = 0
    while i < len(corr_list):
        corr_cnt = 0
        corr_list_len = len(corr_list)
        j = 0
        while j < len(corr_list):
            # 各データと類似のグラフが何個あるかを計算
            corr = np.corrcoef(ResultDatabase[corr_list[i][2] : corr_list[i][2] + 1000], ResultDatabase[corr_list[j][2] : corr_list[j][2] + 1000])[0,1]
            if  corr_th < corr:
                corr_cnt = corr_cnt + 1
                if i != j:
                    # 類似パターンは1個あれば良いので、重複データは削除する
                    # 自分自身は消さないようにif文の条件を設定
                    del corr_list[j]
                else:
                    j = j + 1
            else:
                j = j + 1
        # データのある位置と類似データの個数を記録
        corr_res.append([corr_list[i][0], corr_list[i][1], corr_list[i][2], corr_cnt])
        i = i + 1

    # 類似データの個数が多い順にソート
    corr_res_sort = sorted(corr_res, key=lambda x: x[3], reverse=True)

3. 今回作成したコード

最終的には以下のようなコードを作成しました。
類似データの多い順に3個分のスランプグラフを描画させるようにしています。
また、結果の確認用に波理論の処理を100回ループするようにしています。

    # coding: UTF-8
    # 実戦データ作成用
    import random
    # 結果のcsv出力用
    import csv
    # 相関係数算出用
    import numpy as np
    # グラフ描画用
    import pylab
    
    for test in range(100):
        print("----------")
        print(test + 1, "/100 start.")
        # 実戦データの作成
        # ---ここから----
        # 設定値の設定
        設定 = 1
        # 試行回数の設定
        loop = 3000
        # 途中結果表示の区切り回数
        区切り回数 = 2000
    
        # 設定ごとの小役・ボーナス確率の設定
        header = ['Machine', 'Setting', 'Reaplay', 'Cherry', 'Grape', 'BB_T', 'BB_Ch', 'RB_T', 'RB_Ch']
        set1 = ['MyJug3', '1', '7.29', '36.028', '6.35', '402', '1456.3', '668.7', '1213.6']
        set2 = ['MyJug3', '2', '7.29', '35.949', '6.289', '397.1', '1394.3', '528.5', '1170.2']
        set3 = ['MyJug3', '3', '7.29', '34.693', '6.25', '383.2', '1337.4', '496.4', '1092.2']
        set4 = ['MyJug3', '4', '7.29', '33.522', '6.23', '372.3', '1260.3', '409.6', '1024']
        set5 = ['MyJug3', '5', '7.29', '33.402', '6.179', '352.3', '1213.6', '390.1', '963.7']
        set6 = ['MyJug3', '6', '7.29', '33.233', '6.071', '334.3', '1170.2', '334.3', '862.3']
    
        SetData = [header, set1, set2, set3, set4, set5, set6]
    
        # 結果用の箱の準備
        Result = []
    
        # ループ処理
        # 差枚数を入力する変数
        Total = 0
    
        リプレイ = float(SetData[設定][2])
        チェリー = float(SetData[設定][3])
        ぶどう = float(SetData[設定][4])
        単独BB = float(SetData[設定][5])
        チェリーBB = float(SetData[設定][6])
        単独RB = float(SetData[設定][7])
        チェリーRB = float(SetData[設定][8])
    
        # 乱数範囲の設定
        リプレイ範囲 = round(65536 / リプレイ)
        チェリー範囲 = round(65536 / チェリー)
        ぶどう範囲 = round(65536 / ぶどう)
        単独BB範囲 = round(65536 / 単独BB)
        チェリーBB範囲 = round(65536 / チェリーBB)
        単独RB範囲 = round(65536 / 単独RB)
        チェリーRB範囲 = round(65536 / チェリーRB)
    
        リプレイ範囲_下 = 0
        リプレイ範囲_上 = リプレイ範囲_下 + リプレイ範囲 - 1
        チェリー範囲_下 = リプレイ範囲_上 + 1
        チェリー範囲_上 = チェリー範囲_下 + チェリー範囲 - 1
        ぶどう範囲_下 = チェリー範囲_上 + 1
        ぶどう範囲_上 = ぶどう範囲_下 + ぶどう範囲 - 1
        単独BB範囲_下 = ぶどう範囲_上 + 1
        単独BB範囲_上 = 単独BB範囲_下 + 単独BB範囲 - 1
        チェリーBB範囲_下 = 単独BB範囲_上 + 1
        チェリーBB範囲_上 = チェリーBB範囲_下 + チェリーBB範囲 - 1
        単独RB範囲_下 = チェリーBB範囲_上 + 1
        単独RB範囲_上 = 単独RB範囲_下 + 単独RB範囲 - 1
        チェリーRB範囲_下 = 単独RB範囲_上 + 1
        チェリーRB範囲_上 = チェリーRB範囲_下 + チェリーRB範囲 - 1
    
        # 小役の出現個数カウント用
        リプレイ回数 = 0
        チェリー回数 = 0
        ぶどう回数 = 0
        単独BB回数 = 0
        チェリーBB回数 = 0
        単独RB回数 = 0
        チェリーRB回数 = 0
    
        # ループ処理
        # loopで設定した回転数分まわす
        for j in range(loop):
            # 1回転あたり3枚必要なので、3枚マイナス
            Total = Total - 3
    
            # 1回転ごとに乱数を生成(0~65535の範囲)
            rand = random.randint(0, 65535)
    
            # 小役orボーナスの当選確認と差枚数の加算
            if リプレイ範囲_下 <= rand <= リプレイ範囲_上:
                Total = Total + 3
                リプレイ回数 = リプレイ回数 + 1
            elif チェリー範囲_下 <= rand <= チェリー範囲_上:
                Total = Total + 2
                チェリー回数 = チェリー回数 + 1
            elif ぶどう範囲_下 <= rand <= ぶどう範囲_上:
                Total = Total + 7
                ぶどう回数 = ぶどう回数 + 1
            elif 単独BB範囲_下 <= rand <= 単独BB範囲_上:
                Total = Total + 312
                単独BB回数 = 単独BB回数 + 1
            elif チェリーBB範囲_下 <= rand <= チェリーBB範囲_上:
                Total = Total + 312
                チェリーBB回数 = チェリーBB回数 + 1
            elif 単独RB範囲_下 <= rand <= 単独RB範囲_上:
                Total = Total + 104
                単独RB回数 = 単独RB回数 + 1
            elif チェリーRB範囲_下 <= rand <= チェリーRB範囲_上:
                Total = Total + 104
                チェリーRB回数 = チェリーRB回数 + 1
            else:
                # はずれだったら何もしない
                Total = Total
    
            # 1回転ごとに差枚数を配列に入力
            Result.append(Total)
    
        # 実戦データのcsv出力
        with open('D:\Test\data_mjg.csv', 'w') as file:
            writer = csv.writer(file, lineterminator='\n')
            writer.writerows(np.array([Result]).T[0:区切り回数])
        with open('D:\Test\data_mjg_full.csv', 'w') as file:
            writer = csv.writer(file, lineterminator='\n')
            writer.writerows(np.array([Result]).T)
    
        # ---ここまで----
    
        # データベースファイルの読み込み
        ResultData = np.loadtxt("D:\Test\data_mjg.csv", delimiter= ",") # 2000Gまでのデータ
        ResultData_full = np.loadtxt("D:\Test\data_mjg_full.csv", delimiter= ",")   # 3000Gまでのデータ
        ResultDatabase = np.loadtxt("D:\Test\database_mjg.csv", delimiter= ",") # 100万G分のデータ
    
        # 元データの描画
        pylab.figure()
        pylab.plot(ResultData_full[:区切り回数 + 1000])
    
        # 類似と判定する閾値の設定
        corr_th = 0.7
    
        # 類似した箇所のカウント用変数
        count1 = 0
        corr_list = []
    
        # ビッグデータを少しづつずらしながら、当日のデータと比較
        for i in range(0, len(ResultDatabase) - len(ResultData), 500):
            corr = np.corrcoef(ResultDatabase[i : i + len(ResultData)], ResultData[:])[0,1]
            # 相関係数の高いデータの位置を記録する
            if corr_th < corr:
                count1 = count1 + 1
                corr_list.append([corr, i, i + len(ResultData)])
        print("類似パターン:", len(corr_list), "個")
    
        # 相関係数の高いデータの集まりから、よく出現するパターンを取得する
        corr_res = []
        i = 0
        while i < len(corr_list):
            corr_cnt = 0
            corr_list_len = len(corr_list)
            j = 0
            while j < len(corr_list):
                # 各データと類似のグラフが何個あるかを計算
                corr = np.corrcoef(ResultDatabase[corr_list[i][2] : corr_list[i][2] + 1000], ResultDatabase[corr_list[j][2] : corr_list[j][2] + 1000])[0,1]
                if  corr_th < corr:
                    corr_cnt = corr_cnt + 1
                    if i != j:
                        # 類似パターンは1個あれば良いので、重複データは削除する
                        # 自分自身は消さないようにif文の条件を設定
                        del corr_list[j]
                    else:
                        j = j + 1
                else:
                    j = j + 1
            # データのある位置と類似データの個数を記録
            corr_res.append([corr_list[i][0], corr_list[i][1], corr_list[i][2], corr_cnt])
            i = i + 1
    
        # 類似データの個数が多い順にソート
        corr_res_sort = sorted(corr_res, key=lambda x: x[3], reverse=True)
    
        # 類似データの多いグラフの描画
        # 類似データの多い順にcorr_count個分のスランプグラフを描画
        corr_count = 3
        count = 0
        for i in corr_res_sort:
            data = ResultDatabase[i[2] : i[2] + 1000] - ResultDatabase[i[2]] + ResultData[-1]
            if count == 2:
                pylab.plot(ResultDatabase[i[1] : i[2] + 1000] - ResultDatabase[i[2]] + ResultData[-1], linestyle='--', alpha=0.5)
                print("出現回数:", i[3], "回")
                print("推測と実データの相関係数:", np.corrcoef(ResultData_full[区切り回数 - 1: 区切り回数 - 1 + 1000], ResultDatabase[i[2]: i[2] + 1000] - ResultDatabase[i[2]] + ResultData[-1])[0, 1])
                print("1000G後の差枚数:", ResultData_full[区切り回数 - 1 + 1000] - ResultData_full[区切り回数 - 1], "枚(実データ), ", ResultDatabase[i[2] + 1000] - ResultDatabase[i[2]], "枚(推測)")
                break
            else:
                pylab.plot(ResultDatabase[i[1] : i[2] + 1000] - ResultDatabase[i[2]] + ResultData[-1], linestyle='--', alpha=0.5)
                print("出現回数:", i[3], "回")
                print("推測と実データの相関係数:", np.corrcoef(ResultData_full[区切り回数 - 1 : 区切り回数 - 1 + 1000], ResultDatabase[i[2] : i[2] + 1000] - ResultDatabase[i[2]] + ResultData[-1])[0, 1])
                print("1000G後の差枚数:", ResultData_full[区切り回数 - 1 + 1000] - ResultData_full[区切り回数 - 1], "枚(実データ), ", ResultDatabase[i[2] + 1000] - ResultDatabase[i[2]], "枚(推測)")
                count = count + 1
    
        # 結果の出力(カウント数の割合で算出)
        pylab.axvspan(0, len(ResultData), color="magenta", alpha=0.3)
        pylab.legend(["実データ", "出現数1位", "出現数2位", "出現数3位"], prop={"family":"MS Gothic"})
        pylab.savefig("D:\Test\MJG_EST_" + str(test) + ".png")
        # pylab.show()
    
        print(test + 1, "/100 end.")
        print("----------")

4. 結果の確認

作成したコードを実行した結果はこちら。


とりあえず適当に3つほどグラフを選んでみましたが、何とも言えない感じですね。
良いとも悪いとも言えない絶妙に微妙な結果ですね。

ピックアップした3つ以外の結果も確認してみます。
まとめた結果がこちら。
出現数の多かった上位3パターンに関して、予測部分と実データの相関係数の平均と最終差枚数の誤差の平均を計算しています。


はい、全然使えないですね。(笑)
出現数1位のパターンでも666枚の誤差が発生してます。
ちなみに、相関係数0.2のグラフはこんな感じです。
ほぼ類似データとは言えないですね。



ということで今回波理論をPythonで実装してみました。
心の片隅に淡い期待を抱いていましたが、やはり無理でしたね。

とはいえ、こんな感じで色々やってみるのも面白いですね。


にほんブログ村 スロットブログ スロット情報へ
にほんブログ村

コメント

このブログの人気の投稿

【WEBアプリ】Sキングハナハナ-30のベル確率予想&ベル確率逆算ツール&設定判別ツール

【WEBアプリ】ハナハナホウオウ天翔のベル確率を差枚数から逆算するツール

【WEBアプリ】ハナハナホウオウ天翔の設定判別ツール