CLIPS中文手册

Date Dopey (Dinky Mallard) Date Dopey (Mallard) Date Dopey () CLIPS>

如你所见,在LHS中,多模式是$?name,而在RHS中,只能用?name。输入并运行,你将看到所有有资格入选的Dopey们的名字。多字段通配符照顾到所有字段的个数,同样,注意多字段变量返回时包含在圆括号里面。

假设你想匹配所有的只要是名字中包含Dopey的鸭子,比一定非得是它们的姓氏。下面的例子将会匹配所有包含Dopey的事实并打印出它们的名字:

CLIPS>(defrule dating-ducks

(bachelor $?first Dopey $?last) =>

(printout t “Date” ?first “Dopey” ?last crlf)) CLIPS>(reset) CLIPS(run)

Date () Dopey (Dinky Mallard) Date (Dinky) Dopey () Date () Dopey (Mallard) Date () Dopey () CLIPS>

这里的模式将与所有的只要是包含Dopey的事实匹配。

单或多字段通配符也可以联合使用,举个例子,模式:

(bachelor ? $? Dopey ?)

意味着姓氏和名字的最后一个字可以是任意的,但是最后一个字之前一定是Dopey。同时,这个模式也要求与之匹配的事实至少包含有四个字段,因为$?可以匹配零个或多个字段,其他的必须都匹配一个字段。

尽管多字段在许多情况下的模式匹配中必不可少,但是它们的滥用会带来许多的副作用,因为它们增加了系统的内存消耗,使执行速度变慢。

? 作为一种普通的规则类型,你可以仅在你不知道字段长度的情况下使用$?,不要将$?简单的

用来方便输入。

理想的单身汉

模式中变量的使用有一个非常重要和有用的属性,表述如下:

? 变量在被首次绑定时,仅在规则内保留其值,包含LHS和RHS,除非在RHS中被改变了。 举个例子,在下面的规则中:

(defrule bound

(number-1 ?num) (number-2 ?num) =>)

如果有下面事实:

f-1 (number-1 0) f-2 (number-2 0) f-3 (number-1 1) f-4 (number-2 1) 那么,这条规则这能被f-1,f-2的事实对和f-3,f-4的事实对激活。f-1不能与f-4同时进行匹配,这是因为在模式中,?num已经绑定为一个值,那么事实中的代替字段只能是相同的值。同理,当第一个模式中的?num绑定值到1的时候,第二个模式中?num的值也必须为1。注意这里的规则将会被激活两次。

作为一个实际的例子,输入下面的规则。注意相同的变量?name被同时用在模式中。在(reset)和(run)程序之前,输入(watch all)命令,这样你便可以清楚看到执行了什么。

CLIPS>(clear)

CLIPS>(defrule ideal-duck-bachelor

(bill big ?name) (feet wide ?name) =>

(printout t “The ideal duck is ”?name crlf)) CLIPS>(deffacts duck-assets

(bill big Dopey) (bill big Dorky) (bill litter Dicky) (feet wide Dopey) (feet narrow Dorky) (feet narrow Dicky)) CLIPS>(watch facts)

CLIPS>(watch activations) CLIPS>(reset)

<==f-0 (initial-fact) ==>f-0 (initial-fact) ==>f-1 (bill big Dopey) ==>f-2 (bill big Dorky) ==>f-3 (bill litter Dicky) ==>f-4 (feet wide Dopey)

==>Activation 0 ideal-duck-bachelor: f-1,f-4 ==>f-5 (feet narrow Dorky) ==>f-6 (feet narrow Dicky) CLIPS>(run)

The ideal duck is Dopey CLIPS>

当程序运行时,第一个模式与Dopey和Dorky匹配因为他们都非常富有(big bills),变量?name被分别绑定到他们的名字,当CLIPS尝试匹配第二个模式的时候,只有?name绑定到Dopey的能满足模式(feet wide)。

幸运的鸭子

在生活中有许多情况出现,以系统化的方式行事是非常明智的。如果你的期望方式不能解决问题的时候不妨试试系统化(如去一次次的结婚来找到最完美的配偶这样的普通算法)。

一个被总结起来的办法是保存名单(注意:如果你非常想给人留下深刻的印象,那么给他们一份你的清单)。在我们的例子中,我们将保存一份单身鸭子的清单,将最想找到婚姻的放在最前面。一旦一个理想的单身汉被鉴定符合,我们便将他作为一只幸运鸭升至表的前列。

