Es gibt verschiedene Methoden, um die Konvertierung von endlichen Automaten in reguläre Ausdrücke durchzuführen. Hier werde ich diejenige beschreiben, die normalerweise in der Schule unterrichtet wird und die sehr visuell ist. Ich glaube, es wird in der Praxis am häufigsten verwendet. Das Schreiben des Algorithmus ist jedoch keine so gute Idee.
Methode zum Entfernen des Zustands
Dieser Algorithmus behandelt den Graphen des Automaten und ist daher für Algorithmen nicht sehr geeignet, da er Graphprimitive wie ... state removal benötigt. Ich werde es mit übergeordneten Primitiven beschreiben.
Die Schlüsselidee
Die Idee ist, reguläre Ausdrücke an Kanten zu berücksichtigen und dann Zwischenzustände zu entfernen, während die Kantenbeschriftungen konsistent bleiben.
Das Hauptmuster lässt sich im Folgenden an Figuren ablesen. Die erste hat Bezeichnungen zwischen , die reguläre Ausdrücke e , f , g , h , i sind, und wir möchten q entfernen .p , q, re , f, g, H , iq
Nach dem Entfernen setzen wir zusammen (wobei die anderen Kanten zwischen p und r erhalten bleiben , dies wird hier jedoch nicht angezeigt):e , f, g, H , ipr
Beispiel
Verwenden Sie dasselbe Beispiel wie in Raffaels Antwort :
wir entfernen nacheinander :q2
und dann :q3
dann müssen wir noch einen Stern auf den Ausdruck von bis q 1 anwenden . In diesem Fall ist der Endzustand ebenfalls initial, so dass wir wirklich nur einen Stern hinzufügen müssen:q1q1
(ab+(b+aa)(ba)∗(a+bb))∗
Algorithmus
L[i,j]
ist der Ausdruck der Sprache von bis q j . Zuerst entfernen wir alle Mehrkanten:qiqj
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
Nun ist die staatliche Entfernung. Angenommen, wir möchten den Zustand entfernen :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 i q k q j q kεqiqkqjqk
Nun, wie benutzt man remove(k)
? Sie sollten End- oder Anfangszustände nicht leichtfertig entfernen, da Sie sonst Teile der Sprache vermissen.
for i = 1 to n:
if not(final(i)) and not(initial(i)):
remove(i)
Wenn Sie nur einen Endzustand und einen Anfangszustand der :q sqfqs
e := star(L[s,s]) . L[s,f] . star(L[f,s] . star(L[s,s]) . L[s,f] + L[f,f])
Wenn Sie mehrere Endzustände (oder sogar Anfangszustände) haben, gibt es keine einfache Möglichkeit zum Zusammenführen dieser Zustände außer der Anwendung der transitiven Abschlussmethode. Normalerweise ist dies kein Problem von Hand, aber beim Schreiben des Algorithmus ist dies umständlich. Eine viel einfachere Problemumgehung besteht darin, alle Paare und den Algorithmus im (bereits vom Status entfernten) Diagramm auszuführen, um alle Ausdrücke abzurufen, wobei angenommen wird , dass der einzige Anfangszustand und der einzige Endzustand ist state, dann mache die Vereinigung aller .e s , f s f e s , f(s,f)es,fsfes,f
Dies und die Tatsache, dass dadurch Sprachen dynamischer geändert werden als bei der ersten Methode, machen sie beim Programmieren fehleranfälliger. Ich schlage vor, eine andere Methode zu verwenden.
Nachteile
In diesem Algorithmus gibt es viele Fälle, zum Beispiel, um auszuwählen, welchen Knoten wir entfernen möchten, wie viele Endzustände am Ende vorliegen, ob ein Endzustand auch anfänglich sein kann usw.
Beachten Sie, dass dieser Algorithmus jetzt, da er geschrieben wurde, der Methode der transitiven Schließung sehr ähnlich ist. Lediglich der Kontext der Nutzung ist unterschiedlich. Ich empfehle nicht, den Algorithmus zu implementieren, aber es ist eine gute Idee, die Methode manuell zu verwenden.