class TestAutomata(unittest.TestCase): test_unit = None state_name = "testState" transition_letter = "s" from_state_id = 42 to_state_id = 91 def setUp(self): unittest.TestCase.setUp(self) self.test_unit = Automata() def test_add_and_get_state(self): self.assertIsNone(self.test_unit.get_state(self.state_name)) self.test_unit.add_state(self.state_name) state = self.test_unit.get_state(self.state_name) self.assertIsNotNone(state) self.assertIs(state.name, self.state_name) def test_add_initial_state(self): self.test_unit.add_initial_state(self.state_name) self.assertTrue(self.test_unit.get_state(self.state_name).initial) def test_add_accepting_state(self): self.test_unit.add_accepting_state(self.state_name) self.assertTrue(self.test_unit.get_state(self.state_name).accepting) def test_add_transition(self): self.assertIsNone(self.test_unit.get_transition_by_from_state_id(self.from_state_id)) self.test_unit.add_transition(self.transition_letter, self.from_state_id, self.to_state_id) transition = self.test_unit.get_transition_by_from_state_id(self.from_state_id) self.assertIsNotNone(transition) self.assertIs(transition.from_state_id, self.from_state_id) self.assertIs(transition.to_state_id, self.to_state_id) self.assertIs(transition.letter, self.transition_letter) def test_accepts_rejects_single_char(self): # q0 - a -> (q1) self.test_unit.add_initial_state('q0') self.test_unit.add_accepting_state('q1') self.test_unit.add_transition('a', 'q0', 'q1') self.assertTrue(self.test_unit.accepts('a')) self.assertFalse(self.test_unit.accepts('b')) def test_accepts_rejects_three_chars(self): # q0 - a -> (q1) # (q1) - b -> q0 self.test_unit.add_initial_state('q0') self.test_unit.add_accepting_state('q1') self.test_unit.add_transition('a', 'q0', 'q1') self.test_unit.add_transition('b', 'q1', 'q0') self.assertTrue(self.test_unit.accepts('aba')) self.assertFalse(self.test_unit.accepts('ab'))
def empty_stack(self, stack): merge_nfa = None while stack.length() < 1: #lo tomamos como join nfa2 = stack.pop() nfa1 = stack.pop() initial = nfa2.get_initial_state() final = nfa1.get_final_state() #print("INIT", initial) #print("FINAL", final) for state in nfa2.arr_states(): #print("STATE", state) if (state.get_start() == initial): state.set_start(final) for state in nfa1.arr_states(): if (state.get_start() == final): state.set_start(initial) merge_nfa = Automata([], [], nfa1.get_initial_state(), nfa2.get_final_state(), []) opsNfa2 = nfa2.arr_states() opsNfa1 = nfa1.arr_states() merged = opsNfa2 + opsNfa1 for transition in merged: if (transition.get_transition() != None): merge_nfa.add_state(transition) if not merge_nfa: merge_nfa = self.opStack.pop() self.opStack.add(merge_nfa) return stack
from Automata import Automata myAutomata = Automata() myAutomata.add_initial_state('q0') myAutomata.add_state('q1') myAutomata.add_accepting_state('q2') # q0 - a -> q1 myAutomata.add_transition('a', 'q0', 'q1') # q1 - b -> (q2) myAutomata.add_transition('b', 'q1', 'q2') words = {'ab', 'ba', 'aa', 'bb'} for word in words: if myAutomata.accepts(word): print word + " is accepted.\n" else: print word + " is not accepted.\n"
def evalPostfix(self, tokens): """ Definimos las reglas segun: https://medium.com/swlh/visualizing-thompsons-construction-algorithm-for-nfas-step-by-step-f92ef378581b """ for i in range(0, len(tokens)): currentToken = tokens[i] if currentToken.get_type() == "SYMBOL" and currentToken.get_value( ) == "&": #Regla #1: #0 -> {1: "&"} trans1 = Transition(start=self.stateCounter, transition=currentToken.get_value(), end=self.stateCounter + 1) self.stateCounter += 1 #1 -> {} y es final. trans2 = Transition(start=self.stateCounter, transition=None, end=None) self.stateCounter += 1 #estados, alfabeto, estado inicial, estado final, funcion de transicion au = Automata([], [], trans1.get_start(), trans2.get_start(), []) au.add_state(trans1) au.add_state(trans2) #print(au) #print("DONE &") self.opStack.add(au) elif currentToken.get_type( ) == "SYMBOL" and currentToken.get_value() != "&": #Regla #2: #0 -> {1: "B"} trans1 = Transition(start=self.stateCounter, transition=currentToken.get_value(), end=self.stateCounter + 1) self.stateCounter += 1 #1 -> {} y es final. trans2 = Transition(start=self.stateCounter, transition=None, end=None) self.stateCounter += 1 #estados, alfabeto, estado inicial, estado final, funcion de transicion au = Automata([], [], trans1.get_start(), trans2.get_start(), []) au.add_state(trans1) au.add_state(trans2) #print(au) #print("DONE SYMB") self.opStack.add(au) #sea una operacion elif currentToken.get_type() != "SYMBOL": #regla #3: OR if currentToken.get_type() == BuilderEnum.OR.value: #sacamos del stack nfa2 = self.opStack.pop() nfa1 = self.opStack.pop() #armado de nfa base. #TRANSICIONES transitionInitial1 = Transition( start=self.stateCounter, transition="&", end=nfa1.get_initial_state()) transitionInitial2 = Transition( start=self.stateCounter, transition="&", end=nfa2.get_initial_state()) self.stateCounter += 1 transitionFinal1 = Transition(start=nfa1.get_final_state(), transition="&", end=self.stateCounter) transitionFinal2 = Transition(start=nfa2.get_final_state(), transition="&", end=self.stateCounter) self.stateCounter += 1 #Sacamos todas las transiciones del elem1 y elem2 arr2 = nfa2.arr_states() #array arr1 = nfa1.arr_states() #array #unificamos los nfa unifiedArray = arr2 + arr1 newTrans = [ transitionInitial1, transitionInitial2, transitionFinal1, transitionFinal2 ] finalTrans = unifiedArray + newTrans or_nfa = Automata([], [], transitionInitial1.get_start(), transitionFinal1.get_end(), []) # me devuelve un array de States. for transition in finalTrans: if (transition.get_transition() != None): or_nfa.add_state(transition) #print(or_nfa) #print("DONE OR, to: \n", nfa2, "\n", nfa1 ) self.opStack.add(or_nfa) #REGLA KLEENE if currentToken.get_type() == BuilderEnum.KLEENE.value: nfa = self.opStack.pop() #encontramos estados finales e iniciales: final = nfa.get_final_state() initial = nfa.get_initial_state() #transicion de final a inicial del nfa preexistente finalMod = Transition(start=final, transition="&", end=initial) #estado inicial de nfa preexistente a nuevo estado de trans initialState = Transition(self.stateCounter, "&", initial) self.stateCounter += 1 finalState = Transition(self.stateCounter, None, None) initialEnd = Transition(initialState.get_start(), "&", finalState.get_start()) #transicion de nfa final a final de nuevo nfa finalTofinal = Transition(start=final, transition="&", end=finalState.get_start()) self.stateCounter += 1 kleene_nfa = Automata([], [], initialState.get_start(), finalState.get_start(), []) arr1 = nfa.arr_states() unifiedArray = arr1 newTrans = [ initialState, initialEnd, finalState, finalTofinal, finalMod ] finalTrans = unifiedArray + newTrans for transition in finalTrans: if (transition.get_transition() != None): kleene_nfa.add_state(transition) #print("DONE KLEENE to \n", nfa) self.opStack.add(kleene_nfa) if currentToken.get_type() == BuilderEnum.PLUS.value: nfa = self.opStack.pop() #encontramos estados finales e iniciales: final = nfa.get_final_state() initial = nfa.get_initial_state() target_symbol = None for fn in nfa.arr_states(): if initial == fn.get_start(): target_symbol = fn.get_transition() break midState = Transition(self.stateCounter, transition="&", end=initial) self.stateCounter += 1 cycle_state = Transition(self.stateCounter, transition=target_symbol, end=midState.get_start()) self.stateCounter += 1 #transicion de final a inicial del nfa preexistente finalMod = Transition(start=final, transition="&", end=initial) #estado inicial de nfa preexistente a nuevo estado de trans finalState = Transition(self.stateCounter, None, None) self.stateCounter += 1 initialState = Transition(midState.get_start(), "&", finalState.get_start()) #transicion de nfa final a final de nuevo nfa finalTofinal = Transition(start=final, transition="&", end=finalState.get_start()) plus_nfa = Automata([], [], cycle_state.get_start(), finalState.get_start(), []) arr1 = nfa.arr_states() unifiedArray = arr1 newTrans = [ initialState, finalState, finalTofinal, midState, cycle_state, finalMod ] finalTrans = unifiedArray + newTrans for transition in finalTrans: if (transition.get_transition() != None): plus_nfa.add_state(transition) #print("DONE PLUS to: \n", nfa) self.opStack.add(plus_nfa) if currentToken.get_type() == BuilderEnum.CONCAT.value: nfa2 = self.opStack.pop() nfa1 = self.opStack.pop() initial = nfa2.get_initial_state() final = nfa1.get_final_state() #print("INIT", initial) #print("FINAL", final) for state in nfa2.arr_states(): #print("STATE", state) if (state.get_start() == initial): state.set_start(final) for state in nfa1.arr_states(): if (state.get_start() == final): state.set_start(initial) merge_nfa = Automata([], [], nfa1.get_initial_state(), nfa2.get_final_state(), []) opsNfa2 = nfa2.arr_states() opsNfa1 = nfa1.arr_states() merged = opsNfa2 + opsNfa1 for transition in merged: if (transition.get_transition() != None): merge_nfa.add_state(transition) #print(merge_nfa) #print("DONE CONCAT to \n", nfa1, "\n", nfa2 ) self.opStack.add(merge_nfa) #opstack is ready to be exported return self.opStack