实验二、构造下推自动机实验——PDA

实验题目:构造下推自动机


一、实验题目解答

对解题的整体思路、过程进行提炼和描述,包括算法描述、程序结构、主要变量 说明、设计技巧、调试情况、运行结果、心得体会等。

二、NFA正则表达式

1.形式化定义

根据实验描述,可以将下推自动机进行如下设计,得到此 PDA 的形 式化定义:
1. 状态集为{q1,q2,q3,q4,q5,q6,q7}
2. 输入字母表为{a,b,c}
3. 栈字母表为{b,c,$}
4. 起始状态为 q1
5. 接受状态集为{q7}
在这里插入图片描述
6. 转移函数如下表所示,表中的空白项表示空集

2、解题思路

非形式化地表示,识别该语言的 PDA 先读 a,并且把 a 推人栈。当读完 a 时,机器 把它们全部放到栈中,以使能够把它们与 c 进行匹配。由于机器不知道下面是与 b 匹配 还是与 c 匹配,需要想点办法,在这里迟早要用到非确定性;利用非确定性,这台 PDA 可以猜想 a 是与 b 匹配还是与 c 匹配,如图所示。设 但机器有两个非确定性的分支,每一种可能的猜想是一个分支。如果有一个匹配疲 功,则对应的分支接受,从而整个机器接受。要求证明非确定性是用 PDA 识别这个语言 所不可缺少的。
此处引用

三、实验思路与过程

data = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

实验使用 C++编程实现


第一步

程序中对每个状态都进行转移,最后判断结束时,最后状态为 q7 则接受,状态 为其他则拒绝 实验的整体思路:首先设计一个 State 的类用于模拟 DFA 的总体结构,状态 有4个变量分别为string oldState;//当前状态 char trans;//读取的字符stringnewState;// 新状态 char top;//栈顶字符 char putInStack;//要压入栈中的字符
具体代码如下

class Old2NewRelation {

private:
	string oldState;//当前状态
	char trans;//读取的字符
	string newState;//新状态
	char top;//栈顶字符
	char putInStack;//要压入栈中的字符

public:
	string getOldState() {
		return oldState;
	}
	void setOldState(string oldState) {
		this->oldState = oldState;
	}
	char getTrans() {
		return trans;
	}
	void setTrans(char trans) {
		this->trans = trans;
	}
	string getNewState() {
		return newState;
	}
	void setNewState(string newState) {
		this->newState = newState;
	}
	Old2NewRelation(string oldState, char trans, string newState, char top, char putInStack) {
		this->oldState = oldState;
		this->trans = trans;
		this->newState = newState;
		this->top = top;
		this->putInStack = putInStack;
	}
	string toString() {
		return "state tranfer relation [nowstate:" + oldState + ",  recognition char:" + trans + ", newState:" + newState + ", the operation for stack is :" + putInStack
			+ "replace the top of stack:" + top + "]";
	}
	char getPutInStack() {
		return putInStack;
	}
	void setPutInStack(char putInStack) {
		this->putInStack = putInStack;
	}
	char getTop() {
		return top;
	}
	void setTop(char top) {
		this->top = top;
	}
};

类中具有定义依据形式化定义,状态转移时需要的栈操作,能够有效的赋值 和查找

2、第二步

字符串的输入与输出,对于任意的字符串都可以进行相应操作。具体代码如下:

cout << "input string【only include 'abc'】,judging the number of b is same c,accetp if same,refuse if different" << endl; 
//将字符存入字符数组中 
string str; getline(cin, str);

3、第三步

构造一个具体的 DFA,即将声明一个 Vector 来存储不同的状态变化 结构体 list;

static vector<Old2NewRelation> initRelation() {
	//用‘#’表示空字符
	//分别表示 当前状态-识别字符-转移状态-栈顶元素-替换栈顶的元素
	vector<Old2NewRelation> list;
	list.push_back(Old2NewRelation("q1", '#', "q2", '#', '$'));
	list.push_back(Old2NewRelation("q2", 'a', "q4", '#', '#'));
	list.push_back(Old2NewRelation("q2", 'b', "q2", '#', 'b'));
	list.push_back(Old2NewRelation("q2", 'c', "q3", 'b', '#'));
	list.push_back(Old2NewRelation("q2", 'c', "q6", '#', 'c'));
	list.push_back(Old2NewRelation("q2", '#', "q7", '$', '#'));
	list.push_back(Old2NewRelation("q3", 'a', "q4", '#', '#'));
	list.push_back(Old2NewRelation("q3", 'b', "q2", '#', 'b'));
	list.push_back(Old2NewRelation("q3", 'c', "q3", 'b', '#'));
	list.push_back(Old2NewRelation("q3", 'c', "q6", '#', 'c'));
	list.push_back(Old2NewRelation("q3", '#', "q7", '$', '#'));
	list.push_back(Old2NewRelation("q4", 'a', "q4", '#', '#'));
	list.push_back(Old2NewRelation("q4", 'b', "q5", 'c', '#'));
	list.push_back(Old2NewRelation("q4", 'b', "q2", '#', 'b'));
	list.push_back(Old2NewRelation("q4", 'c', "q3", 'b', '#'));
	list.push_back(Old2NewRelation("q4", 'c', "q6", '#', 'c'));
	list.push_back(Old2NewRelation("q4", '#', "q7", '$', '#'));
	list.push_back(Old2NewRelation("q5", 'a', "q4", '#', '#'));
	list.push_back(Old2NewRelation("q5", 'b', "q5", 'c', '#'));
	list.push_back(Old2NewRelation("q5", 'b', "q2", '#', 'b'));
	list.push_back(Old2NewRelation("q5", 'c', "q6", '#', 'c'));
	list.push_back(Old2NewRelation("q5", '#', "q7", '$', '#'));
	list.push_back(Old2NewRelation("q6", 'a', "q4", '#', '#'));
	list.push_back(Old2NewRelation("q6", 'b', "q5", 'c', '#'));
	list.push_back(Old2NewRelation("q6", 'c', "q6", '#', 'c'));
	list.push_back(Old2NewRelation("q6", '#', "q7", '$', '#'));
	return list;
}
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

4、第四步开始遍历字符

主函数是首先定义开始的起始和终止状态,和定义一个栈;然后开始识别字 符对于已经确定的下推自动机。然后每一次遍历都保存子集这样才能够遍历所有 的可能。然后就和字符串进行比较匹配,进行相应的栈进栈出操作来进行匹配。 代码在附件中。

三、测试运行

提示:这里对文章进行总结:例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
调试程完全成功,可在附件的代码当中测试

四、心得体会

本次实验自己有了做第一次实验的思路,首先构造相应的类来完善结构,之后构 造具体的 PDA 能够很好的识别,达到预期目的。自己终于完成,自己即能够了 解到相关的结构实现,能够更加深入了解 PDA,而且还提升了自己的编码能力, 希望下次继续努力,谢谢老师。
代码也不知道放哪就百度网盘吧:链接:https://pan.baidu.com/s/1MFBDH1iM9MasVPERqoAVhA
提取码:8zq6
复制这段内容后打开百度网盘手机App,操作更方便哦

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值