基础概念
专家系统的核心模块:
- 知识列表:包含推理所需的数据
- 知识库:包含所有规则
- 推理机:对运行进行总体控制
clips仅仅支持正向链规则,不支持反向链规则。知识列表在clips中对应(facts)
,知识库包含对应规则defrule
和模板deftemplate
等。
字段
字段是clips的基础数据,有字符组合形成的。clips有7种类型的字段:
- 浮点型:
1.5
、-0.9
、9e10
和-3.5e1
等 - 整型
- 符号型:可打印的ASCII字符,以分解符为结尾
- 字符串型:双引号内部的数据。
- 外部地址:用户自定义函数
- 示例名
- 示例地址
事实
Clips中的信息块称为事实,由关系名、后跟零个或者多个槽组成的数据。必须使用模板来创建一个合法关系名的槽。一般方式为:
(deftemplate <relation-name> [<optional-comment>]
<slot-defination>*
)
其中,<slot-defination>
的语法是:
(slot <slot-name> | multislot <slot-name>)
multislot
表示可以有多个字段。代码示例:
(deftemplate person
(slot name) ; 唯一的姓名
(slot age) ; 唯一的年龄
(multislot address) ; 可以有多个地址
)
增加和删除事实
clips维护一个(facts)
事实列表,可以在事实列表中进行数据的添加和删除。
添加语法:
(assert <fact>+)
代码示例:
(deftemplate person
(slot name)
(slot age)
(multislot address)
)
(assert (person (name Sam) (age 22) (address Beijing NewYork)))
(facts)
一般来说,clips不接受重复的事实。
可以选择性地输出事实:
(facts [<start> [<end> [<maximum>]]])
start
表示起始位置,end
表示结束位置,都是闭区间;maximum
表示最多显示事实的个数。
retract
表示删除事实,基本语法是:
(retract <fact-index>+)
不能删除不存在的事实。
修改和复制事实
modify
表示修改自定义模板事实的槽值,基本语法是:
(modify <fact-index> <slot-modifier>+)
其中,<slot-modifier>
的定义是:
(<slot-name> <slot-value>)
代码示例:
(deftemplate person
(slot name)
(slot age)
(multislot address)
)
(assert (person (name Sam) (age 22) (address Beijing NewYork)))
(modify 1 (name Lily) (address London))
(facts)
duplicate
和modify
作用基本一致,不过不删除原来的事实,用法示例:
(deftemplate person
(slot name)
(slot age)
(multislot address)
)
(assert (person (name Sam) (age 22) (address Beijing NewYork)))
(assert (person (name Tom) (age 21) (address Shanghai)))
(duplicate 1 (name Lily) (address London))
(facts)
注意,复制的事实会追加到最后。
监视
这相当于进行调试,基本语法是:
(watch <watch-item>)
其中,<watch-item>
的符号可以是:
facts
:事实rules
:规则activations
:激活statistics
:统计complilations
:编译focus
:焦点all
:所有的符号
如果想要取消监视,那么之只需执行:
unwatch <watch-item>
箭头向左表示离开内存,向右表示进入内存。
自定义事实结构
需要使用deaffects
进行声明,基本语法是:
(deffacts <deffacts name> [<optional-comment>]
<facts>*
)
注意,这里的facts
必须有事实结构名,之后需要执行(reset)
命令进行说明。如果不执行(reset)
,那么声明的代码无效。注意,必须先执行deffacts
,然后执行的(reset)
命令才有效。
(reset)
命令删除列表中的所有事实,然后启用现有的自定义事实语句声明事实,给出代码示例:
(deftemplate person
(slot name)
(slot age)
)
(deffacts persons "person lists"
(person (name Sam) (age 11))
(person (name Daming) (age 20))
(person (name Amy) (age 15))
)
(reset)
(facts)
规则及其组成
一个规则的基础定义如下:
(defrule <rule-name> [optional comment]
<patterns>* ; Left-Hand Side (LHS) of the rule
=>
<actions>* ; Right-Hand Side (RHS) of the rule
)
patterns
和actions
可以嵌套使用,如果进行嵌套,那么需要匹配对应的括号。如果<patterns>
是空,那么clips会自动添加一个init-fact
作为规则,这个规则会在(reset)
命令执行时触发,之后<actions>
会被添加到议程Agenda
中。
如果有多个模式,那么模式之间是默认“与”规则
举个简单的规则代码例子:
(clear)
(deftemplate emergency
(slot type) ; type可以是fire(火灾)和flood(水灾)等
)
(deftemplate response
(slot action) ; 采取的行动
)
(defrule fire-emergency "An example rule"
(emergency (type fire))
=>
(assert (response (action activate-sprinkler-system)))
)
关于议程Agenda
的概念:如果规则的所有模式与事实匹配,那么规则就被激活(Activated)并放入日程Agenda
中,这是一个已经被激活的规则集合。
议程与执行
(run [<limit>])
表示执行日程。<limit>
表示规则最大的数目,不写或者是-1
表示执行所有的日程。举个简单的例子:
(clear)
(deftemplate person
(slot name)
)
(defrule isTom "check Tom"
(person (name Tom))
=>
(printout t "This is Tom" crlf) ; t表示终端、crlf表示换行
)
(reset)
(assert (person (name Tom)))
(agenda)
则会输出规则。
clips
的规则有个“反射”特性。通俗地说,就是一个已经在日程中的规则,如果执行了,那么再次执行(run)
命令的时候,不会被触发,因为此时该规则已经被移出Agenda
了。如果想要再次触发,需要执行refresh
操作,基本规则是:
(refresh <rule-name>)
如果上述代码最后追加(run)
,那么(agenda)
不会输出日程,因为已经进行(run)
操作,规则匹配后被移出日程了。如果想要再次加入日程,那么在代码最后追加:
(refresh isTom)
此时再执行(agenda)
命令,就可以进行日程输出了。
结构处理命令
几个常用的结构命令:
(list-defrules)
:显示所有的规则(list-deftemplates)
:显示所有的模板(list-deffacts)
:显示所有的定义事实(ppdefrule <defrule-name>)
:显示规则的文本内容(ppdeffacts <deffacts-name>)
:显示定义的事实内容(undefrule <defrule-name>)
:删除规则(undeftemplate <deftemplate-name>)
:删除模板(undeffacts <deffacts-name>)
:删除事实(clear)
:清除所有的信息,同时会恢复initial-facts
自定义事实
其他的一些内容
设置断点
调试程序时,需要单独进行设置断点,执行以下命令:
(set-break <rule-name>)
那么,在指定的<rule-name>
触发前,会暂停执行的过程。(show-breaks)
是显示断点。在断点处,执行(run)
命令会继续向下执行到下一个断点处。
调入和保存结构
可以把文件中的结构加载进入到clips解释器中,基本操作是:
(load <file-name>)
也可以把有关的结构保存到对应的.clp
文件中,基本操作是:
(save <file-name>)