下面的程序显示了通过增加两个规则到ideal-duck-bachelor规则,执行该过程:

(defrule ideal-duck-bachelor

(bill big ?name) (feet wide ?name) =>

(printout t “The ideal duck is ”?name crlf) (assert (move-to-front ?name)))

(defrule move-to-front

?move-to-front <- (move-to-front ?who) ?old-list <- (list $?front ?who $?rear) =>

(retract ?move-to-front ?old-list) (assert (list ?who ?front ?rear)) (assert (change-list yes)))

(defrule print-list

?change-list <- (change-list yes) (list $?list)

=>

(retract ?change-list)

(printout t “List is: ”?list crlf))

(deffacts duck-bachelor-list

(list Dorky Dinky Dicky))

(deffacts duck-assets

(bill big Dicky) (bill big Dorky) (bill litter Dinky) (feet wide Dicky) (feet narrow Dorky) (feet narrow Dinky))

最初的表在duck-bachelor-list自定义事实中给出,当程序运行后,将会提供一个新的最有可能候选的表。

CLIPS>(unwatch all) CLIPS>(reset) CLIPS>(run)

The ideal duck is Dicky

List is :(Dicky Dorky Dinky) CLIPS>

注意move-to-front规则中的声明(change-list yes),没有这条声明,print-list规则将会总是触发在初始事实。该声明是一个关于用控制事实(control fact)来控制另一个规则激活的例子,你应该仔细的学习这个例子并弄清为什么使用它。另一个控制方法是模块,将会在CLIPS参考指南中详细讨论。

move-to-front规则移除旧的名单,增加新的名单。如果旧的名单没有被移除的话,那么print-list规则能激活两个规则到议程中,但是只有一个被触发。只有一个被触发的原因是

print-list规则移除了控制事实调用同一规则的其他激活。你不会提前预知哪一个将会被触发,所以在打印的时候新的表单也许会被旧的替代了。

第五章 格式

Style today ,gone tomorrow

本章中,你将学习关键词deftemplate的用法,deftemplate代表定义模板(define template)的意思。这个关键词能帮助你写出具有明确定义模式的规则。

“精彩”先生

自定义模板(deftemplate)类似于C语言中的结构定义。deftemplate定义模式中一组相关的字段,这类似于在C语言中用结构来定义一组相关数据。自定义模板是由一些被命名为slot的字段构成的表。自定义模板允许通过字段名而不一定由指定的字段顺序来进行存取。在专家系统程序中,自定义模板有助于编写好的格式,同时它在软件工程中也是非常有用的。

slot被称之为单槽(single-slot)或多槽(multislot)。单槽包含且仅包含一个字段,而多槽则可以包含零个或多个字段。自定义模板中可以使用任意数目的单槽和多槽。写一个槽的时候,先写字段名(attribute)后面紧跟着字段值。注意,一个只有一个槽值的多槽并没有单槽那样的严格。类比想像一下,将多槽看成是一个碗橱,里面也许有许多的碗碟。碗橱里只有一个碟子却并不等同于就一个单独的碟子(单槽)。然而,单槽的槽值(或变量)也可以与只有一个字段的多槽(或多槽变量)相匹配。

下面是一个有关自定义模板的例子,通过考察每个鸭子的属性来判定哪个最有可能是母鸭的最佳婚姻对象。 Attributes Value name “Dopey Wonderful” assets rich age 99 prospect关系的自定义模板可以被写成如下形式,空格和注释用来增加程序的可读性。

(deftemplate prospect ; 自定义模板关系名

“vital information” ; 可选注释 (slot name ; 字段名 (type STRING) ; 字段类型

(default ?DERIVE)) ; 字段“名字”的默认值 (slot assets

(type SYMBOL) (default rich)) (slot age

(type NUMBER) ; NUMBER类型可以是整型INTEGER或浮点型FLOAT (default 80)))

在本例中,自定义的构成如下: ? 一个自定义模板关系名 ? 字段属性

? 字段类型,可以是一下任意一种允许的类型:SYMBOL,STRING,NUMBER或其他。

联系客服:779662525#qq.com(#替换为@)