1、第一章 事实 如果你忽视事实,你将永远不会担心自己的过错。 本章将对专家系统的基本概念做简单的介绍。你将会知道在CLIPS中怎样插入和移出事实。如果你正在使用的机器是苹果机或者是IBM(或可兼容)的CLIPS视窗版本,那么你可以通过鼠标来选择相关的命令来代替输入命令行。键盘上的箭头键也可以移动光标对菜单选项进行选择。 序言 CLIPS是一种被用来编写专家系统应用程序的计算机语言。专家系统是一组计算机程序,专门用来模仿人类专家的技能和知识。相比之下,一些普通的程序如报表程序,文本处理器,电子表格,电脑游戏等等,并没有包含人类的技能和知识。(专家的定义之一:就是某人带着他的公文包在离家50
2、公里之外。) CLIPS之所以被称之为专家系统工具,是因为它是一个开发专家系统的完整环境,包括一个整合版本和一个调试工具。壳这一词被保留在CLIPS负责推理的部分中。CLIPS的壳提供了专家系统的基本元素: 1. 事实表和实例表:数据的全局存储。 2. 数据库:包括所有的规则和规则表。 3. 推理机:控制所有规则的执行。 CLIPS的程序一般包含有规则,事实和对象。推理机决定了哪条规则应该被执行和在什么时候被执行。一个用CLIPS写成的基于规则库的专家系统程序是一个数据-驱动型程序,程序里的事实,对象数据通过推理机的激活执行。 这里有一个例子可以帮助你知道CLIP
3、S是如何与其他程序语言如Java,Ada,BASIC,FORTRAN和C区别开来的。在程序语言中,执行并不一定需要数据,那是因为在那些语言中的声明已经足够引起执行了。举例说明,在BASIC语言中,PRINT 2+2的声明会被立即执行,该声明是一个完整的声明,并不需要额外的数据去驱动执行。然而,在CLIPS中,规则的执行必需数据来驱动。 最初,CLIPS仅有表示规则和事实的能力,然而,在6.0版本中已经允许规则与对象的匹配,与规则与事实匹配一样。同时,通过发送消息来应用对象不必需要规则了,如果你仅仅只是用对象,那么推理机都可以不需要。在第一章到第七章中,我们将讨论CLIPS的事实和规则,八到十
4、二章中包含了CLIPS的对象特点。 开始和结束 你可以在你的系统中输入相应的运行代码来启动CLIPS,你将看到CLIPS的提示如下所示: CLIPS> 此时,你可以开始在CLIPS中直接输入命令,这种直接输入命令的方式被称之为最高阶层。如果你拥有CLIPS的图形界面版本(GUI),你也可以用鼠标选择相应的菜单来代替输入命令行。请参考CLIPS GUI 版本的CLIPS界面向导,探讨一下其里面的命令支持。在本书中,为了简约和一致性,我们假设所有的命令均为输入方式。 离开CLIPS的一般方式是输入exit命令,如下: (exit) 按照CLIPS提示点击返回键
5、
建表
与其他编程语言一样,CLIPS也有关键字。举个例子,如果你想在事实表中输入数据,你可以使用assert命令。
作为一个assert实例,在CLIPS提示后面正确输入下面的命令:
CLIPS>(assert (duck))
这里,assert命令以(duck)作为其参数。记住点击回车键将命令行发送到CLIPS。你将看到如下响应:
6、ssert)和它的参数(duck)均用圆括弧括住,像其他一些专家系统语言一样,CLIPS采用LISP式样语法,用圆括弧作为分隔符。虽然CLIPS并不是采用LISP语言编写,但是LISP影响了CLIPS的发展。 检查两遍 假设你想查看一下事实表中的内容,如果你的CLIPS支持GUI,你便可以在菜单中选择相应的命令,或者,你还可以通过键盘键入相应的命令行。接下来,我们将来描述一下键盘命令。 查看事实库的键盘命令是facts命令。在CLIPS提示后输入(facts),CLIPS响应后会将事实表列出。一定记得将命令用圆括弧括住,否则CLIPS会不识别。在该实例中,(facts)命令的句法如下:
7、 CLIPS>(facts) f-0 (initial-fact) f-1 (duck) For a total of 2 facts. CLIPS> f-0和f-1为CLIPS对事实分配的事实标识。每个事实被添加进CLIPS,被分配唯一的事实标识,以“f”开头,后面的数字为事实索引。当启动CLIPS,输入如clear或reset(随后有详细的探讨)后,事实索引将会被归零,然后随着每个事实的添加(assert)逐步加一。(clear)和(reset)命令同时增加一个(initial-fact)事实,编号为f-0。在CLIPS的早期版本中,该事实被CLIPS隐式用来初始化一
8、些规则和被用户显式调用来使事实库初始化,但是现在,该事实仅被用来提供向后兼容性。 如果你将duck在事实表中输入两次,将会出现什么结果呢?让我们试试看,增加一个新事实(duck),然后调用(facts)命令如下所示: CLIPS>(assert (duck)) FALSE CLIPS>(facts) f-0 (initial-fact) f-1 (duck) For a total of 2 facts. CLIPS> CLIPS返回FALSE消息,表示不可能执行该条命令,且你将只能见到原始的事实:“f-1 (duck)”。这说明CLIPS不能接受事实的复制输入。
9、然而,CLIPS中还有一个超越命令:set-fact-duplication,该命令允许事实的重复输入。
当然,你可以输入其他不同的事实。举个例子,增加一个(quack)事实,然后运行(facts)命令,如下:
CLIPS>(assert (quack))
10、因此会出现事实索引的“丢失”。类似于一个足球运动员离开球队如果没有被补充,其他队员的号码不会因为缺失号码而发生调整(除非他们非常讨厌这个离队的家伙,想要忘掉他曾在队中效力过)。 清除所有事实 Clear命令将所有的事实从内存中移出,代码如下所示: CLIPS>(facts) f-0 (initial-fact) f-1 (duck) f-2 (quack) For a total of 3 facts. CLIPS>(clear) CLIPS> 事实表中的所有事实被清除。 (clear)命令实质上将CLIPS恢复到起始启动状态,它清除了CLIPS的内存空
11、间,重置事实标识为0和增加了一个(initial-fact)事实。增加(animal-is duck)事实,然后查看事实表,会发现(animal-is duck)的事实标识为f-1,这是因为(clear)命令重置了事实表的标识。该命令事实上并不只是起清除所有事实的作用,除此之外,它还清除所有的规则,在下一章中你就会看到。
下面的实例显示了怎样将三个事实加入到事实表,并用(facts)命令查看,然后(clear)命令将这三个事实从内存中清除并重置事实标识为f-0。
CLIPS>(clear)
CLIPS>(assert (a) (b) (c))
12、facts) f-0 (initial-fact) f-1 (a) f-2 (b) f-3 (c) For a total of 4 facts. CLIPS>(facts 0) f-0 (initial-fact) f-1 (a) f-2 (b) f-3 (c) For a total of 4 facts. CLIPS>(facts 1) f-1 (a) f-2 (b) f-3 (c) For a total of 3 facts. CLIPS>(facts 2) f-2 (b) f-3 (c) For a total of 2 facts. CL
13、IPS>(facts 1 2)
f-0 (initial-fact)
f-1 (a)
f-2 (b)
For a total of 2 facts.
CLIPS>(facts 1 3 2)
f-0 (initial-fact)
f-1 (a)
f-2 (b)
For a total of 2 facts.
CLIPS>
注意,仅用一个(assert)便可以增加三个事实:(a),(b)和(c)。最高索引为3,通过CLIPS的信息消息
14、法为:(facts [
15、信号的输入来源于一个麦克风;(2)对于那些有科学主义倾向的人,也许还得对“quack”信号做一个傅立叶变换;(3)电视里那些叫卖神奇的祛皱,减肥广告。等等)。只有用deftemplates才叫做占位符,将在第五章中进行详细的介绍。 注:这里的(3)提到的电视广告,意思是电视广告里的广告者会大呼小叫的对他们的产品爆发欢呼,声音像鸭子叫一样,讽刺幽默。 (duck)事实是一个单独,未命名占位符的事实,值为duck。下面有一个关于单字段事实的例子,一个字段即是一个值的占位符。类比想像一下字段,就像碟子(字段)盛食物(值)一样的道理。 未命名字段的顺序非常重要。举例,如果一个事实被定义为:
16、 (Brian duck) 表示一个叫Brian的猎人射杀了一只鸭子,那么事实: (duck Brian) 则表示鸭子猎手射杀了一个叫Brian的猎人。与之相比,命名字段的顺序是不重要的,稍后你将在deftemplate中看到。 事实上,一个好的软件工程应该采用关系型表示法来表述字段,一个好的事实表示如下: (hunter-game duck Brian) 表示第一个字段代表猎人,第二个字段代表游戏名称。 现在,一些定义是必需的了。一个表是一组无内在序列的项目集合。之所以称一个表为有序的,意味着表中的位置是非常重要的。一个多字段是有序字段,每个字段
17、都有一个值,特殊符号nil意思是无,通常作为一个占位符用在空字段中。举例如下: (duck nil) 可以表示猎人的捕鸭袋中今天一无所获。 注意,nil表示了一个占位符,虽然它没有值。举例,试想一个字段就是一个邮箱,没有邮箱和邮箱中没有信件是完全两码事。如果没有nil,这个事实就是一个单字段事实(duck),如果一个规则依赖于两字段激活,则该单字段事实不会被激活,稍后你会看到的。 这里有许多不同有效的字段类型:float,integer,symbol,string,external-address,fact-address,instance-name和instance-ad
18、dress。这些字段类型用来存储字段值的类型。未命名的字段中,值的类型由你的输入决定。在deftemplates中,你可以显式的声明字段所包含值的类型。显式的声明加强了软件工程的概念,是产生一个高效软件的编程训练。 Symbol是一类字段类型,该类型起始于一个可印刷的ASCII码并被选择性的加一个0或更多的可印刷字符。字段由空格或占位符被普通的分隔。举例: (duck-shot Brian Gary Rey) 有四个字段,指示了所有的杀鸭猎人。在这个事实中,字段被空格分隔,并由圆括弧括起来。 事实中不能嵌入其他的事实。举例,下面即是一个非法的事实: (duck (s
19、hot Brian Gary Rey)) 然而,如果“shot”被当作一个字段名,上面的事实可能是一个合法的deftemplate事实。后面的三个人名为该字段下的值。 CLIPS区分大小写。同样,CLIPS中特定的符号有特殊的意义。 ‘’ ( ) & | < ~ ; ? $ “&”,“|”和“~”不会独立的使用或作为符号的任何部分。 一些字符的作用等同于分隔符以结束一个符号。下面的字符的作用等同于分隔符号。 l 所有的不可印刷的ASCII码,包括空格,回车键,制表键和换行键。 l 双引号,“” l 起始和结束
20、圆括号,() l &号 l 竖线,| l 小于,<.这也是尖括号的一部分。 l 波浪字符,~ l 分号,;指示一个注释的开始,回车键结束 l ?和$?也许不能作为一个符号的开始,但是可以插入其中 分号在CLIPS的作用是指示一个注释的开始,如果你试图增加一个分号,CLIPS便会认为你在输入一段注释并等待你的完成。如果你在最高阶层(top-level)中不经意的输入了一个分号,那么输入一个圆括号的结束部分:)并回车。CLIPS会以一个错误消息响应并提示给你(就像生活中的某些时候,你得做些错误的事情以
21、使得某些事情正确)。 随着你通读这本手册,你将会逐渐明白上面那些符号的意义。除了“&”,“|”和“~”之外,你将使用其他的表示符号,然而,也许对于有些人,在读程序和试图理解程序运行机理时有些困惑。通常情况下,最好是避免使用这些符号来表示字符,除非你有更好的理由需要用到它们。 下面是这些符号的一些例子: duck duck1 duck_soup duck-soup duck1-1_soup-soup d!?#%^ 第二类类型的字段是string。一个字符串必须用双引号引起来,双引号是字段的一部分。引号中可以有0个或多个字符。一些例子如下: “duck” “
22、duck1” “duck/soup” “duck soup” “duck soup is good!!!” 第三和第四种字段类型为数字型字段。该字段用来表示整型或浮点型字段。浮点型通常被简化为float。(float-point->float) CLIPS中的数字均为“long long”整型或双精度浮点型。没有小数点的数字即是整型,除非它们不属于整型范围。整型的范围由数字的位数决定,N,用来表示整型如下所示: -2N-1 … 2N-1-1 对于64位机器“long long”整型,符合该范围的数字为: -9,223,372,036,854,775,808 …
23、 9,223,372,036,854,775,807
下面给出一些数字的例子,增加下面的数据到事实中,最后一个数字为指数表示法,用“e”或“E”代替乘以10。
CLIPS>(clear)
CLIPS>(facts)
f-0 (initial-fact)
For a total of 1 fact.
CLIPS>(assert (number 1))
24、LIPS>(assert (distance 3.5e5))
25、 a total of 8 facts. CLIPS> 如你所见,CLIPS将输入的指数表示法转换成数字350000.0,这是因为当数字足够小,就会被从指数表示转换到浮点型格式。 注意上面的每个数字前面都有一个符号开头,如“number”,“x”,“y”等。在CLIPS6.0版本以前,允许仅一个数字的事实,然而,现在必需一个符号作为第一字段,同时,CLIPS的一些专用字段不能用来作为第一字段,但是可以用来作为其他字段。举个例子,专用关键字not用来指代否定模式,但是不能作为一个事实的第一字段。 一个事实由一个或多个被圆括弧括住的字段组成。为了简单化,我们在前面七章中将仅仅讨论事实
26、但也有许多对模式匹配应用于对象做了讨论。例外的是,一些函数如assert和retract仅仅只能用于事实,而不能用于对象。对对象相应的处理方法将会在第八到第十二章中讨论。 一个事实可以是有序的,也可能是无序的。所有前面你已经看到的事实都是有序事实,因为字段的顺序决定了它们的不同。举个例子,注意,CLIPS会自动将包含相同数字“1”,“2”和“3”的事实区分开。 f-6 (coordinates 1 2 3) f-7 (coordinates 1 3 2) 有序事实必须用字段对位于其定义的数据。举例说明,有序事实(duck Brian)有两个字段,同样(Brian duck
27、)也有两个字段,然而,CLIPS将其看作两个不同的事实,因为有序事实字段的值是不同的。相反,事实(duck-Brian)仅有一个字段,因为有一个“-”符号将两个值连结。
定义模板事实(Deftemplate facts),稍后会做详细的表述,它是无序的,因为它用命名字段来定义数据。这与在C和其他语言中应用结构体一样。
多字段通常被由一个或多个的空格,制表,回车或表格组成的空白隔离开来。举例说明,输入下面的例子,你将发现每个被存储的事实都是一样的。
CLIPS>(clear)
CLIPS>(assert (The duck says “Quack”))
28、PS>(facts)
f-0 (initial-fact)
f-1 (The duck says “Quack”)
For a total of 2 facts.
CLIPS>(clear)
CLIPS>(assert (The duck says “Quack” ))
29、都写在一行的效果是一样的。
CLIPS>(clear)
CLIPS>(assert (The
duck
says
“Quack”))
30、initial-fact) f-1 (The duck says “Quack”) f-2 (The duck says “Quack ”) For a total of 3 facts. CLIPS> 如你所见,在双引号中插入的回车在字符串输出中会将双引号的后半部分移到下一行。CLIPS会认为f-1与f-2是两个不同的事实,这一点很重要。 同样,我们也注意到CLIPS会保存事实中字段里的大写和小写字母。也就是“The”中的“T”和“Quack”中的“Q”。CLIPS被认为是区分大小写的,因为它将大写和小写字母区别对待。举例说明,增加事实(duck)和(Duck),然后调用
31、facts)命令,你会发现CLIPS增加了两个不同的事实(duck)和(Duck),这正是因为CLIPS是区分大小写的缘故。
下面的例子将更清楚的表现了回车应用于表中,增加可读性的作用。增加下面的事实,使用空格和回车将字段合适的安排在行中。破折号和减号被使用来创建单字段,这样,CLIPS就会将“fudge sauce”作为一个单字段了。
CLIPS>(clear)
CLIPS>(assert (grocery-list
ice-cream
cookies
candy
fudge-sauce))
32、fact) f-1 (grocery-list ice-cream cookie candy fudge-sauce) For a total of 2 facts. CLIPS> 如你所见,CLIPS将回车和制表置换为单空格。当人们在读一段程序时,使用合适的空格会带来许多方便,CLIPS会将其自动置换为单空格。 监视事实 CLIPS提供了一些帮助你调试程序的命令。其中一个命令可以帮助你连续监视事实(watch facts)的增加和撤销,这比你总是不断输入(facts)命令来查看事实表中的变化要方便得多。 监视事实是通过输入(watch facts)命令来实现的,如下例
33、子所示:
CLIPS>(clear)
CLIPS>(watch facts)
CLIPS>(assert (animal-is duck))
==>f-1 (animal-is duck)
34、))
==>f-1 (animal-is duck)
35、后面的内容将会被CLIPS忽略。 (watch facts) (watch instances) ; 应用于对象 (watch slots) ; 应用于对象 (watch rules) (watch activations) (watch messages) ; 应用于对象 (watch message-handlers) ; 应用于对象 (watch generic-functions) (watch methods) ; 应用于对象 (watch deffunctions) (watch compilations) ;
36、默认的 (watch statistics) (watch globals) (watch focus) (watch all) ; 监视所有项目 随着你使用到CLIPS的更多功能,你将发现(watch)命令在调试过程中非常的有用。通过输入unwatch命令可以关闭监视(watch)命令。举例说明,如果要关闭监视编译,则输入(unwatch compilations)即可。 一点帮助 CLIPS提供有效的在线帮助。获得帮助只需输入(help)命令然后回车即可。不久,你将会看到一个细目菜单。更多的关于(help)命令的信息,请参考HELP_USAGE帮助章节
37、退出帮助的方法是一直按回车键,直到CLIPS提示出现。如果出现错误消息提示,则表明CLIPS没有找到帮助文件:clips.hlp,你可以用(help-path)命令来找出CLIPS该文件的路径。 第二章 规则 如果你想你的生活硕果累累,那么别打破规则---而是去制定规则! 在前面一章中的学习中,你已经对事实有所了解了。现在你将马上看到专家系统的规则将怎样利用事实驱动程序执行。 构造良好的规则 完成一项有价值的工作,专家系统必须得有事实和规则。前面你已经知道了事实的添加和撤销,现在你将了解规则是怎样工作的。一条规则与程序语言如Java,C或Ada中的IF THEN表述非常相似。IF
38、THEN规则可以用自然语言与计算机语言来混合表示,如下所示: IF certain conditions are true THEN execute the following actions 上述表述又被称为伪代码,伪代码字面的意思是错误的代码。伪代码不能被计算机识别和执行,但是它对书写可执行代码提供了有用的指南。伪代码在文档规则中也非常有用。如果你记住IF THEN的类比特性,那么将规则从自然语言转化到CLIPS语言将很简单。随着你CLIPS实践的增加,你将发现在CLIPS中写规则非常的简单。你可以在CLIPS中直接输入规则,也可以新建一个文本文件,将规则写在里面,然后加
39、载到CLIPS中来。
关于鸭子叫声规则的伪代码可以写成如下形式:
IF the animal is a duck
THEN the sound made is quack
下面是采用CLIPS语法将上面的伪代码写成一个事实和一个命名为duck的事实。规则名紧跟在关键字defrule后面。虽然你可以将规则都写在一行里面,但是我们通常将规则分成几段放在几行里书写,便于程序的阅读和编辑。
CLIPS>(unwatch facts)
CLIPS>(clear)
CLIPS>(assert (animal-is duck))
40、le duck (animal-is duck) => (assert (sound-is quack))) CLIPS> 如果你按照上面正确的输入,你便会看到CLIPS的提示符出现,否则,你将会看到一个错误消息提示。如果你得到一个错误消息,也许是你拼错了关键字或你遗漏了圆括号。记住,在一个声明中,圆括弧的左边和右边部分的数目是配套的。 下面将给出一个相同的规则,该规则中增加了对规则每部分的注释。同时也增加了可选的规则头(rule-header)注释:“Here comes the quack”。规则中只能包含一个规则头注释,且必须写在规则名之后和第一个模式(pattern)
41、之前。虽然现在我们只是讨论基于事实的模式匹配,一般来说,模式的匹配时基于模式实体上(pattern entity)的。模式实体是一个事实,也可以是一个用户定义类的实例。基于对象的模式匹配将稍后讨论。 CLIPS基于模式实体来进行模式匹配。当然,由空格,制表和回车组成的空格将规则的几个部分分隔开来,以增强可读性。其他的注释由分号引导,直到按下回车键结束一行。CLIPS忽略注释里的内容。 (defrule duck “Here comes the quack” ; 规则头 (animal-is duck) ; 模式 =>
42、 ; THEN箭头 (assert (sound-is quack))) ; 执行 l CLIPS中,同时刻只能仅有一个规则名存在。 输入同一个规则名,如本例中的“duck”,将会更替前面规则名为“duck”里已经存在的一切。也就是说,CLIPS中可能有许多条规则,但是只能有一条被命名为“duck”的规则。这与其他程序语言中一个程序名只能标识唯一程序段是一样的道理。 规则的常规语法如下所示: (defrule rule_name “optinal_comment” (pattern_1
43、) ; 由一些在“=>”之前的元素组成的规则左部分 (pattern_2) . . . (pattern_N) => (action_1) ; 由一些在“=>”之后的元素组成的规则右部分 (action_2) . . . (action_M)) ; 最后一个“)”是与“defrule”前面的“)”配 ; 套的。保证你的圆括弧完整,否则你将得到错误 ; 消息提示 整个规则必须用圆括弧括住,每个模式(pattern)和每个行为(action)都必须
44、用圆括弧括住。行为通常是一类没有返回值(return value)的函数,但是它可以完成一些有用的执行,如(assert)和(retract)。举个例子,一个行为可以是(assert (duck))。这里的函数名是“assert”,它的参数是“duck”。注意,我们并没有希望得到一个如数字型的返回值,而是使得事实(duck)被增加到CLIPS中去。CLIPS中的函数(function)是一段可执行代码,该段代码被特定的函数名标识,返回有用的值或产生有用的副作用,如(printout)。 一个规则通常包含有多个模式和行为。模式和行为的数量并不一定得相等,这就是上面例子中用N和M来代指的意义。
45、 零个或多个模式写在规则名之后。每个模式包含一个或多个字段。在上面的duck规则中,模式为(animal-is duck),字段为“animal-is”和“duck”。CLIPS试图将模式与事实表中的事实进行匹配,如果规则的模式与事实匹配成功,规则将会被激活(activated)而放入到议程(agenda)中。议程中存放的是所有被激活的规则集合。议程中通常包含零个或多个激活的规则。 规则中,模式后面的符号“=>”被称之为箭号(arrow),箭号是IF-THEN规则的THEN部分开始的标记(也许可以被读作“意味着”)。 规则的最后部分为零个或多个行为,当规则被触发(fire)时,这些行为将会
46、被执行。在我们的实例中,行为是增加一个事实(sound-is quack)。Fire一词意味着CLIPS已经选定了议程中某条规则并执行。 l 当议程中没有激活的规则时,程序停止执行。 当议程中有多条激活规则时,CLIPS自动决定哪条规则将被合理的触发。CLIPS依照增加优先权和特权(salience)来对议程的激活排序。 规则中箭号之前的被称之为左部(LHS),箭号之后的部分被称之为右部(RHS)。如果没有指定模式,则CLIPS会在输入(reset)命令后自动的激活该条规则。 让鸭子叫吧 CLIPS通常会执行议程中最高优先权规则右部的行为部分。随后该条规则将会被移出议程
47、接下来最高特权规则的行为将会被执行。这样持续执行下去,直到议程中没有激活的规则或输入了停止激活的命令为止。 你可以通过议程(agenda)命令来查看议程中的内容,举例说明: CLIPS>(agenda) 0 duck: f-1 For a total of 1 activation. CLIPS> 第一个数字“0”表示规则“duck”的激活特权值,“f-1”为事实的标识,(animal-is duck)为匹配激活。如果没有显式的声明特权值,则CLIPS默认为0。特权值的范围为-10000到10000。本书中,我们将用default的定义来作为标准
48、方式。 如果议程中仅有一个规则,该规则将被触发。前面知道了duck-sound规则的模式左部为: (animal-is duck) 该模式刚好与(animal-is duck)事实符合,因此duck-sound规则将会被触发。 模式的字段被称之为字面约束(literal constraint)。之所以称之为字面意味着有一个常数值,与之对立的是值可以改变的变量。在此例中,字面为“animal-is”和“duck”。 输入run命令即可使程序运行。敲入(run)并回车,然后输入(facts)命令查看通过该规则有哪些事实被添加。 CLIPS>(run) CLIPS>(
49、facts) f-0 (initial-fact) f-1 (animal-is duck) f-2 (sound-is quack) For a total of 3 facts. CLIPS> 在操作之前,让我们使用save命令来保存duck规则,这样你就可以避免重复输入了(如果你还没有将这些保存到编辑器中)。输入命令如下: (save “duck.clp”) 将CLIPS内存中的规则保存到命名为“duck.clp”的文件中,“.clp”是一个简单方便的扩展名,让我们方便知道这是一个CLIPS的源文件。注意,从CLIPS内存中保存下的代码只保留了双引号内可
50、选规则头的注释,而分号后的注释就没有了。 踢你的鸭子 也许此时你会有一个有趣的问题,如果重复执行(run),结果会这样?当一个规则被事实满足时,该规则会被触发,然而,如果你重复执行(run),你会发现该条规则不将被触发了。这也许让人有一点沮丧,然而,在你做出一些极端的减轻沮丧的事情之前---如狠踢你的宠物鸭---你得多了解一些专家系统的基本原理。 当规则的模式与下面的几点匹配时,规则被激活: 1. 之前不存在的不同的新的模式实体 2. 该模式实体存在,但是被撤销或者被重新添加了。举个例子,旧模式实体的副本便是一个新的模式实体。 规则和匹配的模式目录,都是被激活的。如果是






