const Ensemble * voisins( const Automate* automate, int origine, char lettre ){ Cle cle; initialiser_cle( &cle, origine, lettre ); Table_iterateur it = trouver_table( automate->transitions, (intptr_t) &cle ); if( ! iterateur_est_vide( it ) ){ return (Ensemble*) get_valeur( it ); }else{ return automate->vide; } }
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 ajouter_transition( Automate * automate, int origine, char lettre, int fin ){ ajouter_etat( automate, origine ); ajouter_etat( automate, fin ); ajouter_lettre( automate, lettre ); Cle cle; initialiser_cle( &cle, origine, lettre ); Table_iterateur it = trouver_table( automate->transitions, (intptr_t) &cle ); Ensemble * ens; if( iterateur_est_vide( it ) ){ ens = creer_ensemble( NULL, NULL, NULL ); add_table( automate->transitions, (intptr_t) &cle, (intptr_t) ens ); }else{ ens = (Ensemble*) get_valeur( it ); } ajouter_element( ens, fin ); }
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; }
Cle * creer_cle( int origine, char lettre ){ Cle * result = xmalloc( sizeof(Cle) ); initialiser_cle( result, origine, lettre ); return result; }