6.Making Your Own Rules
~表示取反
6.7.salience和conflict resolution
每个rule都有一个称为salience的属性,用于表述rule的优先级。所以被触发的rule中优先级最高的第一个执行,依此类推。在rule中包含一个salience声明可以迫使其总是最先或最末执行。
Jess> (defrule example-6 (declare (salience -100)) (command exit-when-idle) => (printout t "exiting..." crlf))
salience的值越小执行次序越靠后,反正则靠前。默认的salience值为0。salience的值可以是正数、全局变量或程序调用(参考set-salience-evaluation命令)。
当有多条salience优先级相同的rule被触发时,rule执行的先后次序由conflict resolution strategy决定。Jess自带两种策略:
"depth"(默认策略)
"breadth"
在"depth"策略中,最近被触发的rule将优先与其他含有相同salience的rule而先被执行。
在"breadth"策略中,rule根据其被触发的先后次序执行。
在多数情况下这两种策略差别造成的影响并不大,但在有些问题中conflict resolution
strategy却至关重要。可以用Java编写自定义的strategy,参考"extending Jess with Java"一章。可以使用set-strategy命令来设置当前strategy。
注意:通常不建议使用salience,原因如下:一、试图强迫rule按某一特定次序执行在基于rule的编程中被认为是一种不健壮的方式。二、使用salience将会对执行过程产生负面影响,至少对其自带的conflict resolution strategy不利。
可以通过agenda命令查看已被激活(activated)但尚未执行(fired)的rule列表。
6.8."and"
多个pattern可以由add连成一个列表。当且仅当列表中所有的pattern都匹配时,该列表才算匹配。单独的and使用并不复杂,但加入or和not这样的条件元素后,可以用于构建复杂的逻辑条件。
每个rule的LHS(左手边)的所有条件暗含了and条件元素。
6.9."or"
多个pattern可以由or连成一个列表。只要列表中有一个或多个pattern匹配时,该列表就算匹配。如果有超过一个subpattern匹配,则or已被匹配了超过一次:
Jess> (defrule or-example-1 (or (a) (b) (c)) =>) Jess> (assert (a) (b) (c)) Jess> (printout t (run) crlf)
3
一组and连接的pattern组可以嵌入一个or连接的pattern,反之亦然。在下面的例子中Jess将重组这些pattern次序使得其中的or位于顶层。例:
Jess> (defrule or-example-2a (and (or (a) (b)) (c)) =>)
将自动被重组为:
Jess> (defrule or-example-2b (or (and (a) (c)) (and (b) (c))) =>)
关于逻辑等价德摩根第二定理定义如下:
(not (or (x) (y))) => (and (not (x)) (not (y)))
由此可以将or提到顶层。
注意:如果rule的LHS(右手边)使用了一个由匹配该rule左手边条件后定义的变量,并且该变量在一个or的pattern的多个分支(且不是所有的分支)中被定义,则可能会出现一个运行时错误。
6.10."not"
在前面加not后,任何一个pattern都可以作为一个列表(list)。此时表示一个或一组fact与pattern都不匹配。例:
(defrule example-7 (person ?x) (not (married ?x)) => (printout t ?x " is not married!" crlf))
注意:一个not pattern不能定义任何在subsequent pattern中使用的变量(因为一个not pattern不能匹配任何fact,所以不能用于定义任何变量的值),当变量仅在一个not pattern中可用时,可以向该not pattern中引入这些变量;例:
Jess> (defrule no-odd-numbers (not (number ?n&:(oddp ?n))) => (printout t "There are no odd numbers." crlf))
同理,not pattern也不能捆绑pattern。
仅当有一个fact与其匹配,或与rule的LHS(左手边)的not相邻的前一个pattern被evaluate时,一个not CE(IBM customer engineer) 被evaluate。
6.11.exists
列表中的pattern可以以exists开头.如果存在任何能与该pattern匹配的fact则exists CE为true,反之为false.exists仅对只执行一次的rule有效,尽管有时会有多个fact可能被激活.
Jess> (defrule exists-demo (exists (honest ?)) => (printout t "There is at least one honest man!" crlf))
如果存在任何honest men,则该规则被执行且仅执行一次。