【问题标题】:Find maximum among facts in CLIPS在 CLIPS 中的事实中查找最大值
【发布时间】:2013-12-15 00:54:26
【问题描述】:

我是专家系统的新手,尤其是 CLIPS 方面的新手(除了英语 :-))。

我正在尝试使用复杂的比较谓词在事实中找到最大值(在某种意义上)。比较谓词被实现为一个以两个事实作为参数的函数。简而言之,我需要 CLIPS 来遍历所有事实,使用我的谓词进行比较并返回一个最大的事实。

一种解决方案可能是使用 CLIPS 规则评估下一个表达式:

( 存在 x) 而不是 ((Exists 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。不同之处在于我的问题是关于整个事实的比较,而不仅仅是一个位置。

是否可以找到一次激活规则的最大值?如果可能,请说明方法。

【问题讨论】:

    标签: clips


    【解决方案1】:

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

    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> 
    

    【讨论】:

      猜你喜欢
      • 2011-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      相关资源
      最近更新 更多