前言:这是我学习编译原理,课程实验的内容,课程早已结束,现整理发表。

一、实验任务

  1. 存储NFA与DFA;
  2. 编程实现子集构造法将NFA转换成DFA。
  3. 先完善DFA,再最小化DFA。

二、实验内容

  1. 确定NFA与DFA的存储格式。要求为3个以上测试NFA准备好相应有限自动机的存储文件。
  2. 用C或JAVA语言编写将NFA转换成DFA的子集构造法的程序。
  3. 准备3个以上测试DFA文件。(提示:其中一定要有没有最小化的DFA)
  4. DFA手动完善。(状态转换映射要是满映射)
  5. 用C或JAVA语言编写用等价划分法最小化DFA的程序。

其实这部分内容要求没这么简单的,还有验证是否转换成功,怎么验证呢?只要你求出原来的和改后的某个子集(如长度小于某个N),再证实两个语言集合完全相同。不过当初我忘了这个了,后来验收的时候才发现没写,所以这部分我也不会加进来了。 ̄ω ̄=


三、存储格式

3 // 字符集中的字符个数 (以下两行也可合并成一行)
/ * o // 以空格分隔的字符集。O代表任意非/和*的字符
5 // 状态个数 (以下两行也可合并成一行)
1 2 3 4 5 // 状态编号。若约定总是用从1开始的连续数字表示,则此行可省略
1 // 开始状态的编号。若约定为1,则此行可省
1 // 结束状态个数。若约定为1,则此行可省略
5 // 结束状态的编号
2  -1  -1 // 状态1的所有出去的转换。按字符集中的字符顺序给出。-1表示出错状态
-1  3  -1
-1  4   3
5   4   3
-1  -1  -1

这部分不会照搬的,到后面输入会修改。不过大致还是这样的格式。


四、程序设计

  • 实现思路

想想还是写一点点吧,否则感觉缺点什么。

nfa和dfa来看的大致都知道了,转换的话只要是用子集构造法。至于子集构造法怎么样的,大家自己查吧,我要说的就是注意空字符的到达处理,循环需要注意。
而dfa最小化是最简单的吧,我反正就是先分为先分为是接受状态的集合和不是接受状态的集合,然后把转换状态相同的分为一个状态就可以了。当然,要修改状态的转换。

  • 文件说明:

      1. intArr.h intArr.cpp 数组类,用于实现数字集合的并,删除,查找2. NFA_To_DFA.h NFA_To_DFA.cpp dfa转nfa的类3. minimalDFA.h minimalDFA.cpp 最小化dfa的类4. main.cpp 主函数
    
  • 类设计说明

1)intArr类

class intarr
{
public:intarr();intarr(intarr &arr1);                   //复制构造函数int inline getSize(){return size;}      //获取集合大小void cleanArr();                        //清空集合元素void operator &= (int num);             //重载&=,并入单个元素void operator &= (intarr &arr1);        //重载&=,并入一个集合void getSort();                         //对集合元素从小到大排序int &operator[](int i);                 //重载[],可以向数组一样获得元素bool operator == (intarr &arr1);        //重载==,判断两个集合是否相等bool getNum(int num);                   //判断一个数字是否在集合中void delNum(int num);                   //删除一个数字int getNumber();                        //获得创建对象的个数private:int *arr=NULL;      //数组指针int size;           //数组大小static int number;  //创建对象的个数
};

2) NFA_To_DFA类

dfa中的dfa集合

struct state
{int stateNum;        //这个状态的编号int *nextNum;        //根据输入字符将会指向哪些状态intarr nfaArr;       //NFA状态集bool isMake = false; //是否标记static int maxNum;   //最大状态标号
};

共享的一个dfa状态,作为一个中间状态用于创建新的dfa状态

struct sstate
{intarr nfaArr; //NFA状态集int stateNum = 0;
};

nfa转dfa的类

class nfa_to_dfa
{public:nfa_to_dfa(std::string fn); //默认构造函数void getIntArr(int num, std::string s);void closure_s();                     //空字符匹配void closure_T(int num, int charNum); //字符集匹配void inStates();                      //是否在当前DFA状态中了void read();                          //读取NFA数据void convert();                       //开始转换void output();~nfa_to_dfa() {} //析构函数private:std::string charracters;          //nfa字符集int charrLength = 0;              //字符集的长度int statesNumber = 0;             //nfa状态个数,默认为0int currState = 1;                //开始状态编号,默认为1,不用输入int endNum = 1;                   //nfa接受状态个数,默认为1int *acceptStates = NULL;         //nfa接受状态集std::string **convertFrom = NULL; //转换表std::string filePath;             //文件输入对象sstate shareState;                //一个共享对象,用于转换int acceptNum = 0;      //转换出的dfa接受状态个数intarr DfaAcceptstates; //dfa接受状态集
};

