【问题标题】:storing values in clips into variable将剪辑中的值存储到变量中
【发布时间】:2020-07-21 16:27:16
【问题描述】:

我有一个模板

(deftemplate Product
(slot productId (type INTEGER))
(slot uom (default EA))
(slot quantity (type INTEGER))
(slot amount))

我正在使用代码

(defrule sum_of_quantity
   (exists (Product (productId 1 | 2 | 3)(amount ?amount)))
   =>
   (bind ?totalQuantity 0)
   (do-for-all-facts ((?p Product))
                     (or (eq ?p:productNumber 1)
                         (eq ?p:productNumber 2)
                         (eq ?p:productNumber 3))
      (bind ?totalQuantity (+ ?totalQuantity ?p:quantity)))
     (if (>= ?amount 5000) then
   (printout t "TotalQuantity is " ?totalQuantity crlf)))

在这里我收到一条错误消息: defrule的RHS中引用了未定义的变量。

我要检查每个产品的数量是否大于5000。我们怎么做。

【问题讨论】:

  • 您发布的代码不会产生上述错误。您得到的错误是因为 Product deftemplate 不包含规则引用的 productNumber 插槽。
  • 抱歉,我发布的代码发生了变化。现在我得到了同样的错误。我该如何解决这个问题

标签: rules rule-engine clips


【解决方案1】:

一个可以被多个不同事实匹配的简单事实模式可能会导致一个规则的多次激活:

CLIPS> 
(deftemplate product
   (slot id)
   (slot amount))
CLIPS>    
(deffacts products
   (product (id 1) (amount 1000))
   (product (id 2) (amount 3000))
   (product (id 3) (amount 6000)))
CLIPS> 
(defrule print-amount
   (product (id ?id) (amount ?amount))
   =>
   (printout t ?id ": " ?amount crlf))
CLIPS> (reset)
CLIPS> (agenda)
0      print-amount: f-3
0      print-amount: f-2
0      print-amount: f-1
For a total of 3 activations.
CLIPS> (run)
3: 6000
2: 3000
1: 1000
CLIPS> 

当允许执行每个激活时,从与激活关联的产品事实中检索可变数量。所以有 3 个规则触发,数量分别为 6000、3000 和 1000。

一个存在的条件元素只匹配一次,而不管它包含的事实模式匹配的次数:

CLIPS> 
(defrule exists
   (exists (product (id ?id) (amount ?amount)))
   =>)
CLIPS> (agenda)
0      exists: *
For a total of 1 activation.
CLIPS>

列出议程时,会显示一个 *,表示该模式已匹配,但与特定事实不匹配。如果您尝试在规则的操作中访问变量数量,则会收到错误消息。这是因为变量数量在模式之外没有任何意义,因为它没有特定的值。如果任意选择与事实模式匹配的事实之一来提供金额的值,您将获得不可预知的行为。

重写规则的最简单方法是将金额检查从规则的操作移至存在模式:

(defrule sum_of_quantity
   (exists (Product (productId 1 | 2 | 3)
                    (amount ?amount&:(>= ?amount 5000))))
   =>
   (bind ?totalQuantity 0)
   (do-for-all-facts ((?p Product))
                     (or (eq ?p:productId 1)
                         (eq ?p:productId 2)
                         (eq ?p:productId 3))
      (bind ?totalQuantity (+ ?totalQuantity ?p:quantity)))
   (printout t "TotalQuantity is " ?totalQuantity crlf))

您的 do-for-all-facts 查询还引用了 productNumber 而不是 productId。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 2020-01-11
    • 2016-05-10
    相关资源
    最近更新 更多