def _build_basic_sm(char): sm = StateMachine() sm.add_init_state(0) sm.add_finish_state(1) sm.add_catch_state(1) sm.add_transition(sm.init_state, sm.catch_state, char) return sm
def generate_simple_smc(): sm = StateMachine() sm.add_init_state(0) sm.add_finish_state(1) sm.add_catch_state(1) sm.add_transition(0, 1, 'a') return sm
def build(self): self._reset_dfa() self.dfa = StateMachine() self.dfa.language = self.nfa.language self.dfa.add_init_state(0) dfa_states = dict() unmarked_queue = [] # очередь с помеченными состояниями ДКА marked_queue = [] start_state_list = self.nfa.get_e_closure(self.nfa.init_state) unmarked_queue.append(start_state_list) dfa_states[0] = start_state_list dfa_state_num = 1 while len(unmarked_queue) > 0: start_state_list = unmarked_queue.pop() marked_queue.append(start_state_list) for symbol in self.dfa.language: move_list = self.nfa.get_move_list(start_state_list, symbol) end_state_list = self.nfa.get_e_closure_list(move_list) if end_state_list is not None and end_state_list not in marked_queue: unmarked_queue.append(end_state_list) dfa_states[dfa_state_num] = end_state_list dfa_state_num += 1 # Переход в ДКА start_state = get_dict_value_by_key(dfa_states, start_state_list) end_state = get_dict_value_by_key(dfa_states, end_state_list) if start_state is not None and end_state is not None: self.dfa.add_transition(start_state, end_state, symbol) for state in end_state_list: if state in self.nfa.finish_states: self.dfa.add_finish_state(end_state)
def test_check_tran_is_empty(self): smc = StateMachine() smc.add_init_state(0) smc.add_finish_state(1) with self.assertRaises(BaseException): smc._check_smc()
def test_check_init_is_none(self): smc = StateMachine() smc.add_transition(0, 1, 'a') with self.assertRaises(BaseException): smc._check_smc()
def test_check_states_is_empty(self): smc = StateMachine() with self.assertRaises(BaseException): smc._check_smc()
def test_add_finish_correct(self): smc = StateMachine() smc.add_finish_state(1) self.assertEqual(smc.finish_states, [1]) self.assertEqual(smc.states, [1])
def test_add_finish_not_int(self): smc = StateMachine() with self.assertRaises(TypeError): smc.add_finish_state('a')
def test_add_tran_correct(self): smc = StateMachine() smc.add_transition(0, 1, 'a') self.assertEqual(smc.transitions[0], [0, 1, 'a']) self.assertEqual(smc.states, [0, 1]) self.assertEqual(smc.language, ['a'])
def _build_and_sm(sm1, sm2): sm = StateMachine() sm.add_init_state(sm1.init_state) for transition in sm1.transitions: sm.add_transition(transition[0], transition[1], transition[2]) if sm1.catch_state > 0: sm2.renumber_states(sm1.catch_state - 1) else: sm2.renumber_states() for transition in sm2.transitions: sm.add_transition(transition[0], transition[1], transition[2]) sm.add_finish_state(sm2.catch_state) sm.add_catch_state(sm2.catch_state) return sm
def test_add_tran_end_not_int(self): smc = StateMachine() with self.assertRaises(TypeError): smc.add_transition(0, 'a', 'a')
def test_add_catch_correct(self): smc = StateMachine() smc.add_catch_state(1) self.assertEqual(smc.catch_state, 1)
def test_add_catch_non_empty(self): smc = StateMachine() smc.add_catch_state(1) with self.assertRaises(ValueError): smc.add_catch_state(2)
def test_add_init_correct(self): smc = StateMachine() smc.add_init_state(0) self.assertEqual(smc.init_state, 0)
def _build_zero_or_more_sm(sm1): sm = StateMachine() sm.add_init_state(0) sm1.renumber_states() sm1.add_transition(sm1.catch_state, sm1.init_state, BaseConfig.EPSILON) for transition in sm1.transitions: sm.add_transition(transition[0], transition[1], transition[2]) sm.add_finish_state(sm1.catch_state + 1) sm.add_catch_state(sm1.catch_state + 1) sm.add_transition(sm.init_state, sm1.init_state, BaseConfig.EPSILON) sm.add_transition(sm.init_state, sm.catch_state, BaseConfig.EPSILON) sm.add_transition(sm1.catch_state, sm.catch_state, BaseConfig.EPSILON) sm.states = sorted(sm.states) sm.transitions = sorted(sm.transitions) return sm
def _build_or_sm(sm1, sm2): sm = StateMachine() sm.add_init_state(0) sm1.renumber_states() sm2.renumber_states(from_number=sm1.catch_state) sm.add_transition(sm.init_state, sm1.init_state, BaseConfig.EPSILON) sm.add_transition(sm.init_state, sm2.init_state, BaseConfig.EPSILON) for transition in sm1.transitions: sm.add_transition(transition[0], transition[1], transition[2]) for transition in sm2.transitions: sm.add_transition(transition[0], transition[1], transition[2]) sm.add_finish_state(sm2.catch_state + 1) sm.add_catch_state(sm2.catch_state + 1) sm.add_transition(sm1.catch_state, sm.catch_state, BaseConfig.EPSILON) sm.add_transition(sm2.catch_state, sm.catch_state, BaseConfig.EPSILON) sm.states = sorted(sm.states) return sm
class DfaNfa: def __init__(self, nfa): self.nfa = nfa if not nfa or not isinstance(nfa, StateMachine): raise TypeError('Nfa must be non empty StateMachine class member') self.dfa = None def _reset_dfa(self): self.dfa = None def build(self): self._reset_dfa() self.dfa = StateMachine() self.dfa.language = self.nfa.language self.dfa.add_init_state(0) dfa_states = dict() unmarked_queue = [] # очередь с помеченными состояниями ДКА marked_queue = [] start_state_list = self.nfa.get_e_closure(self.nfa.init_state) unmarked_queue.append(start_state_list) dfa_states[0] = start_state_list dfa_state_num = 1 while len(unmarked_queue) > 0: start_state_list = unmarked_queue.pop() marked_queue.append(start_state_list) for symbol in self.dfa.language: move_list = self.nfa.get_move_list(start_state_list, symbol) end_state_list = self.nfa.get_e_closure_list(move_list) if end_state_list is not None and end_state_list not in marked_queue: unmarked_queue.append(end_state_list) dfa_states[dfa_state_num] = end_state_list dfa_state_num += 1 # Переход в ДКА start_state = get_dict_value_by_key(dfa_states, start_state_list) end_state = get_dict_value_by_key(dfa_states, end_state_list) if start_state is not None and end_state is not None: self.dfa.add_transition(start_state, end_state, symbol) for state in end_state_list: if state in self.nfa.finish_states: self.dfa.add_finish_state(end_state) def minimize(self): if self.dfa is None: raise TypeError('Use build() first') dfa_classes = [] classes_queue = [] # Начальное разбиение finish_states = self.dfa.finish_states without_finish_states = list(set(self.dfa.states) - set(finish_states)) dfa_classes.append(finish_states) dfa_classes.append(without_finish_states) classes_queue.append(finish_states) classes_queue.append(without_finish_states) # Поиск эквивалентных классов состояний while classes_queue: curr_queue_item = classes_queue.pop() for symbol in self.dfa.language: # Список состояний, в которых есть переход в состояния из curr_queue_item # по символу symbol curr_end_list = self.dfa.get_come_list(curr_queue_item, symbol) if curr_end_list is not None: dfa_classes_frozen = copy.deepcopy(dfa_classes) for curr_dfa_class in dfa_classes_frozen: intersection = set(curr_end_list) & set(curr_dfa_class) subtraction = set(curr_dfa_class) - set(curr_end_list) if len(intersection) > 0 and len(subtraction) > 0: index = dfa_classes.index(curr_dfa_class) dfa_classes.pop(index) dfa_classes.append(list(intersection)) dfa_classes.append(list(subtraction)) if curr_dfa_class in classes_queue: index = classes_queue.index(curr_dfa_class) classes_queue.pop(index) classes_queue.append(list(intersection)) classes_queue.append(list(subtraction)) else: if len(intersection) <= len(subtraction): classes_queue.append(list(intersection)) else: classes_queue.append(list(subtraction)) for dfa_class in dfa_classes: if len(dfa_class) > 1: self.dfa.combine_states(dfa_class) def run(self, chain): if self.dfa is None: raise TypeError('Use build() first') self.nfa.draw() self.dfa.draw() self.dfa.debug_print_info() print('Входная строка: ', chain) is_valid = True i = 0 curr_state = self.dfa.init_state while is_valid and i < len(chain): print('Текущий символ: ', chain[i]) next_state = self.dfa.get_move(curr_state, chain[i]) if next_state is not None and len(next_state) == 1: print('Переход: ', curr_state, '---> ', end='') curr_state = next_state.pop() print(curr_state, 'по символу ', chain[i]) else: print('Переход не существует') is_valid = False i += 1 if curr_state in self.dfa.finish_states: print('Достигнуто принимающее состояние') else: print('Принимающее состояние не достигнуто') is_valid = False print('\nРезультат: ', is_valid) return is_valid
def test_add_tran_symbol_not_char(self): smc = StateMachine() with self.assertRaises(TypeError): smc.add_transition(0, 1, 2)