3)minimalDFA类

最小化dfa的一个状态,用结构体描述

struct minState
{static int maxNum;      //最大状态数intarr sameState;       //相同的输出的状态集合int  minNum;            //这个最小dfa的状态标int *nextState=NULL;    //不同输入字符的情况下指向不同状态的集合int isAcceptState=0;    //是否为接受状态
};

最小化dfa。算法思想:
先将状态划分为接受状态和非接受状态。对于dfa中在输入相同的字符转到相同的状态的状态把这些状态划分到一组。

class minDfa
{public:minDfa(std::string str);  //构造函数void read();              //读取数据void divide();            //划分dfavoid output();            //状态集bool isqueal();           //判断两个最小化dfa是否相等private:std::string charracters;  //字符集int charLength=0;int stateNum = 0;         //状态个数,默认为0int currState = 1;        //开始状态编号,默认为1int endNum = 1;           //接受状态个数,默认为1int *acceptState = NULL;  //接受状态int **convertFrom = NULL; //转换表minState *states;         //最小化dfa状态集std::string path;         //要读取文件的路劲
};

五、实验测试

  • 输入的nfa文件中

     第一行 为字符集 ,?表示空字符第二行 为状态个数,默认为从状态1开始,所以不用输入开始状态 第三行 为行为接受状态个数 第四行 为接受状态 第五行 开始为状态转换表。列为字符集,对应为一个二维数组,在哪个状态输入哪个字符转到哪个状态,-1为错误状态。
    
  • NFA转换为DFA

1)nfa_to_dfa的输入文件nd:(aa|b)*(a|bb)*

ab?
4
1
3
2,1,3,
1,-1,-1,
3,4,-1,
-1,3,-1,

2)在文件dfa_to_nfa中输出:

ab
5
4
1 2 3 5
{1,3,}      2 3
{2,3,}      1 4
{1,3,4,}        2 3
{4,}        -1 5
{3,}        5 4 

3)作为minDfa的输入文件dfa:

ab
5
4
1 2 3 5
2 3
1 4
2 3
-1 5
5 4 

4)最小化mindfa输出

{1,3,}   1: 2 1      isacceptstate:1
{2,}    2: 1 3      isacceptstate:1
{4,}    3: -1 4         isacceptstate:0
{5,}    4: 4 3      isacceptstate:1
***********

六、实验总结

来看怎么写的肯定要失望了,因为除了贴了些类的说明,也没有什么好参考的。我也知道我该写下是怎么写nfa转dfa,dfa怎么转换的,代码该怎么写,但是,太久了,我忘记了,你们可以直接看代码理解。还有如果对比是不是觉得我分文件啊,用结构体啊,用类啊写的好复杂啊,其实我也觉得挺复杂的,但是事实上大规模的代码实现分文件写是很好的,方便修改,如果一个文件维护修改会很麻烦,当初我也是第一次写这么多的分文件代码。但总的收获是不少的,中间遇到了许多问题,可以的话,试下这样写吧。


七、资料下载

具体代码见NFA_TO_NFA

