Клипы - небольшая рутинная программа

У меня есть 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)
        )

person lusian_andrei    schedule 16.12.2013    source источник
comment
Что именно вы пробовали? Поделитесь кодом ... Вы искали перед тем, как спросить? Вы не можете ожидать, что мы сделаем для вас программу ... Мы можем только помочь вам отладить вашу программу ...   -  person Acelasi Eu    schedule 16.12.2013
comment
вы должны отредактировать вопрос, чтобы добавить эти детали :)   -  person Acelasi Eu    schedule 16.12.2013
comment
@AcelasiEu не могли бы вы мне помочь?   -  person lusian_andrei    schedule 16.12.2013
comment
Нет, роликов не знаю, просто помогал вам соблюдать правила .. Я теперь заменил свой отрицательный голос на положительный :) Молодец!   -  person Acelasi Eu    schedule 16.12.2013


Ответы (2)


Вам нужно решить две проблемы. Во-первых, определенные вами шаблоны могут соответствовать одному и тому же факту несколько раз (например, датчик L1 будет привязан к a, b и c). Чтобы обойти это, вам нужно убедиться, что a, b и c уникальны. Один из способов сделать это следующий (обратите внимание, что я также добавил отсутствующий "(" перед вашим оператором 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> 

Это простое решение вашей проблемы. Если вы, вероятно, измените количество датчиков "не в порядке", которые должны запускать правило, то вам, вероятно, следует заменить сравнение имен "зашитых" датчиков более общей логикой (например, вы можете вычислить общее количество датчиков, не отвечающих требованиям, и сравните это с вашим порогом).

person bogatron    schedule 16.12.2013

Вот еще один способ сделать это:

(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> 
person Gary Riley    schedule 17.12.2013