有限オートマトンを正規表現に変換する方法は?


115

正規表現を同じ言語を受け入れる(最小限の)NFAに変換することは、Thompsonのアルゴリズムなどの標準アルゴリズムを使用すると簡単です。しかし、他の方向はより面倒であるように思われ、結果の表現が面倒な場合があります。

NFAを同等の正規表現に変換するためのアルゴリズムは何ですか?時間の複雑さや結果のサイズに関して利点はありますか?

これは参考質問になるはずです。メソッドの一般的な説明と重要な例を含めてください。


2
cstheory.SEでの同様の質問に注意してください。これは、おそらく視聴者には向いていません。
ラファエル

すべての回答は正式な手法を使用してDFAからREを記述します。分析による私の手法は比較的簡単で客観的であると私は自分のansweで示しています。この決定論的有限オートマトンの言語は何ですか いつか役に立つと思います。はい、のコースいつか私自身は、REを書くために、正式な方法(アーデン定理)を使用しています質問です。この例で与えられたような複雑です:DFAのための正規表現書き方
Grijesh Chauhan

回答:


94

有限オートマトンから正規表現への変換を行う方法はいくつかあります。ここでは、学校で通常教えられる非常に視覚的なものについて説明します。実際に最も使用されていると思います。ただし、アルゴリズムを作成することはあまり良い考えではありません。

状態削除方法

このアルゴリズムは、オートマトンのグラフの処理に関するものであり、...状態の削除などのグラフプリミティブが必要なため、アルゴリズムにはあまり適していません。高レベルのプリミティブを使用して説明します。

キーアイデア

アイデアは、エッジの正規表現を考慮し、エッジラベルの一貫性を保ちながら中間状態を削除することです。

主なパターンは、以下の図で見ることができます。最初は間のラベルがある正規表現です、我々は削除する。e f g h i qp,q,re,f,g,h,iq

pqrオートマトン

削除したら、します(と間の他のエッジは保持しますが、これには表示されません)。p re,f,g,h,ipr

ここに画像の説明を入力してください

ラファエルの答えと同じ例を使用して:

1-2-3オートマトン

を連続して削除し。q2

1-3オートマトン

そして:q3

1つのオートマトン

その後、我々はまだからの発現にスターを適用する必要がに。この場合、最終状態も初期であるため、スターを追加するだけです。q 1q1q1

(ab+(b+aa)(ba)(a+bb))

アルゴリズム

L[i,j]からまでの言語の正規表現です。まず、すべてのマルチエッジを削除します。q jqiqj

for i = 1 to n:
  for j = 1 to n:
    if i == j then:
      L[i,j] := ε
    else:
      L[i,j] := ∅
    for a in Σ:
      if trans(i, a, j):
        L[i,j] := L[i,j] + a

さて、状態の削除。状態を削除するとします。qk

remove(k):
  for i = 1 to n:
    for j = 1 to n:
      L[i,i] += L[i,k] . star(L[k,k]) . L[k,i]
      L[j,j] += L[j,k] . star(L[k,k]) . L[k,j]
      L[i,j] += L[i,k] . star(L[k,k]) . L[k,j]
      L[j,i] += L[j,k] . star(L[k,k]) . L[k,i]

紙の鉛筆で、アルゴリズムの両方であなたのような式を簡素化する必要があることに注意してくださいstar(ε)=εe.ε=e∅+e=e∅.e=∅(手でそれがいないときあなただけのエッジを書いていない、あるいは自己ループのために、そこにあるときに無視とまたはと間に遷移はありません)Q j個のq Kεq kqiqkqjqk

さて、使い方はremove(k)?最終状態または初期状態を軽く削除しないでください。削除すると、言語の一部が失われます。

for i = 1 to n:
  if not(final(i)) and not(initial(i)):
    remove(i)

最終状態と初期状態 1つしかない場合、最終式は次のようになります。q sqfqs

