Python 有限自动机是如何在代码中实现的?
如何在Python代码中实现这方面的Python 有限自动机是如何在代码中实现的?,python,finite-automata,automata,dfa,nfa,Python,Finite Automata,Automata,Dfa,Nfa,如何在Python代码中实现这方面的dfa或nfa 在python中有哪些好方法? 它们是否曾用于实际项目中?表示DFA的一种简单方法是将其作为字典字典。为每个州创建一个按字母表字母键控的字典,然后创建一个按州键控的全局字典。例如,以下来自 可以用以下词典表示: dfa = {0:{'0':0, '1':1}, 1:{'0':2, '1':0}, 2:{'0':1, '1':2}} 在指定初始状态和接受值集后,针对从相关字母表中提取的输入字符串“运行”dfa非常简
dfa
或nfa
在python中有哪些好方法?
它们是否曾用于实际项目中?表示DFA的一种简单方法是将其作为字典字典。为每个州创建一个按字母表字母键控的字典,然后创建一个按州键控的全局字典。例如,以下来自 可以用以下词典表示:
dfa = {0:{'0':0, '1':1},
1:{'0':2, '1':0},
2:{'0':1, '1':2}}
在指定初始状态和接受值集后,针对从相关字母表中提取的输入字符串“运行”dfa非常简单:
def accepts(transitions,initial,accepting,s):
state = initial
for c in s:
state = transitions[state][c]
return state in accepting
您从初始状态开始,一个字符一个字符地遍历字符串,每一步只需查找下一个状态。当您完成对字符串的单步处理后,只需检查最终状态是否在接受状态集中
比如说
>>> accepts(dfa,0,{0},'1011101')
True
>>> accepts(dfa,0,{0},'10111011')
False
对于NFA,您可以在转换字典中存储可能的状态集而不是单个状态,并使用
随机
模块从可能的状态集中选择下一个状态。这里我为NFA提供了一个递归解决方案。考虑下面的NFA:
可以使用列表列表表示转换,如下所示:
transition = [[[0,1],[0]], [[4],[2]], [[4],[3]], [[4],[4]],[[4],[4]]]
注意:状态4是一种假设状态。一旦你进入那种状态,你就不能再前进了。当您无法从当前状态读取输入时,它很有用。您直接转到状态4,并说当前进度不接受输入(通过返回检查其他可能性)。e、 g,如果您处于q1
,且当前输入符号为'a'
,则转到状态4并停止进一步计算
以下是Python代码:
#nfa simulation for (a|b)*abb
#state 4 is a trap state
import sys
def main():
transition = [[[0,1],[0]], [[4],[2]], [[4],[3]], [[4],[4]]]
input = raw_input("enter the string: ")
input = list(input) #copy the input in list because python strings are immutable and thus can't be changed directly
for index in range(len(input)): #parse the string of a,b in 0,1 for simplicity
if input[index]=='a':
input[index]='0'
else:
input[index]='1'
final = "3" #set of final states = {3}
start = 0
i=0 #counter to remember the number of symbols read
trans(transition, input, final, start, i)
print "rejected"
def trans(transition, input, final, state, i):
for j in range (len(input)):
for each in transition[state][int(input[j])]: #check for each possibility
if each < 4: #move further only if you are at non-hypothetical state
state = each
if j == len(input)-1 and (str(state) in final): #last symbol is read and current state lies in the set of final states
print "accepted"
sys.exit()
trans(transition, input[i+1:], final, state, i) #input string for next transition is input[i+1:]
i = i+1 #increment the counter
main()
如果使用递归,则不需要范围(len(input))上的for循环。你把代码复杂化了。这是一个简化的版本
import sys
def main():
transition = [[[0,1],[0]], [[4],[2]], [[4],[3]], [[4],[4]]]
input = raw_input("enter the string: ")
input = list(input) #copy the input in list because python strings are immutable and thus can't be changed directly
for index in range(len(input)): #parse the string of a,b in 0,1 for simplicity
if input[index]=='a':
input[index]='0'
else:
input[index]='1'
final = "3" #set of final states = {3}
start = 0
trans(transition, input, final, start)
print "rejected"
def trans(transition, input, final, state):
for each in transition[state][int(input[0])]: #check for each possibility
if each < 4: #move further only if you are at non-hypothetical state
state = each
if len(input)==1:
if (str(state) in final): #last symbol is read and current state lies in the set of final states
print "accepted"
sys.exit()
else:
continue
trans(transition, input[1:], final, state) #input string for next transition is input[i+1:]
main()
导入系统
def main():
转换=[[0,1],[0]],[[4],[2]],[[4],[3]],[[4],[4]]
输入=原始输入(“输入字符串:”)
input=list(input)#复制列表中的输入,因为python字符串是不可变的,因此不能直接更改
对于范围内的索引(len(input)):#为了简单起见,在0,1中解析a,b的字符串
如果输入[索引]=“a”:
输入[索引]=“0”
其他:
输入[索引]=“1”
final=“3”#最终状态集={3}
开始=0
传输(转换、输入、最终、启动)
打印“已拒绝”
def传输(转换、输入、最终、状态):
对于每个处于过渡状态的[state][int(输入[0])]:#检查每个可能性
如果每个<4:#仅当您处于非假设状态时才进一步移动
状态=每个
如果len(输入)==1:
if(str(state)in final):#读取最后一个符号,当前状态位于最终状态集中
打印“已接受”
sys.exit()
其他:
持续
trans(转换,输入[1:],最终,状态)#下一个转换的输入字符串为输入[i+1:]
main()
如果您正在寻找更面向对象的dfa实现,这里是我的dfa实现版本。然而,约翰·科尔曼的回答给了我一点启发
class Node:
def __init__(self, val):
self.val = val
self.links = []
def add_link(self, link):
self.links.append(link)
def __str__(self):
node = "(%s):\n" % self.val
for link in self.links:
node += "\t" + link + "\n"
return node
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
def equals(self, node):
ok = (self.val == node.val)
if len(self.links) == len(node.links):
for i in range(len(self.links)):
ok = ok and (self.links[i] == node.links[i])
return ok
else:
return False
class Link:
def __init__(self, from_node, etiquette, to_node):
self.from_node = from_node
self.etiquette = etiquette
self.to_node = to_node
def __str__(self):
return "(%s --%s--> %s)" % (self.from_node.val, self.etiquette, self.to_node.val)
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
def equals(self, link):
return (self.from_node == link.from_node) and (self.etiquette == link.etiquette) and (self.to_node == link.to_node)
class Automata:
def __init__(self, initial_node, nodes, terminal_node):
self.initial_node = initial_node
self.nodes = nodes
self.terminal_node = terminal_node
def get_next_node(self, current_node, etiquette):
for link in current_node.links:
if link.etiquette == etiquette:
return link.to_node
return None
def accepts(self, string):
node = self.initial_node
for character in string:
node = self.get_next_node(node, character)
return self.terminal_node.equals(node)
def __str__(self):
automata = "Initial node: %s\nTerminal node: %s\n" % (self.initial_node.val, self.terminal_node.val)
for node in self.nodes:
automata += node
return automata
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
if __name__ == '__main__':
pass
s0 = Node("s0")
s1 = Node("s1")
s2 = Node("s2")
s0_0_s0 = Link(s0, '0', s0)
s0_1_s1 = Link(s0, '1', s1)
s1_0_s2 = Link(s1, '0', s2)
s1_1_s0 = Link(s1, '1', s0)
s2_0_s1 = Link(s2, '0', s1)
s2_1_s2 = Link(s2, '1', s2)
s0.add_link(s0_0_s0)
s0.add_link(s0_1_s1)
s1.add_link(s1_0_s2)
s1.add_link(s1_1_s0)
s2.add_link(s2_0_s1)
s2.add_link(s2_1_s2)
a = Automata(s0, [s0, s1, s2], s0)
print(a)
print(a.accepts('1011101')) #True
print(a.accepts('10111011')) #False
我已经实现了适用于任何dfa的dfa。但这不是在面向对象模式中
states=list(map(int,input("Enter States : ").split(" ")))
symbols=list(input("Enter Symbols : ").split(" "))
initial_state=int(input("Enter initial state : "))
final_states=list(map(int,input("Enter final states : ").split(" ")))
transitions=[]
inlists=[]
for i in range(len(symbols)):
print("Enter transitions for symbol "+symbols[i]+" from all states :")
for j in range(len(states)):
inlists.append(int(input()))
transitions.append(inlists)
inlists=[]
cur_state=initial_state
while(1):
cur_state=initial_state
string=input("Enter string : ")
if string=='#':
break
for symbol in string:
print("["+str(cur_state)+"]"+"-"+symbol+"->",end="")
cur_state=transitions[symbols.index(symbol)][cur_state]
if cur_state in final_states:
print("["+str(cur_state)+"]")
print("String is accepted.")
else:
print("["+str(cur_state)+"]")
print("String is not accepted.")
接受字符串101*和001*对@John Coleman的修改 #仅接受101+00101001的Dfa
dfa101 = {0:{'1':1},
1:{'0':2},
2:{'1':3},
3:{'0':3, '1':3}}
#Dfa for accepting only 001+00101001
dfa001={0:{'0':1},
1:{'0':2},
2:{'1':3},
3:{'0':3, '1':3}}
def accepts(transitions,initial,accepting,s):
state = initial
try:
for c in s:
state = transitions[state][c]
if(state in accepting):
return 'Accepted'
else:
return 'Rejected'
except:
return 'Rejected'
print('Dfa of 101+ ',accepts(dfa101,0,{3},'10101111000')) #Accepted
print('Dfa of 001+ ',accepts(dfa001,0,{3},'00101010101')) #Accepted
这个问题非常广泛。除非你能把它缩小到一个具体的、客观的、可回答的问题,否则它很可能会被关闭。无论如何是的,它们用于实际项目中。“状态机”是一种常见的实现技术。python中有一种可能的方法:真正的正则表达式可以与DFA匹配;事实上,任何正则语言都可以表示为正则表达式或DFA。谢谢,伙计。这是一个很好的回答。
dfa101 = {0:{'1':1},
1:{'0':2},
2:{'1':3},
3:{'0':3, '1':3}}
#Dfa for accepting only 001+00101001
dfa001={0:{'0':1},
1:{'0':2},
2:{'1':3},
3:{'0':3, '1':3}}
def accepts(transitions,initial,accepting,s):
state = initial
try:
for c in s:
state = transitions[state][c]
if(state in accepting):
return 'Accepted'
else:
return 'Rejected'
except:
return 'Rejected'
print('Dfa of 101+ ',accepts(dfa101,0,{3},'10101111000')) #Accepted
print('Dfa of 001+ ',accepts(dfa001,0,{3},'00101010101')) #Accepted