ecaについて

ecaとは

ecaとは... wikiではあいまい回避で結構いろいろな定義がリストされるが、ここで話したいのは、elementary cellar automaton ... 一次元セルオートマトンのこと。

細かい話は、wikiを参照.

セルオートマトンのプログラムを書いてみた。

#!/usr/bin/env python
class eca:
        def __init__(slf,rule,N):
                slf.rule=rule
                slf.N=N
                slf.i=0
                slf.status=[ [ 0 for i in range(slf.N)] for j in range(2)]

        def next_func(slf,l,s,r):
                d=int("%s%s%s" % (l,s,r),2)
                return (slf.rule >> d ) % 2

        def next_id(slf):
                if slf.i==0:return 1
                else:return 0

        def next(slf):
                s=slf.status[slf.i]
                t=slf.status[slf.next_id()]
                for i in range(slf.N):
                        t[i]=slf.next_func(s[i-1 % slf.N],s[i],s[(i+1) % slf.N])
                slf.i=slf.next_id()
                return slf.prnt()

        def prnt(slf):
                def char_prnt(c):
                        if c==1:return "+"
                        else:return " "
                return  "".join([char_prnt(i) for i in slf.status[slf.i] ])

        def set_status(slf,i,s):
                slf.status[slf.i][i]=s

        def get_status(slf,i):
                return slf.status[slf.i][i]

if __name__=="__main__":
        d=eca(110,50)
        d.set_status(25,1)
        for j in range(130): print d.next()

で、これだけでは面白くないので、深さ優先探索で一次セルオートマトンの逆に推移するプログラムを書いてみた。

#!/usr/bin/env python

import eca

class inverse_eca:
        def __init__(slf,rule,N):
                slf.rule=rule
                slf.N=N
                slf.i=0
                slf.status=[ [ 0 for i in range(slf.N)] for j in range(2)]
                slf.tlst=[[] for i in range(2)]
                for i in range(8):
                        slf.tlst[(slf.rule >> i) % 2].append("%03d" % int(format(i,'b')))

        def inverse_func(slf,s,k):
                tmp=[ i for i in slf.tlst[s] ]
                return [ [int(i[0]),int(i[2])] for i in tmp if int(i[1])==k]

        def next_id(slf):
                if slf.i==0:return 1
                else:return 0

        def next(slf):
                s=slf.status[slf.i]
                t=slf.status[slf.next_id()]
                tmp=[[0,1] for i in range(slf.N)]

                def recur_func(p_lst,i,k):
                        if not k in p_lst[i]:return False
                        idec,iinc= (i-1) % slf.N,(i+1) % slf.N
                        n_tset=slf.inverse_func(s[i],k)
                        for nt in n_tset:
                                if nt[0] in p_lst[idec] and nt[1] in p_lst[iinc]:
                                        if len(p_lst[i])==1 and len(p_lst[idec])==1 and len(p_lst[iinc])==1:
                                                return True
                                        save_idec  ,save_i   = p_lst[idec],p_lst[i]
                                        p_lst[idec],p_lst[i] = [nt[0]],[k]
                                        if recur_func(p_lst,iinc,nt[1]):
                                                return True
                                        p_lst[idec],p_lst[i] = save_idec,save_i
                        return False

                if not recur_func(tmp,0,0) and not recur_func(tmp,0,1):
                        print "Falt!!!! "
                        return slf.prnt()
                for i in range(slf.N):t[i]=tmp[i][0]

                slf.i=slf.next_id()
                return slf.prnt()

        def prnt(slf):
                def char_prnt(c):
                        if c==1:return "*"
                        else:return " "
                return  "".join([char_prnt(i) for i in slf.status[slf.i] ])

        def set_status(slf,i,s):
                slf.status[slf.i][i]=s

        def get_status(slf,i):
                return slf.status[slf.i][i]

        def set_statusstr(slf,str):
                i=0
                for s in str:
                        if s=='*':slf.status[slf.i][i]=1
                        else:slf.status[slf.i][i]=0
                        i+=1



if __name__=="__main__":

        rule=90
        N=50
        init_N=int(N/2)

        def trans(obj,tn):
                for i in range(tn):print "%2d,%s|" %(i,obj.next())
        def eca_copy(obj,obj2):
                for i in range(obj.N):obj2.set_status(i,obj.get_status(i))

        d=eca.eca(rule,N)
        e=inverse_eca(rule,N)

        d.set_status(init_N,1)
        print "%2d,%s|" %(0,d.prnt())
        trans(d,30)
        eca_copy(d,e)
        trans(e,5)

後者は、全体のセルの状態に対して非決定性オートマトンの実装にはなっていないので、推移先(通常のセルオートマトンにおいての推移元)の状態がなければ停止します。

覚書でした。