Files
c-automates-giiiiive/Aloyse et Vincent/nfa_mccluskey.c
2024-12-16 02:48:28 +01:00

128 lines
4.6 KiB
C

#include "nfa_mccluskey.h"
#include "regexp.h"
#include <stdio.h>
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;
}