Il existe plusieurs méthodes pour convertir des automates finis en expressions régulières. Je vais décrire ici celui qui est enseigné à l’école et qui est très visuel. Je crois que c'est le plus utilisé dans la pratique. Cependant, l'écriture de l'algorithme n'est pas une si bonne idée.
Méthode de suppression d'état
Cet algorithme concerne le traitement du graphe de l'automate et n'est donc pas très approprié pour les algorithmes car il nécessite des primitives de graphe telles que ... la suppression de l'état. Je vais le décrire en utilisant des primitives de niveau supérieur.
L'idée clé
L'idée est de prendre en compte les expressions régulières sur les bords, puis de supprimer les états intermédiaires tout en préservant la cohérence des étiquettes.
Le schéma principal peut être vu dans les figures suivantes. Le premier a des étiquettes entre qui sont des expressions rationnelles et nous voulons supprimer .e , f , g , h , i qp,q,re,f,g,h,iq
Une fois supprimés, nous composons ensemble (tout en préservant les autres arêtes entre et mais cela ne s’affiche pas):p re,f,g,h,ipr
Exemple
En utilisant le même exemple que dans la réponse de Raphaël :
on enlève successivement :q2
et ensuite :q3
alors nous devons toujours appliquer une étoile sur l'expression de à . Dans ce cas, l’état final est également initial, il suffit donc d’ajouter une étoile:q 1q1q1
(ab+(b+aa)(ba)∗(a+bb))∗
Algorithme
L[i,j]
est l'expression rationnelle de la langue de à . Tout d'abord, nous supprimons tous les multi-bords: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
Maintenant, la suppression de l'état. Supposons que nous voulions supprimer l'état :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]
Notez que les deux avec un crayon de papier et avec un algorithme vous devez simplifier les expressions comme star(ε)=ε
, e.ε=e
, ∅+e=e
, ∅.e=∅
(à la main que vous écrivez ne tout simplement pas le bord quand il ne , ou même pour une auto-boucle et vous ignorez quand il y a pas de transition entre et ou et )∅εqiqkqjqk
Maintenant, comment utiliser remove(k)
? Vous ne devez pas supprimer les états final ou initial à la légère, sinon vous allez perdre des parties de la langue.
for i = 1 to n:
if not(final(i)) and not(initial(i)):
remove(i)
Si vous n'avez qu'un seul état final et un seul état initial l'expression finale est la suivante:qfqs
e := star(L[s,s]) . L[s,f] . star(L[f,s] . star(L[s,s]) . L[s,f] + L[f,f])
Si vous avez plusieurs états finaux (ou même des états initiaux), il n'existe pas de moyen simple de les fusionner, mis à part l'application de la méthode de fermeture transitive. Habituellement, ce n'est pas un problème à la main, mais cela est gênant lors de l'écriture de l'algorithme. Une solution beaucoup plus simple consiste à énumérer toutes les paires et à exécuter l'algorithme sur le graphe (déjà supprimé) pour obtenir toutes les expressions supposant que est le seul état initial et le seul final. état, puis en faisant l'union de tous .(s,f)es,fsfes,f
Ceci et le fait que cela modifie les langages de manière plus dynamique que la première méthode la rendent plus sujette aux erreurs lors de la programmation. Je suggère d'utiliser une autre méthode.
Les inconvénients
Il existe de nombreux cas dans cet algorithme, par exemple pour choisir le nœud à supprimer, le nombre d'états finaux à la fin, le fait qu'un état final peut également être initial, etc.
Notez que maintenant que l’algorithme est écrit, cela ressemble beaucoup à la méthode de fermeture transitive. Seul le contexte de l'utilisation est différent. Je ne recommande pas d'implémenter l'algorithme, mais utiliser la méthode pour le faire à la main est une bonne idée.