编译原理课程设计2报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.实现了LR(0)分析器总控程序,对输入的表达式进行文法分析
1.2需求分析
识别文法活前缀的DFA、DFA的状态转化矩阵及LR(0)项目集规范族的构造
LR(0)分析表的构造
LR(0)分析器总控程序的构造
1.3设计
1.3.1设计思想
(一)识别文法的LR(0)项目集规范族的构造
采用 (闭包)的构造一个文法G的LR(0)项目规范簇。
(3)CSP最小冲突法
约束满足问题(CSP)是一类数学问题,它的定义为一组状态必须满足于若干约束或限制的对象(object)。CPSs表示的是问题中的实体,有限数量、同类型的约束加之于变量之上,这类问题通过约束满足方法解决。CSPs是人工智能和运筹学的热门主题,这是因为它们公式中的规律提供了一个分析和解决很多不相关问题的共同基础。CSPs通常表现出高复杂性,需要结合启发式搜索和联合搜索方法来在合理的时间内解决问题。布尔可满足性问题(SAT), ,可满足性的理论(SMT)和回答集编程(ASP)大致可以认为是特定形式的约束满足问题
找到一个可能存在的正确的答案
在尝试了所有可能的分步方法后宣告该问题没有答案
在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。
(2)遗传算法
遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)的抽象表示(称为染色体)的种群向更好的解进化。传统上,解用二进制表示(即0和1的串),但也可以用其他表示方法。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中,整个种群的适应度被评价,从当前种群中随机地选择多个个体(基于它们的适应度),通过自然选择产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。
#16}
#17}
#18}
#19}
(2)遗传算法
#20void evolution()
#21{
#22
#23int i = 0, mate1, mate2;
#24while (i<POPSIZE)
#25{
#26mate1 = select();
#27mate2 = select();
#28//cout<<mate1<<" "<<mate2<<endl;
2.3.2算法代码
(1)回溯法
#1void Solve(int rowCurrent, int *&NQueen, int n, int &count)
#2{
#3if (count == 0)
#4{
#5if (rowCurrent == n) //当前行数触底,即完成了一个矩阵,将它输出
#6{
#7count++;
#8return;
#9}
#10for (int i = 0; i < n; i++)
#11{
#12NQueen[rowCurrent] = i; //row行i列试一试
#13if (Check(rowCurrent, NQueen))
#14{
#15Solve(rowCurrent + 1, NQueen, n, count); //移向下一行
假定是文法G的任一项目集,定义和构造的闭包的算法:
(1)I的任何项目都属于 ;
(2)若 属于 ,那么,对任何关于B的产生式 ,项目 也属于 ;
(3)重复执行上述两个步骤直至 不再增大。
其中初始 ,为对文法G进行拓广构造 而引进的不出现在G中的非终结符。
定义状态转换函数 , 的第一个变元 是一个项目集,第二个变元 是一个文法符号。函数值 定义为 。
1.5用户手册
直接运行程序即可,没有用户要操作的地方。
1.6测试数据及结果
请看第1.4.1节。
1.7源程序清单
AdjMWGraph.cpp
AdjWGraphApp.h
CreatAdjWGraph.h
read.cpp
SeqList.h
SeqQueue.h
SeqStack.h
GraphMindTest.cpp
#47if (conflict < min_conflict) {
#48min_conflict = conflict;
#49optimal_col = i;
#50}
#51}
#52if (optimal_col != cur_col) {//要更新col,pdiag,cdiag
#53col[cur_col]--;
#54pdiag[getP(row, cur_col)]--;
#55cdiag[getC(row, cur_col)]--;
#56
#57col[optimal_col]++;
#58pdiag[getP(row, optimal_col)]++;
#59cdiag[getC(row, optimal_col)]++;
在程序运行时,解环复原的时候需要传入std::vector,此时容易出现内存泄漏问题。
这个时候需要将std::vector定义为全局变量,并采用引用传值方式销毁std::vector,避免内存泄漏。
一开始在建环的时候直接调用了链表的删除函数,导致程序陷入死循环,应直接将后续节点销毁,注意,此处可链表删除完全不同。
其中 = {任何形如 的项目| 属于 }
(二)LR(0)分析表的构造
1.3.2设计表示
主要的函数:
#001DijkPrintLoad//代价一致的宽度优先
#002Non_recDfs//有限制的深度优先
#003Greedy//贪婪搜索算法
#004ASearch//A*算法
1.4调试分析
1.4.1调试结果与比较
#38int cur_col = R[row];
#39int optimal_col = cur_col;//最佳列号,设置为当前列,然后更新
#40int min_conflict = col[optimal_col] + pdiag[getP(row, optimal_col)] - 1
#41+ cdiag[getC(row, optimal_col)] - 1;//对角线冲突数为当前对角线皇后数减一
编译原理课程设计报告
班级:191134
学号:20131000479
学生姓名:陈聪儿
指导老师:刘远兴
日期:2015年11月
第 1 章
罗马利亚度假问题
1.1题目内容
1.实现了对任意给定的文法G,识别文法活前缀的DFA、DFA的状态转化矩阵及LR(0)项目集规范族的构造
2.判断该文法是否为LR(0)文法,实现了LR(0)分析表的构造,并输出到指定文件中;
第 2 章
N皇后问题
2.1题目内容
设计目的:
分别用回溯法(递归)、GA算法和CSP的最小冲突法求解n皇后问题。
设计内容:
1.输入n,并用运行时间比较几种算法在相同规模的问题时的求解效率,并列表给出结果。
2.比较同一算法在n不相同时的运行时间,分析算法的时间复杂性,并列表给出结果。
2.2需求分析
n皇后问题:在n*n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上
2.3设计
2.3.1设计思想
(1)回溯法
回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:
#63return qualify();//qualify相对更耗时,所以只在满足上面基本条件后才检查
#64}
#65}
#66//当前点就是最佳点,一切都保持不变
#67return false;//如果都没变的话,肯定不满足终止条件,否则上一次就应该返回true并终止了
#68}
2.4调试分析
2.4.1调试中遇到的问题
1.代价一致的宽度优先
2.有限制的深度优先
3.贪婪搜索算法
4.A*算法
1.4.2算法比较与总结
节点数
路径长度
效率
Optimality:
Completeness:
BFS
11
418
2
ຫໍສະໝຸດ BaiduNo
YES
DFS
12
605
3
No
NO
Greedy
2
450
1
NO
NO
A*算法
3
450
4
YES
YES
1.4.3调试中遇到的问题
用C/C++编程过程中遇到的问题,最令人头疼的莫过于对指针的管理了,有时候一不小心就成了野指针,运行时往往出错。
#60R[row] = optimal_col;
#61if (col[cur_col] == 1 && col[optimal_col] == 1
#62&& pdiag[getP(row, optimal_col)] == 1 && cdiag[getC(row, optimal_col)] == 1) {
#33newpop[i + 1].fitness = fitness_count(newpop[i + 1]);
#34i += 2;
#35}
#36}
本函数为产生新的种群函数,其中select()为选择操作,crossover()为交叉操作
(3)CSP最小冲突
#37bool adjust_row(int row) {
#42for (int i = 0; i < N; i++) {//逐个检查第row行的每个位置
#43if (i == cur_col) {
#44continue;
#45}
#46int conflict = col[i] + pdiag[getP(row, i)] + cdiag[getC(row, i)];
#29crossover(oldpop[mate1], oldpop[mate2], newpop[i], newpop[i + 1]);
#30mutation(newpop[i]);
#31newpop[i].fitness = fitness_count(newpop[i]);
#32mutation(newpop[i + 1]);
1.2需求分析
识别文法活前缀的DFA、DFA的状态转化矩阵及LR(0)项目集规范族的构造
LR(0)分析表的构造
LR(0)分析器总控程序的构造
1.3设计
1.3.1设计思想
(一)识别文法的LR(0)项目集规范族的构造
采用 (闭包)的构造一个文法G的LR(0)项目规范簇。
(3)CSP最小冲突法
约束满足问题(CSP)是一类数学问题,它的定义为一组状态必须满足于若干约束或限制的对象(object)。CPSs表示的是问题中的实体,有限数量、同类型的约束加之于变量之上,这类问题通过约束满足方法解决。CSPs是人工智能和运筹学的热门主题,这是因为它们公式中的规律提供了一个分析和解决很多不相关问题的共同基础。CSPs通常表现出高复杂性,需要结合启发式搜索和联合搜索方法来在合理的时间内解决问题。布尔可满足性问题(SAT), ,可满足性的理论(SMT)和回答集编程(ASP)大致可以认为是特定形式的约束满足问题
找到一个可能存在的正确的答案
在尝试了所有可能的分步方法后宣告该问题没有答案
在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。
(2)遗传算法
遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)的抽象表示(称为染色体)的种群向更好的解进化。传统上,解用二进制表示(即0和1的串),但也可以用其他表示方法。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中,整个种群的适应度被评价,从当前种群中随机地选择多个个体(基于它们的适应度),通过自然选择产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。
#16}
#17}
#18}
#19}
(2)遗传算法
#20void evolution()
#21{
#22
#23int i = 0, mate1, mate2;
#24while (i<POPSIZE)
#25{
#26mate1 = select();
#27mate2 = select();
#28//cout<<mate1<<" "<<mate2<<endl;
2.3.2算法代码
(1)回溯法
#1void Solve(int rowCurrent, int *&NQueen, int n, int &count)
#2{
#3if (count == 0)
#4{
#5if (rowCurrent == n) //当前行数触底,即完成了一个矩阵,将它输出
#6{
#7count++;
#8return;
#9}
#10for (int i = 0; i < n; i++)
#11{
#12NQueen[rowCurrent] = i; //row行i列试一试
#13if (Check(rowCurrent, NQueen))
#14{
#15Solve(rowCurrent + 1, NQueen, n, count); //移向下一行
假定是文法G的任一项目集,定义和构造的闭包的算法:
(1)I的任何项目都属于 ;
(2)若 属于 ,那么,对任何关于B的产生式 ,项目 也属于 ;
(3)重复执行上述两个步骤直至 不再增大。
其中初始 ,为对文法G进行拓广构造 而引进的不出现在G中的非终结符。
定义状态转换函数 , 的第一个变元 是一个项目集,第二个变元 是一个文法符号。函数值 定义为 。
1.5用户手册
直接运行程序即可,没有用户要操作的地方。
1.6测试数据及结果
请看第1.4.1节。
1.7源程序清单
AdjMWGraph.cpp
AdjWGraphApp.h
CreatAdjWGraph.h
read.cpp
SeqList.h
SeqQueue.h
SeqStack.h
GraphMindTest.cpp
#47if (conflict < min_conflict) {
#48min_conflict = conflict;
#49optimal_col = i;
#50}
#51}
#52if (optimal_col != cur_col) {//要更新col,pdiag,cdiag
#53col[cur_col]--;
#54pdiag[getP(row, cur_col)]--;
#55cdiag[getC(row, cur_col)]--;
#56
#57col[optimal_col]++;
#58pdiag[getP(row, optimal_col)]++;
#59cdiag[getC(row, optimal_col)]++;
在程序运行时,解环复原的时候需要传入std::vector,此时容易出现内存泄漏问题。
这个时候需要将std::vector定义为全局变量,并采用引用传值方式销毁std::vector,避免内存泄漏。
一开始在建环的时候直接调用了链表的删除函数,导致程序陷入死循环,应直接将后续节点销毁,注意,此处可链表删除完全不同。
其中 = {任何形如 的项目| 属于 }
(二)LR(0)分析表的构造
1.3.2设计表示
主要的函数:
#001DijkPrintLoad//代价一致的宽度优先
#002Non_recDfs//有限制的深度优先
#003Greedy//贪婪搜索算法
#004ASearch//A*算法
1.4调试分析
1.4.1调试结果与比较
#38int cur_col = R[row];
#39int optimal_col = cur_col;//最佳列号,设置为当前列,然后更新
#40int min_conflict = col[optimal_col] + pdiag[getP(row, optimal_col)] - 1
#41+ cdiag[getC(row, optimal_col)] - 1;//对角线冲突数为当前对角线皇后数减一
编译原理课程设计报告
班级:191134
学号:20131000479
学生姓名:陈聪儿
指导老师:刘远兴
日期:2015年11月
第 1 章
罗马利亚度假问题
1.1题目内容
1.实现了对任意给定的文法G,识别文法活前缀的DFA、DFA的状态转化矩阵及LR(0)项目集规范族的构造
2.判断该文法是否为LR(0)文法,实现了LR(0)分析表的构造,并输出到指定文件中;
第 2 章
N皇后问题
2.1题目内容
设计目的:
分别用回溯法(递归)、GA算法和CSP的最小冲突法求解n皇后问题。
设计内容:
1.输入n,并用运行时间比较几种算法在相同规模的问题时的求解效率,并列表给出结果。
2.比较同一算法在n不相同时的运行时间,分析算法的时间复杂性,并列表给出结果。
2.2需求分析
n皇后问题:在n*n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上
2.3设计
2.3.1设计思想
(1)回溯法
回溯法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:
#63return qualify();//qualify相对更耗时,所以只在满足上面基本条件后才检查
#64}
#65}
#66//当前点就是最佳点,一切都保持不变
#67return false;//如果都没变的话,肯定不满足终止条件,否则上一次就应该返回true并终止了
#68}
2.4调试分析
2.4.1调试中遇到的问题
1.代价一致的宽度优先
2.有限制的深度优先
3.贪婪搜索算法
4.A*算法
1.4.2算法比较与总结
节点数
路径长度
效率
Optimality:
Completeness:
BFS
11
418
2
ຫໍສະໝຸດ BaiduNo
YES
DFS
12
605
3
No
NO
Greedy
2
450
1
NO
NO
A*算法
3
450
4
YES
YES
1.4.3调试中遇到的问题
用C/C++编程过程中遇到的问题,最令人头疼的莫过于对指针的管理了,有时候一不小心就成了野指针,运行时往往出错。
#60R[row] = optimal_col;
#61if (col[cur_col] == 1 && col[optimal_col] == 1
#62&& pdiag[getP(row, optimal_col)] == 1 && cdiag[getC(row, optimal_col)] == 1) {
#33newpop[i + 1].fitness = fitness_count(newpop[i + 1]);
#34i += 2;
#35}
#36}
本函数为产生新的种群函数,其中select()为选择操作,crossover()为交叉操作
(3)CSP最小冲突
#37bool adjust_row(int row) {
#42for (int i = 0; i < N; i++) {//逐个检查第row行的每个位置
#43if (i == cur_col) {
#44continue;
#45}
#46int conflict = col[i] + pdiag[getP(row, i)] + cdiag[getC(row, i)];
#29crossover(oldpop[mate1], oldpop[mate2], newpop[i], newpop[i + 1]);
#30mutation(newpop[i]);
#31newpop[i].fitness = fitness_count(newpop[i]);
#32mutation(newpop[i + 1]);