仮想計算機構

IT業界と無縁な派遣社員のブログ

圧縮されたルールテーブルから元のルールテーブルを復元する

セルオートマトンはセルの次の状態を決めるために遷移規則を必要とします。例えば Tempesti loop であれば以下のページにあるルールを使います。
ruletablerepository/Tempesti.table at gh-pages · GollyGang/ruletablerepository · GitHub

このページを見ると一番最初のルールは
2,b,0,0,0,a,1,1,1,a
です。これは以下のルールと同義です。

1b0
120 -> a
1a0

Tempesti loop では Moore近傍を用いるので、中心セルの斜め方向にあるセルの状態も考慮して計9個のセル状態から次のセルの状態を決めます。ところで、Tempesti loop の状態数は10なので0から9までの数値を使うので、a や b といった記号は使わないはずです。この記号の意味はなんでしょうか。

Tempesti.tableには
var a = {5,6,7,8,9}
var b= {5,6,7,8,9}
とあります。

これは a は5から9までの数字を取りうるよーという意味です。つまりルール「2,b,0,0,0,a,1,1,1,a」が実際に表現しているのは1つのルールではなく、下記の25個のルールです。

2500051115
2600051115
2700051115 
2800051115
2900051115
2500061116
2600061116
2700061116 
2800061116
2900061116
2500071117 
2600071117
2700071117
2800071117
2900071117
2500081118
2600081118 
2700081118
2800081118
2900081118 
2500091119
2600091119
2700091119
2800091119
2900091119 

このように a や b といった記号を使っていたのはルールの数が膨大になってしまうのを防ぐためだったわけです。ただ、私が以前作ったりしているセルオートマトンのプログラムは上述の表記法に対応したプログラムになっていないので、Tempesti.tableをそのまま使うことができません。ルールが膨大な量になるかもしれませんが、以前作ったプログラムを再利用するために、ルールをすべて書き下す必要があります。

プログラム

Tempesti.tableを読み込み、a や b などの記号を含まないルールの集合を書きだすプログラムをPythonで作成しました。

f = open("Tempesti.table","r")
g = open("test.txt","a+")
lines = f.readlines()
d = dict()
for line in lines:
    if line[0]=="#":
        continue
    elif line[0:3]=="var":
        expr = line.split(" ")[1]
        v, s = expr.split("=")
        l = s[1:-2].split(",")
        d[v] = l
    elif True not in [k in line for k in d.keys()]:
        g.write(line.replace(",",""))
    else:
        rules = [line]
        for k in d.keys():
            l = []
            ids = []
            processed_rules = []
            for i,rule in enumerate(rules):
                if k in rule:
                    processed_rules.append(rule)
                    for v in d[k]:
                        l.append(rule.replace(k,v))
            for r in processed_rules:
                rules.remove(r)
            rules.extend(l)
        for r in rules:
            g.write(r.replace(",",""))

f.close()
g.close()

実行結果

もともとのTempesti.tableは1062行のファイルでした。展開後のファイルの中身はどうでしょうか。

PS > Get-Content .\test.txt -totalcount 10
n_states:10
neighborhood:Moore
symmetries:none
2500051115
2600051115
2700051115
2800051115
2900051115
2500061116
2600061116

記号がちゃんと数字に置換されています。大丈夫そうです。
展開後のファイルの行数も確認します。

PS >  $log = Get-Content .\test.txt                  
PS >  $log | Measure-Object -Line -Character -Word | Format-List Lines,Words,Characters


Lines      : 35325 
Words      : 35325 
Characters : 381330

35325行です。めちゃくちゃ増えています。ただ、メモリが足りなくなるほど膨大な量というわけでもないので、展開後のルールを使ってTempesti loop を作れそうです。