0

I am trying to find average value of temperature observations in JessTab which requires joining facts from multiple classes. The following rule:

(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)))

in the WM has the following form:

(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)))

and while running it the following error appears:

Jess reported an error in routine Context.getVariable while executing (nth$ 3 ?res) while executing (bind ?q (nth$ 3 ?res)) while executing defrule MAIN::averageOfObsValue655 while executing (run). Message: No such variable res. Program text: ( run ) at line 137.

Edi
  • 109
  • 11

1 Answers1

0

It seems (and your latest observation confirms it) that accumulate cannot be applied to a CE with a conjunction. The best way is to create temporary facts containing the values over which the average needs to be computed, but care must be taken to create distinct temporary fact.

(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
)

These Value facts can be easily accumulated:

(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))
laune
  • 31,114
  • 3
  • 29
  • 42
  • In RBS, there may be a mode for the Engine where duplicate facts are automatically deleted. Not sure whether Jess has this mode, and how it is (de)activated. I haven't found a reference to this in the Jess documentation. Apparently it is the unmodifiable default behaviour. - Adding a note to my A. – laune Dec 27 '14 at 16:46
  • Thanks it works :). But, only distinct v values are asserted on WM, since same values overwrite each other and thus the average value is not correct. Any idea how to solve this... – Edi Dec 27 '14 at 16:52
  • I've just added s.th. to my A. I'm not sure what is unique in the triplet of your facts; if necessary add another slot. -- A fact is a "truth" and it can't be repeated in Jess - it doesn't become any truer. – laune Dec 27 '14 at 16:53
  • 1
    An alternative approach would be to accumulate the values into a singe fact. In that case, don't insert but modify and use no-loop to avoid looping. Needs a first high-salience rule to create the sum with its slot set to zero. – laune Dec 27 '14 at 16:55
  • I used the URI as per unique value of new slot and it gives the result. Thanks again for the quick responses – Edi Dec 27 '14 at 17:11