• 1. Drools入门手册--许建辉
  • 2. 高尔夫球员的位置?已经知道有四个高尔夫球员,他们的名字是Fred,Joe,Bob,Tom; 今天他们分别穿着红色,蓝色,橙色以及格子衣服。并按照从左往右的顺序站成一排。 我们将最左边的位置定位1,最右边的位置定为4,中间依次是2,3位置。 现在我们已经了解的情况是: 1)高尔夫球员Fred,目前不知道他的位置和衣服颜色 2)Fred紧挨的右边球员穿蓝色的衣服 3)Joe排在第2个位置 4)Bob穿着格子短裤 5)Tom没有排在第1位或第4位,也没有穿橙色衣服 现在要求你根据上述条件获得四个球员分别的位置和穿着。 如果要求使用编程方式获得结果,这显然是一个很有挑战性的工作,你可以思考一下。 而使用规则引擎的方式来思考问题,我们其实是要从各种可能的排列中将需要的结果挑出来 因此我们只需要将球员所有可能的排列组合(位置及颜色)出来,放入Working Memory中 然后让规则引擎帮我们挑出来就可以了。 If(..){..}else{…}咱们习惯看程序!
  • 3. 引出话题--drools人工智能   人工智能(Artificial Intelligence,简称AI)是 计算机学科的一个分支,二十世纪七十年代以来被称 为世界三大尖端技术之一(空间技术、能源技术、人 工智能)。人工智能是研究使计算机来模拟人的某些 思维过程和智能行为(如学习、推理、思考、规划等 )的学科。 专家系统 所谓“专家”,一般都拥有某一特定领域的大量 知识,以及丰富的经验。在解决问题时,专家 们通常拥有一套独特的思维方式,能较圆满地 解决一类困难问题,或向用户提出一些建设性 的建议等。 什么是专家系统呢?简单地讲,专家系统就是 一个具有智能特点的计算机程序,它的智能化 主要表现为能够在特定的领域内模仿人类专家 思维来求解复杂问题。因此,专家系统必须包 含领域专家的大量知识,拥有类似人类专家思 维的推理能力,并能用这些知识来解决实际问 题。例如,一个医学专家系统就能够像真正的 专家一样,诊断病人的疾病,判别出病情的严 重性,并给出相应的处方和治疗建议等等。 例 如个人理财专家系统、寻找油田的专家系统、 贷款损失评估专家系统、各类教学专家系统等。 基于规引擎的专家系统 Java规则引擎 --drools
  • 4. 基于规则的专家系统构成知识事实推理引擎演绎法:从一个初始的事实出发,不断地应用规则得出结论(或执行指定的动作)。 归纳法:则是根据假设,不断地寻找符合假设的事实。 Rete算法 以后版本
  • 5. 基于规则的专家系统构成(1)初始化事实(2)比较规则与事实Pattern Matcher :样品匹配(3)冲突的规则 放入冲突集合(4)解决冲突,将激活的规则按顺序放入Agenda。 (5)执行Agenda中的规则
  • 6. 规则引擎相关构件 信息元(Information Unit)信息服务(Information Services)队列管理器规则集( Queue Manager Rule Set) 队列管理器(Queue Manager)
  • 7. 处理过程分为四个阶段进行
  • 8. 规则引擎工作机制
  • 9. Java规则引擎工作机制
  • 10. Java规则引擎API——JSR-941>Java规则引擎API体系结构业务规则引擎架构
  • 11. Java规则引擎API——JSR-94规则引擎API将管理API和运行时API加以分开,从而为这些包提供了较好粒度的安全控制.规则引擎API并没有提供明显的安全机制,它可以和J2EE规范中定义的标准安全API联合使用.安全可以由以下机制提供,如Java authentication and authorization service (JAAS),the Java cryptography extension (JCE),Java secure Socket Extension (JSSE),或者其它定制的安全API.JAAS能被用来定义规则执行集的许可权限,从而只有授权用户才能访问。2>Java规则引擎API安全问题
  • 12. Java规则引擎API——JSR-943>异常与日志 规则引擎API定义了javax.rules.RuleException作为规则引擎异常层次的根类.所有其它异常都继承于这个根类.规则引擎中定义的异常都是受控制的异常(checked exceptions),所以捕获异常的任务就交给了规则引擎。规则引擎API没有提供明确的日志机制,但是它建议将Java Logging API用于规则引擎API。
  • 13. 规则语言
  • 14. 规则语言规则文件通常是以drl扩展名结尾规则的 规则文件的完整结构 package package-name imports globals functions Queries rules规则文件
  • 15. 规则语言规则具有如下主体结构: rule "name"      attributes      when          LHS     then          RHS end 两边的引号也是可选的 ATTRIBUTES(通常是可选项)指出规则的行为表现 LHS是规则的条件部分 RHS是允许Java语义代码 规则构成
  • 16. 规则语言尽力避免使用的: rule query when then end null and or not exists collect accumulate from forall true false eval 避免使用 package function global import template attributes enabled salience duration init action reverse result contains excludes memberOf matches in date-effective date-expires no-loop auto-focus activation-group agenda-group dialect rule-flow-group规则保留字
  • 17. 规则语言单行注释 # this is a single line comment // this is also a single line comment 多行注释 /* this is a multi-line comment */注释
  • 18. 规则语言Package
  • 19. Import 标记就像java中的含义一样。对于任何要用在规则中的对象,你需要指定完整的路径和类型名。Drools从同名的java包中自动导入类。 expander Expander标记是可选的,用来指定DSL配置(通常保存在独立文件中)。这为解析器提供了如何理解你自定义的规则语言。 API允许用编程方式附加DSL模板,如果expander没有声明在源文件中。规则语言
  • 20. Global不会插入到Working Memory中,因此当全局变量发生改变时,引擎不会得知;因为这个原因,全局变量不能用在条件约束上,除非这个值不会发生改变。在条件约束中错误使用全局变量会导致意想不到的结果。引擎不会通知和跟踪全局变量的值变更。不正确的在约束中使用全局变量会带来让人惊讶的结果——糟糕的惊讶,就像医生对你的X光片说“那里有些有趣的东西”一样。 如果多个Package声明了同样的全局变量,那么它们必须有相同的类型,并指向同一个全局变量。规则语言global全局变量 为了使用全局变量,你必须 在规则文件中声明全局变量并使用它 global java.util.List myGlobalList; rule "Using a global" when eval( true ) then myGlobalList.add( "Hello World" ); end在working memory上设置全局变量的值。最好是在将fact插入working memory之前设置完所有全局变量 List list = new ArrayList(); WorkingMemory wm =rulebase.newStatefulSession(); wm.setGlobal( "myGlobalList", list );
  • 21. 规则语言Function 函数最大的用处是被规则的推论(then)部分中的行为所调用,特别是当一个行为操作需要反复被调用时——如发送邮件。典型的函数声明如下所示: function String hello(String name) { return "Hello "+name+"!"; } Drools4.0支持静态方法导入 import static my.package.Foo.hello rule "using a static function" when eval( true ) then System.out.println( hello( "Bob" ) ); end
  • 22. 规则语言Rule LHS:规则指定“when”作为一系列条件的集合 RHS :指定一系列操作 规则不能进行嵌套 规则语法 rule "" * when * then * end规则示例 rule "Approve if not rejected" salience -100 agenda-group "approval" when not Rejection() p : Policy(approved == false, policyState:status) exists Driver(age > 25) Process(status == policyState) then log("APPROVED: due to no objections."); p.setApproved(true); end
  • 23. 规则语言Rule 属性 要从Drools中获得最大的收获,你必须十分的了解每一个属性。
  • 24. N/A是指表格中空出的地方要填的一栏,与你的情况不合。例如:有的表格问你有几个孩子,你连结婚都没有结,自然填N/A。 注释关键字默认值 类型描述no-loop false Boolean 当规则在推论中对fact进行修改后,可能会导致该规则的重新激活,引起递归。设置no-loop为true可以阻止该规则被再次激活。salience 0integer 每一个规则有一个整数类型的优先级属性,默认为0,这个整数可以使正负数。优先级数字高的规则会比优先级低的规则先执行。agenda-group MAIN String Agenda group允许用户对分隔Agenda执行区提供更多的控制。只有在具有焦点的agenda group中的规则才能够激发。auto-focusfalse Boolean 自动获取焦点 。 当规则的auto-focus属性为true时,如果该规则符合激活条件,则该规则所在agenda-group自动获得焦点,允许规则激发。 activation-group N/A String 在同名activation-group中的规则将以互斥的方式激发。这个意思时在这个组中第一条被激发的规则将取消其它规则的激发,即使它们已经在激发队列中。Activation-group属性可以是任何字符,只要所有你需要放在同一个组中的规则中的activation-group属性是相同的即可。 注:这个组之前被称为Xor-group,但是从技术上来说它与Xor并不完全一样,但是当你听到别人说xor-group时,你知道这就是activation-group。dialect 由Package指定默认值 可能值: "java" or "mvel"String Dialect指定在LHS代码表达式或RHS代码块中使用的语言。当前两种语言有效,Java和MVEL。Dialect可以在Package级别统一指定,而Rule属性中指定的dialect将局部覆盖掉Package中的定义。date-effective N/A String 包含日期/时间定义 规则只能在date-effective指定的日期和时间之后激活。date-exptires N/A String, 包含日期/时间定义 如果当前时间在date-expires指定的时间之后,规则不能激活。duration N/A long Duration指出规则将在指定的一段时间后激发,如果那个时候规则的激活条件还是处于true的情况下。
  • 25. 规则语言LHS (when) 条件元素 LHS是空的,那它被重写为eval(true) rule "no CEs" when then * endrule "no CEs" when eval( true ) then * end
  • 26. 规则语言LHS (when) 条件元素 模式实体关系图
  • 27. 规则语言LHS (when) 条件元素 Compound:复合的 Restriction:限制, 约束 Constraint:约束, 强制 Pattern:模范, 式样, 模式, 样品
  • 28. 字段约束分为单值约束,复合值约束和多重约束 规则语言LHS (when) 条件元素 Field Constraints 字段约束
  • 29. 规则语言LHS (when) 条件元素 单值约束 操作符: 正则表达式约束:字段匹配(Matches)用于任何有效的Java正则表达式。 Cheese( type matches "(Buffalo)?\S*Mozerella" ) Cheese( type not matches “(Buffulo)?\S*Mozerella” ) ‘contains’ 用来检查是否字段的集合或数组包含指定的对象。 CheeseCounter( cheeses contains "stilton" ) // contains with a String literal CheeseCounter( cheeses contains $var ) // contains with a variable not containts用来检查是否字段的集合或数组不包含指定的对象。 CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal CheeseCounter( cheeses not contains $var ) // not contains with a variable 注意: 为向后兼容性,'excludes'作为'not contains'的一个同义字提供。
  • 30. ‘memberof’ 用来检查字段是否是集合或数组的成员;集合必须是绑定的变量。 CheeseCounter( cheese memberof $matureCheeses ) 'not memberof'用来检查字段是否不是集合或数组的成员;集合必须是绑定的变量。 CheeseCounter( cheese not memberof $matureCheeses ) 字符串约束 字符串约束是最简单的约束格式,将字段与指定的字符串求值:数值,日期,string或者boolean。 Cheese( quantity == 5 )//数值 Cheese( bestBefore < "27-Oct-2007" )//日期 Cheese( type == "stilton" )//字符串 Cheese( smelly == true )// boolean ,注 不允许 Cheese(smelly) Cheese( smelly == SomeClass.TRUE )// boolean 绑定变量约束 '$',这通常用来显示变量与字段的区别 Person( likes : favouriteCheese )//任何匹配的Person实例的favouriteCheese字段 Cheese( type == likes ) $stilton : Cheese( type == "stilton" ) Cheesery( cheeses contains $stilton )规则语言LHS (when) 条件元素
  • 31. 返回值约束 Person( girlAge : age, sex == "F" ) Person( age == ( girlAge + 2) ), sex == 'M' ) 复合值约束 复合值约束用在可能有多个允许值的时候,当前只支持‘in’ 和‘not in’两个操作。 'in' 和'not in'运算式实际上被语法分析器重写成多个!= and ==组成的多重约束。 Person( $cheese : favouriteCheese ) Cheese( type in ( "stilton", "cheddar", $cheese ) 多重约束 Person( age > 30 && < 40 ) Person( age ( (> 30 && < 40) || (> 20 && < 25) ) ) Person( age > 30 && < 40 || location == "london" ) 内联的Eval约束 Inline-eval约束可以使用任何有效的语言表达式,只要它最终能被求值为boolean 元数据类型——避免使用任何Drools关键字作为声明。自动代入 (autovivification)机制用来自动建立字段绑定变量.当构建器发现标识不是当前 定义的变量名是,它将尝试将它作为对象的字段来问,这种情况下,构建器自动在 inline-eval中建立该字段的同名变量 Person( girlAge : age, sex = "F" ) Person( eval( girlAge == boyAge + 2 ), sex = 'M' ) 规则语言LHS (when) 条件元素
  • 32. 嵌套访问 ********** and &&’符合作为‘and’的同义选择,不推荐使用 Or ‘||’符号作为or的同义操作,不推荐使用,只是因为历史的原因在语法中保留。 Eval 本质上是一个大杂烩(catch all),它允许任何语义代码被执行,只要最后返回一个boolean值。 not not Bus(color == "red") not ( Bus(color == "red", number == 42) ) not ( Bus(color == "red") and Bus(color == "blue")) exists exists Bus(color == "red") exists ( Bus(color == "red", number == 42) ) //brackets are optional exists ( Bus(color == "red") and Bus(color == "blue")) 规则语言LHS (when) 条件元素
  • 33. Forall Forall条件元素在Drools中完全支持一阶逻辑。Forall条件元素在所有匹配最初模 式的fact也同时匹配后面的模式的情况下为true。 rule "All english buses are red" when forall( $bus : Bus( type == 'english') Bus( this == $bus, color = 'red' ) ) then # all english buses are red end规则语言LHS (when) 条件元素
  • 34. 规则语言注释
  • 35. 规则语言注释
  • 36. RHS是对于规则的推论或操作部分的简称;这部分应当包含一系列需要执行的操作。 在RHS中使用命令式或条件式代码是不好的习惯,因为规则应当是原子态的——“什么时候这样,然后就做这些”,不是“什么时候这样,可能做这些”。规则的RHS部分应该保持简短的,这保持它是声明性和可读性的。如果你发现你需要在RHS中使用命令式或and/or条件代码,那你可能需要将规则拆分为多个规则。 RHS的主要目的是插入,删除修改working memory数据。这里有一些方法帮助你用来修改working memory;不需要首先引用working memory实例。规则语言The Right Hand Side (then)
  • 37. "update(object, handle);" 将告诉引擎对象已经改变(已经被绑定到LHS中的那一个),并且规则需要重新检查。 "insert(new Something());" 将在working memory中放置一个你新建的对象。 “insertLogical(new Something());” 与insert类似,但是当没有更多的fact支持当前激发规则的真值状态时,对象自动删除。 "retract(handle);" removes an object from working memory. 如果你为插入引擎的java bean对象提供属性变更监听器,那么当对象改变时可以不用调"update" 查阅KnowledgeHelper接口获得更多高级操作 KnowledgeHelper接口在RHS代码块中可以通过一个名称是drools的变量访问。规则语言The Right Hand Side (then)
  • 38. 对自动封箱/拆箱 现在的jdk1.5和jdk5规则自动在这种情况下进行封箱/拆箱处 理。当进行字段约束的求值时,系统尝试强制将值变为可 比较的格式,因此元数据可以与对象封装器进行比较。 规则语言The Right Hand Side (then)
  • 39. 查询中仅仅包含规则LHS部分的结构(不用指定when或then)。它提供了查询working memory 中符合约束条件的对象的一个简单办法。 要获得查询结果,使用 WorkingMemory.getQueryResults("name"),”name”就是指query的名称。查询名称对于RuleBase来说是全局性的,因此在为一个RuleBase服务的不同Package中不要使用重复的查询名称。规则语言Query
  • 40. 规则语言Query的一个例子query "people over the age of 30" person : Person( age > 30 ) End 规则定义文件QueryResults results = workingMemory.getQueryResults( "people over the age of 30" ); System.out.println( "we have " + results.size() + " people over the age of 30" ); System.out.println( "These people are are over 30:" ); for ( Iterator it = results.iterator; it.hasNext(); ) { QueryResult result = ( QueryResult ) it.next(); Person person = ( Person ) result.get( "person" ); System.out.println( person.getName() + "\n" ); } JAVA调用代码
  • 41. 设置规则所属的规则流组 rule 'YourRule' ruleflow-group 'group1' when ... then ... end 规则流规则流
  • 42. 规则语言规则流使用eclipse新建规则流