我有一个模板
(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>
当允许执行每次激活时,从与激活相关的产品事实中检索可变金额。所以有三种规则触发,数量分别为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))
您的"做所有事实"查询也引用了productNumber而不是productId。