Automate* copier_automate( const Automate* automate ){ Automate * res = creer_automate(); Ensemble_iterateur it1; // On ajoute les états de l'automate for( it1 = premier_iterateur_ensemble( get_etats( automate ) ); ! iterateur_ensemble_est_vide( it1 ); it1 = iterateur_suivant_ensemble( it1 ) ){ ajouter_etat( res, get_element( it1 ) ); } // On ajoute les états initiaux for( it1 = premier_iterateur_ensemble( get_initiaux( automate ) ); ! iterateur_ensemble_est_vide( it1 ); it1 = iterateur_suivant_ensemble( it1 ) ){ ajouter_etat_initial( res, get_element( it1 ) ); } // On ajoute les états finaux for( it1 = premier_iterateur_ensemble( get_finaux( automate ) ); ! iterateur_ensemble_est_vide( it1 ); it1 = iterateur_suivant_ensemble( it1 ) ){ ajouter_etat_final( res, get_element( it1 ) ); } // On ajoute les lettres for( it1 = premier_iterateur_ensemble( get_alphabet( automate ) ); ! iterateur_ensemble_est_vide( it1 ); it1 = iterateur_suivant_ensemble( it1 ) ){ ajouter_lettre( res, (char) get_element( it1 ) ); } // On ajoute les transitions Table_iterateur it2; for( it2 = premier_iterateur_table( automate->transitions ); ! iterateur_ensemble_est_vide( it2 ); it2 = iterateur_suivant_ensemble( it2 ) ){ Cle * cle = (Cle*) get_cle( it2 ); Ensemble * fins = (Ensemble*) get_valeur( it2 ); for( it1 = premier_iterateur_ensemble( fins ); ! iterateur_ensemble_est_vide( it1 ); it1 = iterateur_suivant_ensemble( it1 ) ){ int fin = get_element( it1 ); ajouter_transition( res, cle->origine, cle->lettre, fin ); } }; return res; }
Automate *automate_accessible( const Automate * automate){ Automate* clone = copier_automate(automate); Ensemble* etats = creer_ensemble(NULL, NULL, NULL); Ensemble_iterateur it_etat; Ensemble_iterateur it_lettre; // On calcule l'ensemble des états accessibles for(it_etat = premier_iterateur_ensemble(get_initiaux(automate)); ! iterateur_ensemble_est_vide( it_etat ); it_etat = iterateur_suivant_ensemble( it_etat )){ ajouter_elements(etats, etats_accessibles(automate, get_element(it_etat))); ajouter_element(etats, get_element(it_etat)); } // On détermine les états qui ne sont pas accessibles => ceux qui sont dans get_etats mais pas dans etats Ensemble* non_accessible = creer_difference_ensemble(get_etats(automate), etats); // On parcourt l'ensemble obtenu for(it_etat = premier_iterateur_ensemble(non_accessible); ! iterateur_ensemble_est_vide( it_etat ); it_etat = iterateur_suivant_ensemble( it_etat )){ const intptr_t etat_courant = get_element(it_etat); // On cherche toutes les transitions partant d'un état for(it_lettre = premier_iterateur_ensemble(get_alphabet(automate)); ! iterateur_ensemble_est_vide( it_lettre ); it_lettre = iterateur_suivant_ensemble( it_lettre )){ Cle cle; initialiser_cle( &cle, etat_courant, get_element(it_lettre)); Table_iterateur it = trouver_table( clone->transitions, (intptr_t) &cle ); // Si on trouve une transition partant d'un état non accessible if( !iterateur_est_vide( it ) ){ delete_table( clone->transitions, (intptr_t) &cle); // on la supprime } } // si c'est un état final, on pense à le supprimer if (est_un_etat_final_de_l_automate(automate, etat_courant)) { retirer_element(clone->finaux, etat_courant); } // si c'est un état initial, on pense à le supprimer if (est_un_etat_initial_de_l_automate(automate, etat_courant)) { retirer_element(clone->initiaux, etat_courant); } } // On supprime tous les états non accessibles de l'automate deplacer_ensemble(clone->etats, etats); return clone; }
void print_automate( const Automate * automate ){ printf("- Etats : "); print_ensemble( get_etats( automate ), NULL ); printf("\n- Initiaux : "); print_ensemble( get_initiaux( automate ), NULL ); printf("\n- Finaux : "); print_ensemble( get_finaux( automate ), NULL ); printf("\n- Alphabet : "); print_ensemble( get_alphabet( automate ), print_lettre ); printf("\n- Transitions : "); print_table( automate->transitions, ( void (*)( const intptr_t ) ) print_cle, ( void (*)( const intptr_t ) ) print_ensemble_2, "" ); printf("\n"); }
/** * \par Implémentation * La fonction ne considère que les derniers états atteints avant de tester si au moins un est final</br> * \par * On lit un mot depuis l'ensemble des états initiaux puis réitère à partir des voisins trouvés à l'étape précédente * @param automate * @param mot * @return */ int le_mot_est_reconnu( const Automate* automate, const char* mot ){ Ensemble * fins = copier_ensemble(get_initiaux(automate)); int i; for(i = 0; i < strlen(mot); i++) { fins = delta(automate, fins, mot[i]); } Ensemble_iterateur it1; for( it1 = premier_iterateur_ensemble(fins); ! iterateur_ensemble_est_vide( it1 ); it1 = iterateur_suivant_ensemble( it1 ) ){ if (est_un_etat_final_de_l_automate(automate, get_element(it1))) return 1; } return 0; }
int test_execute_fonctions(){ BEGIN_TEST int res = 1; Automate * automate2; Automate * automate; Automate * result = NULL; Ensemble * ens = NULL; Ensemble * ens1 = NULL; automate = creer_automate(); result = NULL; ajouter_lettre( automate, 'a' ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; ajouter_etat_final( automate, 1 ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; ajouter_etat_initial( automate, 1 ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); get_initiaux( automate ); liberer_automate( automate ); automate = creer_automate(); get_finaux( automate ); liberer_automate( automate ); automate = creer_automate(); get_alphabet( automate ); liberer_automate( automate ); automate = creer_automate(); result = NULL; est_un_etat_initial_de_l_automate( automate, 1 ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; est_un_etat_final_de_l_automate( automate, 1 ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; est_une_lettre_de_l_automate( automate, 'a' ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); ens = NULL; ens1 = creer_ensemble( NULL, NULL, NULL ); ens = delta_star( automate, ens1, "aba" ); if( ens ) liberer_ensemble( ens ); liberer_ensemble( ens1 ); liberer_automate( automate ); automate = creer_automate(); result = NULL; le_mot_est_reconnu( automate, "abaa" ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = mot_to_automate( "abbaa" ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); ens = NULL; ens = etats_accessibles( automate, 0 ); if( ens ) liberer_ensemble( ens ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = automate_accessible( automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = miroir( automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = automate_co_accessible(automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = creer_automate_des_prefixes( automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = creer_automate_des_suffixes( automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; result = creer_automate_des_facteurs( automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); automate = creer_automate(); result = NULL; ens = creer_ensemble( NULL, NULL, NULL ); result = creer_automate_des_sur_mot( automate, ens ); if( result ) liberer_automate( result ); liberer_automate( automate ); liberer_ensemble( ens ); automate = creer_automate(); automate2 = creer_automate(); result = NULL; result = creer_automate_de_concatenation( automate, automate2 ); if( result ) liberer_automate( result ); liberer_automate( automate ); liberer_automate( automate2 ); automate = creer_automate(); result = NULL; result = creer_automate_des_sous_mots( automate ); if( result ) liberer_automate( result ); liberer_automate( automate ); return res; }
int test_creer_automate(){ BEGIN_TEST; int result = 1; Automate * automate = creer_automate(); ajouter_lettre( automate, 'a' ); ajouter_lettre( automate, 'd' ); ajouter_etat( automate, 3 ); ajouter_etat_final( automate, 6 ); ajouter_transition( automate, 3, 'a', 5 ); ajouter_transition( automate, 3, 'b', 3 ); ajouter_etat_final( automate, 5 ); ajouter_etat_initial( automate, 3 ); TEST( 1 && est_un_etat_de_l_automate( automate, 3) && est_un_etat_de_l_automate( automate, 5) && est_un_etat_de_l_automate( automate, 6) , result ); TEST( 1 && ! est_un_etat_final_de_l_automate( automate, 3) && est_un_etat_final_de_l_automate( automate, 5) && est_un_etat_final_de_l_automate( automate, 6) , result ); TEST( 1 && est_un_etat_initial_de_l_automate( automate, 3) && ! est_un_etat_initial_de_l_automate( automate, 5) , result ); TEST( 1 && est_une_lettre_de_l_automate( automate, 'a') && est_une_lettre_de_l_automate( automate, 'b') && est_une_lettre_de_l_automate( automate, 'd') && ! est_une_lettre_de_l_automate( automate, 'c') , result ); TEST( 1 && est_une_transition_de_l_automate( automate, 3, 'a', 5 ) && est_une_transition_de_l_automate( automate, 3, 'b', 3 ) && ! est_une_transition_de_l_automate( automate, 3, 'b', 5 ) && ! est_une_transition_de_l_automate( automate, 3, 'a', 3 ) && ! est_une_transition_de_l_automate( automate, 5, 'a', 3 ) && ! est_une_transition_de_l_automate( automate, 5, 'b', 3 ) && ! est_une_transition_de_l_automate( automate, 5, 'a', 5 ) && ! est_une_transition_de_l_automate( automate, 5, 'b', 5 ) , result ); const Ensemble* ens = get_initiaux( automate ); TEST( 1 && ens && est_dans_l_ensemble( ens, 3 ) && ! est_dans_l_ensemble( ens, 5 ) && ! est_dans_l_ensemble( ens, 6 ) , result ); ens = get_finaux( automate ); TEST( 1 && ens && ! est_dans_l_ensemble( ens, 3 ) && est_dans_l_ensemble( ens, 5 ) && est_dans_l_ensemble( ens, 6 ) , result ); ens = get_alphabet( automate ); TEST( 1 && ens && est_dans_l_ensemble( ens, 'a') && est_dans_l_ensemble( ens, 'b') && ! est_dans_l_ensemble( ens, 'c') && est_dans_l_ensemble( ens, 'd') , result ); liberer_automate( automate ); return result; }
void creergraphe(Automate *a){ FILE* f=fopen("./auto.gv","w+"); fprintf(f, "digraph graphe {\n\trankdir=S;\n\tsize=\"8,5\"\n\tnode [shape = doublecircle];\n\t"); Ensemble_iterateur it; for(it = premier_iterateur_ensemble(get_finaux(a)); ! iterateur_ensemble_est_vide( it ); it = iterateur_suivant_ensemble( it )){ fprintf(f, "%d ", (int)get_element( it)); } fprintf(f,";\n\t"); fprintf(f,"\n\tnode [shape = circle];\n\t"); Table_iterateur it2; for( it2 = premier_iterateur_table(get_transitions( a )); ! iterateur_ensemble_est_vide( it2 ); it2 = iterateur_suivant_ensemble( it2 ) ){ Cle * cle = (Cle*) get_cle( it2 ); Ensemble * fins = (Ensemble*) get_valeur( it2 ); for( it = premier_iterateur_ensemble( fins ); ! iterateur_ensemble_est_vide( it ); it = iterateur_suivant_ensemble( it ) ){ int fin = get_element( it ); fprintf(f,"%d",(int)get_origine_cle(cle)); fprintf(f," -> "); fprintf(f,"%d",(int)fin); fprintf(f," [ label =\""); char lettre=get_lettre_cle(cle); fprintf(f,"%c",lettre); fprintf(f, ":"); fprintf(f,"%d",get_cout_cle(cle)); fprintf(f,"\"];\n\t"); } } fprintf(f,"node [shape = point];\n\t"); for(it = premier_iterateur_ensemble(get_initiaux(a)); ! iterateur_ensemble_est_vide( it ); it = iterateur_suivant_ensemble( it )){ fprintf(f,"i%d ",(int)get_element(it)); } fprintf(f,";\n\t"); for(it = premier_iterateur_ensemble(get_initiaux(a)); ! iterateur_ensemble_est_vide( it ); it = iterateur_suivant_ensemble( it )){ fprintf(f,"i%d",(int)get_element(it)); fprintf(f," -> "); fprintf(f,"%d",(int)get_element(it)); fprintf(f," [ label =\"start\" ];\n\t"); } fprintf(f,"}\n"); fclose(f); }
int est_un_etat_initial_de_l_automate( const Automate* automate, int etat ){ return est_dans_l_ensemble(get_initiaux(automate), etat); }
// À chaque itération de l'algo, on prend une lettre du premier ou du second automate, jusqu'à ce qu'on arrive à la dernière lettre. // Produit cartésien des états. // Exemple : mot 1 : aaaa, mot 2 : bbbb // Quelques résulats possibles : aabbaabb; aaaabbbb: bbbbaaaa; aaababbb: baababba Automate * creer_automate_du_melange( const Automate* automate1, const Automate* automate2 ){ int i, j, k, nbelau1, nbelau2, etat_act, et1, et2; int ** nouveaux_etats = NULL; Automate * melange = creer_automate(); Ensemble_iterateur it1, it2; Table_iterateur it_transition; Table *cle1 = creer_table( ( int(*)(const intptr_t, const intptr_t) ) comparer_int , ( intptr_t (*)( const intptr_t ) ) copier_int, ( void(*)(intptr_t) ) supprimer_int ); Table *cle2 = creer_table( ( int(*)(const intptr_t, const intptr_t) ) comparer_int , ( intptr_t (*)( const intptr_t ) ) copier_int, ( void(*)(intptr_t) ) supprimer_int ); const Ensemble * finaux1 = get_finaux(automate1); const Ensemble * finaux2 = get_finaux(automate2); const Ensemble * initiaux1 = get_initiaux(automate1); const Ensemble * initiaux2 = get_initiaux(automate2); nbelau1 = taille_ensemble(automate1->etats); nbelau2 = taille_ensemble(automate2->etats); nouveaux_etats = malloc(nbelau1 * sizeof(int *)); for(i=0; i<nbelau1; i++) nouveaux_etats[i]=malloc(nbelau2 * sizeof(int)); k = 0; // Création des états, états initiaux, états finaux de l'automate. for (it1 = premier_iterateur_ensemble(automate1->etats), i=0; ! iterateur_ensemble_est_vide(it1); it1 = iterateur_suivant_ensemble(it1), i++){ et1 = get_element(it1); add_table(cle1, et1, i); for (it2 = premier_iterateur_ensemble(automate2->etats), j=0; ! iterateur_ensemble_est_vide(it2); it2 = iterateur_suivant_ensemble(it2), j++){ et2 = get_element(it2); ajouter_etat(melange, k); add_table(cle2, et2, j); if (est_dans_l_ensemble(finaux1, et1) && est_dans_l_ensemble(finaux2, et2)) ajouter_etat_final(melange, k); if (est_dans_l_ensemble(initiaux1, et1) && est_dans_l_ensemble(initiaux2, et2)) ajouter_etat_initial(melange, k); nouveaux_etats[i][j] = k; k++; } } // Les transitions sont ensuite crées // D'abord celles de l'ancien automate 1 for (it_transition = premier_iterateur_table(automate1->transitions); !iterateur_est_vide(it_transition); it_transition = iterateur_suivant_table(it_transition)) { Cle * cle = (Cle*) get_cle(it_transition); Ensemble * fins = (Ensemble*) get_valeur(it_transition); for (it1 = premier_iterateur_ensemble(fins), i=0; ! iterateur_ensemble_est_vide(it1); it1 = iterateur_suivant_ensemble(it1), i++){ etat_act = get_element(it1); for(i = 0; i < nbelau2; i++) { ajouter_transition(melange, nouveaux_etats[(int)get_valeur(trouver_table(cle1, cle->origine))][i], cle->lettre, nouveaux_etats[(int)get_valeur(trouver_table(cle1, etat_act))][i]); } } } // Puis celles de l'ancien automate 2 for (it_transition = premier_iterateur_table(automate2->transitions); !iterateur_est_vide(it_transition); it_transition = iterateur_suivant_table(it_transition)) { Cle * cle = (Cle*) get_cle(it_transition); Ensemble * fins = (Ensemble*) get_valeur(it_transition); for (it1 = premier_iterateur_ensemble(fins), i=0; ! iterateur_ensemble_est_vide(it1); it1 = iterateur_suivant_ensemble(it1), i++){ etat_act = get_element(it1); for(i = 0; i < nbelau1; i++) { ajouter_transition(melange, nouveaux_etats[i][(int)get_valeur(trouver_table(cle2, cle->origine))], cle->lettre, nouveaux_etats[i][(int)get_valeur(trouver_table(cle2, etat_act))]); } } } liberer_table(cle1); liberer_table(cle2); return melange; }
Automate * creer_automate_de_concatenation( const Automate* automate1, const Automate* automate2 ){ /** * \par Implémentation * * On créé un automate, copie de automate1 avec comme états finaux ceux de automate2 */ Automate* concat = copier_automate(automate1); deplacer_ensemble(concat->finaux, automate2->finaux); /** * Puis on créé un modificateur qui nous permet de passer en paramètres de fonction * l'automate de destination et une valeur de décalage des états. * Cette valeur permet de ne pas avoir deux états avec la même valeur. */ int decalage = get_max_etat(automate1); AutomateInt* modificateur = creer_automate_int(); modificateur->automate = concat; modificateur->valeur = decalage; /** * On ajoute les transitions de l'automate 2 avec les états décalés. */ pour_toute_transition(automate2, incrementer_etats_transition, modificateur); liberer_automate_int(modificateur); /** * Pour chaque état initial du second automate */ Ensemble_iterateur initial2; for( initial2 = premier_iterateur_ensemble(get_initiaux(automate2)); ! iterateur_ensemble_est_vide( initial2 ); initial2 = iterateur_suivant_ensemble( initial2 )){ /** * Pour chaque lettre de son alphabet */ Ensemble_iterateur lettre; for( lettre = premier_iterateur_ensemble(get_alphabet(automate2)); ! iterateur_ensemble_est_vide(lettre); lettre = iterateur_suivant_ensemble(lettre)){ Cle cle; printf("initial2 : %d\n", (int) get_element(initial2)); printf("lettre : %c\n", (char) get_element(lettre)); initialiser_cle(&cle, (int) get_element(initial2), (char) get_element(lettre)); Table_iterateur destination = trouver_table(automate2->transitions, (intptr_t) &cle); printf("avant clé\n"); print_cle(&cle); printf("après clé\n"); if (!iterateur_est_vide(destination)){ AutomateTransition* modif_trans = creer_automate_transition(); modif_trans->automate = concat; modif_trans->lettre = get_element(lettre); Ensemble* destinations = (Ensemble*) get_valeur(destination); Ensemble_iterateur etat_dest; /** * Pour chaque transition de la forme (i2, a2, q2), avec i2 intial, a2 lettre de l'alphabet * et q2 état de l'automate2 */ for( etat_dest = premier_iterateur_ensemble(destinations); ! iterateur_ensemble_est_vide(etat_dest); etat_dest = iterateur_suivant_ensemble(etat_dest)){ modif_trans->destination = get_element(etat_dest)+decalage; /** * On ajoute une transition dans l'automate de concaténation ayant pour origine * un état initial, la lettre a2 et l'état q2 */ pour_tout_element(get_finaux(automate1), simuler_epsilon_transition, modif_trans); } initialiser_cle(&cle, (int) get_element(initial2) + decalage, get_element(lettre)); delete_table(concat->transitions, (intptr_t) &cle); liberer_automate_transition(modif_trans); } } } return concat; }