我是专家系统中的新手,尤其是CLIPS中的新手(也包括英语:-))。
我正在尝试使用复杂的比较谓词在事实中找到一个最大值(某种意义上)。比较谓词被实现为以两个事实作为参数的函数。简而言之,我需要CLIPS来处理所有事实,使用我的谓词进行比较,并返回一个最大的事实。
一种解决方案是使用CLIPS规则评估下一个表达式:
(存在x)而不存在((存在y)(y!= x)和(y> x))
其中“>”代表我的谓词,x和y是事实,例如:
(deftemplate fact (slot name ... ) ... )
(deffunction my-predicate ""
(?fact1 ?fact2)
...
)
(defrule find-max ""
?fact1 <- (fact (name ?name1) )
( not (test (my-predicate ?fact1 (fact (name ?name2 )))))
=>
...
)
Run Code Online (Sandbox Code Playgroud)
但是此示例由于我的谓词函数调用中有关第二个参数的错误消息而无法正常工作。
另一种解决方案是制作中间事实,该中间事实用谓词的比较函数的特定名称和值表示基本事实。但这需要多次迭代才能完成最终结果。
我更喜欢第一种解决方案,但我不知道如何编码。我想我需要在回答像这个问题。所不同的是,我的问题是关于整个事实的比较,而不仅仅是一个狭缝。
是否可以找到一次激活规则的最大值?如果可能,请说明如何。
通常,这是通过简单的比较来完成的:
CLIPS> (clear)
CLIPS>
(deftemplate fact (slot name) (slot value))
CLIPS>
(deffacts test-data
(fact (name data-1) (value 3))
(fact (name data-2) (value 1))
(fact (name data-3) (value 2))
(fact (name data-4) (value 2))
(fact (name data-5) (value 4))
(fact (name data-6) (value 3)))
CLIPS>
(defrule find-max-value
(fact (name ?name1) (value ?value1))
(not (fact (value ?value2&:(> ?value2 ?value1))))
=>
(printout t "Fact " ?name1 " is the maximum" crlf))
CLIPS> (reset)
CLIPS> (run)
Fact data-5 is the maximum
CLIPS>
Run Code Online (Sandbox Code Playgroud)
如果绑定比较所需的所有插槽值并将它们传递给函数,则相同的基本方法也可以使用:
CLIPS> (clear)
CLIPS>
(deftemplate fact (slot name) (slot value))
CLIPS>
(deffacts test-data
(fact (name data-1) (value 3))
(fact (name data-2) (value 1))
(fact (name data-3) (value 2))
(fact (name data-4) (value 2))
(fact (name data-5) (value 4))
(fact (name data-6) (value 3)))
CLIPS>
(deffunction my-predicate (?value1 ?value2)
(> ?value1 ?value2))
CLIPS>
(defrule find-max-value
(fact (name ?name1) (value ?value1))
(not (fact (value ?value2&:(my-predicate ?value2 ?value1))))
=>
(printout t "Fact " ?name1 " is the maximum" crlf))
CLIPS> (reset)
CLIPS> (run)
Fact data-5 is the maximum
CLIPS>
Run Code Online (Sandbox Code Playgroud)
但是,将事实传递给函数是有问题的,因为您不能将模式绑定到非条件元素内的事实地址。如果事实具有作为唯一标识符的插槽,则可以使用它来检索指向事实的指针(尽管我不推荐这种方法):
CLIPS> (clear)
CLIPS>
(deftemplate fact (slot name) (slot value))
CLIPS>
(deffacts test-data
(fact (name data-1) (value 3))
(fact (name data-2) (value 1))
(fact (name data-3) (value 2))
(fact (name data-4) (value 2))
(fact (name data-5) (value 4))
(fact (name data-6) (value 3)))
CLIPS>
(deffunction my-predicate (?fact1 ?fact2)
(> (fact-slot-value ?fact1 value) (fact-slot-value ?fact2 value)))
CLIPS>
(defrule find-max-value
?fact1 <- (fact (name ?name1))
(not (fact (name ?name2&:(my-predicate (nth$ 1 (find-fact ((?fact2 fact))
(eq ?fact2:name ?name2)))
?fact1))))
=>
(printout t "Fact " ?name1 " is the maximum" crlf))
CLIPS> (reset)
CLIPS> (run)
Fact data-5 is the maximum
CLIPS>
Run Code Online (Sandbox Code Playgroud)
我建议做的是使用事实查询功能对事实进行迭代以找到最大值:
CLIPS> (clear)
CLIPS>
(deftemplate fact (slot name) (slot value))
CLIPS>
(deffacts test-data
(fact (name data-1) (value 3))
(fact (name data-2) (value 1))
(fact (name data-3) (value 2))
(fact (name data-4) (value 2))
(fact (name data-5) (value 4))
(fact (name data-6) (value 3)))
CLIPS>
(deffunction my-predicate (?fact1 ?fact2)
(> (fact-slot-value ?fact1 value) (fact-slot-value ?fact2 value)))
CLIPS>
(deffunction find-max (?template ?predicate)
(bind ?max FALSE)
(do-for-all-facts ((?f ?template)) TRUE
(if (or (not ?max) (funcall ?predicate ?f ?max))
then
(bind ?max ?f)))
(return ?max))
CLIPS>
(reset)
CLIPS> (facts)
f-0 (initial-fact)
f-1 (fact (name data-1) (value 3))
f-2 (fact (name data-2) (value 1))
f-3 (fact (name data-3) (value 2))
f-4 (fact (name data-4) (value 2))
f-5 (fact (name data-5) (value 4))
f-6 (fact (name data-6) (value 3))
For a total of 7 facts.
CLIPS> (find-max fact my-predicate)
<Fact-5>
CLIPS>
(defrule find-max
=>
(bind ?fact (find-max fact my-predicate))
(if ?fact
then
(printout t "Fact " (fact-slot-value ?fact name) " is the maximum" crlf)))
CLIPS> (run)
Fact data-5 is the maximum
CLIPS>
Run Code Online (Sandbox Code Playgroud)
尽管CLIPS不支持,但是许多语言都支持累积条件元素,这使执行这种类型的计算变得更加容易。例如,在Jess中,您可以执行以下操作:
Jess>
(deftemplate fact (slot name) (slot value))
TRUE
Jess>
(deffacts test-data
(fact (name data-1) (value 3))
(fact (name data-2) (value 1))
(fact (name data-3) (value 2))
(fact (name data-4) (value 2))
(fact (name data-5) (value 4))
(fact (name data-6) (value 3)))
TRUE
Jess> (if FALSE then 3 else 4)
4
Jess>
(defrule find-max-value
?c <- (accumulate (bind ?max FALSE)
(if (or (not ?max) (> ?value ?max))
then (bind ?max ?value))
?max
(fact (value ?value)))
=>
(printout t "The max is " ?c crlf))
TRUE
Jess> (reset)
TRUE
Jess> (run)
The max is 4
1
Jess>
Run Code Online (Sandbox Code Playgroud)