Skip to content

Instantly share code, notes, and snippets.

@dvdblk
Last active January 16, 2017 14:37
Show Gist options
  • Save dvdblk/2d9648b5b39be6c3b0b242c96f66c941 to your computer and use it in GitHub Desktop.
Save dvdblk/2d9648b5b39be6c3b0b242c96f66c941 to your computer and use it in GitHub Desktop.
Creates a union from two DFA's
3
3
1
2
1 2
2 3 3
2 2 2
3 3 3
3
3
1
1
2
3 2 3
2 2 2
3 3 3
class State:
def __init__(self, identifier):
self.identifier = str(identifier)
self.transition_funcs = {}
def __str__(self):
return self.identifier
def add_transition(self, withChar, to):
self.transition_funcs[withChar] = to
class DFA:
def __init__(self, alphabet_count):
self.states = []
self.alphabet = list(map(chr, range(97, 97+alphabet_count)))
self.initial_state = None
self.accepting_states = []
def add_state(self, state, initial = False, accepting = False):
self.states.append(state)
if initial:
self.initial_state = state
if accepting:
self.accepting_states.append(state)
def output_DFA(self):
print(len(self.states))
print(len(self.alphabet))
print(self.initial_state.identifier)
print(len(self.accepting_states))
print(" ".join(map(str, self.accepting_states)))
for i in range(len(self.states)):
self.print_state(i)
def print_state(self, nr):
result = ""
for letter in self.alphabet:
result = result + self.states[nr].transition_funcs[letter] + " "
print(result)
if __name__ == "__main__":
dfa_array = []
#read file and create DFA's from input file
with open("zadani02.aut", "r") as input_file:
def rl(no_strip = False):
read = input_file.readline
if no_strip:
return read()
return read().rstrip('\n')
for _ in range(2):
number_of_states = int(rl())
alphabet_count = int(rl())
initial_state = int(rl())
accepting_states_count = int(rl())
accepting_states = list(map(int, rl().split()))
# only 1 accepting state DFA fix...
accepting_states_dict = dict(map(lambda x: (x+1,True) if x+1 in accepting_states else (x+1,False), range(0,number_of_states)))
dfa = DFA(alphabet_count)
for i in range(1,number_of_states+1):
row = rl().split()
state = State(i)
for j in range(alphabet_count):
state.add_transition(dfa.alphabet[j], row[j])
dfa.add_state(state, i == initial_state, accepting_states_dict[i])
dfa_array.append(dfa)
#dfa.output_DFA()
line = rl(True)
if not line: break
# compute their union...
unified_dfa = DFA(len(dfa_array[0].alphabet))
current_state = 1
unified_temp_states_queue = [(dfa_array[0].initial_state.identifier+"-"+dfa_array[1].initial_state.identifier,current_state)]
unified_states = {}
while unified_temp_states_queue:
top_item = unified_temp_states_queue.pop(0)
if top_item[0] not in unified_states:
state = State(top_item[1])
current_state = top_item[1]
# get the new state from 2 input DFA's
states_to_be_unified = top_item[0].split("-")
first = dfa_array[0].states[int(states_to_be_unified[0])-1]
second = dfa_array[1].states[int(states_to_be_unified[1])-1]
for letter in dfa_array[0].alphabet:
first_to = first.transition_funcs[letter]
second_to = second.transition_funcs[letter]
result = first_to +"-"+ second_to
if result not in [itm[0] for itm in unified_temp_states_queue]:
current_state += 1
unified_temp_states_queue.append((result, current_state))
state.add_transition(letter, result)
unified_states[top_item[0]] = top_item[1]
is_initial = (dfa_array[0].initial_state == first) or (dfa_array[1].initial_state == second)
is_accepting = (first in dfa_array[0].accepting_states) or (second in dfa_array[1].accepting_states)
unified_dfa.add_state(state, is_initial, is_accepting)
# and rename states
for state in unified_dfa.states:
for letter in state.transition_funcs:
state.transition_funcs[letter] = str(unified_states[state.transition_funcs[letter]])
unified_dfa.output_DFA()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment