一、简介
- Rete算法:是一种高效的模式匹配算法用来实现产生式规则系统
空间换时间,用内存换取匹配速度
- Rete算法通过规则条件生成了一个网络,每个规则条件是网络中的一个节点
- rete 分为:
- 规则编译:指根据规则集生成推理网络的过程
- 运行时执行: 指将数据送入推理网络进行筛选的过程
二、规则编译
规则编译:根据规则文件推理生成网络的过程
1. 根节点(RootNode)
- 是所有对象进入网络的入口,然后进入到 TypeNode
2. TypeNode
- 是 fact,即规则所用到的 pojo;
- 每个 fact 是一个 TypeNode
- TypeNode 就是类型检查,引擎只让匹配 Object 类型的对象到达节点,
能够传播到 AlphaNodes、LeftInputAdapterNodes (作为betaNodes的左端输入节点)和 BetaNodes
举例:有两个fact ,Person 和cheese,则节点图如下所示
3. AlphaNode
首图的蓝色节点
- 用来评估字面条件
例如: person.age>10 就是一个 alpha node 节点
当一条规则有多条字面条件,这些字面条件被链接到一起
Drools 通过散列法优化了从 ObjectTypeNode 到 AlphaNode 的传播:
- 每次一个 AlphaNode 被加到一个 ObjectTypeNode 时,就以字面值作为 key ,以 AlphaNode 作为 value 加入 HashMap
- 当一个新的实例进入 ObjectTypeNode 时,不用传递到每一个 AlphaNode ,直接从 HashMap 中获得正确的 AlphaNode ,避免不必要的字面检查
4. Bate Node
- 用来对两个对象进行对比、检查
约定 BetaNode 的两个输入称为左边(Join Node)和右边(NotNode):
- 左边通常是一个
a list of objects
左边的输入被称为 Beta Memory,会记住所有到达过的语义
- 右边通常是
a single object
右边的输入成为 Alpha Memory,会记住所有到达过的对象
5. 构建 rete 网络
-
创建根节点
-
加入一条规则
a. 取出规则中的一个模式 ,检查模式中的参数类型,如果是新类型(即新 fact 类型),则加入一个类型节点模式就是规则中的最小一个匹配项例如(如: age>10;age<20)
b. 检查模式对应的 Alpha 节点是否已存在:
- 若已存在,则记录下节点位置
- 若未存在,则将模式作为一个 Alpha 节点加入到网络中,同时根据 Alpha 节点的模式建立 Alpha 内存表
c. 重复 b 直到所有的模式处理完毕
d. 组合 Beta 节点: Beta 左输入节点为 Alpha(1),右输入节点为 Alpha(2)Beta(i) 左输入节点为 Beta(i-1),右输入节点为 Alpha(i)
e. 重复 d 直到所有的 Beta 节点处理完毕
f. 将动作(Then 部分)封装成叶节点(Action 节点)作为 Beta(n) 的输出节点 -
重复 2) 直到所有规则处理完毕
案例
-
案例一:
举例:条件
Cheese (name=”cheddar”), Person(favouriteiteCheese==”cheese.name”)
关联操作:Cheese.name == Person.favouriteiteCheese
节点图如下所示:
- 黄色 node 称为 LeftInputAdapterNode,作用是将一个 single Object 转化为一个单对象数组,传播到 JoinNode 节点
-
案例二:drools
rule when Cheese( $cheddar : name == "cheddar" ) $person : Person( favouriteCheese == $cheddar ) then System.out.println( $person.getName() + " likes cheddar" ); end rule when Cheese( $cheddar : name == "cheddar" ) $person : Person( favouriteCheese != $cheddar ) then System.out.println( $person.getName() + " does not like cheddar" ); end
- Drools 通过节点的共享来提高规则引擎的性能
三、运行时执行
- WME:工作存储区元素(Working Memory Element,存储区的最小单位),WME 是为事实建立的元素,是用于和非根结点代表的模式进行匹配的元素
- Token:WME 列表,包含多个 WME
RETE 算法对于不同结点,进行 WME 或 token 和结点对应模式的匹配过程:
-
若 WME 的类型和根节点的后继结点 TypeNode 所指定的类型相同,则将该事实保存在该TypeNode 结点对应的 alpha 存储区,该 WME 被传到后继结点继续匹配或放弃后续匹配
TypeNode 存储: 每次一个 AlphaNode 被加到一个 ObjectTypeNode 时,就以字面值作为 key,以 AlphaNode 作为 value 加入 HashMap
- 当一个新的实例进入 ObjectTypeNode 时,可以直接从 HashMap 中获得正确的 AlphaNode,避免了不必要的字面检查
-
若 WME 被传递到 alpha 结点,则会检测 WME 是否和该结点对应的模式相匹配:
- 若匹配,则会将该事实保存在该 alpha 结点对应的存储区中,该 WME 被传递到后继结点继续匹配
- 否则会放弃该 WME 的后续匹配
alpha 存储:检测 WME 是否和该结点对应的模式相匹配
- 若匹配,则将该事实保存在该 alpha 结点对应的存储区中,该 WME 被传递到后继结点继续匹配
-
若 WME 被传递到 beta 结点的右端,则会加入到该 beta 结点的 right 存储区,并和 left 存储区中的 Token 进行匹配:
- 匹配成功,则会将该 WME 加入到 Token 中,然后将 Token 传递到下一个结点
- 否则会放弃该 WME 的后续匹配
bate 存储区:每个非根结点都有一个存储区
1-input(alpha)
结点有 alpha 存储区和一个输入口2-input(bate)
结点有 left 存储区和 right 存储区和左右两个输入口
其中 left 存储区是 beta 存储区,right 存储区是 alpha 存储区
WME 是为事实建立的元素,是用于和非根结点代表的模式进行匹配的元素
-
若 Token 被传递到 beta 结点的左端,则会加入到该 beta 结点的 left 存储区,并和 right 存储区中的WME进行匹配:
- 匹配成功,则该 Token 会封装匹配到的 WME 形成新的 Token,传递到下一个结点
- 否则会放弃该 Token 的后续匹配
-
若 WME 被传递到 beta 结点的左端,将 WME 封装成仅有一个 WME 元素的 WME 列表做为 Token,然后按照上述所示的方法进行匹配
-
若 Token 传递到终结点,则和该根结点对应的规则被激活,建立相应的 Activation,并存储到Agenda 当中,等待激发
-
若 WME 被传递到终结点,将 WME 封装成仅有一个 WME 元素的 WME 列表做为 Token,然后按照上述所示的方法进行匹配