Existen varios métodos para realizar la conversión de autómatas finitos a expresiones regulares. Aquí describiré el que generalmente se enseña en la escuela y que es muy visual. Creo que es el más usado en la práctica. Sin embargo, escribir el algoritmo no es una buena idea.
Método de eliminación del estado
Este algoritmo se trata de manejar el gráfico del autómata y, por lo tanto, no es muy adecuado para los algoritmos, ya que necesita primitivas de gráficos como ... la eliminación del estado. Lo describiré usando primitivas de nivel superior.
La idea clave
La idea es considerar expresiones regulares en los bordes y luego eliminar estados intermedios mientras se mantienen las etiquetas de los bordes consistentes.
El patrón principal se puede ver a continuación en las figuras. El primero tiene etiquetas entre que son expresiones regulares e , f , g , h , i y queremos eliminar q .p,q,re,f,g,h,iq
Una vez eliminados, componimos juntos (conservando los otros bordes entre p y r, pero esto no se muestra en esto):e,f,g,h,ipr
Ejemplo
Usando el mismo ejemplo que en la respuesta de Raphael :
eliminamos sucesivamente :q2
y luego :q3
entonces todavía tenemos que aplicar una estrella en la expresión de a q 1 . En este caso, el estado final también es inicial, por lo que realmente solo necesitamos agregar una estrella:q1q1
(ab+(b+aa)(ba)∗(a+bb))∗
Algoritmo
L[i,j]
es la expresión regular del lenguaje de a q j . Primero, eliminamos todos los bordes múltiples: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
Ahora, la eliminación del estado. Supongamos que queremos eliminar el estado :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
Ahora, ¿cómo usarlo remove(k)
? No debe eliminar a la ligera los estados finales o iniciales, de lo contrario, perderá partes del lenguaje.
for i = 1 to n:
if not(final(i)) and not(initial(i)):
remove(i)
Si solo tiene un estado final y un estado inicial , la expresión final es:q sqfqs
e := star(L[s,s]) . L[s,f] . star(L[f,s] . star(L[s,s]) . L[s,f] + L[f,f])
Si tiene varios estados finales (o incluso estados iniciales), entonces no hay una forma simple de fusionarlos, aparte de aplicar el método de cierre transitivo. Por lo general, esto no es un problema a mano, pero es incómodo al escribir el algoritmo. Una solución mucho más simple es enumerar todos los pares y ejecutar el algoritmo en el gráfico (ya eliminado) para obtener todas las expresiones suponiendo que es el único estado inicial es el único final estado, luego haciendo la unión de todos .e s , f s f e s , f(s,f)es,fsfes,f
Esto, y el hecho de que esto está modificando los lenguajes más dinámicamente que el primer método lo hace más propenso a errores al programar. Sugiero usar cualquier otro método.
Contras
Hay muchos casos en este algoritmo, por ejemplo, para elegir qué nodo debemos eliminar, el número de estados finales al final, el hecho de que un estado final también puede ser inicial, etc.
Tenga en cuenta que ahora que el algoritmo está escrito, esto se parece mucho al método de cierre transitivo. Solo el contexto del uso es diferente. No recomiendo implementar el algoritmo, pero usar el método para hacerlo a mano es una buena idea.