JESS: [EXTERNAL] Jess asserts fact that is not true

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

JESS: [EXTERNAL] Jess asserts fact that is not true

Dwight Hare

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.

 

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

)

 

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

Reply | Threaded
Open this post in threaded view
|

Re: JESS: [EXTERNAL] Jess asserts fact that is not true

Wolfgang Laun-2
On 26/06/2012, Dwight Hare <[hidden email]> 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.

-W

>
> 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 [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

RE: JESS: [EXTERNAL] Jess asserts fact that is not true

Dwight Hare
Duh. I had early on gotten into the habit of assigning the LHS clause to a variable (as I did below in "?r <- ...") and then accessing the slots using dotted vars that I had completely forgotten this alternative way of assigning a slot value to a var in a rule. It works correctly now without the global and it retracts the fact when I change the value representing the current time.

Apologies for wasting everyone's time with this stupid question.

Dwight

-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Wolfgang Laun
Sent: Tuesday, June 26, 2012 9:59 PM
To: [hidden email]
Subject: Re: JESS: [EXTERNAL] Jess asserts fact that is not true

On 26/06/2012, Dwight Hare <[hidden email]> 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.

-W

>
> 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 [hidden email]'
in the BODY of a message to [hidden email], NOT to the list (use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------




--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [hidden email]'
in the BODY of a message to [hidden email], NOT to the list
(use your own address!) List problems? Notify [hidden email].
--------------------------------------------------------------------