Jess notes 6 自定义规则 (3)

6.15.'accumulate'条件元素

'accumulate'条件元素比较复杂,并难于理解,但却十分强大。可以用于对fact计数、统计fields,以及将数据存入collection等。以下将仅作简单介绍:

accumulate CE语法规则如下:

(accumulate <initializer> <action> <result> <conditional element>)在匹配中碰到accumulate CE时(特别的是:当preceding pattern匹配时,或当其所包含的CE匹配时)将产生下列事件:

1.创建一个新的执行上下文(execution context)

2.context初始化。

3.如果该CELHS激活,则将包括所有从对应memory中取出的匹配标识。如果是被RHS激活,则每个匹配的LHS都会被访问到。由于每个都被访问到,因此所有与之对应的RHS也会被访问。

4.每个被考虑到的token,其所定义的变量被捆绑到执行上下文(execution context),并被执行。

5.如果当前有一个pattern正在被绑定,则结果被绑定到指定的变量。

6.最后,accumulate CE匹配圆满完成,继续下一个条件元素的匹配。

 

从上述事件可以看出用"accumulate"能为每个匹配执行一段相应的代码,并返回accumulated的结果。例如:下列rule对年收入超过$100,000的雇员进行计数。一个初始化为0的变量,每匹配一次就自动加一,且该变量与pattern binding绑定。

Jess> (deftemplate employee (slot salary) (slot name))
Jess> (defrule count-highly-paid-employees
	?c <- (accumulate (bind ?count 0) ;; initializer
	(bind ?count (+ ?count 1)) ;; action
	?count ;; result
	(employee (salary ?s&:(> ?s 100000)))) ;; CE
	=>
	(printout t ?c " employees make more than $100000/year." crlf))

 

经过以下变换后将所有姓名存储在ArrayList中,而不是打印满足条件的雇员列表。

Jess> (defrule count-highly-paid-employees
	?c <- (accumulate (bind ?list (new java.util.ArrayList)) ;; initializer
	(?list add ?name) ;; action
	?list ;; result
	(employee (name ?name)
	(salary ?s&:(> ?s 100000)))) ;; CE
	=>
	(printout t (?c toString) crlf))

 

注:匹配一个fact可能引起accumulate对大量的其它fact反复运算,使得计算开销过大。因此使用时需慎重。

 

6.16.'unique'条件元素

unique CE已被取消。该参数不会产生语法错误,但也不会执行。

 

6.17.节点索引hash(node index hash value)

node index hash value是一个可调的性能参数,可设为全局参数或为每个rule单独设置。所设值越小占用内存越小,但可能以牺牲性能为代价。设置的值越大占用内存空间越大,但ruleLHS执行速度越快。

通常会为rule设置一个较大的值,由此可能会产生许多部分匹配(最好选择质数)

Jess> (defrule nihv-demo
	(declare (node-index-hash 169))
	(item ?a)
	(item ?b)
	(item ?c)
	(item ?d)
	=>)

 

详细使用说明参见set-node-index-hash函数。

 

6.18.deftemplate中的'slot-specific'声明

defrules一样,deftemplate的定义中可以包含一个声明(declare)部分。在此可声明许多不同属性。其中一个是"slot-specific"。一个带有这种说明的template的匹配方式也与众不同:如果由此template构造一个fact,该factruleLHS相匹配并被其修正,结果取决于被修正的slot是否在pattern中被定义并用于匹配该fact。如下例:

Jess> (deftemplate D (declare (slot-specific TRUE)) (slot A) (slot B))
Jess> (defrule R
	?d <- (D (A 1))
	=>
	(modify ?d (B 3)))

 

如果不用"slot-specific"声明,则该rule将陷入无限循环中。因为它修正了一个与LHS匹配的fact,且被修正的fact仍然匹配。通过该声明,可以只执行一次。这是许多初学者所期望的默认设置,这一现象的科学术语称之为反射(refraction)

 

6.19.rule中的'no-loop'声明

如果一个rule包含声明(declare (no-loop TRUE)),则无论如何该rule不会被再次激活执行。特别是:如果一个no-loop rule与一个fact相匹配,并且该rule修改了同样的fact而该fact仍然匹配,但该rule不会再次执行,从而避免无限循环。实质上是"slot-specific"的一种加强形式。

你可能感兴趣的:(C++,c,C#)