编译原理 NFA -> DFA 确定化 + 最小化

测试NFA状态转换图:

当时测试的时候把把一些数据写死了,写在了一个data.txt文件里了,文件的内容是这样的;

0 1 e
0 7 e
1 2 e
1 4 e
2 3 a
4 5 b
3 6 e
5 6 e
6 7 e
7 8 a
8 9 b
9 10 b
6 1 e

源码:

from tabulate import tabulate

def e_closure(idx,c):
    closure = set()
    q = [idx]
    closure.add(idx)
    while len(q):
        t = q[0]
        for i in node_list[t]:
            if i[1] == c:
                closure.add(i[0])
                q.append(i[0])
        q.pop(0)
    return closure


def n_closure(idx,c):
    closure = set()
    for i in node_list[idx]:
        if i[1] == c:
            closure.add(i[0])
    return closure

# state_num = eval(input('状态数量:'))
# char_num = input('字母表中字母:')
# e_num = eval(input('定义式数量:'))
# st_state = eval(input('开始状态:'))
# ed_state = eval(input('结束状态:'))
state_num = 11
char_num = 'ab'
e_num = 13
st_state = 0
ed_state = 10

existed = []
node_list = [[] for i in range(state_num)]
d_queue =[]

for line in open('data.txt','r'):
    xyw = line.strip('\n')
    pro = xyw.split(' ')
    x = eval(pro[0])
    y = eval(pro[1])
    w = (pro[2])
    node_list[x].append((y,w))
if not st_state:
    for i in range(st_state):
        node_list.pop(0)
for i in  range(len(node_list)):
    print(i,':',node_list[i])

queue = []  # 状态I列表
check_queue = []
t = e_closure(st_state,'e')
queue.append(t)
check_queue.append(t)
while(len(queue)):
    tt = queue[0]
    tmp = []
    tmp.append(tt)
    for c in char_num:
        I = set()
        for i in tt:
            I = I.union(n_closure(i,c))
        for i in I:
            I = I.union(e_closure(i,'e'))
        if I not in check_queue:
            queue.append(I)
            check_queue.append(I)
        tmp.append(I)
    d_queue.append(tmp.copy())
    queue.pop(0)

print('子集法状态表:','\n',tabulate(d_queue,headers=['I','Ia','Ib'],tablefmt='plain'),end = '\n')

equal_list =[]
hash_map = dict()
cnt = 0
for i in d_queue:
    for j in i:
        j = str(j)
        if  j not in hash_map.keys():
            hash_map[j] = cnt
            cnt += 1
for i in d_queue:
    process = []
    for j in i:
        j = str(j)
        process.append(chr(65 + hash_map[j]))
    equal_list.append(process.copy())

print('确定化状态表:','\n',tabulate(equal_list,headers=['I','Ia','Ib'],tablefmt='plain',numalign='right'))

n_state = []
t_state = []

for i in range(len(d_queue)):
    if ed_state in d_queue[i][0]:
        t_state.append(i)
    else:
        n_state.append(i)
print('\n','第一次分组:')
print('不含终态的子集:',n_state)
print('含终态的子集:',t_state,'\n')

vis = [0 for i in range(1000)]
a = [0 for i in range(1000)]
ans = [[] for i in range(1000)]
nums = []
ok = [0 for i in range(1000)]

for i in n_state:
    vis[i] = 1
for i in t_state:
    vis[i] = 2

for i in range(len(equal_list)):
    n = 0
    for j in range(len(equal_list)):
        x = vis[j] * pow(10,len(equal_list[j]) - 1)
        for zz in range(1,len(equal_list[j])):
            aa = ord(equal_list[j][zz]) - ord('A')
            x += vis[aa] * pow(10,len(equal_list[j]) - zz - 1)
        if x == a[j]:
            n += 1
        a[j] = x
        ans[x].append(j)
        if ok[x] == 0:
            nums.append(x)
            ok[x] = 1
    ok = [0 for i in range(1000)]
    if n== state_num:
        break
    lenn = 1
    for j in range(len(nums)):
        for k in range(len(ans[nums[j]])):
            vis[ans[nums[j]][k]] = lenn
        lenn+=1
    ans = [[] for i in range(1000)]
    nums = []

res = []

for i in range(len(equal_list)):
    qwq = []
    qwq.append(chr(65 + i))
    qwq.append(vis[i])
    res.append(qwq.copy())

print(tabulate(res,headers=['状态','集合'],tablefmt='plain',numalign='left'))

给老师看可以加分!!!!

1. 实验内容 每一个正规集都可以由一个状态数最少的DFA所识别,这个DFA是唯一的(不考虑同构的情况)。任意给定的一个DFA,根据以下算法设计一个C程序,将该DFA 简为与之等价的最简DFA。 2. 实验设计分析 2.1 实验设计思路 根据实验指导书和书本上的相关知识,实现算法。 2.2 实验算法 (1)构造具有两个组的状态集合的初始划分I:接受状态组 F 和非接受状态组 Non-F。 (2)对I采用下面所述的过程来构造新的划分I-new. For I 中每个组G do Begin 当且仅当对任意输入符号a,状态s和读入a后转换到I的同一组中; /*最坏情况下,一个状态就可能成为一个组*/ 用所有新形成的小组集代替I-new中的G; end (3)如果I-new=I,令I-final=I,再执行第(4)步,否则令I=I=new,重复步骤(2)。 (4)在划分I-final的每个状态组中选一个状态作为该组的代表。这些代表构成了简后的DFA M'状态。令s是一个代表状态,而且假设:在DFA M中,输入为a时有从s到t转换。令t所在组的代表是r,那么在M’中有一个从s到r的转换,标记为a。令包含s0的状态组的代表是M’的开始状态,并令M’的接受状态是那些属于F的状态所在组的代表。注意,I-final的每个组或者仅含F中的状态,或者不含F中的状态。 (5)如果M’含有死状态(即一个对所有输入符号都有刀自身的转换的非接受状态d),则从M’中去掉它;删除从开始状态不可到达的状态;取消从任何其他状态到死状态的转换。 。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值