Everything Jess does is deterministic, but you can't say the same
thing about Java. In the situation we have here, Jess's behavior is
being influenced by some randomness introduced by Java itself. In
particular, things are happening in different orders due to the fact
that the Java hashCode() method returns different values for your
Trigger and Template objects on each run.
In your program, you add the objects to working memory, and then call
(reset). Remember that what reset does is (among other things) clear
working memory, assert "initial-fact", then create new shadow facts
for the Java objects previously in working memory. Jess keeps track
of those objects in an "IdentityHashMap", and when it comes time to
reinstall them, the order in which the IdentityHashMap iterates over
them is the order in which the new facts will be asserted. This, in
turn, will affect the order in which rules are activated with any
given group of facts.
So your choices are to call "reset" before, rather than after, adding
your objects (which makes sense anyway), or to write your rules so
that this ordering either doesn't matter or is determined by some
other means (i.e., using the "key" slot, for example.) Either way you
would have deterministic behavior.
On May 27, 2007, at 1:10 PM, NicolasF wrote:
Hello everybody,
I have one "Template" shadow-fact and two "Trigger" shadow-facts. I
have a rule ("MAIN::triggers-template") activated by both "Trigger"
shadow-facts. This rule is pre-emptive. So once fired by a first
"Trigger" fact, it won't be fired by the second one. Each of the
"Trigger" shadow-facts have a unique slot named "key".
Generally the output of the Jess program (a simple clp file) looks
like this:
------------------------------------------
Jess, the Rule Engine for the Java Platform
Copyright (C) 2006 Sandia Corporation
Jess Version 7.0p1 12/21/2006
[Activation: MAIN::triggers-template f-3, f-2, ; time=4 ; salience=0]
[Activation: MAIN::triggers-template f-3, f-1, ; time=4 ; salience=0]
For a total of 2 activations in module MAIN.
f-0 (MAIN::initial-fact)
f-1 (MAIN::Trigger (class <Java-Object:java.lang.Class>)
(dynamicSlot 0) (key 1) (priority 0) (template <Java-
Object:trigger.Template>) (templateKey 1) (OBJECT <Java-
Object:trigger.Trigger>))
f-2 (MAIN::Trigger (class <Java-Object:java.lang.Class>)
(dynamicSlot 0) (key 2) (priority 0) (template <Java-
Object:trigger.Template>) (templateKey 1) (OBJECT <Java-
Object:trigger.Trigger>))
f-3 (MAIN::Template (class <Java-Object:java.lang.Class>) (key 1)
(state 0) (OBJECT <Java-Object:trigger.Template>))
For a total of 4 facts in module MAIN.
******* Trigger [key 2] (Fact Id 2) triggers template [key 1]
------------------------------------------
However, sometimes the shadow-facts doesn't have the same order in
the working memory. It is really strange, because I am using the
same clp file. So the shadow-facts are added in the same order. As
you can see below, instead to be fired by the [key 2] shadow-facts
(Fact Id 2), the rule is fired by [key 1] shadow-facts (Fact Id 3).
See the last line of the output with "*******".
------------------------------------------
Jess, the Rule Engine for the Java Platform
Copyright (C) 2006 Sandia Corporation
Jess Version 7.0p1 12/21/2006
[Activation: MAIN::triggers-template f-1, f-3, ; time=4 ; salience=0]
[Activation: MAIN::triggers-template f-1, f-2, ; time=4 ; salience=0]
For a total of 2 activations in module MAIN.
f-0 (MAIN::initial-fact)
f-1 (MAIN::Template (class <Java-Object:java.lang.Class>) (key 1)
(state 0) (OBJECT <Java-Object:trigger.Template>))
f-2 (MAIN::Trigger (class <Java-Object:java.lang.Class>)
(dynamicSlot 0) (key 2) (priority 0) (template <Java-
Object:trigger.Template>) (templateKey 1) (OBJECT <Java-
Object:trigger.Trigger>))
f-3 (MAIN::Trigger (class <Java-Object:java.lang.Class>)
(dynamicSlot 0) (key 1) (priority 0) (template <Java-
Object:trigger.Template>) (templateKey 1) (OBJECT <Java-
Object:trigger.Trigger>))
For a total of 4 facts in module MAIN.
******* Trigger [key 1] (Fact Id 3) triggers template [key 1]
------------------------------------------
This strange behavior seems to occur randomly. Sometimes it happens
only after many attempts. In the beginning, I thought that it was
caused by a rule ("INIT::modify-trigger-1") that modified a
"Template" shadow-facts. This rule was called before the pre-
emptive rule ("MAIN::triggers-template"). But I commented the
"modify-trigger-1" rule and its module (INIT) and the problem
occurs still. Here is the source code:
------------------------------------------
(import trigger.Template)
(import trigger.Trigger)
(deftemplate MAIN::Trigger
(declare (slot-specific TRUE) (from-class trigger.Trigger)))
(deftemplate MAIN::Template
(declare (slot-specific TRUE) (from-class trigger.Template)))
(defglobal ?*idle* = 0)
(defglobal ?*triggered* = 1)
; Constructor : Template(int aKey, int aState)
(bind ?template (new trigger.Template 1 ?*idle*))
(add ?template)
; Constructor : Trigger(int aKey, int aPriority, int aTemplateKey,
int aDynamicSlot, Template aTemplate)
(bind ?trigger1 (new trigger.Trigger 1 0 (?template getKey) 0 ?
template))
(add ?trigger1)
(bind ?trigger2 (new trigger.Trigger 2 0 (?template getKey) 0 ?
template))
(add ?trigger2)
;(bind ?trigger3 (new trigger.Trigger 3 1 (?template getKey) 0 ?
template))
;(add ?trigger3)
(reset)
;(defmodule INIT)
;
;(defrule INIT::modify-trigger-1
; ?triggerFact <-
; (MAIN::Trigger
; (key 1)
; )
; =>
; (printout t "******* Facts before modification." crlf)
; (facts)
; (modify ?triggerFact (dynamicSlot 1))
; (printout t "******* Facts after modification." crlf)
; (facts)
; (printout t "******* Trigger [key 1] dynamicSlot has been
modified." crlf)
; )
(defrule MAIN::triggers-template
?templateFact <-
(MAIN::Template
(key ?templateKey)
(state ?*idle*)
(OBJECT ?template))
?triggerFact <-
(MAIN::Trigger
(key ?key)
(priority ?p1)
(template ?template))
(not
(MAIN::Trigger
(priority ?p2&:(< ?p2 ?p1))
(template ?template)))
=>
(facts)
(printout t "******* Trigger [key " ?key "] (Fact Id " (?
triggerFact getFactId) ") triggers "
"template [key " ?templateKey "]" crlf)
(modify ?templateFact (state ?*triggered*))
)
;(focus INIT)
(agenda)
(run)
------------------------------------------
I would be glad, if anybody could help me to figure out something.
Thanks in advance,
NicolasF
--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users
[EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify owner-jess-
[EMAIL PROTECTED]
--------------------------------------------------------------------
---------------------------------------------------------
Ernest Friedman-Hill
Advanced Software Research Phone: (925) 294-2154
Sandia National Labs FAX: (925) 294-2234
PO Box 969, MS 9012 [EMAIL PROTECTED]
Livermore, CA 94550 http://www.jessrules.com
--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the list
(use your own address!) List problems? Notify [EMAIL PROTECTED]
--------------------------------------------------------------------