这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天,今天了解规则引擎的组成部分与核心原理.
一. 认识规则引擎
规则引擎的定义
规则引擎是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策.接受数据输入,解释业务规则,并根据业务规则做出业务决策.
规则引擎的优点
- 解决开发人员重复编码的问题
- 业务决策与服务本身解耦,提高服务的可维护性缩短开发路径,提高效率
组成部分
- 数据输入:
- 支持接受使用预定义的语义编写的规则作为策略集.比如:"price > 500",接受业务的数据作为执行过程中的参数,比如价格,标签等.
- 规则理解:
- 能够按照预先定义的词法,语法,优先级,运算符等正确了理解业务理解业务规则所表达的值义
- 规则执行:
- 根据执行时输入的参数对策略集中的规则进行正确的解释和执行.同时对规则执行过程中的数据类型进行检查,确保执行结果正确
应用场景
- 风控对抗 : 与黑灰产对抗过程中,根据黑灰产特征,不断调整和优化对抗策略.
- 活动策略运营 : 及时根据用户效果反馈进行运营策略的优化和调整.
- 数据分析和清洗 : 实现不同数据分析,进行快速整理,清洗和转换.
二. 编译原理基本概念
什么是编译
- 编译的过程就是 把某种语言的源程序,在不改变语义的条件下,转换成另一种语言程序(目标语言程序)
- 如果源代码编译后要在操作系统上运行,那目标代码就是汇编/机器代码
- 如果编译后是在虚拟机里执行,那目标代码就可以不是汇编代码,而是一种解释器可以理解的中间形式的代码即可
词法分析
-
词法分析就是把源代码字符串转换为词法单元(Token)的这个过程。
例如: price > 500 && (isNewUser || userLevel > 5)
--> price > 500 && ( isNewUser || userLevel > 5 ) -
词法单元:由一个词法单元名和一个可选的属性构成
-
词法单元的大致分类
- 关键字:每个关键字有一个词法单元
- 标识符:一个表示所有标识符的词法单元
- 常量:常量词法单元包含的数字和字符串
- 运算符:运算法也是一个词法单元,可以是比较运算符,也可以是算术运算符
- 标点符号:每一个标点符号有一个词法单元。比如括号等等
-
有限自动机:
- 确定的有限自动机就是一个状态机,它的状态数量是有限的。该状态机在任何一个状态,基于输入的字符,都能做一个确定的状态转换。
- 画出一个合理的状态机就可以视为完成一个词法分析
语法分析
-
词法分析是识别一个个的单词,而语法分析就是在词法分析的基础上识别出程序的语法结构.
抽象语法树
-
语法分析出的结构是一个树状结构。这棵树叫做抽象语法树(Abstract Syntax Tree,AST)。树的每个节点(子树)是一个语法单元,这个单元的构成规则就叫“语法”。每个节点还可以有下级节点.
-
-
上下文无关语法
- 无需考虑上下文,就可以判断正确性,可以使用巴斯克范式(BNF)来表示
... a := 0 ... - BNF是描述上下文无关理论的一种具体方法,通过BNF可以实现上下文无关文法的具体化、公式化、科学化,是实现代码解析的必要条件。
<expr> ::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= ( <expr> ) | NumBNF本质上就是树形分解,分解成一棵抽象语法树
- 每个产生式就是一个子树,在写编译器时,每个子树对应一个解析函数。
- 叶子节点叫做 终结符,非叶子节点叫做 非终结符
- 产生式 : 一个表达式可以由另外已知类型的表达式或者符号推导产生.
- 内置符号 : 字面量(string,bool,number)标志符,运算符
- 一个基础表达式可以由常量(string,bool,number)或者标识符(identifier)
- 一个乘法表达式可以由 基础表达式 或者 乘法表达式 * 基础表达式 组成
exp : add ; add : (add '+' mul) | mul ; //加法表达式 a + b + c a + b * c mul : (mul '*' pri) | pri ; // 乘法表达式 a * b * c pri : string | bool | number | identifier ; //基础表达式 weight | 20 | "abcde"
- 无需考虑上下文,就可以判断正确性,可以使用巴斯克范式(BNF)来表示
-
递归下降算法
-
递归下降算法就是自顶向下构造语法树
-
不断对Token(语法分析)进行语法展开(下降),展开过程可能会遇到递归的情况.
按照规则
对
进行语法展开得到:
-
对于一个非终结符,要从左到右依次匹配其产生式中的每个项,包括非终结符和终结符
-
在匹配产生式右边的非终结符时,要下降一层,继续匹配该非终结符的产生式。
-
如果一个语法规则有多个可选的产生式,那么只要有一个产生式匹配成功就行。如果一个产生式匹配不成功,那就回退回来,尝试另一个产生式。这种回退过程,叫做回溯(Backtracking)。
-
类型检查
- 类型综合
- 根据子表达式的类型构造出父表达式的类型.例如:表达式A+B的类型是根据A和B的类型定义的.
- 编译时检查 & 运行时检查
类型检查可以发生在表达式的编译阶段,即在构造语法树的阶段,也可以发生在执行时的阶段.- 编译时 : 需要提前声明参数的类型,在构建语法树过程中进行类型的检查
int1 : int str1 : string - 执行时 : 可以根据执行时的参数输入的指类型,在执行过程中进行类型检查.
int1 : 108 str1 : "300" ```
- 编译时 : 需要提前声明参数的类型,在构建语法树过程中进行类型的检查