e := star(L[s,s]) . L[s,f] . star(L[f,s] . star(L[s,s]) . L[s,f] + L[f,f])

複数の最終状態(または初期状態)がある場合、推移閉包法を適用する以外に、これらの状態をマージする簡単な方法はありません。通常、これは手作業での問題ではありませんが、アルゴリズムを作成する際に厄介です。より簡単な回避策は、すべてのペアを列挙し、(既に状態が削除された)グラフでアルゴリズムを実行して、が唯一の初期状態であり、が唯一の最終状態であると仮定してすべての式を取得することです状態にしてから、すべての結合を行います。e s f s f e s f(s,f)es,fsfes,f

これと、これが最初の方法よりも動的に言語を変更しているという事実により、プログラミング時にエラーが発生しやすくなります。他の方法を使用することをお勧めします。

短所

このアルゴリズムには多くのケースがあります。たとえば、削除するノードの選択、最後の最終状態の数、最終状態も初期状態にできるという事実などです。

アルゴリズムが作成されたので、これは推移閉包法によく似ていることに注意してください。使用法のコンテキストのみが異なります。アルゴリズムを実装することはお勧めしませんが、メソッドを使用して手動で実行することをお勧めします。


1
ノードAのループエッジ(AB) -例では、第2の画像は、ノードを除去した後、「2」は、不足しているエッジがある
パノスカル。

@カバマル:修正。しかし、今では、3番目のイメージのもである必要があり、おそらく最終的な正規表現でも同様だと思います。εab
さまようロジック14年

新しい初期と新しい最終状態追加し、これらを -edges によって元の初期状態と最終状態に接続することにより、任意の数の初期状態と最終状態に対してアルゴリズムを機能させることができます。元の状態をすべて削除ます。その後、式はからまでの単一の残りのエッジで検出されます。これらの状態にはがないため、構築はまたはでループをしません。発信エッジ。または、厳格な場合は、空のセットを表すラベルが付けられます。Q - ε Q + Q - Q + Q -q+qεq+qq+q
ヘンドリック

1
2番目の例にはまだ問題があります。単純化する前に、オートマトンは「ba」を受け入れますが(1、3、1)、単純化した後は受け入れません。
wvxvw

50

方法

私が見た中で最も素晴らしい方法は、解決できる(通常の)言語の方程式システムとしてオートマトンを表現するものです。他のメソッドよりも簡潔な式を生成するように見えるため、特に便利です。

を -transitions なしのNFAとしましょう。すべての状態について、方程式を作成しますεのq個のIA=(Q,Σ,δ,q0,F)εqi

