def do(SM): """RETURNS: A state machines that matches anything which is not matched by SM. Idea: The paths along SM do not guide to acceptance states, but to normal states. Any drop-out is translated into a transition into the 'accept all state'. NOTE: This function produces a finite state automaton which is not applicable by itself. It would eat ANYTHING from a certain state on. """ result = deepcopy(SM) # Not clone accept_all_state_index = index.get() state = State(AcceptanceF=True) state.add_transition(NumberSet_All(), accept_all_state_index) result.states[accept_all_state_index] = state def is_accept_all_state(sm, StateIndex): state = sm.states[StateIndex] if not state.is_acceptance(): return False tm = state.target_map.get_map() if len(tm) != 1: return False elif tm.iterkeys().next() != StateIndex: return False elif not tm.itervalues().next().is_all(): return False # Target is an 'Accept-All' state. Delete the transition. return True for state_index, state in SM.states.iteritems(): # deepcopy --> use same state indices in SM and result result_state = result.states[state_index] assert state.target_map.is_DFA_compliant(), \ "State machine must be transformed to DFA first: nfa_to_dfa.do()" # -- Every transition to 'Accept-All' state becomes a drop-out. for target_index in (i for i in state.target_map.get_target_state_index_list() if is_accept_all_state(SM, i)): result_state.target_map.delete_transitions_to_target(target_index) # -- Every drop-out becomes a transition to 'Accept-All' state. trigger_set = state.target_map.get_trigger_set_union() inverse_trigger_set = trigger_set.get_complement(Setup.buffer_codec.source_set) if not inverse_trigger_set.is_empty(): result_state.add_transition(inverse_trigger_set, accept_all_state_index) # Every acceptance state becomes a non-acceptance state. # Every non-acceptance state becomes an acceptance state. for state_index, state in SM.states.iteritems(): if state.is_acceptance(): result.states[state_index].set_acceptance(False) elif state_index != SM.init_state_index: result.states[state_index].set_acceptance(True) result.clean_up() return result.clone()
def mount_cloned(self, OtherSM, OperationIndex, OtherStartIndex, OtherEndIndex): """Clone all states in 'OtherSM' which lie on the path from 'OtherStartIndex' to 'OtherEndIndex'. If 'OtherEndIndex' is None, then it ends when there's no further path to go. State indices of the cloned states are generated by pairs of (other_i, OperationIndex). This makes it possible to refer to those states, even before they are generated. """ assert OtherStartIndex is not None work_set = set([OtherStartIndex]) if OtherEndIndex is None: done_set = set() else: done_set = set([OtherEndIndex]) while len(work_set) != 0: other_i = work_set.pop() other_state = OtherSM.states[other_i] state_i = state_machine_index.map_state_combination_to_index( (other_i, OperationIndex)) done_set.add(state_i) state = self.states.get(state_i) if state is None: state = State(AcceptanceF=other_state.is_acceptance()) self.states[state_i] = state for other_ti, other_trigger_set in other_state.target_map.get_map( ).iteritems(): target_i = state_machine_index.map_state_combination_to_index( (other_ti, OperationIndex)) # The state 'target_i' either: # -- exists, because it is in the done_set, or # -- will be created because its correspondance 'other_i' is # added to the work set. state.add_transition(other_trigger_set, target_i) if target_i not in done_set: assert other_i in OtherSM.states work_set.add(other_ti) return
def get_all(): """RETURNS: A state machine that 'eats' absolutely everything, i.e. .--- \Any ---. | | (0)--- \Any --->(( 0 ))<--------' """ result = StateMachine() i = index.get() state = State(AcceptanceF=True) state.add_transition(NumberSet(Interval(-sys.maxint, sys.maxint)), i) result.states[i] = state result.get_init_state().add_transition(NumberSet(Interval(-sys.maxint, sys.maxint)), i) return result
def get_all(): """RETURNS: A state machine that 'eats' absolutely everything, i.e. .--- \Any ---. | | (0)--- \Any --->(( 0 ))<--------' """ result = StateMachine() i = index.get() state = State(AcceptanceF=True) state.add_transition(NumberSet_All(), i) result.states[i] = state result.get_init_state().add_transition(NumberSet_All(), i) return result
def mount_cloned(self, OtherSM, OperationIndex, OtherStartIndex, OtherEndIndex): """Clone all states in 'OtherSM' which lie on the path from 'OtherStartIndex' to 'OtherEndIndex'. If 'OtherEndIndex' is None, then it ends when there's no further path to go. State indices of the cloned states are generated by pairs of (other_i, OperationIndex). This makes it possible to refer to those states, even before they are generated. """ assert OtherStartIndex is not None work_set = set([OtherStartIndex]) if OtherEndIndex is None: done_set = set() else: done_set = set([OtherEndIndex]) while len(work_set) != 0: other_i = work_set.pop() other_state = OtherSM.states[other_i] state_i = state_machine_index.map_state_combination_to_index((other_i, OperationIndex)) done_set.add(state_i) state = self.states.get(state_i) if state is None: state = State(AcceptanceF=other_state.is_acceptance()) self.states[state_i] = state for other_ti, other_trigger_set in other_state.target_map.get_map().iteritems(): target_i = state_machine_index.map_state_combination_to_index((other_ti, OperationIndex)) # The state 'target_i' either: # -- exists, because it is in the done_set, or # -- will be created because its correspondance 'other_i' is # added to the work set. state.add_transition(other_trigger_set, target_i) if target_i not in done_set: assert other_i in OtherSM.states work_set.add(other_ti) return
def do(SM): """RETURNS: A state machines that matches anything which is not matched by SM. Idea: The paths along SM do not guide to acceptance states, but to normal states. Any drop-out is translated into a transition into the 'accept all state'. NOTE: This function produces a finite state automaton which is not applicable by itself. It would eat ANYTHING from a certain state on. """ result = deepcopy(SM) # Not clone accept_all_state_index = index.get() state = State(AcceptanceF=True) state.add_transition(NumberSet(Interval(-sys.maxint, sys.maxint)), accept_all_state_index) result.states[accept_all_state_index] = state def is_accept_all_state(sm, StateIndex): state = sm.states[StateIndex] if not state.is_acceptance(): return False tm = state.target_map.get_map() if len(tm) != 1: return False elif tm.iterkeys().next() != StateIndex: return False elif not tm.itervalues().next().is_all(): return False # Target is an 'Accept-All' state. Delete the transition. return True for state_index, state in SM.states.iteritems(): # deepcopy --> use same state indices in SM and result result_state = result.states[state_index] assert state.target_map.is_DFA_compliant(), \ "State machine must be transformed to DFA first: nfa_to_dfa.do()" # -- Every transition to 'Accept-All' state becomes a drop-out. for target_index in (i for i in state.target_map.get_target_state_index_list() if is_accept_all_state(SM, i)): result_state.target_map.delete_transitions_to_target(target_index) # -- Every drop-out becomes a transition to 'Accept-All' state. trigger_set = state.target_map.get_trigger_set_union() inverse_trigger_set = trigger_set.get_complement(Setup.buffer_codec.source_set) if not inverse_trigger_set.is_empty(): result_state.add_transition(inverse_trigger_set, accept_all_state_index) # Every acceptance state becomes a non-acceptance state. # Every non-acceptance state becomes an acceptance state. for state_index, state in SM.states.iteritems(): if state.is_acceptance(): result.states[state_index].set_acceptance(False) elif state_index != SM.init_state_index: result.states[state_index].set_acceptance(True) result.clean_up() return result.clone()