1 简介
1.1 规则
- 每条规则都是一组条件决定的一系列结果
- 一条规则可能与其他规则共同决定最终结果
- 可能存在条件互相交叉的规则,此时有必要规定规则的优先级
规则作为一种知识,其典型运用就是通过实际情况,根据给定的一组规则,得出结论。这个结论可能是某种静态的结果,也可能是需要进行的一组操作。
规则语言可以分为结构化的(Structured)和基于标记的(Markup,通常为xml)。
常见的结构化的规则描述语言:
- srl(Structured Rule Language)
- drl(Drools Rule Language)
常见的基于标记的规则描述语言:
- RuleML(Rule Markup Language)
- SRML(Simple Rule Markup Language)
- BRML(Business Rules Markup Language)
- SWRL(A Semantic Web Rule Language)
1.2 推理机
运用过程叫做推理。如果由程序来处理推理过程,那么这个程序就叫做推理机/推理引擎(Inference Engine)。推理机是专家系统(专家系统是人工智能的一个分支)的核心模块。
推理引擎根据知识表示的不同采取的控制策略也是不同的,常见的类型包括基于神经网络、基于案例和基于规则的推理机。
1.3 规则引擎
基于规则的推理机易于理解、易于获取、易于管理,被广泛采用。这种推理引擎被称为“规则引擎”。
在规则引擎中,将知识表达为规则(rules),要分析的情况定义为事实(facts)。二者在内存中的存储分别称为Production Memory和Working Memory。
- rules和facts:规则引擎接受的输入参数
- Pattern Matcher:根据facts找到匹配的rules
- 正向推理(Forward-Chaining):正向推理也叫演绎法,由事实驱动,从 一个初始的事实出发,不断地应用规则得出结论。首先在候选队列中选择一条规则作为启用规则进行推理,记录其结论作为下一步推理时的证据。如此重复这个过程,直到再无可用规则可被选用或者求得了所要求的解为止。
- 反向推理(Backward-Chaining):反向推理也叫归纳法,由目标驱动,首先提出某个假设,然后寻找支持该假设的证据,若所需的证据都能找到,说明原假设是正确的;若无论如何都找不到所需要的证据,则说明原假设不成立,此时需要另做新的假设。
- Agenda:管理PatternMatcher挑选出来的规则的执行次序
- Execution Engine:在外围负责根据Agenda输出的rules执行具体的操作
1.4 规则引擎的作用
规则引擎可以将规则的定义从代码中分离出来,将推理过程封装到规则引擎内部进行处理,这带来几个好处:
- 规则外部化,即有利于规则知识的复用,也可避免改变规则时带来的代码变更问题
- 由规则引擎使用某种算法进行推理过程,不需要编写复杂晦涩的逻辑判断代码
- 开发人员的不需要过多关注逻辑判断,可以专注于逻辑处理
2 Drools
DROOLS - SAMPLE DROOLS PROGRAM
2.1 概览
完整的drl文件包含以下几个部分:package,import,declares,globals,functions,queries,rules。
|
|
2.2 package和import
与Java类似,drools头部必须要有一个package声明和import声明,且package声明必须放在规则文件的第一行。
2.3 规则定义
一个规则通常包含三个部分:attribute(属性),LHS(条件部分),RHS(结果部分)。
|
|
2.3.1 LHS(条件部分)
- 可以包含多个条件,若条件部分为空的话,引擎自动添加一个eval(true)的条件。
- 多个条件之间可使用and或or连接,默认是and关系。
- 条件的语法:[绑定变量名:]\Object([field约束])
- 绑定变量名:可在该LHS后续的条件中引用
- field约束:当前对象里相关字段的条件限制,多个约束之间用”&&”(and),”||”(or)和”,”(and)连接。约束中可使用的比较操作符包括:>, >=, <, <=, ==, !=, contains, not contains, memberof, not memberof, matches, not matchers
|
|
2.3.2 RHS(结果部分)
- RHS部分定义了当LHS满足时要进行的操作
- RHS中可以编写代码,可以使用LHS部分中定义的绑定变量名以及drl头部定义的全局变量。
- 虽然可以在RHS中直接写java代码,但不建议代码中有条件判断,否则就违背了使用规则的初衷。
2.3.2.1 使用宏函数
RHS中可以使用宏函数对工作空间进行操作。当调用宏函数后,所有为设置“no-loop”属性的规则都会呗重新分配,符合条件的重新触发。
宏函数都是StatefulSession中定义的方法,包括:
- insert:将一个Fact对象插入到当前的Working Memory
- update:对当前Working Memory中的Fact进行更新
- retract:从Working Memory中删除某个Fact对象
|
|
2.3.2.2 modify代码块
modify代码块用于快速修改并更新(update)某个 Fact 对象的多个属性。
|
|
2.3.2.3 drools宏对象
通过使用drools宏对象可以实现在规则文件里直接访问 Working Memory,从而获取对当前的 Working Memory的更多控制。
drools宏对象的常用方法包括:
- drools.getWorkingMemory():获取当前的 WorkingMemory对象
- drools.halt():在当前规则执行完成后,不再执行 其它未执行的规则
- drools.getRule():得到当前的规则对象
- drools.insert(new Object):向当前的WorkingMemory 当中插入指定的对象,功能与宏函数insert相同
- drools.update(new Object):更新当前的WorkingMemory中指定的对象,功能与宏函数update相同
- drools.update(FactHandle Object):更新当前的WorkingMemory中指定的对象,功能与宏函数update相同
- drools.retract(new Object):从当前的WorkingMemory中删除指 定的对象,功能与宏函数retract相同
2.3.2.4 kcontext宏对象
用来得到当前的KnowledgeRuntime对象,KnowledgeRuntime对象可以实现与引擎的各种交互。
2.3.3 规则属性
- salience:设置规则执行的优先级,默认值为0。数字越大越先执行,可以设置为负数,数字相同的使用随机顺序。设置该属性
salience 10
. - no-loop:默认为false。设置为true时,表示该规则只会被引擎检查一次。引擎内部对Fact更新时,忽略本规则的再次检查。
- date-effective:设置规则的开始生效日期,默认接受“dd-MMM-yyyy”格式的字符串。修改日期格式:
System.setProperty("drools.dateformat","yyyy-MM-dd")
- data-expires:设置规则的过期日期,默认接受“dd-MMM-yyyy”格式的字符串。修改日期格式:
System.setProperty("drools.dateformat","yyyy-MM-dd")
。 - enabled:设置规则是否可用,默认为true。
- dialect:设置规则中使用的编程语言,默认为java,可设置为mvel。获取该属性的设置:
drools.getRule().getDialect()
,设置该属性dialect mvel
- duration:指定延迟时间,在另一个线程中触发规则,单位为毫秒。
- activation-group:为规则划指定一个活动组(组名为字符串)。同一个活动组中的规则只执行一个,根据优先级(salience)来决定执行哪一个规则。
- agenda-group:为规则指定一个议程(agenda)组。指定了议程组的规则只有在该议程组得到焦点时才被触发。
- auto-focus:指定了auto-focus属性为true,则该规则自动得到焦点。
- ruleflow-group:指定规则流组。
- lock-on-active:当在规则上使用ruleflow-group属性或agenda-group属性的时候,将lock-on-action属性 的值设置为 true,可避免因某些 Fact 对象被修改而使已经执行过的规则再次被激活执行。
- when
2.4 注释
- 多行注释:
/*注释*/
- 单行注视:
#注释
或//注释
2.5 类型声明
todo
2.6 全局变量
todo
2.7 函数和import function
2.7.1 函数的定义和使用
函数是定义在规则文件中的一段代码,用于将规则文件中会被若干个规则复用的业务操作封装起来,减少规则编写的工作量。函数的可见范围是规则函数所在的规则文件。
函数以function定义。可以是void,也可以有返回值。
|
|
2.7.2 引入静态方法
实际应用当中,可以考虑使用在java类当中定义静态方法的办法来替代在规则文件当中定义函数。
Drools 提供了一个特殊的 import 语句:import function。通过该 import 语句,可以实现将一个java类中静态方法引入到一个规则文件当中,使得该文件当中的规则可以像使用普通的Drools函数一样来使用java类中某个静态方法。
2.8 查询定义
查询用于根据条件在当前的 WorkingMemory 当中查找 Fact。
Drools 当中查询可分为两种:
- 不需要外部传入参数
- 需要外部传入参数
|
|