编译原理:NFA转DFA含数据可视化

作者: Zeker62

第三方库graphviz的安装方法:
https://blog.csdn.net/lizzy05/article/details/88529483

建议直接使用Linux环境,不需要使用环境变量

代码如下

def printlist(l):
    for i in range(len(l)):
        print(l[i], end=" ")
print("----------------------------输入NFA样例-----------------------------")
ab = eval(input("请输入变量的个数"))
print("请输入变量名称(用_(下划线)表示空)")
aabb = []
for i in range(1, ab + 1):
    aabb_eval = input("第" + str(i) + "个变量的名称是: ")
    aabb.append(aabb_eval)
printlist(aabb)
 [a,b,c]
 输入变量的个数之后将为这个创造字典
l = [ for i in range(ab)]   创建和变量相同个数的字典
n = 0
while n < ab:
    print("开始构造变量" + aabb[n] + "的两节点状态")
    while True:
        status = input("请输入起始状态")
        end_status = input("请输入终止状态")
        if status != '' or end_status != '':
            l[n].setdefault(status, end_status)
        else:
            print(aabb[n] + "变量的构造输入已经结束")
            break
    n = n + 1
for i in range(len(l)):
    if aabb[i] == '_':
        print("空变量的节点起始关系为:" + str(l[i]))
    else:
        print("变量" + aabb[i] + "的节点起始关系为:" + str(l[i]))
print(l)
 空变量的节点起始关系为:
 变量a的节点起始关系为:
 变量b的节点起始关系为:
key_list = []
for i in range(len(l)):
    for k in l[i].keys():
        if k not in key_list:
            key_list.append(k)
print("状态节点有:", end=" ")

printlist(key_list)
print()
start = input('请输入起始节点')
end_list = []
a = ""
while a != "":
    a = input("请输入终止节点(集),以表示结束")
    end_list.append(a)
end_list.pop()
print("起始节点是:" + start)
print("终止节点(集)是:", end="")
printlist(end_list)
 变量a的节点起始关系为:
 变量b的节点起始关系为:
 空变量的节点起始关系为:
 状态节点有: 1 3 5 2 4
 请输入起始节点1
 请输入终止节点(集),以表示结束3
 请输入终止节点(集),以表示结束
 起始节点是:1
 终止节点(集)是:3
print()
print("\n-------------------将状态节点保存到文件中-----------------")
with open('nfa.txt', 'w') as f:
    f.write(start + "\n")
    for i in range(len(end_list)):
        f.write(end_list[i] + " ")
    f.write("\n")
    for j in range(len(l)):   j表示第几个字典
        for k in range(len(l[j])):   k表示第几个键值对
            for m in l[j].keys():   m表示第几个键
                f.write(m + " " + aabb[j] + " " + l[j][m] + "\n")
print("\n------------------读取文件中的信息----------------------")
with open('nfa.txt', 'r') as r:
    nfa = []
    for line in r.readlines():   将文件数据内容保存到nfa列表当中
        line_rstrip = line.rstrip('\n')
        nfa.append(line_rstrip)
     print(nfa)
begin_start = nfa[0].split()   起始节点
print(begin_start)
end_end_list = nfa[1].split()   终止节点
print(end_end_list)
 如果是按照前面的方法创建的,那么以上代码没有必要,直接用start和end_list即可
trans_nfa = nfa[2:]
print(trans_nfa)
for i in range(len(trans_nfa)):
    trans_nfa[i] = trans_nfa[i].split()
print(trans_nfa)
 [['1', 'a', '2'], ['3', 'a', '4'], ['1', 'a', '2'], ['3', 'a', '4'], ['1', 'b', '2'], ['3', 'b',
 '4'], ['1', 'b', '2'], ['3', 'b', '4'], ['1', '_', '2']] 所有的状态已经标识好了
state_to_draw = []   状态节点
para_to_draw = []   转换变量
for i in range(len(trans_nfa)):
    state_to_draw.append(trans_nfa[i][0])
    state_to_draw.append(trans_nfa[i][2])
    para_to_draw.append(trans_nfa[i][1])
 print(state_to_draw)
 print(para_to_draw)
state0 = list(set(state_to_draw))   去除节点重复
state0.sort(key=state_to_draw.index)   对节点进行排序
para0 = list(set(para_to_draw))
para0.sort(key=para_to_draw.index)
 print(state0)   ['0', '1', '2', '4', '3', '6', '5', '7', '8', '9', '10']
 print(para0)   ['_', 'a', 'b']
if '_' in para0:
    para0.remove('_')
 去掉空
_closure = dict()   表示空串可以到达的集合
print("\n--------------开始作图-------------------")
from graphviz import Digraph
def draw_nfa():
    g = Digraph('G', filename='nfa.gv', format='png')
    for i in range(len(trans_nfa)):
        g.edge(trans_nfa[i][0], trans_nfa[i][2], label=trans_nfa[i][1])
    for i in range(len(begin_start)):
        g.node(begin_start[i], color='red')
    for i in range(len(end_end_list)):
        g.node(end_end_list[i], shape='doublecircle')
    g.view()
