在CLIPS中查找事实中的最大值

时间:2013-11-28 22:04:13

标签: clips

我是专家系统的新手,尤其是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 )))))
=>
...
)

但由于my-predicate函数调用中有关第二个参数的错误消息,此示例无效。

另一个解决方案是制作代表基本事实的中间事实,其具有谓词的比较函数的特定名称和值。但这需要多次迭代才能完成最终结果。

我更喜欢第一种解决方案,但我不明白如何编码。我想我需要回答这个问题question。不同的是,我的问题是关于整个事实的比较,而不仅仅是一个插槽。

是否有可能找到一次激活规则的最大值?如果可能,请解释如何。

1 个答案:

答案 0 :(得分:4)

通过简单的比较,您通常会这样做:

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> 

如果您绑定比较所需的所有插槽值并将它们传递给函数,则相同的基本方法也可以使用:

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> 
然而,将事实传递给函数是有问题的,因为您无法将模式绑定到非条件元素内的事实地址。如果事实有一个插槽作为唯一标识符,您可以使用它来检索指向事实的指针(虽然我不建议这种方法):

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> 

我建议做的是使用事实查询函数迭代事实来找到最大值:

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> 

虽然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>