我已经阅读了很多关于NFA和DFA的内容,我想在Python中实现一个。我之所以选择Python,是因为它在模拟算法时非常有用。因此,使用Thompson的构造算法,我使用它们的转换实现了状态,并且还构建了表示正则表达式的不同部分的NFA片段。一个用于符号转换,一个用于连接。除了我被困在连接部分之外,因为我试图“粘合”在一起的状态不匹配,并且它们指向不同的对象。
这应该是它,但对我来说q0
的{{1}}起始节点没有转换到它的结束节点,即N(s)
起始节点。
这是我的代码,为简单起见,所有文件都在一个文件中:
N(t)
输出:
class State(object):
def __init__(self, label, isfinish, trans):
self.label = label
self.trans = trans
self.isfinish = isfinish
self.id = label + str(id(self))
NFA_SIMULATE_RUN = False
class NFA(object):
def __init__(self, tup):
self.Q = tup[0]
self.S = tup[1]
self.start = tup[2]
self.end = tup[3]
self.table = {}
for state in self.Q:
trans_list = {}
if not state.isfinish:
for sym in state.trans.keys():
trans_list[sym] = state.trans[sym]
self.table[state] = trans_list
def move(self, state, sym):
assert(state in self.Q),(state + " is not in state set")
assert(sym in self.S),(sym + " is not in alphabet")
if sym not in self.table.keys():
if '' in self.table.keys():
sym = ''
possible_states = self.table[state][sym]
if NFA_SIMULATE_RUN:
i = random.randint(0, len(possible_states) - 1)
chosen_state = possible_states[i]
return chosen_state
return possible_states
def accepts(self, string):
curstate = self.start
for ch in string:
curstate = self.move(curstate, ch)
if curstate.isfinish:
print(string + " accepted!")
else:
print(string + " rejected!")
class SymbolNFA(NFA):
def __init__(self, sym):
self.end = State('qf', True, {})
self.start = State('q0', False, {
sym: self.end
})
self.Q = [self.start, self.end]
self.S = [sym]
super(SymbolNFA, self).__init__((self.Q, self.S, self.start, self.end))
class ConcatNFA(NFA):
def __init__(self, nfa1, nfa2):
self.end = nfa2.end
nfa1.end = nfa2.start
self.start = nfa1.start
self.Q = [self.start, nfa1.end, self.end]
self.S = list(set(nfa1.S) | set(nfa2.S))
super(ConcatNFA, self).__init__((self.Q, self.S, self.start, self.end))
def main():
nfa1 = SymbolNFA('a')
nfa2 = SymbolNFA('b')
nfa3 = ConcatNFA(nfa1, nfa2)
print("NFA 1:\n" + str(nfa1.table))
print("NFA 2:\n" + str(nfa2.table))
print("NFA 3:\n" + str(nfa3.table))
if __name__ == '__main__':
main()
(对不起对象打印,我还没弄清楚如何协调所有状态。)
正如您所看到的,对于前2个Nfa,符号片段,它们的开始状态通过符号正确转换到结束状态对象。但是当我连接它们时,在第一次转换后指定的状态(在这种情况下为'a')不是中间状态,(第一个nfa的结束,第二个nfa的开始)。它指向一些我无法找到的随机状态对象。 “b”转换后指定的状态是正确的,并正确指向整个nfa的结束状态。
为了更好地理解输出,只需将其解释为FA转换表。
任何帮助都表示赞赏,我会告诉您,这是我最初几次使用此类算法,所以我可能会遗漏一些东西。