small routine program
I have 10 sensor that watch an environment. The sensor is 1 if OK and 0 if not. I need to create a functional that will print out a Warning message to the terminal if there are at least 3 sensor that are on 0, and the message warning to be showed only once. This I need to do in clips.
Thank you.
(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)
)
There are two issues you need to deal with. The first is that the patterns you defined can match the same fact multiple times (eg, sensor L1
will be bound to a
, b
, and c
). To get around this, you need to ensure that a
, b
, and c
are unique. One way to do this is as follows (note that I also added a missing "(" in front of your printout
statement):
(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))
Running this rule against your facts gives:
CLIPS> (reset)
CLIPS> (run)
L9L7L2==>WARNING
L9L7L1==>WARNING
L9L2L7==>WARNING
...
L1L2L7==>WARNING
L2L1L7==>WARNING
The warning is now only generated when there are three or more not-OK sensors; however, the output presents the second issue, which is that your warning is being generated multiple times (once for every unique combination of three not-OK sensors). To get around this, you probably want a control fact to prevent the rule from firing multiple times. To achieve this, you could modify the rule with the following:
(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))
This ensures that the rule will only fire once (unless you retract the sensor-warning
fact). Running with the updated rule:
CLIPS> (reset)
CLIPS> (run)
L9L7L2==>WARNING
CLIPS>
This is a simple solution to your problem. If you are likely to change the number of not-OK sensors that should trigger the rule, then you should probably replace the "hardwired" sensor name comparisons with more general logic (eg, you could compute the total number of not-OK sensors and compare that to your threshold).
Here's another way to do it:
(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))
This will print all of the sensors if there are more than 3 that have a value of 0.
CLIPS> (reset)
CLIPS> (run)
L1 L2 L7 L9 ==> WARNING
CLIPS>
链接地址: http://www.djcxy.com/p/76184.html
上一篇: Html帮助程序不使用自定义VirtualPathProvider
下一篇: 小例程