Qi=qiaqjaQj{{ε}, qiF, else

ここで、は最終状態のセットであり、は、aでラベル付けされたからへの遷移があることを意味ます。をまたは(正規表現の定義に応じて)と読むと、これは正規表現の方程式であることがわかります。Fqiaqjqiqja+

システムを解決するために、あなたは、結合性との分配性必要と(文字列連結)の可換性とアーデンの補題が ¹を:

通常の言語をとしましょう。その後、L,U,VΣεU

L=ULVL=UV

解決策は、状態ごとに1つずつある正規表現セットです。は、開始されときにが受け入れることができる単語を正確に記述します。したがって、(が初期状態の場合)が望ましい式です。QiqiQiAqiQ0q0


わかりやすくするために、シングルトンセットをその要素、つまり表します。この例は、Georg Zetzscheによるものです。a={a}

このNFAを検討してください。

例nfa
[ ソース ]

対応する方程式系は次のとおりです。

Q0=aQ1bQ2εQ1=bQ0aQ2Q2=aQ0bQ1

次に、3番目の方程式を2番目の方程式に差し込みます。

Q1=bQ0a(aQ0bQ1)=abQ1(baa)Q0=(ab)(baa)Q0

最後のステップでは、、およびアーデンの補題を適用します。3つの言語はすべて正規であり、であり、補助定理を適用できることに注意してください。次に、この結果を最初の方程式に代入します。L=Q1U=abV=(baa)Q0εU={ab}

Q0=a(ab)(baa)Q0baQ0bb(ab)(baa)Q0ε=((abb)(ab)(baa)ba)Q0ε=((abb)(ab)(baa)ba)(by Arden's Lemma)

したがって、上記のオートマトンで受け入れられる言語の正規表現、つまり、

((a+bb)(ab)(b+aa)+ba).

他のメソッドの結果と比較して非常に簡潔ですが、一意に決定されていないことに注意してください。異なる一連の操作で方程式システムを解くことは、他の同等の結果につながります!-式。


  1. アーデンの補題の証明については、こちらをご覧ください

1
このアルゴリズムの時間の複雑さは何ですか?生成された式のサイズに制限はありますか?
jmite 14

@jmite:わからない。私はこれを実装しようとは思わないが(他の方法はこの点でより実行可能と思われる)、ペンと紙の方法として使用します。
ラファエル

1
ここでは、このアルゴリズムのPrologの実装です:github.com/wvxvw/intro-to-automata-theory/blob/master/automata/...が、そのmaybe_union/2述語が整然と正規表現を作るために、より多くの作業(。共通の接頭辞を排除ESP WRT)を使用することができます。この方法を見るもう1つの方法は、正規表現から右線形文法への翻訳として理解することです。Prologのような統一またはMLのようなパターンマッチングを行う言語は、非常に優れたトランスデューサーになるため、ペンと紙だけではありませんアルゴリズム:)
wvxvw

ただ一つの質問。最初の方程式のεは、Qoが開始状態であるか、最終状態であるためですか?2つの最終状態がある場合、同じ方法が適用されますか?
Georgio3

@PAOK 上記のの定義(行)を確認してください。ためです最終状態です。Qiq0
ラファエル

28

ブルゾゾフスキー代数法

これは、Raphaelの答えで説明されているものと同じ方法ですが、体系的なアルゴリズムの観点から、そして実際にはアルゴリズムの観点からです。どこから始めればよいかがわかれば、実装が簡単で自然であることがわかります。また、何らかの理由ですべてのオートマトンを描画するのが実用的でない場合は、手作業で簡単にすることもできます。

アルゴリズムを書くときは、方程式を常に線形にする必要があることを覚えておく必要があります。これにより、方程式を手作業で解くときに忘れることができる、方程式の優れた抽象的な表現が得られます。

アルゴリズムのアイデア

それがどのように機能するかについては説明しません。これは、前に読むことをお勧めするラファエルの答えでうまく行われているからです。代わりに、余分な計算や余分なケースをあまり行わずに方程式を解く順序に焦点を当てます。

開始アーデンのルールの独創的なソリューション言語式に我々は、フォームの方程式のセットとして、オートマトンを考えることができます。X=ABX=AXB

Xi=Bi+Ai,1X1++Ai,nXn

配列および適宜更新することにより、帰納法によりこれを解決できます。ステップには、次のものがあります。nAi,jBi,jn

Xn=Bn+An,1X1++An,nXn

そして、アーデンの規則は私たちに与えます:

Xn=An,n(Bn+An,1X1++An,n1Xn1)

そして、およびを設定すると、次のようになります。Bn=An,nBnAn,i=An,nAn,i

Xn=Bn+An,1X1++An,n1Xn1

そして、設定することにより、システム内のすべてのニーズを削除できます。Xni,j<n

Bi=Bi+Ai,nBn
Ai,j=Ai,j+Ai,nAn,j

ときにを解くと、次のような方程式が得られます。Xnn=1

X1=B1

ないと。したがって、正規表現を取得しました。A1,i

アルゴリズム

これにより、アルゴリズムを構築できます。上記の帰納法と同じ規則を持たせるために、初期状態はあり、状態の数はと言います。まず、を埋めるための初期化:q1mB

for i = 1 to m:
  if final(i):
    B[i] := ε
  else:
    B[i] := ∅

および:A

for i = 1 to m:
  for j = 1 to m:
    for a in Σ:
      if trans(i, a, j):
        A[i,j] := a
      else:
        A[i,j] := ∅

そして、解決:

for n = m decreasing to 1:
  B[n] := star(A[n,n]) . B[n]
  for j = 1 to n:
    A[n,j] := star(A[n,n]) . A[n,j];
  for i = 1 to n:
    B[i] += A[i,n] . B[n]
    for j = 1 to n:
      A[i,j] += A[i,n] . A[n,j]

最終的な式は次のとおりです。

e := B[1]

実装

アルゴリズムにとって象徴的すぎると思われる連立方程式のように思われる場合でも、これは実装に適しています。Ocaml(リンク切れ)でのこのアルゴリズムの実装を次に示します。関数以外はbrzozowski、すべて印刷するか、Raphaelの例で使用することに注意してください。正規表現を単純化する驚くほど効率的な機能があることに注意してくださいsimple_re


4
リンクは死んでいます
...-コロンボ


24

推移閉包法

この方法はアルゴリズムの形式で簡単に記述できますが、非常に大きな正規表現を生成し、手作業で行うと非実用的です。これは主に体系的すぎるためです。ただし、これはアルゴリズムの優れたシンプルなソリューションです。

キーアイデア

ましょから行くの文字列の正規表現を表すする状態を使用して。してみましょうオートマトンの状態数とします。Ri,jkqiqj{q1,,qk}n

すべてのに対して、からへの正規表現が既にわかっており、中間状態(四肢を除く)がないとします。次に、別の状態の追加が新しい正規表現どのように影響するかを推測できますへの直接遷移がある場合にのみ変化し、次のように表現できます。 q i q jRi,jqiqjqki,jRi,jqk

Ri,j=Ri,j+Ri,k.Rk,k.Rk,j

(は、はです。)R k 1 R R kRRk1RRk

ラファエルの答えと同じ例を使用します。最初は、直接遷移のみを使用できます。

これが最初のステップです(ラベルを持つ自己ループは、最初のを変換ことに注意してください。εε + A aε(ε+a)

R0=[εabbεaabε]

2番目のステップでは、を使用できます(は上記の目的ですでに使用されているため、に名前が変更されています)。動作を確認します。q0q1R0R1

に:。q2q2R2,21=R2,20+R2,10R1,10R1,20=ε+bεa=ε+ba

何故ですか?行くからですするのみ使用中間状態はここに滞在することにより行うことができるよう()、またはしようとして()、そこループ()及び(戻ってくる)。q2q2q1εq1aεb

R1=[εabbε+baa+bbab+aaε+ab]

あなたは次のように計算することができると、あまりにも、そしてので、あなたの最終的な式を与えるだろう最初と最後の両方です。ここでは、式の簡略化が数多く行われていることに注意してください。そうでなければ最初のであろう及び第一のあろう。R 3 R 3 1 1 1 R 0 + A R 1 + A + εε * A R2R3R1,131aR0(+a)aR1((+a)+ε(ε)a)

アルゴリズム

初期化:

for i = 1 to n:
  for j = 1 to n:
    if i == j:
      R[i,j,0] := ε
    else:
      R[i,j,0] := ∅
    for a in Σ:
      if trans(i, a, j):
        R[i,j,0] := R[i,j,0] + a

推移閉包:

for k = 1 to n:
  for i = 1 to n:
    for j = 1 to n:
      R[i,j,k] := R[i,j,k-1] + R[i,k,k-1] . star(R[k,k,k-1]) . R(k,j,k-1)

次に、最終式はです(が初期状態であると仮定):qs

e := ∅
for i = 1 to n:
  if final(i):
    e := e + R[s,i,n]

しかし、それはregularい正規表現を生成すると想像できます。実際、と同じ言語を表すようなものを期待できます。正規表現を単純化することは、実際には役立つことに注意してください。a a()+(a+())(ε)(a+)aa

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.