编译原理学习:随机生成算术表达式

news2024/11/27 21:00:36

最近用Python写了一个随机向右生成数学表达式的算法。如下图所示,点一下运行就能随机生成一个二叉树形式的算术表达式。这个树形图是用“graphviz”画的,完全是它自动布局画出来的,画的还挺不错的。代码在:becomequantum (becomequantum) · GitHub

写这个代码是为了学习编译原理,学习编译原理是因为俺想写一个万能的词法和语法分析器,也就是只写一套代码,就能分析各种编程语言等形式化的语言。要实现这点,只能用上面编译原理教程里提到的方法。也就是语法分析器的代码不靠手写,而是有个万能的语法分析器,只要你给出某个语言的声明式规范,这个万能语法分析器就能帮你解析。

我知道已经有这样的轮子存在了,但我还是想自己造一个。要造这样一个轮子,首先得搞定表达式识别,其实语法分析中,也就是表达式识别最复杂,搞定它了,别的就好搞定了。但要搞定表达式识别这个事情,从上面这些教程中看,还是挺复杂的。这个表达式的产生式看着就挺复杂的,我都懒得去理解它。

我刚开始看这些视频的时候,半天都看不明白“终结符”和“非终结符”到底是啥意思,后来才发现“终结”对应的就是树里的叶子节点,“非终结”对应的就是非叶子节点,这才明白是咋回事。这个外国人啊,就是喜欢造各种新的形式化语言和新的术语,结果就是一大堆不知所云的概念把人搞得稀里糊涂。所以我决定不了这些概念,和前人整的那些算法,用自己的思路解决这个问题。

算法领域里的所有问题其实都可以归结到图里,算法的流程图也是图。简单的数组遍历也可以看成是在遍历线性图。所以可以说一切算法就是建立在图遍历的基础之上的。所以各种计算机领域的问题,你都用图里面的概念去理解就行了,这样就能看穿不同概念之间的共同特性,也就是融汇贯通了。

于是我先思考了一下表达式生成的问题,我觉得上面那个表达式的产生式不好理解,利用它生成算法我也不知道咋弄,我也懒得继续看教程去把它搞清楚,因为我觉得它把这个问题搞复杂了。我的思路是从状态机出手,假如要用状态机生成一个任意算术表达式,这个状态机会是咋样的。写了一下发现这个表达式生成状态机其实挺简单的,三个状态就行了,如上图所示。第一步和第二步都很简单,第一步就生成一个左边的叶子节点,因为是要向右生成,所以一开始的左节点就直接变为叶子,不让它继续发展出子树。第二步就是随一个运算符。第三步先随机决定一下生成是否终结,终结就生成一个右边的叶子节点。如果不终结,就会跳转到第一步继续生成,也就是形成了递归调用。只是这新生成的表达式所处的位置又分两种情况,如上图所示。

之所以只向右生成,是因为在识别表达式的时候,也是从左往右顺序进行的。等我写完这个生成代码之后就发现,其实这个生成的状态转换流程,完全也可以用在识别上,状态机的结构是一样的,只是每个状态要做的事情是“反过来的”。识别具体咋弄下次再说,俺现在还没把代码写出来。然后我有一个重要领悟就是,这个生成的算法是可逆的啊,意思就是,流程结构不变,改一下每个状态所进行的操作,生成状态机就能变成识别状态机。这又让我想起了上半年研究出来的精准线段识别算法,这个算法也可以看成是Bresenham画直线算法的逆算法,只不过这个逆算法的流程要比正向的复杂一点。这就有意思了,难倒各种生成算法都是能逆回去的?生成算法的逆算法就是识别算法,一般来说生成算法比较容易,识别算法比较难。对于计算机来说是这样的,但对于人脑来说似乎不是这样,所以我猜我们是还没有找到把各种生成算法逆回去的高效算法。等都找到了,AI识别就不需要整一堆浮点数神经元训练半天了,基于逻辑算法的AI识别效率会大大提升。

现在的AI算法其实就好比是用随机投针之类的蒙特卡洛方法算圆周率,也能算,但收敛的慢,效率很低。用公式算,尤其是用拉马努金的公式算效率会高很多。所以等基于逻辑公式的AI出现之后,就会对现在基于概率的AI形成降维打击!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1168945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu 系统内核 kernel panic

Ubuntu 系统内核 kernel panic 不能进入系统:报错end kernel panic -not syncing: attemped to kill init! exit code 0x00000100 系统启动的时候,按下‘e’键进入grub编辑界面,编辑grub菜单,选择“kernel /vmlinuz-XXXXro root…

【LeetCode:117. 填充每个节点的下一个右侧节点指针 II | DFS | BFS】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

【强化学习】15 —— TRPO(Trust Region Policy Optimization)

文章目录 前言TRPO特点策略梯度的优化目标使用重要性采样忽略状态分布的差异约束策略的变化近似求解线性搜索算法伪代码广义优势估计代码实践离散动作空间连续动作空间 参考 前言 之前介绍的基于策略的方法包括策略梯度算法和 Actor-Critic 算法。这些方法虽然简单、直观&…

银行和金融企业为何青睐这8款项目管理工具

银行、金融行业中主流的8款项目管理系统:1.PingCode;2.Worktile;3.Microsoft Project;4.Jira by Atlassian;5.Asana;6.Trello;7.Wrike;8.Teambition。 银行和金融性质的公司在项目管…

【C++】多态 ⑪ ( 纯虚函数和抽象类 | 纯虚函数语法 | 抽象类和实现 | 代码示例 )