draw_nfa()
print("\n------------nfa作图完毕------------------")
print("\n-----------开始进行NFA转DFA---------------")
 寻找所有空闭包
for i in range(len(state0)):
    res = [state0[i]]   第i个节点
     print(res)
    for j in range(len(trans_nfa)):
        if trans_nfa[j][0] == state0[i] and trans_nfa[j][1] == '_':
             如果目前研究的节点里面存在着空
            res.extend(trans_nfa[j][2])
             这里用
    _closure[state0[i]] = list(set(res))
     到此,一个状态所有的空闭包都会显现出来,接下来只要一查到底即可
 print(_closure)
 {'0': ['1', '0', '7'], '1': ['1', '2', '4'], '2': ['2'], '4': ['4'], '3': ['6', '3'], '6': ['7', '6', '1'], '5': ['5', '6'], '7': ['7'], '8': ['8'], '9': ['9'], '10': ['10']}
 空闭包的递归查询------
def find_closure(state_input):
    state_now = _closure[state_input]   查询输入一个状态下是否有空闭包 ['1', '0', '7']
    state_now_list = []
    for state_now_para in state_now:
        state_now_list = state_now_list + _closure[state_now_para]   递归查询
    state_now_list = list(set(state_now_list))
     尝试输出
    print(state_now_list)   ['0', '7', '1', '2', '4']
    while set(state_now) != set(state_now_list):   多次查询
        state_now = state_now_list
        state_now_list = []
        for state_now_para in state_now:
            state_now_list = state_now_list + _closure[state_now_para]
        state_now_list = list(set(state_now_list))
    return state_now_list
A = find_closure(state0[0])   初始状态的空闭包
print(A)   ['1', '7', '4', '2', '0']
def find_state(l_state):
    res = dict()   创建一个字典,里面的值是状态集合
    for c in para0:   ['_', 'a', 'b']
        res_two = []
        for i in range(len(l_state)):
            for j in range(
                    len(trans_nfa)):   [['0', '_', '1'], ['1', '_', '2'], ['1', '_', '4'], ['2', 'a', '3'], ['3', '_', '6'], ['4', 'b', '5'], ['5', '_', '6'], ['6', '_', '7'], ['7', 'a', '8'], ['8', 'b', '9'], ['9', 'b', '10'], ['6', '_', '1'], ['0', '_', '7']]
                if trans_nfa[j][0] == l_state[i] and trans_nfa[j][1] == c:
                    res_two.append(trans_nfa[j][2])
        result = []
        for k in res_two:
            result = result + find_closure(k)
        res[c] = list(set(result))
    return res
number = 0
length = 1
state_list = []
state_list.append(A)   [['0', '7', '1', '2', '4']]
while number < length:
    A2 = find_state(state_list[number])
    number = number + 1
    for c in para0:
        temp = 1
        for p in range(length):
            if set(A2[c]) == set(state_list[p]):
                temp = 0
        if temp == 1:
            state_list.append(A2[c])
            length = length + 1
print(state_list)
 [['0', '2', '4', '1', '7'],
 ['2', '3', '6', '4', '8', '1', '7'],
 ['2', '6', '4', '5', '1', '7'],
 ['9', '2', '6', '4', '5', '1', '7'],
 ['2', '6', '4', '10', '5', '1', '7']]

获取开始节点和结束节点
dfa_begin = []
dfa_end = []
for i in range(len(begin_start)):
     查看是否存在空......变量
    dfa_begin.append(find_closure(begin_start[i]))
for j in range(len(end_end_list)):
    for k in range(len(state_list)):
        if end_end_list[j] in state_list[k]:
            如果nfa的结束节点是在的某一个状态列表里面
            if state_list[k] not in dfa_end:
                dfa_end.append(state_list[k])
print(dfa_begin)
print(dfa_end)
while [] in state_list:
    state_list.remove([])
print('DFA状态表: ', state_list)
print("DFA起始状态: ", dfa_begin)
print("DFA终止状态:", dfa_end)
 DFA状态表为: [['4', '2', '0', '1', '7'], ['4', '2', '1', '7', '8', '3', '6'], ['4', '2', '1', '7', '6', '5'], ['4', '2', '1', '7', '9', '6', '5'], ['4', '2', '1', '7', '10', '6', '5']]
 DFA开始状态: [['4', '2', '0', '1', '7']]
 DFA终止状态: [['4', '2', '1', '7', '10', '6', '5']]
