見出し画像

「しかのこのこのここしたんたん」を生成する有限状態マルコフ言語をpythonで再現してみる。

「しかのこのこのここしたんたん」というマルコフ連鎖

先日、youtubeのホーム画面で次の動画を見かけました。

その時はサムネを見ただけで内容を確認しなかったのですが、ふとこの動画のことを思い出して、自分で「しかのこのこのここしたんたん」を生成するマルコフ連鎖を考えてみようと思い立ちました。

有限状態マルコフ文法

状態遷移図1

最初、「状態遷移図1」のような文法を考えました。
しかし、これはあまりに冗長です。

  • s1.s2.s3とs4.s5.s6が互いに対称的であること。

  • 「たん」を生成するs1とs6は、「たん」を生成する以外に分岐が存在しないこと。

上の二つを考慮して、次のような状態遷移図を考えました。

状態遷移図2

「状態遷移図2」をpythonで再現する。

import random

list = ['しか', 'の', 'こ', 'し' ,'たん']

def r1():
    r1 = random.randint(1,2)
    return r1

num_list = [1, 2, 3]
def r2():
    r2 = random.choice(num_list)
    return r2

def s2():
    global ch
    global trans
    while r1() == 1:
        ch += list[4]
    else:
        ch += list[0]
        while r2() == 1 or r2() == 2:
            if r1() == 1:
                ch += list[2]
                continue
            else:
                ch += list[1]
                continue
        else:
            ch += list[3]

まず「しか」「の」「こ」「し」「たん」という四つの要素を持ったlistを用意しました。

list = ['しか', 'の', 'こ', 'し' ,'たん']
list2 = ['start->', 's1->', 's2->']

つぎに、「1or2をランダムに生成する関数」と「1or2or3をランダムに生成する関数」を定義しました。

num_list = [1, 2, 3]
def r2():
    r2 = random.choice(num_list)
    return r2

「1or2をランダムに生成する関数」を呼び出し、1が出続ける限り「たん」を生成し、2が出たときに「しか」を生成してs2へ遷移するようにしました。

while r1() == 1:
    trans += list2[0]
    ch += list[4]
else:
    ch += list[0]

s2へ遷移したとき、「1or2or3をランダムに生成する関数」が「1or2」を生成したとき、再び「1or2をランダムに生成する関数」を呼び出し、それぞれ1と2が出たとき「の」と「こ」を生成するようにしました。
また、「1or2or3をランダムに生成する関数」が3を生成したとき「し」を生成し、初期状態に戻すようにしました。

       
        while r2() == 1 or r2() == 2:
            if r1() == 1:
                trans += list2[2]
                trans += list2[2]
                ch += list[2]
                continue
            else:
                trans += list2[2]
                trans += list2[2]
                ch += list[1]
                continue
        else:
            ch += list[3]

いままでの一連の処理を三回繰り返せば、「しかのこのこのここしたんたん」が1,417,176分の1の確率で生成されることになります。

最後に

これを自動化し、いくつかのグラフを付したアプリを紹介します。

「しかのこのこのここしたんたん」マルコフ連鎖生成器

このアプリでは一番上の段に左から「生成された連鎖の大きさを10ごとに区切った棒グラフ」と「関数の実行回数1回目・二回目・三回目それぞれまでに発生した遷移の数の円グラフ」と「連鎖の長さの確率密度関数」が並び、二段目には生成された連鎖の遷移の順番を表示し、三段目には生成された連鎖そのものと状態遷移図が載っています。

この記事が気に入ったらサポートをしてみませんか?