#include "nfa_mccluskey.h" #include "regexp.h" #include mccluskey_auto *nfa_to_mccluskey(nfa *thenfa) { // Nombre d'états dans le NFA uint n = thenfa->trans->size_graph; // Créer l'automate généralisé avec n+2 états mccluskey_auto *mccluskey = (mccluskey_auto *)malloc(sizeof(mccluskey_auto)); mccluskey->size = n + 2; mccluskey->matrix = (regexp ***)malloc((n + 2) * sizeof(regexp **)); // Initialiser toutes les cellules de la matrice à NULL for (uint i = 0; i < n + 2; i++) { mccluskey->matrix[i] = (regexp **)malloc((n + 2) * sizeof(regexp *)); for (uint j = 0; j < n + 2; j++) { mccluskey->matrix[i][j] = NULL; } } // Ajouter les transitions du NFA à l'automate généralisé for (uint q = 0; q < n; q++) { // 0 à taille de l'alphabet for (uint a = 0; a < thenfa->trans->size_alpha; a++) { // récupérer la liste des états accessibles depuis l'état `q` par une // transition étiquetée par la lettre `a` dans le NFA dequeue *transitions = thenfa->trans->edges[q][a]; for (uint k = 0; k < size_dequeue(transitions); k++) { uint r = lefread_dequeue(transitions, k); // regarde si la transition existe déjà if (mccluskey->matrix[q + 2][r + 2] == NULL) { // si elle n'existe pas on la crée // on crée une expression régulière qui représentant la lettre a mccluskey->matrix[q + 2][r + 2] = reg_letter(thenfa->alpha_names[a]); } else { // si elle existe on fait l'union avec la lettre a mccluskey->matrix[q + 2][r + 2] = reg_union(mccluskey->matrix[q + 2][r + 2], reg_letter(thenfa->alpha_names[a])); } } } } // Ajouter les transitions de l'état initial de l'automate généralisé vers les // états initiaux du NFA for (uint i = 0; i < size_dequeue(thenfa->initials); i++) { // on lie l'état initial uint initial_state = lefread_dequeue(thenfa->initials, i); // on crée une transition epsilon pour decaler les états initiaux du NFA // pour n'avoir qu'un seul état initial mccluskey->matrix[0][initial_state + 2] = reg_epsilon(); } // Ajouter les transitions des états finaux du NFA vers l'état final de // l'automate généralisé for (uint i = 0; i < size_dequeue(thenfa->finals); i++) { // on lie l'état final uint final_state = lefread_dequeue(thenfa->finals, i); // on crée une transition epsilon pour decaler les états finaux du NFA pour // n'avoir qu'un seul état final mccluskey->matrix[final_state + 2][1] = reg_epsilon(); } return mccluskey; } regexp *nfa_mccluskey(nfa *thenfa) { // Convertir le NFA en un automate généralisé // on recupère le mccluskey_auto de thenfa // premiere transphormation du NFA en automate généralisé mccluskey_auto *gen_auto = nfa_to_mccluskey(thenfa); // Nombre d'états dans l'automate uint n = gen_auto->size; // on recupère la matrice de l'automate regexp ***matrix = gen_auto->matrix; // Appliquer l'algorithme de Brzozowski-McCluskey // k est l'état intermédiaire que l'on veut supprimer for (uint k = 2; k < n; ++k) { for (uint i = 0; i < n; ++i) { for (uint j = 0; j < n; ++j) { // si il y a une transition de i à k et de k à j if (matrix[i][k] != NULL && matrix[k][j] != NULL) { regexp *new_expr; // on crée une nouvelle transition de i à j en passant par k // on verifie si il y a une boucle sur k if (matrix[k][k] != NULL) { new_expr = reg_concat(matrix[i][k], reg_star(matrix[k][k])); new_expr = reg_concat(new_expr, matrix[k][j]); } else { // Créer une nouvelle expression pour la transition de i à j via k // sans boucle new_expr = reg_concat(matrix[i][k], matrix[k][j]); } // Si une transition directe de i à j existe déjà, faire l'union des // deux expressions if (matrix[i][j] != NULL) { new_expr = reg_union(matrix[i][j], new_expr); } // Mettre à jour la matrice avec la nouvelle expression matrix[i][j] = new_expr; } } } } // L'expression régulière finale est dans matrix[0][1] regexp *final_regexp = matrix[0][1]; // Libérer la mémoire de l'automate généralisé for (uint i = 0; i < n; ++i) { for (uint j = 0; j < n; ++j) { if (matrix[i][j] && !(i == 0 && j == 1)) { // reg_free(matrix[i][j]); } } free(matrix[i]); } free(matrix); free(gen_auto); return final_regexp; }