文章目录 一、纯虚函数和抽象类1、纯虚函数2、纯虚函数语法3、抽象类和实现 二、完整代码示例 一、纯虚函数和抽象类 1、纯虚函数 纯虚函数 : 在 C 语言中 , " 纯虚函数 " 是 特殊类型的 虚函数 , " 纯虚函数 " 在 父类 中 声明 , 但是没有实现 ; 抽象类 …

计算虚拟化2——内存虚拟化

目录 物理机内存访问过程 虚拟地址VA和物理地址PA概念 MUU实现VA到PA所使用的映射表 内存虚拟化类型 内存软件辅助虚拟化 内存硬件辅助虚拟化 内存虚拟化-内存超分配 内存共享 内存置换 内存气泡 物理机内存访问过程 内存的基本知识 内存都是从物理地址0开始的&…

基于LDA主题+协同过滤+矩阵分解算法的智能电影推荐系统——机器学习算法应用(含python、JavaScript工程源码)+MovieLens数据集(二)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据爬取及处理 相关其它博客工程源代码下载其它资料下载 前言 前段时间,博主分享过关于一篇使用协同过滤算法进行智能电影推荐系统的博文《基于TensorFlowCNN协同过滤算法的智能电影推荐系统——深…

文献查询辅助工具,查看文献影响因子期刊,显示文献排名,翻译文献

插件工具:easyScholar 适配浏览器(Edge、chrome、Firefox),本文以Edge为例: 1.打开Edge浏览器,输入: edge://extensions/ 2.点击获取Microsoft Edge扩展 3.搜索 easyscholar,然后…

Hive【Hive(八)自定义函数】

自定义函数用的最多的是单行函数&#xff0c;所以这里只介绍自定义单行函数。 Coding 导入依赖 <dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>3.1.3</version></dependency>…

路由器基础(十):防火墙配置

一、防火墙默认的区域 防火墙是基于安全区域进行工作的安全设备。 一个安全区域是若干接口所连网络的集合&#xff0c;这些网络中的用户具有相同的安全属性。 通常防火墙认为在同一安全区域内部发生的数据流动是不存在安全风险的&#xff0c;不需要实施任何安全策略。只有当不同…

代码随想录Day36 动态规划05 LeetCode T1049最后一块石头的重量II T494 目标和 T474 一和零

前言 : 动规五部曲 理论基础 : 代码随想录Day34 LeetCode T343整数拆分 T96 不同的二叉搜索树-CSDN博客 1.明白dp数组的含义 2.明白递推公式的含义 3.初始化dp数组 4.注意dp数组的遍历顺序 5.打印dp数组排错 LeetCode T1049 最后一块石头的重量II 题目链接:1049. 最后一块石头…

LeetCode:117. 填充每个节点的下一个右侧节点指针 II(C++)

117. 填充每个节点的下一个右侧节点指针 II 题目描述&#xff1a; 给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将…

Promise的并发控制 - 从普通并发池到动态并发池

一、场景 给你一个有200个URL的数组&#xff0c;通过这些URL来发送请求&#xff0c;要求并发请求数不能超过五个。 这是一道很常考的面试题&#xff0c;接下来让我们来学习一下Promise并发控制 二、普通并发池的实现 主要思路就是&#xff0c;判断当前队列是否满&#xff0c;…

【IDEA】在工具栏设置快速创建包和类的图表

页面效果&#xff1a; 操作步骤&#xff1a; 设置 --> 外观与行为 --> 菜单与工具栏 --> 点击 主工具栏 --> 点击 ---- --> 点击 号 --> 添加操作 主菜单 --> 文件 --> 文件打开操作 --> 打开项目操作 --> 新建 --> 往下找 找到 clas…

单行自动横向滚动——css实现

效果 封装组件 <template><div ref"container" class"scroll-area"><divref"content":class"[isScroll ? scroll : no-scroll]":style"{ color: fontColor }">{{ content }}</div></div> &…

c++值deque容器

1.deque容器介绍 deque 是 double-ended queue 的缩写&#xff0c;又称双端队列容器。deque容器支持从头部和尾部双端插入、删除数据。与vector容器不同的是&#xff0c;vector容器是一段连续的空间&#xff0c;而deque没有所谓容量的概念&#xff0c;因为它是动态的以分段连续…

Spring Boot 常见面试题

目录 1.Spring Boot 快速入门什么是 Spring Boot&#xff1f;有什么优点&#xff1f;Spring Boot 与 Spring MVC 有什么区别&#xff1f;Spring 与 Spring Boot 有什么关系&#xff1f;✨什么是 Spring Boot Starters?Spring Boot 支持哪些内嵌 Servlet 容器&#xff1f;如何设…

掌握RESTful API:规范与设计详解

前言 RAML (RESTful API Modeling Language) 和 OAS (OpenAPI Specification) 都是用于描述和定义 RESTful API 的规范。它们分别提供了不同的功能和优势。 RAML&#xff08;RESTful API Modeling Language&#xff09;&#xff1a; RAML简介 RAML&#xff08;RESTful API M…

CSC公派研究生项目|北语北外2024年寒假英语培训班正在招生

北京语言大学出国部、北京外国语大学出国部近期发布了2024年寒假“国家建设高水平大学公派研究生项目”英语培训的通知&#xff0c;知识人网小编特归纳整理&#xff0c;供有需求的同学参考。 北京语言大学 我部将于2024年寒假举办“国家建设高水平大学公派研究生项目”英语培训…

银行账单转换beancount

用了beancount来记账后&#xff0c;发现每月的账单手动记是一件极其麻烦的事情。 然后再github搜索一通后&#xff0c;有double-entry-generator&#xff08;https://github.com/deb-sig/double-entry-generator&#xff09;能转换支付宝/微信的账单&#xff0c;但是没有自己用…