Сложный условный элемент в накоплении в правилах Jess

Я пытаюсь найти среднее значение наблюдений за температурой в JessTab, что требует объединения фактов из нескольких классов. Следующее правило:

(defrule averageOfObsValue  
?res <- 
(accumulate  
    (progn (bind ?s 0)(bind ?n 0)) 
    (progn (bind ?s (+ ?s ?v)) (++ ?n)) 
    (create$ ?n ?s ?qo) 
    (and  
        (object (is-a http..#ObservationValue) 
                (OBJECT ?ov)
                (http..#hasDataValue ?v)
        )
        (object (is-a http..#SensorOutput) 
                (OBJECT ?so) 
                (http..#hasValue ?ov)
        )
        (object (is-a http..#Observation)
                (OBJECT ?o)
                (http..#observationResult ?so)
                (http..#qualityOfObservation ?qo)
        )   
    )
)
=>  
(bind ?q (nth$ 3 ?res))  
(bind ?s (nth$ 2 ?res))  
(bind ?n (nth$ 1 ?res))  
(if (= (?q getURI) "http..#Temperature") then
(printout t "Average value is " (/ ?s ?n) " of " ?n " temperature observations." crlf)))

в WM имеет следующий вид:

(defrule MAIN::averageOfObsValue 
   (or 
     (and 
       (object (is-a http..#ObservationValue) 
               (OBJECT ?ov) 
               (http..#isValueOf ?so) 
               (http..#hasDataValue ?v))) 
     (and 
       (object (is-a http..#SensorOutput) 
               (OBJECT ?so) (http..#isObservationResultOf ?o))) 
     (and 
       (object (is-a http..#Observation) 
               (OBJECT ?o) (http..#qualityOfObservation ?qo)))) 
   => 
   (bind ?q (nth$ 3 ?res)) 
   (bind ?s (nth$ 2 ?res)) 
   (bind ?n (nth$ 1 ?res)) 
   (if (= (?q getURI) "http..#Temperature") then
   (printout t "Average value is " (/ ?s ?n) " of " ?n " temperature observations." crlf)))

и при запуске появляется следующая ошибка:

Джесс сообщил об ошибке в подпрограмме Context.getVariable при выполнении (nth$ 3 ?res) при выполнении (bind ?q (nth$ 3 ?res)) при выполнении defrule MAIN::averageOfObsValue655 при выполнении (run). Сообщение: Нет такой переменной res. Текст программы: ( run ) в строке 137.


person Edi    schedule 27.12.2014    source источник
comment
В строке (progn (bind ?s 0)(bind ?n 0) довольно очевидная синтаксическая ошибка - нет закрывающей скобки.   -  person laune    schedule 27.12.2014
comment
@laune Я исправил это и изменил вопрос   -  person Edi    schedule 27.12.2014


Ответы (1)


Представляется (и ваше последнее наблюдение это подтверждает), что аккумуляция не может быть применена к ВЭ с конъюнкцией. Лучший способ — создать временные факты, содержащие значения, по которым необходимо вычислить среднее, но необходимо позаботиться о создании отдельных временных фактов.

(deftemplate Value (slot v)(slot s)

(defrule createValueFacts
    (declare (salience 100))
    (object (is-a http..#ObservationValue) 
            (OBJECT ?ov)
            (http..#hasDataValue ?v)
    )
?s<-(object (is-a http..#SensorOutput) 
            (OBJECT ?so) 
            (http..#hasValue ?ov)
    )
    (object (is-a http..#Observation)
            (OBJECT ?o)
            (http..#observationResult ?so)
            (http..#qualityOfObservation ?qo)
    )
=>
    (assert (Value (v ?v)(s ?s))   ; using slot s to make fact unique
)

Эти Value факты можно легко собрать:

(defrule averageOfObsValue 
?res <- (accumulate  
    (progn (bind ?s 0)(bind ?n 0)) 
    (progn (bind ?s (+ ?s ?v)) (++ ?n)) 
    (create$ ?n ?s) 
    (Value (v ?v)))
=>
(bind ?s (nth$ 2 ?res))  
(bind ?n (nth$ 1 ?res))  
(printout t "Average value is " (/ ?s ?n) " of " ?n " temperature observations." crlf))
person laune    schedule 27.12.2014
comment
В ДБО может быть режим для Движка, при котором повторяющиеся факты автоматически удаляются. Не уверен, есть ли у Джесс этот режим и как он (де)активируется. Я не нашел ссылки на это в документации Jess. По-видимому, это неизменяемое поведение по умолчанию. - Добавление примечания к моему А. - person laune; 27.12.2014
comment
Спасибо, это работает :). Но в WM утверждаются только разные значения v, поскольку одни и те же значения перезаписывают друг друга, и поэтому среднее значение неверно. Любая идея, как решить эту... - person Edi; 27.12.2014
comment
Я только что добавил s.th. на мой А. Я не уверен, что уникального в тройке ваших фактов; при необходимости добавьте еще один слот. -- Факт есть истина, и повторить его в Джесс невозможно -- правдивее он не становится. - person laune; 27.12.2014
comment
Альтернативным подходом было бы аккумулировать значения в один факт. В этом случае не вставляйте, а изменяйте и используйте no-loop, чтобы избежать зацикливания. Требуется первое важное правило для создания суммы с нулевым слотом. - person laune; 27.12.2014
comment
Я использовал URI в соответствии с уникальным значением нового слота, и это дает результат. Еще раз спасибо за быстрые ответы - person Edi; 27.12.2014