def from_range(cls, alphabet: list, n_states: int, n_start_states: int, n_final_states: int): # Create a new empty list to hold generated states states = [] # Generate n states and label them sequantially, addimg them to the states list for i in range(0, n_states): states.append(State.from_range("S" + str(i), alphabet, n_states)) # Create a new empty DFA new_dfa = DFA() # Assign the alphabet to the DFA new_dfa.alphabet = alphabet # Create a new dictionary where the state name is the key and the state object is the # value, assign it to the DFA new_dfa.states = { k: v for k, v in [(state.name, state) for state in states] } # Assign n random start states, record their names in a set member variable new_dfa.assign_n_random_start_state_names(n_start_states) # Run bfs to determine which states are reachable and which are unreachable, # return the result bfs_output = new_dfa.bfs() # Assign which states are reachable and unreachable based on the output of bfs, # record their names in set member variables new_dfa.assign_reachable_unreachable_state_names(bfs_output) # After BFS, remove states that are unreachable from the states dictionary data structure new_dfa.remove_unreachable_states() # Assign n random final states, record their names in a set member variable new_dfa.assign_n_random_final_state_names(n_final_states) # Create transition table with only reachable states new_dfa.table_df = new_dfa.create_transition_table() # Check if the resultant dfa is valid (i.e. at least one final state is reachable from # any of the start states) invalid = new_dfa.check_invalid() # If for whatever reason it is invalid (shouldn't be possible), regenerate a new random # DFA if invalid: return DFAFactory.from_range(alphabet, n_states, n_start_states, n_final_states) else: return new_dfa
def from_parameters(cls, alphabet: list, states: list): # Create a new empty DFA new_dfa = DFA() # Assign the alphabet to the DFA new_dfa.alphabet = alphabet # Create a new dictionary where the state name is the key and the state object is the # value, assign it to the DFA new_dfa.states = { k: v for k, v in [(state.name, state) for state in states] } # Iterate over the states assigned to the dfa, find all states which are start states # and add them to the start_state_names set member variable new_dfa.start_state_names = new_dfa.find_start_state_names() # Run bfs to determine which states are reachable and which are unreachable, # return the result bfs_output = new_dfa.bfs() # Assign which states are reachable and unreachable based on the output of bfs, # record their names in set member variables new_dfa.assign_reachable_unreachable_state_names(bfs_output) # After BFS, remove states that are unreachable from the states dictionary data structure new_dfa.remove_unreachable_states() # Iterate over the remaining states assigned to the dfa, find all states which are final # states and add them to the final_state_names set member variable new_dfa.final_state_names = new_dfa.find_final_state_names() # Create transition table with only reachable states new_dfa.table_df = new_dfa.create_transition_table() # Check if the resultant dfa is valid (i.e. at least one final state is reachable from # any of the start states) invalid = new_dfa.check_invalid() # If the DFA is invalid, throw an error if invalid: raise ValueError("Proposed DFA is not valid") else: return new_dfa