【问题标题】:How to add multiple variable in CLIPS?如何在 CLIPS 中添加多个变量?
【发布时间】:2020-06-16 10:57:20
【问题描述】:

我想根据事实添加并打印三种产品的总数量。如果数量大于 1,我也需要对产品 1 进行检查。

(defrule sum_of_quantity
 (or

(Product (productNumber 1)(quantity ?quantity0))

(Product (productNumber 2)(quantity ?quantity1))

(Product (productNumber 3)(quantity ?quantity2)))

=>

(bind ?totalQuantity (integer(+ ?quantity0 ?quantity1 ?quantity2)))

(printout t "TotalQuantity is " ?totalQuantity crlf)) 



I am actually new to clips and is finding it difficult to write rules

【问题讨论】:

  • 当您尝试运行此代码时会发生什么?为什么这是错的?请完整引用收到的任何错误,或者,如果它运行但输出错误,请显示所需的与当前输出。
  • 我得到的错误是 Defrule 的 RHS 中引用的未定义变量数量 1。错误: (defrule MAIN::sum_of_quantity (或 (Product (productNumber 1) (quantity ?quantity0)) (Product (productNumber 2) (quantity ?quantity1)) (Product (productNumber 3) (quantity ?quantity2))) => ( bind ?totalQuantity (integer (+ ?quantity0 ?quantity1 ?quantity2))) (打印输出 t "TotalQuantity is " ?totalQuantity crlf))

标签: rules rule-engine clip clips


【解决方案1】:

or 条件元素通过创建多个规则来工作,一个规则用于在规则。每个生成的规则都使用与原始规则相同的操作。因此,您的 sum_of_quantity 规则被转换为以下三个规则(它们共享相同的名称):

(defrule sum_of_quantity
   (Product (productNumber 1)(quantity ?quantity0))
   =>
   (bind ?totalQuantity (integer(+ ?quantity0 ?quantity1 ?quantity2)))
   (printout t "TotalQuantity is " ?totalQuantity crlf)) 

(defrule sum_of_quantity
   (Product (productNumber 2)(quantity ?quantity1))
   =>
   (bind ?totalQuantity (integer(+ ?quantity0 ?quantity1 ?quantity2)))
   (printout t "TotalQuantity is " ?totalQuantity crlf)) 

(defrule sum_of_quantity
   (Product (productNumber 3)(quantity ?quantity2)))
   =>
   (bind ?totalQuantity (integer(+ ?quantity0 ?quantity1 ?quantity2)))
   (printout t "TotalQuantity is " ?totalQuantity crlf)) 

查看生成的规则可以看到,在规则的操作中存在未绑定在规则条件中的变量。因此,当使用 or 条件元素时,规则动作中引用的任何变量都必须绑定在每个排列中。

一些基于规则的语言提供“收集”条件元素,可以轻松计算规则条件的总和,但遗憾的是 CLIPS 不提供此功能。但是,您可以使用 do-for-all-facts 查询函数来迭代规则操作中的一组事实:

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate Product
   (slot productNumber)
   (slot quantity))
CLIPS>    
(defrule sum_of_quantity
   (exists (Product (productNumber 1 | 2 | 3)))
   =>
   (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)))
   (printout t "TotalQuantity is " ?totalQuantity crlf))
CLIPS> 
(assert (Product (productNumber 1) (quantity 10))
        (Product (productNumber 2) (quantity 20))
        (Product (productNumber 3) (quantity 30))
        (Product (productNumber 4) (quantity 40)))
<Fact-4>
CLIPS> (run)
TotalQuantity is 60
CLIPS> 

在此示例中,exists 条件元素用于规则的条件中,因此无论存在多少 Product 事实,都只有一次激活。如果存在 productNumber 为 1、2 或 3 的任何 Product 事实,则此规则将激活。如果您希望所有 productNumbers 都是必需的,则可以这样编写模式:

(exists (Product (productNumber 1))
        (Product (productNumber 2))
        (Product (productNumber 3)))

规则的操作使用 do-for-all-facts 函数迭代每个 Product 事实并将数量槽添加到运行总计中。

【讨论】:

  • 您好,这非常有效。但我有一个额外的查询。如果我有一个额外的条件来检查产品 1 的数量应该大于 2 怎么办。我该如何将其纳入其中?
  • (产品 (productNumber 1) (数量 ?q&:(> ?q 2)))
【解决方案2】:

sum_of_quantity 规则表示产品 1、2、3 之间需要至少一个产品。不过,它试图将所有三个产品的数量相加。这在逻辑上是不正确的。

这就是引擎试图告诉你的。右手边 (RHS) 指的是一个变量 (quantity1),一旦您运行规则,它可能不会被定义。这是因为即使只声明了productNumber 1,您的规则也会激活。

只需删除规则中的 or 条件即可。要查看激活的规则,只需声明数量为0 的所有缺失产品。

【讨论】:

  • 如果我只需要产品 1 是强制性产品而其他两个是非强制性产品怎么办
  • 您可以简单地声明带有0 数量的可选产品。如果您想强制第一个产品为 != 而不是 0,您可以使用如下测试条件:(test (&gt; ?q0 0))
猜你喜欢
  • 2020-12-20
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
相关资源
最近更新 更多