实验题目:构造下推自动机
一、实验题目解答
对解题的整体思路、过程进行提炼和描述,包括算法描述、程序结构、主要变量 说明、设计技巧、调试情况、运行结果、心得体会等。
二、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、第四步开始遍历字符
主函数是首先定义开始的起始和终止状态,和定义一个栈;然后开始识别字 符对于已经确定的下推自动机。然后每一次遍历都保存子集这样才能够遍历所有 的可能。然后就和字符串进行比较匹配,进行相应的栈进栈出操作来进行匹配。 代码在附件中。
三、测试运行
调试程完全成功,可在附件的代码当中测试
四、心得体会
本次实验自己有了做第一次实验的思路,首先构造相应的类来完善结构,之后构 造具体的 PDA 能够很好的识别,达到预期目的。自己终于完成,自己即能够了 解到相关的结构实现,能够更加深入了解 PDA,而且还提升了自己的编码能力, 希望下次继续努力,谢谢老师。
代码也不知道放哪就百度网盘吧:链接:https://pan.baidu.com/s/1MFBDH1iM9MasVPERqoAVhA
提取码:8zq6
复制这段内容后打开百度网盘手机App,操作更方便哦