def test_is_current_state_accepting(self): # setup # create stuff for new config: temp_state = State("Alons_first_state", True) temp_word = Word([1, 123, 44]) temp_bound_variable = dict() # run temp_config = Config(temp_state, temp_word, temp_bound_variable) # test assert temp_config.is_current_state_accepting() is True
def test_y_war_read(self): # setup # create stuff for new config: temp_state = State("Alons_first_state", True) temp_remain_word = Word([1, 123, 44]) temp_bound_variable = dict() # run temp_config = Config(temp_state, temp_remain_word, temp_bound_variable) temp_config.set_y_read() # test assert temp_config.is_y_read is True
def copy(self): """ :return: this function returns a copy of the DVFA """ # Run BFS to get a map of every state in A: new state in copy of A bfs_queue = [self._starting_state] visited_states = dict() visited_states[self.starting_state] = State( name=self.starting_state.name, is_accepting=self.starting_state.is_accepting) for state in bfs_queue: for symbol, neighbor in state.transition_map.items(): if neighbor not in visited_states.keys(): visited_states[neighbor] = State( name=neighbor.name, is_accepting=neighbor.is_accepting) bfs_queue.append(neighbor) visited_states[state].add_transition( symbol=symbol, state=visited_states[neighbor]) return DVFA(starting_state=visited_states[self.starting_state])
def test_has_finished(self): # This test suppose to FAIL! # We are creating a CONFIG with a word that is not empty # and testing if we have finished # setup # create stuff for new config: temp_state = State("Alons_first_state", True) temp_remain_word = Word([1, 123, 44]) temp_bound_variable = dict() # run temp_config = Config(temp_state, temp_remain_word, temp_bound_variable) # test assert temp_config.has_finished() is True
def test_bound_variables_map(self): # setup temp_state = State("Alons_first_state", True) temp_word = Word([1, 123, 44]) temp_bound_variable = dict() # run # dict.key is current letter on a run # dict.value is Variable name temp_bound_variable[123] = "x1" temp_config = Config(temp_state, temp_word, temp_bound_variable) # test assert temp_config.bound_variables_map[123] == "x1"
def _recursive_unwinding(A, current_tuple: tuple, u_states_dict: dict, is_first: bool) -> State: """ The first run of recursive unwinding will init current_tuple and tuple_set, this was done so that each call to _recursive_unwinding will create one state exactly :param A: The target DVFA :param current_tuple: The current tuple of <state, set> where set is a frozenset of the letters used to reach state :param u_states_dict: A dict containing all {tuple:state} state is from the new (unwinded) DVFA :param is_first: Set True for the first call, False for the rest, used to init params :return: State that is the first state of the DVFA """ if is_first: # init some data structures, frozenset can be used as a key in dict, as its immutable starting_tuple = (A.starting_state, frozenset()) current_tuple = starting_tuple # construct the result state # name for ex. "s1 (x1,y)" new_name = "{0} ({1})".format(current_tuple[0].name, ",".join(current_tuple[1])) # so that L(A) will be the same as L(U(A)) is_accepting = current_tuple[0].is_accepting # create the state and put it in the dict, the dict has two purposes: # I) so that we can save newly generated states, this is done to prevent state duplication (and in some cases, # infinite loops) # II) return value to the user new_state = State(name=new_name, is_accepting=is_accepting) u_states_dict.update({current_tuple: new_state}) # the newly minted state transition map transition_map = dict() # iterate on each {symbol,state} transition of this state. for symbol, next_state in current_tuple[0].transition_map.items(): next_symbols = set() if symbol == "y": # optimization # if symbol is wildcard, don't pass on all the var_set. next_symbols = next_symbols.union(current_tuple[1]) next_symbols.add("y") next_symbols = frozenset(next_symbols) elif symbol in A.var_set: # if symbol is known as a variable or a WILDCARD in this DVFA, # then add it to current tuple read variables set, # because its a variable that was read in order to get to this state. next_symbols = next_symbols.union(current_tuple[1]) next_symbols.add(symbol) next_symbols = frozenset(next_symbols) else: # if the symbol is not in this DVFA variable set. next_symbols = frozenset(current_tuple[1]) # if true - it means that the state we need already exists in u_states_dict, we can simply take an existing # state from the unwinded DVFA next_tuple = (next_state, next_symbols) if next_tuple in u_states_dict.keys(): result_state = u_states_dict[(next_state, next_symbols)] transition_map[symbol] = result_state # else - we need to calculate the rest of the transitions else: result_state = DVFA._recursive_unwinding( A=A, current_tuple=next_tuple, u_states_dict=u_states_dict, is_first=False) transition_map[symbol] = result_state # create the state's transition map for sym, state in transition_map.items(): new_state.add_transition(sym, state) return new_state
def new_state(s1: State, s2: State): is_current_state_accepting = s1.is_accepting and s2.is_accepting current_state_name = BooleanOperatorConstruct.new_state_name(s1=s1, s2=s2) return State(name=current_state_name, is_accepting=is_current_state_accepting)