diff --git a/DFA.py b/DFA.py new file mode 100644 index 0000000..0c66545 --- /dev/null +++ b/DFA.py @@ -0,0 +1,98 @@ +"""Autómata finito determinista""" +#Código adaptado del original de Vijaya Gajanan +#https://medium.com/swlh/automata-theory-in-python-part-1-deterministic-finite-automata-95d7c4a711f5 + +class DFA: + + def __init__(self): + #Se inicia el objeto DFA + self.Q = self.populate_states() + self.SIGMA = self.populate_alphabet() + self.DELTA = self.populate_transition_function() + self.START_STATE, self.ACCEPT_STATES = self.set_start_accept() + self.CURRENT_STATE = None + + def set_start_accept(self): + #Toma el estado inicial (START_SATATE) y los estados de aceptación (ACCEPT_STATE) dado por el usuario y checa si pertenecen al conjunto de estados + while(True): + start = input("Da el estado inicial: ") + accept = input("Da el o los estados de aceptación (separados por espacio): ").split() + #Se asegura que el estado inicial y de aceptación estén en el conjunto + if (start in self.Q) and (set(accept).issubset(set(self.Q))): + return start, accept + else: + print("Por favor da estados que estén en tu conjunto de estados Q : {}.\nLos estados de aceptación deben ser un subconjunto de Q\n".format(self.Q)) + + def populate_states(self): + #Toma los estados dados por el usuario (Q) + Q_input = input("Da la lista de estados separados por espacio: ").split() + print("Estados : {}".format(Q_input)) + return Q_input + + def populate_alphabet(self): + #Toma el alfabeto dado por el usuario (SIGMA) + SIGMA_input = input("Da el alfabeto de entrada separado por espacios: ").split() + print("Alfabeto : {}".format(SIGMA_input)) + return SIGMA_input + + def populate_transition_function(self): + #Crea la función de transición (Q X SIGMA -> Q) y la imprime + transition_dict = {el : {el_2 : 'REJECT' for el_2 in self.SIGMA} for el in self.Q} + + for key, dict_value in transition_dict.items(): + print("Da la transición para el estado {}. De ser necesario, usa 'RECHAZO'.".format(key)) + + for input_alphabet, transition_state in dict_value.items(): + transition_dict[key][input_alphabet] = input("ESTADO ACTUAL : {}\tALFABETO DE ENTRADA : {}\tSIGUIENTE ESTADO : ".format(key, input_alphabet)) + + print("\nFUNCIÓN DE TRANSICIÓN Q X SIGMA -> Q") + print("ESTADO ACTUAL\tALFABETO DE ENTRADA\tPRÓXIMO ESTADO") + for key, dict_value in transition_dict.items(): + for input_alphabet, transition_state in dict_value.items(): + print("{}\t\t{}\t\t{}".format(key, input_alphabet, transition_state)) + + return transition_dict + + def run_state_transition(self, input_symbol): + #Toma el estado actual y va al siguinete estado de acuerdo al símbolo de entrada + if (self.CURRENT_STATE == 'RECHAZO'): + return False + print("ESTADO ACTUAL : {}\tSÍMBOLO DE ENTRADA : {}\t PRÓXIMO ESTADO : {}".format(self.CURRENT_STATE, input_symbol, self.DELTA[self.CURRENT_STATE][input_symbol])) + self.CURRENT_STATE = self.DELTA[self.CURRENT_STATE][input_symbol] + return self.CURRENT_STATE + + def check_if_accept(self): + #Checa si el estado actual es de aceptación + if self.CURRENT_STATE in self.ACCEPT_STATES: + return True + else: + return False + + def run_machine(self, in_string): + #Corre la máquina con la cadena de entrada + self.CURRENT_STATE = self.START_STATE + for ele in in_string: + check_state = self.run_state_transition(ele) + #Checa si el estado no es RECHAZO + if (check_state == 'RECHAZO'): + return False + return self.check_if_accept() + +if __name__ == "__main__": + check = True + print("\nAutómata Finito Determinista (DFA).") + machine = DFA() + while(check): + choice = int(input("\nElige la opción:\n1. Correr el DFA con la cadena de entrada\n2. Cambiar el DFA\n3. Salir \nDa Opción : ")) + if (choice == 2): + machine = DFA() + elif (choice == 1): + input_string = list(input("Da la cadena de entrada : ")) + print("ACEPTADA" if machine.run_machine(input_string) else "RECHAZADA") + else: + check = False + + + + + diff --git a/README.md b/README.md index df2262a..33b1d6d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,69 @@ # dfa-python -Código para construir autómatas finitos deterministas en python. \ No newline at end of file +Código para construir autómatas finitos deterministas en python. Adaptado del original de **Vijaya Gajanan** (https://medium.com/swlh/automata-theory-in-python-part-1-deterministic-finite-automata-95d7c4a711f5). + +La operación es interactiva, pidiendo los estados, el alfabeto, estado de enrada y estados de salida, al igual que la tabla de transiciones. + +>Autómata Finito Determinista (DFA). +>Da la lista de estados separados por espacio: + +Introduce los nombres de los estados, por ejemplo: q0 q1 q2 (*presiona enter*) + +Al no poner los espacios el programa lo interpretará como un único estado. + +>Estados : ['q0', 'q1', 'q2'] +>Da el alfabeto de entrada separado por espacios: + +De la misma manera introduce los símbolos del alfabeto, por ejemplo: 0 1 + +>Alfabeto : ['0', '1'] +>Da la transición para el estado q0. De ser necesario, usa 'RECHAZO'. +>ESTADO ACTUAL : q0 ALFABETO DE ENTRADA : 0 SIGUIENTE ESTADO : + +Introduce el estado siguiente a partir del estado q0 al leer un '0'. +Este proceso se repite para todos los estados y todos los símbolos del alfabeto. El programa no cuenta con un proceso para confirmar que los estados dados estén en la lista, es algo que debe mejorarse. De dar estados fuera del conjunto hasta el final aparecerá un error. + +A partir de los valores dados se construye la tabla de transiciones: + +>FUNCIÓN DE TRANSICIÓN Q X SIGMA -> Q +>ESTADO ACTUAL ALFABETO DE ENTRADA PRÓXIMO ESTADO +>q0 0 q1 +>q0 1 q0 +>q1 0 q2 +>q1 1 q2 +>q2 0 q1 +>q2 1 q0 + +Enseguida se pide el estado inicial, como es un autómata finito determinista recuerda que sólo acepta un estado inicial. + +>Da el estado inicial: + +Posteriormente pedirá los estados finales. + +>Da el o los estados de aceptación (separados por espacio): + +Una vez introducidos revisará que los estados proporcionados estén en la lista de estados dado, de no ser así volverá a pedir el estado inicial y el o los de salida. + +Si los estados están en el conjunto se pide elegir la opción: + +>Elige la opción: +>1. Correr el DFA con la cadena de entrada +>2. Cambiar el DFA +>3. Salir + +Para correr el autómata dado se elige la opción 1, la opción 2 en caso de haber cometido un error permite definir de nuevo el autómata (desde cero), para no hacer nada más y salir se elige la opción 3 (por supuesto que en cualquier momento del proceso se puede hacer Ctrl-c). + +>Da Opción : 1 +>Da la cadena de entrada : 1001 +>ESTADO ACTUAL : q0 SÍMBOLO DE ENTRADA : 1 PRÓXIMO ESTADO : q0 +>ESTADO ACTUAL : q0 SÍMBOLO DE ENTRADA : 0 PRÓXIMO ESTADO : q1 +>ESTADO ACTUAL : q1 SÍMBOLO DE ENTRADA : 0 PRÓXIMO ESTADO : q2 +>ESTADO ACTUAL : q2 SÍMBOLO DE ENTRADA : 1 PRÓXIMO ESTADO : q0 + + +Al final aparecerá la palabra **ACEPTADA** o **RECHAZADA** de acuerdo a si se llega a un estado de aceptación o uno de rechazo. + +Hay detalles por mejorar, no he probado que pasa al dar el estado como rechazo. Tomen la idea y adáptenla a su gusto y necesidades. + + +