作者:张渊 夏清国( 西北工业大学计算机学院, 西安710072)
出自:《科学技术与工程》 第 6 卷第 11 期 2006 年 6 月
摘要
在软件应用中若能抽取出规则, 可以使软件实体更灵活, 规则引擎使得这成为可能。其算法Rete 也逐渐发展成为了一种最重要的主流算法。先着重叙述了规则引擎的原理及其JAVA API, 其次阐述了Rete 算法, 最后简单介绍了Jess 与开源项目产品Drools。
关键词
规则引擎 Rete算法 Java API Doorls J2EE
中图法分类号 TP311.11; 文献标识码 B
JAVA 实现中, 基本分为三层, 每层又对应优秀的框架用以使开发者集中开发最关键之处, 其中包括表现层框架( Struts, JSF 等) 、持久层框架( JDO 及Entity Beans 等) 以及结构化框架(例如 EJB)。在这些框架中, 却没有商业逻辑框架。图1 显示了目前这种状态[1]。
图1 用于Java 应用的框架
这里需要规则引擎。本文着重阐述规则引擎原理及其所用Rete 算法, 并说明了两种主流框架。
在企业级目前企业发展有一种趋势, 那就是商业规则经常变动, 而且变动的原因多半来自非开发人员, 且对于即使是开发人员, 很多复杂的规则也很难推导出算法和抽象出数据模型。而且这些商业规则往往不能作为稳定的需求, 也就是说可能在设计和编码后还在变化。且业务规则往往嵌在系统各处代码中, 给系统的维护、更新带来极大困难, 更不可能让非开发人员来管理。规则引擎正是解决了这个问题。
1 规则引擎
1.1 业务规则
一个业务规则包含一组条件和在此条件下执行的操作, 它们表示业务规则应用程序的一段业务逻辑。业务规则通常应该由业务分析人员和策略管理者开发和修改, 但有些复杂的业务规则也可以由技术人员使用面向对象的技术语言或脚本来定制。
业务规则的理论基础是:设置一个或多个条件, 当满足这些条件时会触发一个或多个操作[3]。
1.2 规则引擎的架构
规则引擎的架构如 图2所示:
规则引擎的推理步骤如下:
a. 将初始数据输入至工作内存;
b. 使用模式匹配将规则库中的规则和数据比较;
c. 如果执行规则存在冲突, 即同时激活了多个规则, 将冲突的规则放入冲突集合;
d. 解决冲突, 将激活的规则按顺序放入议程中;
e. 执行其中的规则;
重复步骤b 至e, 直到执行完毕议程中的所有规则。任何一个规则引擎都需要很好地解决规则的推理机制和规则条件匹配的效率问题。当引擎执行时, 会根据规则执行队列中的优先顺序逐条执行规则执行实例, 由于规则的执行部分可能会改变工作区的数据对象, 从而会使队列中的某些规则执行实例因为条件改变而失效, 必须从队列中撤销;也可能会激活原来不满足条件的规则, 生成新的规则执行实例进入队列。于是就产生了一种“动态”的规则执行链, 形成规则的推理机制。这种规则的“链式”反应完全是由工作区中的数据驱动的。
2 Rete 算法
2.1 简介
大部分规则引擎产品的算法, 基本上都来自于Charles Forgy 博士于1979 年提出Rete 算法及其变体, Rete 算法是目前效率最高的一个前向链形推理算法, 其核心思想是将分离的匹配项根据内容动态构造匹配树, 以达到显著降低计算量的效果。
2.2 算法描述
Rete 模式匹配算法是在模式匹配中利用推理机的时间冗余性和规则结构的相似性, 通过保存中间去处来提高推理效率的一种模式匹配算法。
在模式匹配过程中, 规则的前提中可能会有很多相同的模块, 因此在匹配规则前提时, 将进行大量的重复运算, 这样就带来时间冗余性问题。例如:
RULE1:if (A>B) and D or C then E=100
RULE2:if (A>B) and (B<C) then E=200
RULE3:if (!(A>B) or (B<C)) then E=300
若要匹配这3 条规则时, 对于表达式A>B 要进行三次计算, 对B<C 需要两次计算。Rete 采用的方法为: 令M1=A>B, M2=B<C; 则规则可改为:
RULE1:if (M1) and D or C then E=100
RULE2:if (M1) and (M2) then E=200
RULE3:if (!(M1) or (M2)) then E=300
这样只有当A 或B 发生变化时, 才重新计算E1; 同样当B 或C 发生变化时, 重新计算E2。这样的推理避免了在每次进行模式匹配都重复计算相同的表达式, 而只要检测相关参数是否变化来决定是否更新表达式, 这样在推理过程中节省了大量时间和开销, 从而提高了推理效率。
3 两种主流规则引擎简介
JSR94 规范定义了一组规则引擎的JAVA API,描述了一系列规则引擎的基本操作。这一系列操作的定义是基于一个假设, 即大多数客户端需要执行一个多步规则引擎周期: 解析规则, 把对象放入引擎, 命中规则, 和从引擎中获取结果对象。
规范定义的类和接口在javax.rules 和javax.rules.admin 包中。javax.rules 中包含用于规则引擎运行时客户端的类和接口, 它们提供了从一个注册的规则执行集获取规则会话( rule session) , 并和规则会话交互的方法。而管理API 提供了从外部资源, 加载规则执行集的方法, 这些外部资源包括URI、输入流、XML 文档、二进制抽象语法树和Reader。管理API 还包括注册和注销规则执行集的方法。只有注册的规则执行集才能够通过运行时客户API 访问。
比如: Sandia National 实验室的Jess 规则引擎;开源软件Drools 规则引擎等[5]。
3.1 Jess
在Jess 中, 规则的表达形式沿用了CLIPS 的语法结构, 通过对规则前件和后件的限定, 它可以支持内容丰富的模式匹配语言。另外, Jess 支持面向过程的编程方式, 它提供了一些语句来控制规则后件的操作流程, 如使用if...then...else 和while...do...语句, 这样它就能很有效地利用面向过程编程的优势。总之, Jess 的这些特性使系统拥有很强的知识表示能力。
例如:
( defrule library- rule- 1
( book ( name ?X) ( status late) ( borrower ?Y) )
( borrower ( name ?Y) ( address ?Z) )
=>
( send- late- notice ?X ?Y ?Z) )
这套规则可以被翻译作中文这样理解: Thisrule might be
库规则#1:
如果出现一本超期的名字为X 的书, 它是名字为Y 的人所借, 并且, Z 知道借者的地址, 则给Y 发送一条关于X 书的通知到Z 处[6]。
3.2 Drools
Drools 也是基于Charles Forgy' s 的Rete 算法的, 专为Java 语言所设计的规则引擎。Rete 算法应用于面向对象的接口将使基于商业对象的商业规则的表达更为自然。Drools 是用Java 写的, 但能同时运行在Java 和.Net 上。
Drools 提供了声明式程序设计(DeclarativeProgramming) , 并且使用域描述语言(Domain Specific Languages(DSL) ) 为问题域定义了某种模式的Xml, 从而可以用来描述用户问题域。DSLs 包含的Xml 元素( Element) 和属性(Attribute) 代表了问题域中各种要素。例如:规则集是符合特定模式的Xml 文件( 详见XmlSpy 的链接)。规则“语言”实际就是Portal 表达软件包的使用, 可以扩充以满足规则引擎的额外要求。
Drools规则集的扩展名为.rls, 一般包括标签〈cr:rule- set〉、规则〈cr:rule〉、每个规则中又定义有测试条件〈cr:condition〉与动作〈cr:actions〉。
例如:
<rule- set name="test rules"
<rule name="books">
<parameter identifier="x">
<java:class>com.zhang.rules</java:class>
</parameter>
<java:condition>x.getStatus( ) .equals( "y:borrower")</java:condition>
<java:consequence>vo.setMassage( z,"late book")</java:consequence>
</rule>
</rule- set>
4 结束语
基于Rete 算法的Java 规则引擎API (JSR- 94)允许客户程序使用统一的方式和不同厂商的规则引擎产品交互, 一定程度上给规则引擎厂商提供了标准化规范。但其几乎没有定义什么是规则引擎,当然也没有深入到规则是如何构建和操纵的、规则调用的效用、规则与Java 语言的绑定等方面。并且JSR- 94 在对J2EE 的支持上也不足[1]。Jess 与Drools则各有千秋, 但规则语言的标准化, JSR- 94 的进一步的充实深化都有待研究。
致谢: 感谢李广生、张河清、欧建深给予我的帮助。
参考文献
1 Browne P. Using Drools in your enterprise java application. http://www.onjava.com/pub/a/onjava/2005/08/24/drools. html. 08/2005
2 Rupp N A. An introduction to the Drools project, http://www.theserverside.com/articles/content/Drools/article.html.05/2004
3 何仁杰, 梁冰. 用规则引擎替换代码. http://blog.csdn.net/csdnloading/archive/2005/02/02/277276.aspx. 2004
4 李国乐. Java 规则引擎与其API . http:/ /www- 128. ibm. com/developerworks/cn/java/j- java- rules/#IDACCWOB. 07/2005
5 JSR94:Java Rule Engine APIhttp://jcp.org/en/jsr/detail?id=94.2005
6 Ernest J. Friedman- Hill .Jess, The Java Expert System Shell http://herzberg.ca.sandia.gov/jess. 1997