On 26/06/2012, Dwight Hare <d.h...@paritycomputing.com> wrote:
> I am trying to reason about the passage of time in my rules. I would like to
> write the following rule:
> (defrule Test
>                     ?r <- (logical (CurrentTime))
>                     (logical (Condition (time ?time&:(> (+ ?time 5)
> ?r.t))))
>                 =>
>                     (assert (Condition-met))
> )
> Where "CurrentTime" is a fact that holds the current time, and I change the
> slot value "t" as time progresses. The rule fires if the "time" slot in the
> Condition plus 5 is greater than the current time (that is, is true within
> the last 5 time increments). But this syntax is not allowed because you
> cannot access a dotted variable (the "?r.t") here.

Why not simply

(defrule Test
                    (logical (CurrentTime ?ct))
                    (logical (Condition (time ?time&:(> (+ ?time 5) ?ct))))
                    (assert (Condition-met))

which avoids all that global rigmarole?

More below.

> My first alternative was to declare a defglobal called "*time*" and have
> that change value as time progresses. But there is no way to make the global
> a "logical" dependency of the asserted condition-met so it doesn't get
> retracted when the global changes in value sufficient to make the rule no
> longer be true.
> I came up with a workaround where in addition to the defglobal "*time*" I
> assert a Fact called CurrentTime that holds the same value in the "t" slot.
> Now my rule is:
> (defrule Test
>                     ?r <- (logical (CurrentTime (t ?t&:(= ?t ?*time*))))
>                     (logical (Condition (time ?time&:(> (+ ?time 5)  
> ?*time*))))  ; Note I use the global here instead of the dotted var but the
> value is the same
>                 =>
>                     (assert (Condition-met (globtime ?*time*)(facttime
> ?r.t)))
> )

The fallacy is buried in the second pattern which compares the
(unchanged) Condition with the value in the global *time*. You know
that this has changed, but the Jess Engine doesn't. It works in the
first pattern because you change the CurrentTime fact, and so this
pattern is re-evaluated.

Don't use globals in LHS patterns unless they are immutable.


> This says that if there is a CurrentTime fact whose slot "t" has the same
> value as the global "*time*" and there is a Condition whose "time" slot plus
> 5 is greater than that time, then assert the Condition-met. My java code
> sets the global to "4", asserts the fact "(CurrentTime (t 4))", and then
> asserts the fact "(Condition (time 0))". Since all the conditions are met
> the rules engine asserts the fact "(MAIN::Condition-met (globtime 4)
> (facttime 4))". All is well though a bit clumsy. Now I want to move time
> forward where the "Condition-met" should no longer be true. I change the
> global to 10 and modify the CurrentTime fact and set the "t" slot to 10
> too.
> Then I run the rules engine and it retracts the "(MAIN::Condition-met
> (globtime 4) (facttime 4))" but then mysteriously asserts
> "(MAIN::Condition-met (globtime 10) (facttime 10))". Since the Condition
> time of 0 plus 5 is not greater than 10, it should not have asserted this.
> Here is a dump of the facts in the rules engine at the end:
> 0: (MAIN::CurrentTime (t 10))
> 1: (MAIN::Condition (time 0))
> 3: (MAIN::Condition-met (globtime 10) (facttime 10))
> I see no justification for the 3rd fact given the only rule I have.
> Is there a better way of accomplishing this?
> Dwight

To unsubscribe, send the words 'unsubscribe jess-users y...@address.com'
in the BODY of a message to majord...@sandia.gov, NOT to the list
(use your own address!) List problems? Notify owner-jess-us...@sandia.gov.

Reply via email to