オートマトン初歩の初歩
   2012.7.19 hiratara
オートマトンとは

普通は有限オートマトンのこと

 DFA(Deterministic Finite Automaton)

 NFA(Nondeterministic Finite Automaton)

プッシュダウン・オートマトン、生け垣オー
トマトンなど
DFA

文字の列を入力にとる

入力した列を受理するか否か判定する

有限個の状態を持ち、入力された文字に応じ
て順次遷移する
DFA
                               0
       0
                       1
A             B            C
       1

                           1
0

001, 101, 10110 → 受理
000, 010, 10000 → 受理しない
DFAの構成要素
状態 (A, B, C)

アルファベット (0, 1)

遷移関数 ( (A, 0) → A, (A, 1) → B, ...)

開始状態 (A)

受理状態 (B, C)
NFA


DFAの拡張

遷移先が1つではなく複数

空文字(ε)による遷移を許す
NFA
                        ε

                        0
A              B            C
        1

 1

10, 1010, 111010 → 受理
01, 1111, 10100 → 受理しない
NFAの構成要素

状態 (A, B, C)

アルファベット (0, 1)

遷移関数 ( (A, 0) → Φ, (A, 1) → (A, B), (A, ε)
→ Φ, ...)

開始状態 (A)
DFAとNFAの特徴


DFAは単純でシミュレーションしやすい

NFAは表現力が高く人間が作りやすい

DFAとNFAは等価である
DFAとNFAの特徴


DFAは単純でシミュレーションしやすい

NFAは表現力が高く人間が作りやすい

DFAとNFAは等価である
NFAをDFAに変換する
                1

          1            0
    A         A, B             A,C
                       1
          0
                           0

状態集合のベキ集合を
  とるとよい
                0, 1
正規表現

アルファベット (ε, 0, 1)

選択 ( 0|1 )

結合 ( 01 )

繰り返し (1*)
ふつうの正規表現

ほとんどは先ほどの演算で書ける

 [01] → 0|1

 0? → 0|

 1+ → 11*

 . → [01]

書けないもの → 後方参照 (.+)(1)
正規表現の特徴


人間にわかりやすい記述で言語を指定できる
(言語 = 文字列の集合)

NFA、DFAと等価
正規表現の特徴


人間にわかりやすい記述で言語を指定できる
(言語 = 文字列の集合)

NFA、DFAと等価
正規表現をNFAに
0
    0
             0|1
                       0
                   ε
                   ε
1                      1
    1
正規表現をNFAに
01
      0   ε   1


          ε
0*
      ε   0
正規表現をNFAに
                       ε
(01|0)*
                   0       ε   1

          ε    ε
               ε
                   0
          ε
DFAを正規表現に


GNFA(Generalized Nondeterministic Finite
Automaton) を経由する

  遷移を正規表現で書いたもの
DFAを正規表現へ

            0
    0
        1
    1

            1
0
DFAを正規表現へ

    開始状態と受理状態を加える
                        0
        0
ε               1
        1
            ε       ε
                        1
    0
DFAを正規表現へ

    同じ状態間の遷移をまとめる
                        0|1
        0
ε               1
        1
            ε       ε
    0
DFAを正規表現へ

         00*1           0|1

   0*1          1


            ε       ε


状態を減らしていく
DFAを正規表現へ

                         0|1

      0*1(00*1)* 1


                     ε
0*1(00*1)*
DFAを正規表現へ



0*1(00*1)*| 0*1(00*1)* 1(0|1)*
ここまでのまとめ


DFAとNFAと正規表現は等価

DFAは実装が容易でパフォーマンスも良い

NFAや正規表現は表現力があり人間に優しい
DFAの限界

正規 (DFA)

文脈自由 (バッカス・ナウア記法)

判定可能 (チューリングマシンが停止する)

認識可能 (ループしてもよい)
応用1: 逆FizzBuzz


問題: FizzBuzz の逆写像を作りなさい


例えば、{‘fizz’, ‘buzz’, ‘fizz’} が入力された
ら、 {3, 4, 5, 6} を返す
NFAで表現できる
           buzz               fizz
      3              5                    6

           fizz    buzz              fizz            fizz
fizz                              fizz
                               buzz
           fizzbuzz       fizz                             9
           fizzbuzz              fizz                 buzz
      15                 12                   10
応用1: 逆FizzBuzz


受理される経路で、もっとも距離が小さい物
を求めれば良い

ただし、DFAに変換すると距離情報が捨てら
れるのでNG
応用2: 曖昧検索の高速化


 問: 単語辞書の中から、ユーザが入力した文字
 列に近い文字列を選び出す

 力づくで計算する場合は、全単語について編
 集距離を求めて最小値をとる
応用2: 曖昧検索の高速化

 例: 辞書が「Python、Perl、PHP」で入力が
 Phone だった場合
 Phone → Pyhone → Pythone → Python
 Phone → Peone → Perne → Perle → Perl
 Phone → Phpne → Phpn → Php

 Perlだけ編集距離が4、後は3
応用2: 曖昧検索の高速化
【辞書】      ユーザの入力 “photo”
basic
c
c++
java
haskell
perl
php
python
ruby
応用2: 曖昧検索の高速化
【辞書】       ユーザの入力 “photo”
basic
c
c++
java
haskell
          photoと編集距離がn以下の単語
perl
php       を受理するオートマトンを作る
python
ruby
応用2: 曖昧検索の高速化
【辞書】        ユーザの入力 “photo”


c
c++       basic
java
haskell
perl
php               辞書の最初の単語を
python       オートマトンに入力する
ruby
応用2: 曖昧検索の高速化
【辞書】        ユーザの入力 “photo”


c
c++       basic              bhoto
java
haskell
perl
php       バックトラックにより次に受理
python      されるはずの単語を求める
ruby
応用2: 曖昧検索の高速化
【辞書】      ユーザの入力 “photo”
basic

c++       c
java
haskell
perl
php       “bhoto”より大きい次の候補を
python    辞書から取り出し、続ける
ruby
Levenshtein Automata
      c       m         s


  . ε, .   . ε, .   . ε, .
      c       m         s


  . ε, .   . ε, .   .   ε, .
       c      m         s
NFAをDFAにする

                        s
            m
                    m


[^c]            c


       c
           複雑なので略
受理される単語を探す
例: “ocn”の次に受理される単語
                s
             m
                     m


 [^c]            c


        c
            複雑なので略
受理される単語を探す
    “oc”の後、nは駄目。
    o,p,q,r,...も駄目       s
             m
                     m


 [^c]            c


        c
            複雑なので略
受理される単語を探す
        バックトラックする
                         s
             m
                     m


 [^c]            c


        c
            複雑なので略
受理される単語を探す
    “oc”が駄目だったので、
        “od”, “oe”, “of” ... s
             m
                       m


 [^c]            c


        c
            複雑なので略
受理される単語を探す
            “om” であればOK
                           s
               m
                       m


 [^c]              c


        c
             複雑なので略
受理される単語を探す
        “oms” は受理される
                         s
             m
                     m


 [^c]            c


        c
            複雑なので略
受理される単語を探す


“ocn”から”oms”までの単語は受理されない
→つまり編集距離が遠い
→編集距離を求めず、飛ばしてよい
まとめ


オートマトンは様々な理論の基礎
知っておけば読める情報が増える

DFAへ変換することで、ロジックの見直しや
パフォーマンスの改善に繋がる

Levenshtein Automata