7

我有 10 个观察环境的传感器。如果正常,则传感器为 1,否则为 0。如果至少有 3 个传感器处于 0 状态,我需要创建一个函数,它将向终端打印一条警告消息,并且消息警告只显示一次。这是我需要在剪辑中完成的。

谢谢你。

   (deffacts listaSenzor
    (sensor L1 0)
    (sensor L2 0) 
    (sensor L3 1)
    (sensor L4 1)
    (sensor L5 1)
    (sensor L6 1)
    (sensor L7 0)
    (sensor L8 1)
    (sensor L9 0)
    )
    (defrule rr
        (sensor ?a  0 )
        (sensor ?b  0 )
        (sensor ?c  0 )
        =>
        printout t ?a ?b ?c "==>WARNING" crlf)
        )
4

2 回答 2

2

您需要处理两个问题。首先是您定义的模式可以多次匹配同一事实(例如,传感器L1将绑定到abc)。为了解决这个问题,您需要确保abc是唯一的。一种方法如下(请注意,我还在您的printout声明前添加了一个缺失的“(”):

(deffacts listaSenzor
    (sensor L1 0)
    (sensor L2 0) 
    (sensor L3 1)
    (sensor L4 1)
    (sensor L5 1)
    (sensor L6 1)
    (sensor L7 0)
    (sensor L8 1)
    (sensor L9 0))
(defrule rr
    (sensor ?a 0)
    (sensor ?b 0)
    (sensor ?c 0)
    (test (neq ?a ?b))
    (test (neq ?a ?c))
    (test (neq ?b ?c))
=>
    (printout t ?a ?b ?c "==>WARNING" crlf))

根据您的事实运行此规则会给出:

CLIPS> (reset)
CLIPS> (run)
L9L7L2==>WARNING
L9L7L1==>WARNING
L9L2L7==>WARNING
...
L1L2L7==>WARNING
L2L1L7==>WARNING

现在仅当存在三个或更多不正常传感器时才会生成警告;但是,输出显示了第二个问题,即您的警告被多次生成(对于三个不正常传感器的每个唯一组合一次)。为了解决这个问题,您可能需要一个控制事实来防止规则多次触发。为此,您可以使用以下内容修改规则:

(defrule rr
    (not (sensor-warning))
    (sensor ?a 0)
    (sensor ?b 0)
    (sensor ?c 0)
    (test (neq ?a ?b))
    (test (neq ?a ?c))
    (test (neq ?b ?c))
=>
    (assert (sensor-warning))
    (printout t ?a ?b ?c "==>WARNING" crlf))

这确保了规则只会触发一次(除非您收回sensor-warning事实)。使用更新的规则运行:

CLIPS> (reset)
CLIPS> (run)
L9L7L2==>WARNING
CLIPS> 

这是解决您问题的简单方法。如果您可能会更改应该触发规则的不正常传感器的数量,那么您可能应该用更通用的逻辑替换“硬连线”传感器名称比较(例如,您可以计算不正常传感器的总数和将其与您的阈值进行比较)。

于 2013-12-16T15:22:27.943 回答
2

这是另一种方法:

(deftemplate sensor
   (slot id)
   (slot value))

(deffacts listaSenzor
   (sensor (id L1) (value 0))
   (sensor (id L2) (value 0)) 
   (sensor (id L3) (value 1))
   (sensor (id L4) (value 1))
   (sensor (id L5) (value 1))
   (sensor (id L6) (value 1))
   (sensor (id L7) (value 0))
   (sensor (id L8) (value 1))
   (sensor (id L9) (value 0)))

(defrule rr
   (exists 
      (sensor (id ?id1) (value 0))
      (sensor (id ?id2&~?id1) (value 0))
      (sensor (id ?id3&~?id2&~?id1) (value 0)))
   =>
   (bind ?sensors (create$))
   (do-for-all-facts ((?f sensor)) (eq ?f:value 0)
      (bind ?sensors (create$ ?sensors ?f:id)))
   (printout t (str-implode ?sensors) " ==> WARNING" crlf))

如果超过 3 个传感器的值为 0,这将打印所有传感器。

CLIPS> (reset)
CLIPS> (run)
L1 L2 L7 L9 ==> WARNING
CLIPS> 
于 2013-12-17T18:05:41.987 回答