Nichtdeterministische Endliche Automaten (NFAs)
Nichtdeterministische Endliche Automaten (NFAs)
Nichtdeterministische Endliche Automaten (NFAs)
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
<strong>Nichtdeterministische</strong><br />
<strong>Endliche</strong> <strong>Automaten</strong><br />
Einführung<br />
Beispiel: Wir bezeichnen mit Lk⊣ die Menge aller Wörter<br />
(über {0,1}), deren k-letzter Buchstabe eine 1 ist.<br />
Es gilt: Jeder DFA für Lk⊣ hat mindestens 2 k Zustände.<br />
Dazu reicht es zu zeigen, dass keine zwei der 2 k Wörter<br />
in {0,1} k aus dem Startzustand zum gleichen Zustand<br />
führen können. Sonst seien x und y zwei solche<br />
Wörter, o.B.d.A. xi = 1 und yi = 0. Dann führen<br />
xz und yz mit z = 0 i−1 auch zu einem gleichen Zustand,<br />
werden also beide akzeptiert oder beide nicht,<br />
was aber nicht erlaubt ist, da xz ∈ Lk⊣ und yz ∈ Lk⊣.<br />
Nun stellen wir einen endlichen <strong>Automaten</strong> mit k + 1<br />
Zuständen dar, der nur die Wörter aus Lk⊣ akzeptiert:<br />
0,1<br />
q 0<br />
1 0,1<br />
0,1 0,1<br />
q1 q 2<br />
q k<br />
− Für Wörter aus Lk⊣ existieren akzeptierende Rechenwege<br />
(aber auch nicht-akzeptierende).<br />
− Für andere Wörter existiert kein akzeptierender<br />
Rechenweg.<br />
Beobachtung: Die Übergänge im Beispiel sind nicht<br />
eindeutig (deterministisch). Sie stellen keine Funktion<br />
dar, sondern eine Relation.<br />
1
<strong>Nichtdeterministische</strong><br />
<strong>Endliche</strong> <strong>Automaten</strong><br />
Definition<br />
Definition: Ein nichtdeterministischer endlicher<br />
Automat (NFA: nondeterministic finite automaton)<br />
wird definiert durch:<br />
• ein endliches Eingabealphabet Σ<br />
• eine endliche Zustandsmenge Q<br />
• einen Startzustand q0 ∈ Q<br />
• eine Menge akzeptierender Zustände F ⊆ Q<br />
• eine Zustandsüberführungsrelation ˆδ ⊆(Q×Σ)×Q.<br />
Interpretation: (q, a, q ′ ) ∈ ˆδ genau dann, wenn es erlaubt<br />
ist, vom Zustand q beim Lesen des Buchstaben<br />
a in den Zustand q ′ überzugehen.<br />
Man kann ˆδ auch als eine Abbildung δ : Q ×Σ → P(Q)<br />
mit δ(q, a) = {q ′ | (q, a, q ′ ) ∈ ˆδ} auffassen.<br />
δ lässt sich auf Q × Σ ∗ fortsetzen: δ(q, ǫ) = {q} und<br />
δ(q, w ′ a) = <br />
q ′ ∈δ(q,w ′ ) δ(q′ , a).<br />
Der NFA akzeptiert ein Wort w genau dann, wenn<br />
δ(q0, w) ∩ F = ∅.<br />
Bemerkung: <strong>NFAs</strong> eignen sich i.A. nicht zur unmittelbaren<br />
Realisierung; sie sollten eher als kompakte<br />
Darstellungen von DFAs aufgefasst werden.<br />
2
<strong>NFAs</strong><br />
Äquivalenz zu DFAs<br />
Satz: Zu jedem NFA mit n Zuständen gibt es einen<br />
äquivalenten DFA mit 2 n Zuständen.<br />
Beweis: Gegeben sei ein NFA A = (Σ, Q, q0, F, δ). Wir<br />
konstruieren einen DFA A ′ = (Σ ′ , Q ′ , q ′ 0 , F ′ , δ ′ ) mit<br />
• Σ ′ = Σ<br />
• Q ′ = P(Q)<br />
• q ′ 0<br />
= {q0}<br />
• F ′ = {q ′ ∈ Q ′ | q ′ ∩ F = ∅}<br />
• δ ′ (q ′ , a) = <br />
q∈q ′ δ(q, a).<br />
Nun zeigen wir per Induktion, dass für alle w ∈ Σ ∗ gilt:<br />
δ ′ (q ′ 0 , w) = δ(q0, w).<br />
I.A. (w = ǫ) : δ ′ (q ′ 0, ǫ) = q ′ 0 = {q0} = δ(q0, ǫ)<br />
I.S. (w = w ′ a) : δ ′ (q ′ 0, w ′ a) = δ ′ (δ ′ (q ′ 0, w ′ ), a) I.V.<br />
= δ ′ (δ(q0, w ′ ), a)<br />
= <br />
q∈δ(q0,w ′ )<br />
δ(q, a) = δ(q0, w ′ a)<br />
Damit akzeptieren A ′ und A die gleiche Sprache.<br />
Beobachtung: Bei dieser Potenzmengenkonstruktion<br />
werden oft (exponentiell) mehr Zustände erzeugt als<br />
notwendig. Insbesondere können überflüssige“ Zustände<br />
”<br />
erzeugt werden, die vom Startzustand q ′ 0 gar nicht erreichbar<br />
sind.<br />
3
<strong>NFAs</strong><br />
Umwandlung in DFAs<br />
Der folgende Algorithmus realisiert die Potenzmengenkonstruktion<br />
unter Vermeidung überflüssiger Zustände.<br />
Als Datenstrukturen benutzt er eine Queue Q und ein<br />
Dictionary D.<br />
Algorithmus:<br />
Initialisiere Q und D mit q ′ 0 := {q0}<br />
Solange Q nicht leer ist:<br />
Entnimm q ′ aus Q<br />
Für alle a ∈ Σ:<br />
q ′′ := δ ′ (q ′ , a) (Übergang in A ′ übernehmen)<br />
Falls q ′′ ∈ D: Füge q ′′ in D und Q ein<br />
Korrektheit: Es ist leicht zu sehen, dass dieser Algorithmus<br />
einer Breitensuche aus q ′ 0 in A′ entspricht.<br />
Damit erzeugt er A ′ ohne überflüssige Zustände.<br />
Rechenzeit: Bei jeder Berechnung δ ′ (q ′ , a) müssen<br />
höchstens |Q| Mengen mit jeweils höchstens |Q| Elementen<br />
vereinigt werden (O(|Q| 2 ) Operationen) und<br />
es erfolgt eine Abfrage an D (bei geeigneter Implementierung<br />
O(log |Q ′ |) = O(|Q|) Schlüsselvergleiche).<br />
Damit ist die Rechenzeit höchstens um einen Faktor<br />
O(|Q| 2 ) größer als die Beschreibung des berechneten<br />
DFA (der aber Θ(2 |Q| ) Zustände haben kann).<br />
Bemerkung: Die DFAs, die durch diesen Algorithmus<br />
erzeugt werden, sind nicht notwendigerweise minimal.<br />
4
<strong>NFAs</strong><br />
Blow-up bei Umwandlung in DFAs<br />
Beispiel: Im Folgenden betrachten wir die Ausführung<br />
des Umwandlungsalgorithmus auf einem NFA für L2⊣:<br />
0,1<br />
1 0,1<br />
q q q<br />
0 1 2<br />
Knoten (in A ′ ) Entnehmen aus Q Einfügen in Q<br />
0 − {q0}<br />
1 {q0} {q0, q1}<br />
2 {q0, q1} {q0, q2};{q0, q1, q2}<br />
3 {q0, q2} −<br />
4 {q0, q1, q2} −<br />
5 − −<br />
Dabei wird der folgende DFA erzeugt:<br />
0<br />
{ q<br />
0}<br />
0<br />
{ q q<br />
0, 2}<br />
1<br />
0<br />
0<br />
1<br />
{q<br />
0<br />
, q<br />
1 }<br />
1<br />
{ q q q<br />
0,<br />
1, 2}<br />
Beobachtung: Der im Beispiel erzeugte DFA ist minimal,<br />
da jeder DFA für Lk⊣, wie bereits beschrieben,<br />
mindestens 2 k Zustände haben muss. Also kann bei<br />
der Umwandlung eines NFA in einen äquivalenten DFA<br />
ein exponentieller Blow-up in der Anzahl der Zustände<br />
(im Fall von Lk⊣ von k +1 auf 2 k ) unvermeidbar sein.<br />
1<br />
5
<strong>NFAs</strong><br />
ǫ-Übergänge<br />
Motivation: Für den Entwurf von <strong>NFAs</strong> ist es manchmal<br />
hilfreich, wenn auch Übergänge erlaubt sind, ohne<br />
dass ein Buchstabe gelesen wird. Solche Übergänge<br />
können wir durch das Lesen des leeren Wortes ǫ erfassen.<br />
Definition: Bei einem NFA A = (Σ, Q, q0, F, δ) mit ǫ-<br />
Übergängen ist δ : Q×(Σ∪{ǫ}) → P(Q) die Überführungsfunktion,<br />
wobei q ′ ∈ δ(q, ǫ) bedeutet, dass A, ohne<br />
einen Buchstaben zu lesen, vom Zustand q in den Zustand<br />
q ′ wechseln darf.<br />
Satz: Zu jedem NFA A mit ǫ-Übergängen gibt es einen<br />
äquivalenten NFA A ′ ohne ǫ-Übergänge, der nicht mehr<br />
Zustände als A hat.<br />
Beweis: Wir definieren A ′ = (Σ, Q, q0, F ′ , δ ′ ) wie folgt:<br />
F ′ besteht aus allen Zuständen, von denen aus A mit<br />
ǫ-Übergängen in einen Zustand aus F gelangen kann.<br />
δ ′ (q, a) für a ∈ Σ beinhaltet genau die Zustände, in die<br />
A aus q mit beliebig vielen ǫ-Übergängen und dem anschließenden<br />
Lesen von a gelangen kann. Es ist leicht<br />
zu sehen, dass A ′ die gleiche Sprache wie A akzeptiert.<br />
Für die Konstruktion von A ′ können wir in einem Graphen<br />
mit Q als Knotenmenge und den ǫ-Übergängen<br />
als Kanten eine Tiefensuche (DFS) ausführen. Dann<br />
testen wir für alle (q, a, q ′ ) mit q ′ ∈ δ(q, a), a ∈ Σ und<br />
alle q ′′ ∈ Q, ob q von q ′′ aus mit ǫ-Übergängen erreichbar<br />
ist. Im positiven Fall wird q ′ in δ ′ (q ′′ , a) eingefügt.<br />
Die Laufzeit kann man mit O(|Q| |δ(q, α)|) angeben.<br />
6
<strong>NFAs</strong><br />
Anwendungsbeispiele<br />
Satz: Gegeben seien DFAs Ai = (Σ, Qi, q i 0 , Fi, δi) für<br />
Li (vereinfachend: i ∈ {1,2}). Dann kann ein DFA für<br />
L1 ∪ L2 in Zeit O(|Q1||Q2||Σ|) konstruiert werden.<br />
Beweis: Wir konstruieren den sogenannten Produktautomaten<br />
A = (Σ, Q, q0, F, δ) mit<br />
• Q = Q1 × Q2<br />
• q0 = (q 1 0 , q2 0 )<br />
• F = {(q1, q2)|q1 ∈ F1 ∨ q2 ∈ F2}<br />
• δ((q1, q2), a) = (δ1(q1, a), δ2(q2, a)).<br />
Offensichtlich akzeptiert A ein Wort w genau dann,<br />
wenn w von A1 oder A2 akzeptiert wird.<br />
Bemerkung: Es kann sein, dass minimale DFAs für<br />
L1, L2 und L1∪L2 jeweils |Q1|, |Q2| und |Q1||Q2| Zustände<br />
haben (für beliebig große |Qi|, Übungsaufgabe).<br />
Bemerkung: Der gleiche Ansatz funktioniert auch für<br />
<strong>NFAs</strong>. Allerdings kann ein NFA für L1 ∪ L2 effizienter<br />
konstruiert werden:<br />
Satz: Gegeben seien <strong>NFAs</strong> (DFAs) Ai = (Σ, Qi, qi 0 , Fi, δi)<br />
für Li (i ∈ {1,2}). Dann kann ein NFA für L1 ∪ L2 in<br />
Zeit O((|Q1| + |Q2|)|Σ|) konstruiert werden.<br />
Beweis: Wir konstruieren einen <strong>Automaten</strong> A, der<br />
aus einer Kopie von A1 und einer Kopie von A2 und<br />
einem neuen Startzustand q0 besteht, der durch ǫ-<br />
Übergänge mit q 1 0 und q2 0<br />
verbunden wird. Offensicht-<br />
lich akzeptiert A ein Wort w genau dann, wenn w von<br />
A1 oder A2 akzeptiert wird.<br />
7