将剪辑中的值存储到变量中

storing values in clips into variable

我有一个模板

(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,我们该怎么做。

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

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>

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

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

(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。