def generate_transition(counter, letter, dot): initial_state = State(counter) final_state = State(counter) initial_state.add_transition(letter, final_state) dot.node(initial_state.id, initial_state.name, shape='circle') dot.node(final_state.id, final_state.name, shape='circle') dot.edge(initial_state.id, final_state.id, letter) return {'initial': initial_state, 'final': final_state}
def test_letter_self_loop_returns_False_when_evaluating_if_finite(self): state = State('A') state.add_transition('a', state) is_finite = state.is_finite() self.assertEqual( is_finite, False, 'State with letter self loop does not return False when evaluating if finite' )
def test_epsilon_self_loop_returns_True_when_evaluating_if_finite(self): state = State('A') state.add_transition('_', state) is_finite = state.is_finite() self.assertEqual( is_finite, True, 'State with empty self loop does not return True when evaluating if finite' )
def test_evaluate_non_empty_word_with_no_transitions_in_state_returns_false( self): state = State('A') evaluation = state.evaluate_word('aaa') self.assertEqual( evaluation, False, 'State with no transitions did not return False for a non-empty transitions' )
def test_is_finite_calls_proper_method(self): alphabet = 'abc' initial_state = State('A') initial_state.is_finite = MagicMock(return_value=True) is_pda = False automaton = Automaton(alphabet, initial_state, is_pda) automaton.is_finite() initial_state.is_finite.assert_called()
def test_get_all_words_calls_proper_method(self): alphabet = 'abc' initial_state = State('A') initial_state.get_all_words = MagicMock(return_value=[]) is_pda = False automaton = Automaton(alphabet, initial_state, is_pda) automaton.get_all_words() initial_state.get_all_words.assert_called_with([])
def test_pda_evaluate_word_returns_false_when_there_is_no_next_state(self): state = State('A') state.pda_determine_next_state = MagicMock(return_value=None) evaluation = state.pda_evaluate_word('', []) self.assertEqual( evaluation, False, 'When there is no next state the pda_evaluate_word does not return False' )
def test_evaluate_empty_word(self): state = State('A') # when state is not final evaluation = state.evaluate_word('') self.assertEqual( evaluation, False, 'Non-final state did not return False for an empty word') # when state is final state.is_final = True evaluation = state.evaluate_word('') self.assertEqual(evaluation, True, 'Final state did not return True for an empty word')
def test_pda_evaluate_word_with_empty_word(self): state = State('A') # empty stack and state is final should return true state.is_final = True evaluation = state.pda_evaluate_word('', []) self.assertEqual( evaluation, True, 'PDA word evaluate did not return True when stack is empty, state is final and word is empty' ) # every other case should return false evaluation = state.pda_evaluate_word('', ['a']) self.assertEqual( evaluation, False, 'PDA word evaluate did not return False when stack is not empty, state is final and word is empty' ) state.is_final = False evaluation = state.pda_evaluate_word('', []) self.assertEqual( evaluation, False, 'PDA word evaluate did not return False when stack is empty, state is not final and word is empty' ) evaluation = state.pda_evaluate_word('', ['a']) self.assertEqual( evaluation, False, 'PDA word evaluate did not return False when stack is not empty, state is not final and word is empty' )
def parse_states(line, dot): states = line.split(' ')[1] sts = {} for name in states.split(','): st = State(name) sts[name] = st dot.node(st.id, st.name) return sts
def test_state_with_letter_transition_returns_proper_value(self): state = State('A') transition_state = State('B') transition_state.evaluate_word = MagicMock(return_value=False) state.add_transition('a', transition_state) evaluation = state.evaluate_word('abc') self.assertEqual( evaluation, False, 'State did not return what letter transition state returns')
def test_state_with_epsilon_transition_returns_proper_value(self): state = State('A') transition_state = State('B') transition_state.evaluate_word = MagicMock(return_value=True) state.add_transition('_', transition_state) evaluation = state.evaluate_word('abc') self.assertEqual( evaluation, True, 'State did not return what epsilon transition state returns')
def convert_to_dfa(aut, new=None, iteration=None): if new is None: initial = State('initial') epsilon_closure = [] get_epsilon_closure(aut.initial_state, epsilon_closure) initial.id = str( reduce(lambda x, y: x + y, [int(state.id) for state in epsilon_closure])) new = [(initial, epsilon_closure)] if contains_final_state(epsilon_closure): initial.is_final = True if iteration is None: iteration = 0 if iteration < len(new): sup = {} for letter in aut.alphabet: sup[letter] = get_states_for_letter(new[iteration][1], letter) add_new_states(new, sup) add_transitions(new, sup, iteration) return convert_to_dfa(aut, new, iteration + 1) else: return new
def test_evaluate_word_calls_proper_method(self): # Not PDA alphabet = 'abc' initial_state = State('A') initial_state.evaluate_word = MagicMock(return_value=True) is_pda = False word = 'test' automaton = Automaton(alphabet, initial_state, is_pda) automaton.evaluate_word(word) initial_state.evaluate_word.assert_called_with(word) # PDA is_pda = True initial_state.pda_evaluate_word = MagicMock(return_value=True) automaton = Automaton(alphabet, initial_state, is_pda) automaton.evaluate_word(word) initial_state.pda_evaluate_word.assert_called_with(word, [])
def test_pda_evaluate_word_returns_proper_result_from_next_state(self): state1 = State('A') state2 = State('B') state1.pda_determine_next_state = MagicMock(return_value=state2) state2.pda_evaluate_word = MagicMock(return_value=True) evaluation = state1.pda_evaluate_word('a', []) self.assertEqual(evaluation, True, 'PDA evaluate word does not return expected result')
def test_init(self): alphabet = 'abc' initial_state = State('A') is_pda = False automaton = Automaton(alphabet, initial_state, is_pda) self.assertEqual(automaton.alphabet, alphabet, "Automaton alphabet is not properly set") self.assertEqual(automaton.initial_state, initial_state, "Automaton initial state is not properly set") self.assertEqual(automaton.is_pda, is_pda, "Automaton is_pda is not properly set")
def test_no_loops_returns_true(self): state1 = State('A') state2 = State('B') state3 = State('B') state1.add_transition('_', state2) state1.add_transition('_', state3) is_finite = state1.is_finite() self.assertEqual( is_finite, True, 'State with no following loops does not return True when evaluating if finite' )
def test_init(self): name = 'A' state = State(name) self.assertEqual(state.name, name, 'State constructor does not set the name properly') self.assertEqual( state.is_final, False, 'State constructor did not set is_final properly (should be False)' ) self.assertEqual( state.transitions, {}, 'State constructor did not initialize tansitions as an empty object' )
def add_new_states(new, sup): for s_arr in sup.values(): if len(s_arr) == 0: if not contains_state_with_id(new, 0): new_state = State('0') new_state.id = '0' new.append((new_state, s_arr)) else: epsilon_closure = [] for state in s_arr: get_epsilon_closure(state, epsilon_closure) id = reduce(lambda x, y: x + y, [int(state.id) for state in epsilon_closure]) if not contains_state_with_id(new, id): new_state = State('') new_state.id = str(id) new_state.is_final = contains_final_state(epsilon_closure) new.append((new_state, epsilon_closure))
def generate_kleene(counter, data, dot): initial_state = State(counter) dot.node(initial_state.id, initial_state.name, shape='circle') initial_state.add_transition('_', data['initial']) dot.edge(initial_state.id, data['initial'].id, label='ε') final_state = State(counter) dot.node(final_state.id, final_state.name, shape='circle') data['final'].add_transition('_', final_state) dot.edge(data['final'].id, final_state.id, label='ε') initial_state.add_transition('_', final_state) dot.edge(initial_state.id, final_state.id, label='ε') data['final'].add_transition('_', data['initial']) dot.edge(data['final'].id, data['initial'].id, label='ε') return {'initial': initial_state, 'final': final_state}
def test_state_with_emtpy_and_letter_transitions_checks_letter_transitions_if_empty_transitions_return_false( self): word = 'aa' state = State('A') empty_transitions_state_1 = State('B') empty_transitions_state_1.evaluate_word = MagicMock(return_value=False) empty_transitions_state_2 = State('C') empty_transitions_state_2.evaluate_word = MagicMock(return_value=False) letter_transition = State('D') letter_transition.evaluate_word = MagicMock(return_value=True) state.add_transition('_', empty_transitions_state_1) state.add_transition('_', empty_transitions_state_2) state.add_transition('a', letter_transition) evaluation = state.evaluate_word(word) empty_transitions_state_1.evaluate_word.assert_called() empty_transitions_state_2.evaluate_word.assert_called() letter_transition.evaluate_word.assert_called_with('a') self.assertEqual( evaluation, True, 'State with empty and letter transitions does not return the proper value' )
def test_loop_with_empty_transitions_does_not_create_an_infinite_loop( self): state1 = State('A') state2 = State('B') state3 = State('B') state1.add_transition('_', state2) state2.add_transition('_', state3) state3.add_transition('_', state1) evaluation = state1.evaluate_word('abc') self.assertEqual( evaluation, False, 'Loop with empty transitions does not act as expected')
def test_pda_determine_next_state_priorty(self): root = State('A') child1 = State('B') child2 = State('C') child3 = State('D') child4 = State('E') root.add_transition('a', (child1, '[x,_]')) root.add_transition('a', (child2, '[_,x]')) root.add_transition('_', (child3, '[x,_]')) root.add_transition('_', (child4, '[_,X]')) next_state = root.pda_determine_next_state('a', ['x']) self.assertEqual(next_state, child1) next_state = root.pda_determine_next_state('a', ['y']) self.assertEqual(next_state, child2) next_state = root.pda_determine_next_state('b', ['x']) self.assertEqual(next_state, child3) next_state = root.pda_determine_next_state('b', ['y']) self.assertEqual(next_state, child4)
def test_epsilon_multiple_state_loop_returns_True_when_evaluating_if_finite( self): state1 = State('A') state2 = State('B') state3 = State('C') state1.add_transition('_', state2) state2.add_transition('_', state3) state3.add_transition('_', state1) is_finite = state1.is_finite() self.assertEqual( is_finite, True, 'State with empty multiple state loop does not return True when evaluating if finite' )
def test_get_all_words_walks_all_branches(self): state1 = State('A') state2 = State('B') state3 = State('C') state2.is_final = True state3.is_final = True state1.add_transition('a', state2) state1.add_transition('b', state3) words = [] state1.get_all_words(words) self.assertEqual(len(words), 2, 'Number returned words is not as expected') self.assertIn('a', words, 'Returned words does not contain expected words') self.assertIn('b', words, 'Returned words does not contain expected words')
def test_letter_multiple_state_loop_returns_False_when_evaluating_if_finite( self): state1 = State('A') state2 = State('B') state3 = State('C') state1.add_transition('_', state2) state2.add_transition('a', state3) state3.add_transition('_', state1) is_finite = state1.is_finite() self.assertEqual( is_finite, False, 'State with letter multiple state loop does not return False when evaluating if finite' )