def draw_dfa(state_list, begin, end):
    g = Digraph('G', filename='dfa.gv', format='png')
    begin_aaa = []
    end_aaa = []
    for i in range(len(begin)):
        begin_aaa.append(" ".join(sorted(begin[i])))
    for j in range(len(end)):
        end_aaa.append(" ".join(sorted(end[j])))
    for i in range(len(state_list)):
        dicttttt = find_state(state_list[i])
        for j in para0:
            if state_list[i] != [] and dicttttt[j] != []:
                g.edge(" ".join(sorted(state_list[i])), " ".join(sorted(dicttttt[j])), label=j)
    for k in range(len(begin_aaa)):
        g.node(begin_aaa[k], color='red', shape='circle')
    for i in range(len(state_list)):
        g.node(" ".join(sorted(state_list[i])), color='blue', shape='circle')
    for j in range(len(end_aaa)):
        if end_aaa[j]!=begin_aaa[0]:
            g.node(end_aaa[j], shape='doublecircle')
        else:
            g.node(end_aaa[j], shape='doublecircle',color='red')
    g.view()
draw_dfa(state_list, dfa_begin, dfa_end)
state_dfa_other_name=[ chr(65+i) for i in range(len(state_list))]
['A', 'B', 'C', 'D', 'E']
start_char=state_dfa_other_name[ state_list.index(dfa_begin[0])]
start_char=list(start_char)
print(start_char)
end_char=[]
for i in range(len(dfa_end)):
    s=state_dfa_other_name[state_list.index(dfa_end[i])]
    end_char.append(s)
print(end_char)

效果图:
image image

原文创作:Zeker62

原文链接:https://www.cnblogs.com/Zeker62/p/15350095.html

更多推荐

更多
  • Azure上Linux管理-十、使用 Azure Kubernetes 服务 技术要求,开始使用 AKS,与 Helm 一起工作,使用草稿,管理 Kubernetes,问题,进一步,使用 WSL 和 VS Code,安装依赖,kubectl 安装,使用 Azure CLI 创建集群,AKS 首次部署,创建服务,多
    Apache CN

  • Azure上Linux管理-十一、故障排除和监控您的工作负载 module(load="imuxsock"),技术要求,访问您的系统,Azure 日志分析,性能监控,问题,进一步,不允许远程访问,正在端口上工作,使用 nftables,引导诊断,Linux 登录,配置日志分析服务,安装 Azure
    Apache CN

  • Azure上Linux管理-十二、附录 第一章:探索微软 Azure 云,第二章:Azure 云入门,第三章:Linux 基础管理,第 4 章:管理 Azure,第五章:高级 Linux 管理,第七章:部署虚拟机,第八章:探索连续配置自动化,第 9 章:Azure 中的容器虚
    Apache CN

  • Azure上Linux管理-九、Azure 中的容器虚拟化 cloudconfig,集装箱技术导论,系统生成,Docker,Azure 容器实例,Buildah, Podman, and Skopeo,容器和储存,问题,进一步,容器历史,chroot 环境,OpenVZ,LXC,创建一个带启动的
    Apache CN

  • Azure上Linux管理-七、部署你的虚拟机 ResourceGroup 不存在,创建它:,vnet 不存在,创建 vnet,cloudconfig,Vagrant.config 结束,部署场景,Azure 中的自动部署选项,初始配置,流浪,封隔器,自定义虚拟机和 vhd,问题,进
    Apache CN

  • Azure上Linux管理-八、探索持续配置自动化 了解配置管理,使用 Ansible,使用地球形态,使用 PowerShell DSC,Azure 策略客户端配置,其他解决方案,问题,进一步,技术要求,Ansible 的安装,SSH 配置,裸最小配置,库存文件,Ansible 剧本和模
    Apache CN

  • Azure上Linux管理-五、高级 Linux 管理 技术要求,软件管理,网络,存储,systemd,问题,进一步,RPM 软件管理器,YUM 软件管理,基于 DNF 的软件管理,DPKG 软件管理器,运用 apt 进行软件管理,ZYpp 软件管理,识别网络接口,IP 地址识别,显示路由表
    Apache CN

  • Azure上Linux管理-六、管理 Linux 安全与身份 SELINUX=可以接受以下三个值之一:,permissiveSELinux 打印警告而不是强制执行。,disabled 没有加载 SELinux 策略。,SELINUXTYPE=可以接受以下三个值之一:,targeted 目标进程
    Apache CN

  • Azure上Linux管理-四、管理 Azure 使用 Azure CLI 和 PowerShell 管理 Azure 资源,技术要求,管理存储资源,管理网络资源,管理计算资源,虚拟机资源,问题,进一步,存储帐户,托管磁盘,Azure 文件,Azure Blob,虚拟网络,子网,网络安
    Apache CN

  • Azure上Linux管理-三、Linux 基础管理 Linux Shell,获取帮助,使用文本文件,在文件系统中找到你的方式,流程管理,自由访问控制,问题,执行命令,命令行编辑,与历史一起工作,自动完成,球状,重定向,处理变量,Bash 配置文件,使用手册页,使用信息文档,其他文档,文本
    Apache CN

  • 近期文章

    更多
    文章目录

      推荐作者

      更多