`
hxpwork
  • 浏览: 109555 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

技巧:使用规则寻找最大值

阅读更多
 

使用规则寻找最大值<o:p></o:p>

<o:p> </o:p>

<o:p> </o:p>

原文网址:http://wiki.jboss.org/wiki/Wiki.jsp?page=RulesFindMax<o:p></o:p>


有时你可能想查找fact的最大值。你可以通过使用not实现这个目的,如下例所示(如果你喜欢也可以将它放在一个Query中):<o:p></o:p>

<o:p> </o:p>

rule "Highest Temperature for a Day"<o:p></o:p>

       when<o:p></o:p>

               Day(highest : temp)<o:p></o:p>

               not Day(temp > highest)<o:p></o:p>

       then...<o:p></o:p>

<o:p> </o:p>

感谢Mitch Christensen 提供建议. <o:p></o:p>

[译者注:<o:p></o:p>

   这里为一些初学者解释一下上面规则的执行思路,在说明之前我们先回顾Drools中对于Fact匹配有一个原则:在没有限制条件的情况下,引擎寻找最大限度的组合<o:p></o:p>

   回到规则分析,假设在Working Memory中设置了三个Day对象,temp分别是102030;那么考虑一下规则引擎如何执行。<o:p></o:p>

   首先规则的第一个条件是Day(highest : temp)没有对Day有过滤限制,则上面三个Day对象都会尝试激发"Highest…"规则。假设Day(10)先进入,则对第二个条件,因为highest是上一个条件传过来的变量,所以引擎会为highesttemp建立3种组合:[ Day(10) , Day(10) ] [ Day(10) , Day(20) ] [ Day(10) , Day(30) ],显然后两种组合对于not Day(temp > highest)是不成立的。由此类推只有当Day30)尝试激发规则时才能满足两个条件。<o:p></o:p>

]<o:p></o:p>


Fact的排序过程<o:p></o:p>

类似的方法通常用来对一组关联的fact进行排序处理。例如,要按照timestamp(时间戳)的顺序处理一组Alert Fact,你可以如下进行:<o:p></o:p>

rule "Process Alerts by time received"<o:p></o:p>

    when<o:p></o:p>

        $alert : Alert($oldest : timestamp)<o:p></o:p>

        not Alert(timestamp < $oldest)<o:p></o:p>

    then<o:p></o:p>

        // process the Alert in some application specific way<o:p></o:p>

        $alert.process()<o:p></o:p>

<o:p> </o:p>

        // 必须将处理过的AlertWorking Memory中删除<o:p></o:p>

        // 否则引擎不会对Working Memory中的Fact重新评估<o:p></o:p>

        retract($alert);<o:p></o:p>

end<o:p></o:p>

该规则将按照Alert中的timestamp属性的早晚来依次进行处理,完成处理的Alertworking memory中删除,接着进行下一个的处理。<o:p></o:p>

-Mitch Christensen <o:p></o:p>


Mitch 提供的这种模式是最简单的但不是最有效率的。简单来说,如果有1000Day对象在Working Memory中,则引擎要对 (1+2+…+1000)种组合进行判断(考虑到Drools引擎在碰到第一个不满足条件的组合时就会抛弃Fact)。显然在Day对象数量过于庞大时,这种判断方法会成为性能瓶颈。因此下面是改进后的判断最大值规则:<o:p></o:p>

<o:p> </o:p>

rule "Try day"<o:p></o:p>

   when<o:p></o:p>

       $d : Day($temp : temp)<o:p></o:p>

   then<o:p></o:p>

       assert(new TryDay($d));<o:p></o:p>

end<o:p></o:p>

<o:p> </o:p>

rule "Highest unknown"<o:p></o:p>

   when<o:p></o:p>

       $attempt : TryDay($d : day)<o:p></o:p>

       not (Highest())<o:p></o:p>

   then<o:p></o:p>

       assert (new Highest($d));<o:p></o:p>

end<o:p></o:p>

<o:p> </o:p>

rule "Highest lower"<o:p></o:p>

   when<o:p></o:p>

       $highest: Highest($highDay : day)<o:p></o:p>

       $attempt : TryDay($day : day -> ($day.getTemp() > $highDay.getTemp()))<o:p></o:p>

   then<o:p></o:p>

       $highest.setDay($day);<o:p></o:p>

       modify($highest);<o:p></o:p>

end<o:p></o:p>

<o:p> </o:p>

rule "Highest higher"<o:p></o:p>

   when<o:p></o:p>

       Highest($highest: day)<o:p></o:p>

       $attempt : TryDay($day : day -> ($day.getTemp() <= $highest.getTemp()))<o:p></o:p>

   then<o:p></o:p>

       retract($attempt);<o:p></o:p>

end<o:p></o:p>

rule "Print highest"<o:p></o:p>

   salience -10<o:p></o:p>

   when<o:p></o:p>

       Highest($day : day)<o:p></o:p>

   then<o:p></o:p>

       System.out.println("Highest day is " + $day);<o:p></o:p>

end<o:p></o:p>

Steven Williams <o:p></o:p>

经过测试,当Day的数量为1000时,Mitch的规则执行时间约2000毫秒,而Steven的规则为223毫秒;当Day的数量为2000时,Mitch的规则执行时间约8000毫秒,而Steven的规则为345毫秒<o:p></o:p>


更多关于查找最大值<o:p></o:p>

查找最大值的问题通常并不限制于对单个属性或字段进行比较。<o:p></o:p>

<o:p> </o:p>

当面对这个问题时,让我们概括它为“发现最好”或“发现最佳”的模式,这在现实中是非常有可能碰到的。如最好的投资机会,最好的网络节点,最好的保险策略等等。

这些问题有两个特点使得采用基于规则的方法具有吸引力。第一,当最好的标准经常发生变更时,规则允许我们在代码外对此进行调整(例如:对于有小孩的家庭最好的新家不一定就是没有小孩家庭的最佳选择). 第二, 最好的可能是复杂的事务, 常常难以用语言捕捉,更不用说在程序开发语言中了。

Steven Williams
在上面提供的方案,一旦在碰到更多的判断属性时,当保持性能时,规则的规模将会增加的很快。<o:p></o:p>

假设我们的任务不是仅仅发现最高的温度,而是有一个组合的温度——最高的温度与最高的dewPoint

<o:p></o:p>

public class HeatRecord<o:p></o:p>

{<o:p></o:p>

    int temp;<o:p></o:p>

    int dewPoint;<o:p></o:p>

    .<o:p></o:p>

    .<o:p></o:p>

}<o:p></o:p>

一个简单的解决方案可能是: <o:p></o:p>

rule "Filter" // 测试每一个,如果被另一个超越则删除<o:p></o:p>

        salience 100<o:p></o:p>

        when<o:p></o:p>

               HR1 : HeatRecord($t1:temp, $d1:dewPoint )<o:p></o:p>

               HeatRecord( temp > $t1 ) || HeatRecord( temp == $t1, dewPoint > $d1  )<o:p></o:p>

        then <o:p></o:p>

               retract( HR1 );<o:p></o:p>

end<o:p></o:p>

<o:p> </o:p>

rule "Report" // 报告留下了什么<o:p></o:p>

        salience 50<o:p></o:p>

        when<o:p></o:p>

               HR1 : HeatRecord( )<o:p></o:p>

        then<o:p></o:p>

               System.out.println("The Most Sweltering Conditions were: " + HR1.getTemp() +" "+ HR1.getDewPoint() ); <o:p></o:p>

end<o:p></o:p>

<o:p> </o:p>

如果我们试图使用Steven Williams 提到的方法,它将会是多大?怎样维护? <o:p></o:p>

想一想?
Mike Panihill <o:p></o:p>

<o:p> </o:p>

分享到:
评论

相关推荐

    arcgis工具

    如果搜索不需要区分大小写,可以使用SQL函数将所有的值都转换成大写或者小写。对于基于文件的数据源,例如shape文件或coverages,既可以使用UPPER函数,也可以使用LOWER函数。 例如下面这个查询将选出那些姓名的...

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    8.6.1 例子:使用First_value来计算最大值 206 8.6.2 例子:使用Last_value来计算最小值 207 8.7 其他分析函数 207 8.7.1 Nth_value(11gR2) 207 8.7.2 Rank 209 8.7.3 Dense_rank 210 8.7.4 Row_number 211 ...

    内存管理内存管理内存管理

    文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...

    操作系统(内存管理)

    我们主要使用连接的指针遍历内存来寻找开放的内存块。这里是代码: 清单 6. 主分配程序 void *malloc(long numbytes) { /* Holds where we are looking in memory */ void *current_location; /* This is ...

    黄冈中学高一数学教案

     则Sn就是S1,S2,…,S12中的最大值,由于   解法二:   解法三:  由d可知,a1&gt;a2&gt;a3&gt;…&gt;a12&gt;a13,  ∴ 在1≤n≤12中,存在自然数n,使得an&gt;0,an+1,则Sn就是S1,S2,S3,…,S12中的最大的.    故在S1,...

    你必须知道的495个C语言问题

    然后又使用一些内存分配技巧使namestr数组用起来好像有多个元素,namelen记录了元素个数。它是怎样工作的?这样是合法的和可移植的吗? 2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确说明...

    《你必须知道的495个C语言问题》

    然后又使用一些内存分配技巧使namestr数组用起来好像有多个元素,namelen记录了元素个数。它是怎样工作的?这样是合法的和可移植的吗? 23  2.8 我听说结构可以赋给变量也可以对函数传入和传出。为什么K&R1却明确...

    C语言FAQ 常见问题列表

    然后又使用一些内存分配技巧使 namestr 数组用起来好像有多个元素。这样合法和可移植吗? o 3.7 是否有自动比较结构的方法? o 3.8 如何向接受结构参数的函数传入常数值? o 3.9 怎样从/向数据文件读/写结构? ...

    C#微软培训资料

    4.1 值 类 型 .28 4.2 引 用 类 型 .33 4.3 装箱和拆箱 .39 4.4 小 结 .42 第五章 变量和常量 .44 5.1 变 量 .44 5.2 常 量 .46 5.3 小 结 .47 第六章 类 型 转 换 .48 6.1 隐式类型转换 .48 6.2...

    你必须知道的495个C语言问题(PDF)

    然后又使用一些内存分配技巧使namestr 数组用起 来好像有多个元素。这样合法和可移植吗? . . . . . . . . . . . . 8 2.7 是否有自动比较结构的方法? . . . . . . . . . . . . . . . . . . . . 8 2.8 如何向接受...

    传智播客扫地僧视频讲义源码

    01_初学者的企业用人标准寻找引言 02_socketclient_api模型的抽象_初学者应知的标准_传智扫地僧 03_本套视频总体课程简介 04_就业班课程总体简介_课堂答疑 05_初学者建立信心 06_学员学习标准_排序及问题抛出 07_...

Global site tag (gtag.js) - Google Analytics