CLIPS>(run) CLIPS>(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内存中保存下的代码只保留了双引号内可选规则头的注释,而分号后的注释就没有了。
踢你的鸭子
也许此时你会有一个有趣的问题,如果重复执行(run),结果会这样?当一个规则被事实满足时,该规则会被触发,然而,如果你重复执行(run),你会发现该条规则不将被触发了。这也许让人有一点沮丧,然而,在你做出一些极端的减轻沮丧的事情之前---如狠踢你的宠物鸭---你得多了解一些专家系统的基本原理。
当规则的模式与下面的几点匹配时,规则被激活: 1. 之前不存在的不同的新的模式实体
2. 该模式实体存在,但是被撤销或者被重新添加了。举个例子,旧模式实体的副本便是一个新的模式实体。
规则和匹配的模式目录,都是被激活的。如果是规则或模式实体,或者同时被改变了,激活将会被移除。一个激活的也可以通过命令或另一规则的行为被移除,该规则在移除激活的先决条件前被触发。
推理机通过特权值将激活进行分类。这种分类过程被称之为冲突消解(conflict resolution),因为它消解了决定下一个触发规则的冲突。CLIPS依照议程中最高的特权值进行规则的激活,并移除激活。这种执行被称之为触发,就像神经细胞的激活。当有适当的刺激时,神经细胞会激发出一定的电压脉冲,神经细胞激活后,将遭受折射(refraction)并在一定时期内不能被再次触发。如果没有折射,神经细胞将会在刺激作用下无休止的被激活下去。
如果没有折射效应,专家系统将会经常陷入到无关重要的循环当中去。因为,一旦规则被触发,那么它将在相同的事实作用下无休止的被触发下去。在现实世界中,引起触发的刺激最终都会消失。举个例子,一只真的鸭子也许会游走或在电影里充当一个角色,然而,在计算机世界里,一旦数据被存储,它将一直保存在那儿,除非有外部声明移除或电脑断电。
下面的例子展示了一个规则的激活和触发。注意(watch)命令被用来更好的显示每个事实和激活。右箭号表明激活和事实正在被添加,左箭号表明已存在的事实和激活。
CLIPS>(clear)
CLIPS>(defrule duck
(animal-is duck) =>
(assert (sound-is quack))) CLIPS>(watch facts)
CLIPS>(watch activations)
CLIPS>(assert (animal-is duck)) ==>f-1 (animal-is duck)
==>Activation 0 duck:f-1 ; 激活的默认权值为0,其后是规则名:模式
CLIPS>(assert (animal-is duck)) ; 注意复制的事实不会被输入 FALSE
CLIPS>(agenda) 0 duck: f-1
For a total of 1 activation. CLIPS>(run)
==>f-2 (sound-is quack)
CLIPS>(agenda) ; 当规则被触发后,议程为空 CLIPS>(facts)
f-0 (initial-fact) ; 即使事实已与规则匹配,折射也不会允许该激 f-1 (animal-is duck) ; 活,因为该规则等待事实的激活 f-2 (sound-is quack) For a total of 3 facts. CLIPS>(run) CLIPS>
你也可以撤销事实然后又重新添加作为新的事实来让规则重复触发。
查看规则
在你运行CLIPS时,也许你想查看某一条规则,这里有一个命令:ppdefrule---恰当的打印规则---打印一条规则。查看某条规则,则指定其规则名为ppdefrule的参数即可,举例如下:
CLIPS>(ppdefrule duck) (defrule MAIN::duck
(animal-is duck) =>
(assert (sound-is quack))) CLIPS>
为了增加可读性,CLIPS将规则的不同部分分布在不同的行中。规则箭号之前的模式部分仍然被称之为LHS,箭号之后的行为部分仍然被称之为RHS。术语MAIN引用MAIN模块表明该条规则是自定义的。你可以定义模块,将规则与那些可以被其他编程语言不同包装,模块,过程或函数纳入的声明类比。模块的使用使得编写那些有许多条规则的专家系统变得简单,这样,对于每个模块,它们大多在自己的议程中整合在一起了。如果你想了解更多,请参考CLIPS参考指南。
如果你想打印一条规则,而你又忘掉了该规则的规则名,该怎么办?不用慌,你可以在CLIPS提示符后面使用rules命令来打印出所有的规则名,举例如下:
CLIPS>(rules) Duck
For a total of 1 defrule. CLIPS>
给我写信
规则的RHS部分除了添加一条新规则,你还可以使用printout函数打印出相应的信息。同样,CLIPS有回车换行关键字:crlf,该关键字以换行格式来改进输出效果。有一点小改变就是,crlf不被圆括弧包含。举例如下:
CLIPS>(defrule duck
(animal-is duck) =>
(printout t “quack” crlf)) ; 一定要打出“t” ==>Activation 0 duck:f-1 CLIPS>(run) quack CLIPS>
双引号内的文本即为输出。一定记得在printout命令后输入“t”,这将告知CLIPS将结果输出到电脑的标准输出设备(standard output device)中。通常,标准输出设备是你电脑的终端
(terminal)(因此在printout后面接字母“t”)。然而,这可能会被重新定义,这样标准输出设备也可能是其他的设备,如调制解调器或磁盘。
其他特性
declare salience命令提供对增添到议程中的规则的外部控制。在使用该特性的时候要注意不要太过于自由以免你的程序被人为控制太多。set-incremental-reset命令禁止在规则被输入之前查看该规则的事实。获取增加的重置值命令为:get-incremental-reset。让一条规则重复触发的一个办法是使用refresh规则命令来强制使其重新激活。
load命令载入前面你已经保存在磁盘中命名为“duck.clp”文件或者相应文件夹下的任何文件名里的规则。你还可以使用load命令载入一个包含规则的文本文件。
最快的载入文件的方法是,首先用bsave二进制存储命令将规则存储为机器可读二进制格式。载入的二进制命令为bload。这样,CLIPS内存会不加解释的快速读取这些二进制规则。
另外两个有用的命令可以帮助你通过一个文件来保存和载入事实。它们是save-facts和load-facts。(save-facts)命令将会保存所有事实表中的事实,(load-facts)命令将会导入文件事实表中的事实。
batch命令允许你像在顶层输入一样执行一个文件命令。另外一个有用的命令为你的操作系统提供一个界面。system命令允许操作系统的执行和在CLIPS内的可执行。如果你想了解更多此类信息,请查阅CLIPS参考指南。
第三章 详细资料
问题不是大局,而是细节。
在前面的两章中,你已经学习了CLIPS的基础。现在,你将会学到怎样结合这些基础构建一个强大的程序。
红绿灯
到目前为止,你还只是看到一些仅包含一条规则的简单程序。然而,只包含一条规则的专家系统无疑作用有限。实际的专家系统通常包含上百,上千条规则。让我们来看看一个需要多条规则的应用软件程序吧。
假设你想写一个专家系统来决定一个移动式遥控装置如何对交通灯进行响应,最好是用多条规则去编写这个问题的类型。举个例子,红灯和绿灯情况下的规则按如下书写:
(defrule red-light
(light red) =>
(printout t “Stop” crlf))
(defrule green-light
(light green) =>
(printout t “Go” crlf))
当上述规则被输入到CLIPS后,增加一个 (light red) 事实并运行,你将会看到“Stop”被打印出来。再增加一个(light green)事实并运行,你会看到“Go”被打印出来。
行路
如果你考虑上面所述,交通灯不光只简单的包含有红灯,绿灯,应该还是黄灯存在,同时还有绿色的箭头标识来保护左转等。手型的交通灯亮与灭指示了行人的行与止。行与止的信号取决于我们装置显示是行人还是行车,这可能要关注一些不同的信号。
行人或行车的信息必须被添加,此外交通灯的状态信息也得添加。规则必须覆盖所有的情况,但是它们必须有多个模式。举个例子,假设我们希望当装置状态为行人和行人信号亮时,一个规则被触发,该规则应写成如下所示:
(defrule take-a-walk
(status walking) (walk-sign walk) =>
(printout t “Go” crlf))
上面的规则中包含有两个模式,规则的每个模式必须在事实表中有相对应的事实满足才能触发。看看这些怎样工作,输入上面的规则并添加事实(status walking)和(walk-sign walk),当执行(run),规则的模式均被满足,程序输出“Go”。
你可以在一条规则中加入多条模式或行为。重要的一点是,只有当规则中所有的模式都被事实表中的事实满足时,规则才能被触发。这种约束类型被称为逻辑与条件元素(logical AND conditional element(CE)),是关于布尔型的“与”关系。AND关系只有当所有的条件都为真时才为真。
因为模式为AND类型,如果只有一个模式被满足,规则不会被触发。只有给出规则LHS中所有的模式满足,规则才能被放入到议程中。
策略的问题
策略(strategy)一词最初是一个军事术语,用在战争的谋划和行动中。现在,该术语普遍被用在商海(商海即是战场)中,适用于一个组织为了达到他们的目的所做的高级计划等。“比世界上其他的人卖出更多的多脂汉堡,赚更多的钱!”
在专家系统中,strategy术语的一个用法是激活的冲突消解。那么你也许会说,“那好,我现在就将设计好我的专家系统,以便同一时刻仅有一条规则可能被激活,那么就用不上冲突消解了。”好消息是:如果你成功了,那么冲突消解确实无关紧要,坏消息是:你的成功证明了你的应用软件能被一个连续的程序很好的表达出来,那么你还不如首选在C,Java或者Ada中编写代码,犯不着去编写一个专家系统。
CLIPS提供了七种不同的冲突消解策略:深度优先(depth),广度优先(breadth),LEX,MEA,complexity,simplicity和随机(random)。在不考虑具体的应用软件程序时,很难说清哪一种策略更好。即使那样,判断上面的七种策略哪一个是“最好”的,也相当困难。如果你想了解更多关于这些策略的详细信息,请参考CLIPS参考指南。
深度优先策略(depth strategy)是CLIPS标准默认策略(default strategy)。当CLIPS第一次启动时,该默认设置便会被自动设置,后面,你可以更改默认设置。在深度优先策略中,在高权值的激