My explanation hinges on what happens in the startPropTimer() method.
I'm assuming that it does not create a thread, but instead calls
calcTime() directly or indirectly. If this is the case, then remember
that Rete.run() contains a loop which fires the first rule on the
agenda repeatedly until no more rules are left to fire. This loop
invokes a Defrule.fire() method to fire each rule directly. The fire
() method ultimately invokes all the Jess code on that rule's right
hand side. So if your Initiates rule fires, then ultimately run()
calls fire() which calls calcTime(), and I hope by now you see that
because of this, the next rule can't fire until calcTime() returns.
Jess receives the events because they are send synchronously from
calcTime() -- i.e., calcTime() calls firePropertyChange() which calls
a PropertyChangeListener.propertyChanged() method in Jess which
modifies working memory. But the next rule can't fire until fire()
returns back to the loop in run().
For your PropTimer to function as a true timer, it has to do what the
Hardware objects in the Jess in Action example do: spawn its own
thread and send change events from that separate thread. This will
allow Initiate.fire() to return promptly and continue on to fire
additional rules as the events arrive.
On Jan 4, 2007, at 10:38 PM, Mike Stacey wrote:
Thanks for the reply Ernest.
I have a thread calling Rete.run(). Inside the jess script I create a
hardware interface and hardware monitor much the same as your example
in the temperature controller in your book - chap 14. The hardware
sensor opens a data source which are timestamped instantaneous values
and the monitor class (like the thermometer class) gets data values
from the hardware interface inside a run() method and fires events for
Jess to reason with. This all works fine.
My rules also rely on time periods. I classify data into categories
depending on their values and initiate the relevant category using a
rule. A rule input by the user might have the following semantics:
"Determine if there are any periods of time 20 seconds or more where
data values are greater than 143."
(defrule Initiates
(mon (reading ?r&:(>= ?r 143))
(tstamp ?t&:(> ?t 0)))
(pTime(running ?run&:(= ?run FALSE)))
=>
(printout t ">>>>>>>Initiates: Data "?r" bpm, timestamp "?t", Fluent
truth val: "?run crlf)
;; start the timer which also functions as a flag to indicate
;; that this category is active
(call ?pT startPropTimer))
So if the category hasn't been activated before (running is false) and
the data value is > 143 then I initiate the time dependent category by
starting the propTimer. Property 'running' and method startPropTimer()
are in a class called PropTimer. This class is connected to Jess
using:
(defclass pTime PropTime)
(bind ?pT (new PropTime)
(definstance pTime ?pT)
The Initiates rule works OK.
The terminates rule is a problem. It's function ius to terminate the
category due to the propTimer expiring.
(defrule Terminates
;Terminate when timer reaches 7000, example only
(pTime(elapsedTime ?et&:(>= ?et 7000)))
=>
(printout t ">>>>>>>Terminates: Elapsed time: "?et crlf)
(call ?pT stopPropTimer))
I will use some kind of flag to indicate the start and end times of
the category and may even save all the data in between these times to
a file or something.
So I guess, in response to your prompt, I have only one thread; the
one that starts the rete engine. The timer events are simply fired
from within a loop inside calcTime() - the facts are picked up by Jess
but the terminates rule won't act on them. I have a trace as follows
from watch facts:
<=> f-0 (MAIN::pTime (class <Java-Object:java.lang.Class>)
(elapsedTime 5860) (running TRUE) (OBJECT <Java-Object:PropTime>))
<=> f-0 (MAIN::pTime (class <Java-Object:java.lang.Class>)
(elapsedTime 5875) (running TRUE) (OBJECT <Java-Object:PropTime>))
<=> f-0 (MAIN::pTime (class <Java-Object:java.lang.Class>)
(elapsedTime 5891) (running TRUE) (OBJECT <Java-Object:PropTime>))
etc...
These facts appear after the Initiates rule has fired and before the
terminates rule fires. But, as I mentioned originally, terminates only
fires when the loop inside calcTime() finishes.
I hope this is clearer now?
Thanks again.
Mike
----- Original Message -----
From: "Ernest Friedman-Hill" <[EMAIL PROTECTED]>
To: <[email protected]>
Sent: Friday, January 05, 2007 1:50 PM
Subject: Re: JESS: Shadow facts not working
: Off the top of my head, I'm not sure Jess (or other clients of your
: class) will react to change events being fired during a call to a
: getter method; not only calcTime(), but also presumably Jess will be
: calling getElapsedTime(), and the results might be odd.
:
: But from your description, I suspect the problem is more pedestrian.
: How many threads are involved? For it to work the way you're
: expecting, there would need to be two: one calling calcTime(), and
: the other calling Rete.run() (or the equivalent.) It sounds to me as
: if you just have one that calls run() after calling calcTime(). If
: I'm wrong, then will you please describe what you're doing?
:
: On Jan 4, 2007, at 7:37 PM, Mike Stacey wrote:
:
: > I have a java class which is a bean and fires events when
properties
: > change. My rules fire when this property attains certain values.
The
: > property is a timer which calculates the elapsed time since some
: > previous event happened. This is implemented in a loop within the
: > java class. My jess rule needs to fire when the timer gets to a
: > particular elapsed time.
: >
: > Problem: The rule doesn't fire until the method returns, by which
: > time the timer has run further than it needs to. I have checked
with
: > watch facts and the facts are being asserted in jess continuously
but
: > yet the rule doesn't fire until the caclTime() method exits.
: >
: > In the examle below, when the Terminates rule fires the timer has
: > reached a bit over 10000 instead of 7000. Any suggestions would be
: > greatly appreciated of course. I hope the following is clear
enough
: > to follow...
: >
: > The java code
: > -------------
: > Class PropTime
: >
: > public void calcTime()
: > {
: > long etime = getElapsedTime();
: > // Loop condition only for test purposes at the moment
: > while(etime < 10000)
: > {
: > etime = getElapsedTime();
: > }
: > }
: >
: > /** Returns elapsed time in milliseconds.
: > * PROBLEM: 'Terminates' rule not firing until calcTime()
returns
: > */
: >
: > public long getElapsedTime()
: > {
: > if (startTime == -1)
: > {
: > elapsedTime = 0;
: > System.out.println("0");
: > }
: > if (running)
: > {
: > oldElapsedTime = elapsedTime;
: > elapsedTime = System.currentTimeMillis() - startTime;
: > // Terminate rule should fire when this reaches a given
: > value
: > eventSupport.firePropertyChange("elapsedTime", new
: > Long(oldElapsedTime), new Long(elapsedTime));
: > }
: > else
: > {
: > elapsedTime = stopTime-startTime;
: > }
: > return elapsedTime;
: > }
: >
: > The jess code
: > -------------
: >
: > (defclass pTime PropTime);; create deftemplate from javabean
: > (bind ?pT (new PropTime));; create bean
: > (definstance pTime ?pT);; add bean (shadow fact) to jess memory
: >
: > ; PROBLEM: This rule doesn't fire until the calcTime() method
: > ; finishes
: >
: > (defrule Terminates
: > ; Terminate when timer reaches 7000
: > (pTime(elapsedTime ?et&:(>= ?et 7000)))
: > =>
: > (printout t ">>>>>>>Terminates: Elapsed time: "?et crlf)
: > (call ?pT stopPropTimer))
: >
: >
: >
:
--------------------------------------------------------------------
: > 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]
: --------------------------------------------------------------------
:
:
:
: --
: No virus found in this incoming message.
: Checked by AVG Free Edition.
: Version: 7.5.432 / Virus Database: 268.16.5/616 - Release Date:
4/01/2007 1:34 PM
:
:
--------------------------------------------------------------------
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]
--------------------------------------------------------------------