编译原理——NFA确定化和DFA最小化相关推荐

  1. 正则表达式引擎的构建——基于编译原理DFA(龙书第三章)——5 DFA最小化

    完整引擎代码在github上,地址为:https://github.com/sun2043430/RegularExpression_Engine.git DFA最小化的算法原理 "DFA状 ...

  2. 编译原理---NFA转化为DFA---DFA最小化(自己看)

    算法描述: 伪代码: function E(s){return NFA中状态s经过空转移到达的状态集合: }function Ee(T){return NFA中状态集合T中的每个状态通过空转移到达的状 ...

  3. NFA、DFA模拟、正则表达式转NFA、NFA转DFA、DFA转正则、DFA最小化的python实现项目

    各类自动机模拟实现 项目地址: https://github.com/HuiyuanYan/automaton_simulation 注:这个github链接必须复制重新在浏览器打开,不能通过CSDN ...

  4. 正则表达式转NFA,DFA,最小化DFA

    Exp 2:正则表达式转NFA,DFA,最小化DFA (1)正则表达式应该支持单个字符,运算符号有: 连接 选择(|) 闭包(*) 正闭包(+) 可选(?) 括号 (2)要提供一个源程序编辑界面,让用 ...

  5. python实现dfa过滤算法_Hopcroft算法DFA最小化Python实现

    DFA最小化原理 所谓自动机的化简问题即是对任何一个确定有限自动机DFA M,构造另一个确定有限自动机DFA M',有L(M)=L(M'),并且M'的状态个数不多于M的状态个数,而且可以肯定地说,能够 ...

  6. 编译原理Java实现——DFA最小化

    DFA的最小化 也称为 确定的有穷状态机的化简. DFA的最小化 = 消除无用状态 + 合并等价状态 消除无用状态这里是指删掉那些达到不了的状态.这不是我们的重点,DFS+HashSet不难实现. 其 ...

  7. nfa确定化 dfa最小化_深度学习中的优化:梯度下降,确定全局最优值或与之接近的局部最优值...

    深度学习中的优化是一项极度复杂的任务,本文是一份基础指南,旨在从数学的角度深入解读优化器. 一般而言,神经网络的整体性能取决于几个因素.通常最受关注的是网络架构,但这只是众多重要元素之一.还有一个常常 ...

  8. 编译原理--NFA/DFA

    现成的, 讲义: https://www.cnblogs.com/AndyEvans/p/10240790.html https://www.cnblogs.com/AndyEvans/p/10241 ...

  9. nfa确定化 dfa最小化_深度学习中的不确定性

    原文:What Uncertainties Do We Need in Bayesian Deep Learning for Computer Vision? (NIPS 2017) 深度学习模型给出 ...

  10. [编译原理]词法分析实验之基于 DFA 的单词识别

    Spring-_-Bear 的 CSDN 博客导航 问题描述: 基于 DFA 的单词识别问题的一种描述是:编写一个程序,输入一个确定的有穷自动机(DFA),使用该 DFA 识别单词. 基本要求: 设置 ...

最新文章

  1. 谷歌放出AI平民化大招: 李飞飞宣布推出AutoML云平台,让普通企业也能用上深度学习
  2. 遗留应用现代化场景:如何正确使用RESTful API
  3. 金山WPS发布了Linux WPS Office
  4. 顺序表应用4-2:元素位置互换之逆置算法(数据改进)
  5. MySQL多表查询核心优化
  6. .Net Validator验证框架 [ .Net | Validator Framework | Attribute ]
  7. 使用imbalanced-learn处理数据不均衡问题
  8. 提的最多的数据库“索引”,先来简单了解一下
  9. 简单的java方法_Java简单实用方法一
  10. 让Windows7 x64 IIS7支持32位应用程序
  11. 计算机科学与python编程导论_计算机科学入门和使用Python编程
  12. redis的事务不是原子性
  13. c语言从键盘输入数据数组,//从键盘上输入若干整数,并将其存入数组中,并统计输入数据的个...
  14. 如何在苹果Mac更改通知显示的时长?
  15. linux otl oracle数据库连接例子
  16. linux 串口monitor,串口监视工具CommMonitor如何使用-CommMonitor的使用方法 - 河东软件园...
  17. python 爬取公众号文章_python批量爬取公众号文章
  18. vue上传、修改头像
  19. *TEST 1 for NOIP
  20. Gephi最详细安装教程没有之一

热门文章

  1. Android音频系统学习二:Android音频框架
  2. yolov5导出onnx用netron.app可视化搜索
  3. r语言如何计算t分布临界值_医学统计与R语言:这个Calibration plot有点色!
  4. WebRTC 概念介绍--一篇读懂source、track、sink、mediastream
  5. 【最新汇总】单细胞转录组分析与绘图系列
  6. Photoshop如何调整图层大小?PS调整图层大小快捷键
  7. vlan tag是做什么用的?
  8. 云控微信开发SDK使用教程--微信联系人标签新增,修改通知服务端
  9. 1. 查询表customer——查询姓名和联系人相同的顾客信息
  10. 【文献阅读】MMQA——基于图像、文本和表格的问答(Alon Talmor等人,ICLR,2021)