I am new to Jess The Rule Engine and I am having a trouble with a simple query. I have a simple java bean file and a .clp file . By using java bean file I create word objects and by using .clp I do some processes, by defining rules, on imported java objects which are now in the working memory of Jess. And at the end of the rules that I described I want to perform a query which will find the highest sentenceNumber - sentenceNumber is a slot variable in my Word fact- by using the accumulate conditional element. And also I want to return the resulting value to Java code. The problem is that the query that I wrote gives me error if I do use accumulate CE in the query but not in the defrule.
So my question is : Is it inappropriate to use accumulate CE in a query? I could not find any material which says yes or no.
Below I give you my query :
(defquery get-Total-Sentence-Number
"this query gets the total number of newly created sentences"
;(accumulate <initializer> <action> <result> <conditional element>)
?result <- (accumulate (bind ?max FALSE) ;initializer
(if (or (not ?max);action
(> ?sentenceNumber ?max))
then (bind ?max ?sentenceNumber))
?max ;result
(Word (sentenceNumber ?sentenceNumber))))
Please help. Thank you
p.s. I do not want to use the accumulate CE in a defrule because as I understood a rule will fire itself again and again in every change of the fact list. And I just want to perform this only once which I need it at the end of the rules that I defined.
I think there is a restriction. Anyway, it doesn't really make sense to run an accumulate in a query. It would be easier to define a query returning the facts:
(defquery get-words
(Word (sentenceNumber ?sentenceNumber)))
to run it, and to evaluate the maximum in an iteration over the queried collection:
(bind ?result (run-query* get-words))
(bind ?max 0)
(while (?result next) do
(bind ?snr (?result getString sentenceNumber))
(if (> ?snr ?max) then (bind ?max ?snr))
)
(printout t "max: " ?max crlf)
Later Then I recommend the following approach:
;; define an auxiliary fact
(deftemplate MaxWord (slot maxSentence))
;; initialze one fact
(deffacts maximum
(MaxWord (maxSentence 0))
)
;; a rule to compute the maximum
(defrule setMax
?mw <- (MaxWord (maxSentence ?ms))
(Word (sentenceNumber ?snr & :(> ?snr ?ms)))
=>
(modify ?mw (maxSentence ?snr))
)
;; the query
(defquery getMax
(MaxWord (maxSentence ?maxSentence)))
;; obtain the result
(bind ?result (run-query* getMax))
(?result next)
(bind ?max (?result getString maxSentence))
(printout t "max: " ?max crlf)
Note that this does not work correclty if Word facts are retracted, which is bound to invalidate the maximum.
An entirely different approach can be made by using a rule with accumulate and an initial (auxiliary) fact that needs to be asserted when the rule should fire. This would avoid the frequent repetition of accumulate. Basically:
(defrule "calcMax"
(FreeToCalc)
?result <- (accumulate (bind ?max 0)
(if (> ?sentenceNumber ?max)
then (bind ?max ?sentenceNumber))
?max
(Word (sentenceNumber ?sentenceNumber))))
=>
;;...
)