Rete算法初探

关于rete算法的介绍,能找到的资料不少,但是往往对初学者不友好,一上来就是一堆Fact,TypeNode,AlphaNode之类的术语,非常容易劝退。这里总结一下自己的学习过程,希望从问题出发,方便理解rete算法本身。

举个例子:

例如:我们需要将提供“机票+酒店”、“机票+酒店+贵宾休息室”两种类型的产品给旅客。
机票、酒店、贵宾休息室需要满足一些基本的限制条件。并且:
“机票+酒店”产品要保障:酒店位于目的地且到达当天可以入住。
“机票+酒店+贵宾休息室”产品要保障:酒店位于目的地且到达当天可以入住。贵宾休息室位于出发城市。

假设机票有10种类型,酒店有10中类型,休息室有10种类型,如果通过普通编程的方法需要用3个for循环嵌套,计算量为3个类别的笛卡尔积10*10*10 =1000。接下来看下通过rete算法解决问题。

Rete算法:

规则(rule):

首先是规则的定义,这里直接引用了另一个例子因为我觉得描述的很清楚,同时会把相关概念关联到上面的case:

解释下,A、B、C相当于我们上面的类型,可以想象成A是机票,B是酒店,C是休息室。那么a1,a2相当于机票的属性,同样b1、b2相当于酒店的属性。上面的规则可以理解为(yy的),a1=1(仓位=头等舱),b3=a2(酒店的所在地=机票的目的地),c1=b2(贵宾室的公司=酒店的集团) 。这里只是便于大家理解,这个case 并不直接等同于上面那个问题的解决方案。

这里沿用资料上的case,再增加2个规则。

可以理解为rule_1 是一种组合或者套餐的规则,同样另外2种是其他套餐的组合规则。

事实(Fact)

这个相当我们持有数据,在这个case 里面相当于是机票,酒店,贵宾室的各种数据。

这里的类型有点多,大家对着上面理解就行了。比如有2条A数据,就代表2个航班的机票信息,有3个B,代表3家酒店的信息。

具体示例代码可以参考:MyJavaProject/base/src/main/java/com/hz/yk/drools/demo3 at master · ykdsg/MyJavaProject · GitHub

Rete 网络

根据上面的规则就可以构造rete网络了,结合上面Fact提供的数据方便大家理解。

整个网络划分为2部分,Alpha 网络和Beta网络。

Alpha 网络

图上最左边的Fact 很多地方叫Root Node ,从这里出发,首先遇到的是TypeNode,提供按对象类型过滤的能力。如下图,Cheese类型的事实进入网络后,只需经过Cheese ObjectTypeNode之后的节点。

紧接着后面椭圆形框的select node,更常见的叫法是Alpha Node,主要进行同对象类型内属性的约束或常量测试。类似上面的A.a1=1,B.b1=2

接着就是Alpha Memory,用于保存通过Alpha Node的数据,就是上图中直角方块部分。

Beta 网络

首先是BetaNode,拥有两个输入的节点。用于比较两个对象。两个对象可能是相同或不同的类型。Beta Node主要包含Join Node 和 Not Node两种类型。我们这里只用到了Join Node,通常这块也是实现rete算法的核心。

经过BetaNode 之后会把结果存入Beta Memory,这里跟Alpha Memory很像。这里上图的case中,经过a2==b3 这个Beta Node 之后,是2个type的笛卡尔积,比如上面进入Beta Memory的是A(1,100,a_1),B(2,10,100,b_1)  ;A(1,100,a_1), B(2.11.100,b_2) 。所以如果A对应的Alpah Memory 如果有2个结果,那么这里的Beta Memory 就会有4个。所以如果规则设计的不是很好,这里的内存大小很容易膨胀。再往下也是一样的,通过条件的内容进行笛卡尔积。最后到达Terminal Node。就是规则运算的结果。

总结:

用空间换时间,首先保存了中间结果(通过Alpha Memory,Beta Memory),类似机票、酒店、贵宾室的case,如果通过普通编程的方法需要用3个for循环,计算次数为3个类别数量的笛卡尔积,假设分别都是10,那就是10*10*10 。通过rete算法,计算次数为10+10+10(Alpha节点计算次数),加上2次join操作(Beta节点计算次数)。这样的话相当于如果条件维度(机+酒+景点+。。。)越多,不同规则之间存在相同子条件越多(A规则:机所在地 & 酒店所在地;B规则:酒店所在地 & 景点所在地。那么酒店所在地这个子条件就是相同的),那么rete算法相比普通编程的优势就越大。

带来的问题:

  • 事实可能存在重复保存,比如匹配 Alpha节点1的Fact1,跟匹配Alpha节点2的Fact1,会分别保存在相应的节点缓存中。在某些场景下会大量占用空间。
  • 经过beta node 计算之后,内联的数据量可能比较大。在整个网络很大的情况下这个数据量不好评估。很有可能会造成内存爆炸。

最后想说的,网上的资料到处是抄来抄去的,很多关键点也说的不清楚,后来想通过看下Drools 的源码来了解,但是作为一个工业级的引擎里面有太多性能和可靠性的考虑,充斥了较多无关的代码,非常容易看晕,而且网上关于Drools 源码分析的基本没有,最多的是Drools的使用说明。

推荐:

  1. 有个python的项目py_rete (GitHub - cmaclell/py_rete: Python RETE algorithm ),实现比较精简,如果是研究源码的话,是个更好的选择。
  2. 《AnIntroductionToTheReteAlgorithm》 应该是老外提供的ppt

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值