编译原理实验NFA确定化为DFA.docx
- 文档编号:3871108
- 上传时间:2022-11-26
- 格式:DOCX
- 页数:8
- 大小:63.88KB
编译原理实验NFA确定化为DFA.docx
《编译原理实验NFA确定化为DFA.docx》由会员分享,可在线阅读,更多相关《编译原理实验NFA确定化为DFA.docx(8页珍藏版)》请在冰豆网上搜索。
编译原理实验NFA确定化为DFA
2021.11.02
不确定有穷状态自动机确实定化
一、实验名称
不确定有穷状态自动机确实定化
二、实验目的
输入:
非确定有穷状态自动机NFA
输出:
确定化的有穷状态自动机DFA
三、实验原理
1、NFA定义
一个不确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中
a.K是一个有穷集,它的每个元素称为一个状态;
b.E是一个有穷字母表,它的每个元素称为一个输入符号;
c.f是一个从K×E*到K的子集的映像,即:
K*E*->2k,其中2k表示K的幂集;
d.S包含于K,是一个非空初态集;
e.Z包含于K,是一个终态集。
2、DFA的定义
一个确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中
a.K是一个有穷集,它的每个元素称为一个状态;
b.E是一个有穷字母表,它的每个元素称为一个输入符号;
c.f是转换函数,是K×E->K上的映像,即,如f(ki,a)=kj(ki∈K,kj∈K)就意味着,当前状态为ki,输入字符为a时,将转换到下一状态kj,我们把kj称作ki的一个后继状态;
d.S∈K,是唯一的一个初态;
e.Z包含于K,是一个终态集,终态也称可承受状态或完毕状态。
3、closure函数
状态集合I的ε—闭包,表示为ε—closure(I),定义为一状态集,是状态集I中的任何状态S经任意条ε弧而能到达的状态的集合。
4、move函数
状态集合I的a弧转换,表示为move(I,a),定义为状态集合J,其中J是所有那些从I中的某一状态经过一条a弧而到达的状态的全体。
四、实验思路
本次实验采用python完成。
1、输入
根据课本NFA的定义,输入五元组,依次输入状态集、输入符号、初态集、终态集以及映像,将这些分别存入五个列表中。
其中关于映像的输入格式:
先输入状态一,再输入输入符号,最后输入状态二,一次输入一条弧。
2、closure算法
定义closure函数形式为closure(a,f),其中,a为要做closure闭包的状态集合,f为NFA的映像的集合。
具体思想为:
a.设立一个最终返回结果的列表b,初值与列表a相等。
设立一个空列表s,用于存放每次closure闭包新参加的状态。
b.执行while循环,此循环判断条件为1,即会一直执行下去,直到遇到closure闭包没有新增状态的时候执行完毕。
c.对a中的每一个状态求closure闭包,即判断f中状态一等于a中状态的弧,再判断f中该状态的弧是否为ε〔具体代码中用’$’代替〕,假设是,那么将该弧的状态二参加s中。
d.判断s是否为空,假设为空那么说明此次循环没有新增状态,即说明closure闭包在上一次循环时已执行完毕,输出上次循环的结果b。
假设s不为空,说明本次循环仍然有新增状态,那么将新增状态参加b中,并且将新增的状态集合赋值给a,以新增的状态集继续做循环判断,直到某次循环s为空完毕。
3、move算法
move算法的核心思想与closure算法一致,其函数形式为move(a,e,f),其中e为move算法move(I,a)的a。
move算法只需要求从状态集合中某一状态经过一条a弧而到达的状态全体,所以不需要进展while循环执行屡次,只需执行closure算法中c步骤一次即可。
4、构造子集
建立两个列表C1、C2,其中C1用于存放最终的状态集,C2作为标记使用,对应C1中的子集,假设C1中的子集也进展了closure闭包那么C2中相应元素标记为1,否那么为0。
具体思想为:
a.首先对初态集进展closure闭包,存于C1中,C2的第一个元素赋值为0。
b.标记C2第一个元素为1,对C1中第一个集合先做move算法再做closure算法,假设其中一个算法得出空集合那么直接返回空列表,否那么判断C1中是否有该状态集,假设无那么参加C1中,C2中相应元素赋值为0,表示未标记。
c.重复执行b步骤,直到C2中所有元素为1,表示标记完毕,执行完成,所得到C1为最终状态子集。
5、输出
采用矩阵形式输出,C1中每个状态集合的下标为最终合并后的状态。
五、实验小结
本次实验主要遇到了以下问题:
1、输入存储问题
假设根据课本形式应输入M=(K,E,f,S,Z),再对f进展展开,虽然用算法实现这一形式不难,但是对于后续的操作不太方便,所以最终选择了依次输出五元组,分别存于五个列表中。
2、closure算法问题
最初想用递归的思想实现closure算法,即每次进展一步closure闭包,返回结果为新得到的状态集的closure闭包,但是对于递归完毕的判断条件以及参数的传递不太明确,所以最终没有选择递归,而是选择了死循环里面加上退出循环条件的形式完成。
3、输出问题
输出的形式最终没有实现DFA的状态图而是使用矩阵的形式输出,问题在于对于以状态集合为结点构造状态图这样的图形形式方面的知识不了解,最终以矩阵形式输出。
通过本次实验,对于NFA转换为DFA的过程有了深刻的认识,对于closure算法和move算法的思想非常清楚。
六、附件
1、源代码
K=[]#状态
E=[]#符号
f=[]#弧
S=[]#初态
Z=[]#终态
#输入
print('E21414020国柱')
a=input('输入状态(以空格区分,以换行完毕):
')
K=a.split('')
a=input('输入输入符号(以空格区分,以换行完毕):
')
E=a.split('')
a=input('输入初态(以空格区分,以换行完毕):
')
S=a.split('')
a=input('输入终态(以空格区分,以换行完毕):
')
Z=a.split('')
print('输入弧的条数:
')
n=int(input())
print('输入弧(分别输入状态1,输入符号,状态2,以空格区分换行完毕,ε表示为$)')
foriinrange(n):
f.append([])
a=input()
f[len(f)-1]=a.split('')
#closure算法
defclosure(a,f):
#a为列表
b=a
while1:
s=[]
foriina:
forjinrange(len(f)):
ifi==f[j][0]andf[j][1]=='$':
s.append(f[j][2])
iflen(s)==0:
break
else:
foriins:
b.append(i)
a=s
returnsorted(b)
#move算法
defmove(a,e,f):
#a为列表e为一个符号
s=[]
foriina:
forjinrange(len(f)):
ifi==f[j][0]andf[j][1]==e:
s.append(f[j][2])
returnsorted(s)
#算出最终子集
C1=[]#C1为最终子集
C2=[]
C1.append(closure(S,f))
C2.append(0)
whileC2.pop(len(C2)-1)==0:
C2.append(0)
foriinrange(len(C1)):
ifC2[i]==0:
C2[i]=1
forjinE:
A=move(C1[i],j,f)
ifA==[]:
break
B=closure(A,f)
ifB==[]:
break
k=0
forminC1:
ifB==m:
k=k+1
ifk==0:
C1.append(B)
C2.append(0)
print('输出NFA构造的子集:
')
print(C1)
print('输出DFA:
')
print('S',end='')
forxinE:
print(x,end='')
print('\n')
#输出DFA
foriinrange(len(C1)):
print(i,end='')
forjinE:
a1=move(C1[i],j,f)
ifa1==[]:
print(a1,end='')
continue
a2=closure(a1,f)
ifa2==[]:
print(a2,end='')
continue
forkinrange(len(C1)):
ifC1[k]==a2:
print(k,end='')
break
y=0#判断子集中是否有终态
forminZ:
ifminC1[i]:
y=y+1
ify==0:
print(0)
else:
(1)
print('\n')
2、运行结果截图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 实验 NFA 确定 化为 DFA