changement dossier
This commit is contained in:
246
Aloyse et Vincent/nfa_determi.c
Normal file
246
Aloyse et Vincent/nfa_determi.c
Normal file
@@ -0,0 +1,246 @@
|
||||
/********************************************/
|
||||
/* Determinisation et Minimisation des NFAs */
|
||||
/********************************************/
|
||||
|
||||
#include "nfa_determi.h"
|
||||
#include "nfa.h"
|
||||
|
||||
/************************/
|
||||
/* Procédure principale */
|
||||
/************************/
|
||||
|
||||
// Fonction auxiliaire pour convertir une file d'états en une représentation
|
||||
// entière unique
|
||||
static uint dequeue_to_uint(dequeue *states) {
|
||||
uint result = 0;
|
||||
for (uint i = 0; i < size_dequeue(states); ++i) {
|
||||
result |= (1 << lefread_dequeue(states, i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Fonction auxiliaire pour vérifier si un ensemble d'états est final
|
||||
static bool is_final_state(dequeue *states, dequeue *finals) {
|
||||
for (uint i = 0; i < size_dequeue(states); ++i) {
|
||||
if (mem_dequeue(lefread_dequeue(states, i), finals)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Procédure de déterminisation. Le Booléen names indique si les noms des
|
||||
// nouveaux états (des ensembles d'états de l'ancien NFA) doivent être
|
||||
// sauvegardés dans le DFA.
|
||||
nfa *nfa_determinize(nfa *thenfa, bool recording) {
|
||||
printf("Déterminisation de l'automate1\n");
|
||||
fflush(stdout);
|
||||
// Créer un nouvel automate pour représenter le DFA
|
||||
nfa *dfa = (nfa *)malloc(sizeof(nfa));
|
||||
// Créer un graphe avec la taille de l'alphabet de l'automate initial
|
||||
dfa->trans = create_lgraph_noedges(0, thenfa->trans->size_alpha);
|
||||
dfa->initials = create_dequeue();
|
||||
dfa->finals = create_dequeue();
|
||||
// Copier les noms des lettres de l'alphabet;
|
||||
dfa->alpha_names = nfa_copy_alpha(thenfa);
|
||||
// Initialiser les noms des états si nécessaire
|
||||
if (recording) {
|
||||
dfa->state_names = (char **)malloc(sizeof(char *));
|
||||
} else {
|
||||
dfa->state_names = NULL;
|
||||
}
|
||||
|
||||
// Initialiser l'état initial du DFA
|
||||
// recopier les états initiaux de l'automate initial
|
||||
dequeue *initial_set = create_dequeue();
|
||||
copy_dequeue_right(initial_set, thenfa->initials, 0);
|
||||
// on les transforme en binaires
|
||||
uint initial_state = dequeue_to_uint(initial_set);
|
||||
// On ajoute l'état initial du DFA en decimal à la file des états initiaux du
|
||||
// DFA
|
||||
lefins_dequeue(initial_state, dfa->initials);
|
||||
|
||||
// Utiliser une file pour gérer les ensembles d'états à explorer
|
||||
dequeue *queue = create_dequeue();
|
||||
// Ajouter l'état initial à la file
|
||||
lefins_dequeue(initial_state, queue);
|
||||
|
||||
// tableau de booléens pour marquer les états visités de taille 2^size_graph
|
||||
barray *visited = create_barray(1 << thenfa->trans->size_graph);
|
||||
// Marquer l'état initial comme visité
|
||||
settrue_barray(visited, initial_state);
|
||||
|
||||
// Carte pour stocker les ensembles d'états réels
|
||||
dequeue **state_sets =
|
||||
(dequeue **)malloc((1 << thenfa->trans->size_graph) * sizeof(dequeue *));
|
||||
// on int
|
||||
state_sets[initial_state] = initial_set;
|
||||
|
||||
// Traiter chaque ensemble d'états
|
||||
while (!isempty_dequeue(queue)) {
|
||||
uint current_state = lefpull_dequeue(queue);
|
||||
// stocke cet ensemble d'états initiaux dans le tableau `state_sets` à
|
||||
// l'indice `initial_state`
|
||||
dequeue *current_set = state_sets[current_state];
|
||||
|
||||
// Vérifier si l'état actuel est un état final
|
||||
if (is_final_state(current_set, thenfa->finals)) {
|
||||
lefins_dequeue(current_state, dfa->finals);
|
||||
}
|
||||
|
||||
// Traiter chaque lettre de l'alphabet
|
||||
for (uint letter = 0; letter < thenfa->trans->size_alpha; ++letter) {
|
||||
dequeue *next_set = create_dequeue();
|
||||
|
||||
// Calculer l'ensemble des états atteignables par la lettre actuelle
|
||||
for (uint i = 0; i < size_dequeue(current_set); ++i) {
|
||||
uint state = lefread_dequeue(current_set, i);
|
||||
dequeue *transitions = thenfa->trans->edges[state][letter];
|
||||
for (uint j = 0; j < size_dequeue(transitions); ++j) {
|
||||
uint next_state = lefread_dequeue(transitions, j);
|
||||
|
||||
if (!mem_dequeue(next_state, next_set)) {
|
||||
lefins_dequeue(next_state, next_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convertir le prochain ensemble en une représentation entière unique
|
||||
uint next_state = dequeue_to_uint(next_set);
|
||||
|
||||
// Si le prochain état n'a pas été visité, l'ajouter à la file et le
|
||||
// marquer comme visité
|
||||
if (!getval_barray(visited, next_state)) {
|
||||
settrue_barray(visited, next_state);
|
||||
lefins_dequeue(next_state, queue);
|
||||
state_sets[next_state] = next_set;
|
||||
} else {
|
||||
delete_dequeue(next_set);
|
||||
}
|
||||
|
||||
// Ajouter la transition au DFA
|
||||
if (dfa->trans->size_graph <= current_state) {
|
||||
dfa->trans->size_graph = current_state + 1;
|
||||
dfa->trans->edges = (dequeue ***)realloc(
|
||||
dfa->trans->edges, dfa->trans->size_graph * sizeof(dequeue **));
|
||||
for (uint k = 0; k < dfa->trans->size_graph; ++k) {
|
||||
dfa->trans->edges[k] =
|
||||
(dequeue **)malloc(dfa->trans->size_alpha * sizeof(dequeue *));
|
||||
for (uint l = 0; l < dfa->trans->size_alpha; ++l) {
|
||||
dfa->trans->edges[k][l] = create_dequeue();
|
||||
}
|
||||
}
|
||||
}
|
||||
lefins_dequeue(next_state, dfa->trans->edges[current_state][letter]);
|
||||
}
|
||||
|
||||
// Enregistrer le nom de l'état si nécessaire
|
||||
if (recording) {
|
||||
char *state_name = (char *)malloc(256 * sizeof(char));
|
||||
sprintf(state_name, "{");
|
||||
for (uint i = 0; i < size_dequeue(current_set); ++i) {
|
||||
if (i > 0) {
|
||||
strcat(state_name, ",");
|
||||
}
|
||||
char buffer[10];
|
||||
sprintf(buffer, "%u", lefread_dequeue(current_set, i));
|
||||
strcat(state_name, buffer);
|
||||
}
|
||||
strcat(state_name, "}");
|
||||
dfa->state_names[current_state] = state_name;
|
||||
}
|
||||
|
||||
delete_dequeue(current_set);
|
||||
}
|
||||
|
||||
// Nettoyage
|
||||
delete_dequeue(queue);
|
||||
delete_barray(visited);
|
||||
free(state_sets);
|
||||
|
||||
printf("Fin de la déterminisation1\n");
|
||||
fflush(stdout);
|
||||
return dfa;
|
||||
}
|
||||
|
||||
// Complementation
|
||||
nfa *nfa_complement(nfa *thenfa) {
|
||||
printf("Complémentation de l'automate\n");
|
||||
fflush(stdout);
|
||||
// Déterminiser l'automate
|
||||
nfa *det_nfa = nfa_determinize(thenfa, false);
|
||||
|
||||
// Compléter l'automate déterminisé
|
||||
uint num_states = det_nfa->trans->size_graph;
|
||||
uint num_letters = det_nfa->trans->size_alpha;
|
||||
printf("Complémentation de l'automate1\n");
|
||||
fflush(stdout);
|
||||
|
||||
// Créer un nouvel état de puits
|
||||
uint sink_state = num_states;
|
||||
lgraph *new_trans = create_lgraph_noedges(num_states + 1, num_letters);
|
||||
printf("Complémentation de l'automate2\n");
|
||||
fflush(stdout);
|
||||
// Copier les transitions existantes
|
||||
for (uint state = 0; state < num_states; state++) {
|
||||
for (uint letter = 0; letter < num_letters; letter++) {
|
||||
printf("Complémentation de l'automate3\n");
|
||||
fflush(stdout);
|
||||
dequeue *transitions = det_nfa->trans->edges[state][letter];
|
||||
if (transitions != NULL) {
|
||||
printf("Complémentation de l'automate4\n");
|
||||
fflush(stdout);
|
||||
new_trans->edges[state][letter] = transitions;
|
||||
} else {
|
||||
printf("Complémentation de l'automate5\n");
|
||||
fflush(stdout);
|
||||
new_trans->edges[state][letter] = create_dequeue();
|
||||
printf("Complémentation de l'automate6\n");
|
||||
fflush(stdout);
|
||||
rigins_dequeue(sink_state, new_trans->edges[state][letter]);
|
||||
printf("Complémentation de l'automate7\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ajouter des transitions vers l'état de puits pour les transitions
|
||||
// manquantes
|
||||
for (uint letter = 0; letter < num_letters; letter++) {
|
||||
new_trans->edges[sink_state][letter] = create_dequeue();
|
||||
rigins_dequeue(sink_state, new_trans->edges[sink_state][letter]);
|
||||
}
|
||||
|
||||
printf("Complémentation de l'automate8\n");
|
||||
fflush(stdout);
|
||||
// Créer le nouvel automate avec les transitions complétées
|
||||
nfa *comp_nfa = (nfa *)malloc(sizeof(nfa));
|
||||
comp_nfa->trans = new_trans;
|
||||
comp_nfa->initials = det_nfa->initials;
|
||||
comp_nfa->alpha_names = nfa_copy_alpha(det_nfa);
|
||||
comp_nfa->state_names = nfa_copy_all_names(det_nfa);
|
||||
|
||||
// Inverser les états finaux et non finaux
|
||||
barray *finals_barray = create_barray(num_states + 1);
|
||||
for (uint state = 0; state < num_states; state++) {
|
||||
if (!mem_dequeue(state, det_nfa->finals)) {
|
||||
settrue_barray(finals_barray, state);
|
||||
}
|
||||
}
|
||||
settrue_barray(finals_barray, sink_state);
|
||||
|
||||
// Créer la liste des états finaux
|
||||
comp_nfa->finals = create_dequeue();
|
||||
for (uint state = 0; state <= num_states; state++) {
|
||||
if (getval_barray(finals_barray, state)) {
|
||||
rigins_dequeue(state, comp_nfa->finals);
|
||||
}
|
||||
}
|
||||
printf("Complémentation de l'automate9\n");
|
||||
fflush(stdout);
|
||||
// Libérer la mémoire
|
||||
delete_barray(finals_barray);
|
||||
nfa_delete(det_nfa);
|
||||
|
||||
return comp_nfa;
|
||||
}
|
||||
Reference in New Issue
Block a user