变量
Clips中,变量是一个?
接一个变量名实现的,比如?speed
等。
变量的第一个作用是保存输入的槽值,给出代码示例:
(deftemplate person
(slot name)
(slot eyes)
)
(defrule BuleEyes
(person (name ?name) (eyes blue))
=>
(printout t ?name " has bule eyes." crlf)
)
(deffacts persons
(person (name Jane) (eyes blue))
(person (name Tom) (eyes green))
(person (name Lily) (eyes blue))
)
(reset)
(run)
一个变量首次约束于某一值时,该变量在此规则内便保持该值,其他同名变量必须约束为这第一个变量的值,代码示例:
(undefrule *)
(deftemplate find
(slot eyes)
)
(deftemplate person
(slot name)
(slot eyes)
)
(defrule find-eyes
(find (eyes ?eyes))
(person (name ?name) (eyes ?eyes))
=>
(printout t ?name " has" ?eyes " eyes." crlf)
)
(deffacts persons
(person (name Jane) (eyes blue))
(person (name Tom) (eyes green))
(person (name Lily) (eyes blue))
)
(reset)
(assert (find(eyes blue)))
(run)
上述代码中,因为对find
中的eyes
进行了蓝色约束,那么在规则find-eyes
中,eyes
将一直是蓝色的,所以这里就相当于是查找蓝色眼睛的同学。
Clips中,使用<-
来作为取地址的操作,取地址操作时,相当于是<==
的过程。
代码示例:
(clear)
(deftemplate person
(slot name)
(slot address)
)
(deftemplate moved
(slot name)
(slot address)
)
(defrule process-moved-information
?f1 <- (moved (name ?name) (address ?address))
?f2 <- (person (name ?name))
=>
(retract ?f1) ; 在这里删除中间的事实
(modify ?f2 (address ?address))
)
(deffacts example
(person (name John) (address Lodon))
(moved (name John) (address NewYork))
)
(reset)
(watch rules)
(watch facts)
(run)
如果删除(retract ?f1)
,之后程序进入死循环。理由如下:一个modify
命令可以视为一个retract
命令和一个assert
命令。删除retract
命令后,modify
会先提取出person
,之后再加入一个新的person
结构,原来的moved
结构没有被删除,此时又会满足规则,如此往复,造成无限循环。
如果要输入多个变量,那么可以使用$
符号来表示1个或者多个变量。同时,也可以利用这个特性来匹配第一个或者最后一个数据等,给出代码示例:
(deftemplate person
(multislot name)
)
(defrule print-name
(person (name ?first $? ?last))
=>
(printout t "Person first and last name are " ?first ", " ?last crlf)
)
(assert (person (name John Q. Lamg Smith)))
(facts)
(run)
此时,(run)
的结果只会输出John
和Smith
。注意,$
只需要在LHS中即可,RHS不需要使用该符号。
字段约束
非约束~
符号,相当于一个取反操作,代码示例:
(deftemplate person
(slot name)
(slot hair)
)
(defrule hair-rule
(person (name ?name) (hair ~brown))
=>
(printout t ?name " doesn't has brown hair" crlf)
)
(deffacts persons
(person (name Tom) (hair black))
(person (name Sam) (hair brown))
(person (name Amy) (hair red))
)
(reset)
(run)
或约束|
符号,或操作:
(deftemplate person
(slot name)
(slot hair)
)
(defrule hair-rule
(person (name ?name) (hair brown | black))
=>
(printout t ?name " has dark hair" crlf)
)
(deffacts persons
(person (name Tom) (hair black))
(person (name Sam) (hair brown))
(person (name Amy) (hair red))
)
(reset)
(run)
与约束&
符号,一般与其它符号联合使用,比如判别一个人有黑色或者红色的头发。
(deftemplate person
(slot name)
(slot hair)
)
(defrule dark-hair-rule
(person (name ?name) (hair ?hair & brown | black))
=>
(printout t ?name " has dark hair" crlf)
)
(defrule no-dark-hair-rule
(person (name ?name) (hair ?hair & ~brown & ~black))
=>
(printout t ?name " has no dark hair" crlf)
)
(assert (person (name Tom) (hair black)))
(assert (person (name Sam) (hair white)))
(run)
更强大的规则约束:
(deftemplate person
(slot name)
(slot hair)
)
(defrule myrule
(person (name ?name)
(hair ?hair & ~black & ~brown))
(person (name ?name1 & ~?name)
(hair ?hair1 & black | red))
=>
(printout t "OK" crlf)
)
(watch facts)
(watch rule)
(assert (person (name Tom) (hair red)))
(assert (person (name Sam) (hair black)))
(run)
输出OK
数学表达式和规则求和
Lisp风格的前缀表达式,优先级同C语言,而且只能由括号确定。
(+ 2 2)
(- 2 3 4)
(+ 2 (* 3 4 5))
以一个矩形求和为例:
(deftemplate rectangle
(slot width)
(slot height)
)
(defrule sum-rectangle
(rectangle (height ?height) (width ?width))
=>
(assert (add-to-sum (* ?width ?height)))
)
(defrule sum-areas
?sum <- (sum ?total) ; 为了取出地址,然后从facts中删除即可
?new-area <- (add-to-sum ?area)
=>
(retract ?sum ?new-area) ; 清空原来的列表数据
(assert (sum (+ ?total ?area)))
)
(deffacts initial-data
(rectangle (width 10) (height 10))
(rectangle (width 30) (height 10))
(rectangle (width 22) (height 14))
(rectangle (width 11) (height 71))
(sum 0)
)
(watch facts)
(watch activations)
(watch rules)
(reset)
(run)
(facts)
输出结果是:
CLIPS> (watch facts)
CLIPS> (watch activations)
CLIPS> (watch rules)
<== f-0 (initial-fact)
==> f-0 (initial-fact)
==> f-1 (rectangle (width 10) (height 10))
==> Activation 0 sum-rectangle: f-1
==> f-2 (rectangle (width 30) (height 10))
==> Activation 0 sum-rectangle: f-2
==> f-3 (rectangle (width 22) (height 14))
==> Activation 0 sum-rectangle: f-3
==> f-4 (rectangle (width 11) (height 71))
==> Activation 0 sum-rectangle: f-4
==> f-5 (sum 0)
CLIPS> (reset)
FIRE 1 sum-rectangle: f-4
==> f-6 (add-to-sum 781)
<== f-8 (add-to-sum 308)
==> f-9 (sum 1089)
FIRE 5 sum-rectangle: f-2
==> f-10 (add-to-sum 300)
==> Activation 0 sum-areas: f-9,f-10
FIRE 6 sum-areas: f-9,f-10
<== f-9 (sum 1089)
<== f-10 (add-to-sum 300)
==> f-11 (sum 1389)
FIRE 7 sum-rectangle: f-1
==> f-12 (add-to-sum 100)
==> Activation 0 sum-areas: f-11,f-12
FIRE 8 sum-areas: f-11,f-12
<== f-11 (sum 1389)
<== f-12 (add-to-sum 100)
==> f-13 (sum 1489)
CLIPS> (run)
(facts)
f-0 (initial-fact)
f-1 (rectangle (width 10) (height 10))
f-2 (rectangle (width 30) (height 10))
f-3 (rectangle (width 22) (height 14))
f-4 (rectangle (width 11) (height 71))
f-13 (sum 1489)
For a total of 6 facts.
这是使用中间变量的方式执行推导。而且,Clips编程中,没有循环的语法,一切操作都是函数式处理。
bind绑定函数
该函数核心作用是使用临时变量存储结果,防止重复计算。基本的语法结构是:
(bind <variable> <value>)