JESS: question about writing rule that is based on comparing the number of one kind of facts and that of another

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

JESS: question about writing rule that is based on comparing the number of one kind of facts and that of another

Felix Chan-2
Hi,

I am trying to find a way to write a rule that is based on comparing
the number of one kind of facts and the number of another kind. I am
sure experienced JESS users must have seen this requirement before and
likely have a "standard", perhaps elegant way of dealing with it. But
I am sorry to say that I am still struggling with it after some time.

I've got an insurance policy that relates to multiple cars and
drivers. So I have a policy fact and one or more car and driver facts
in the working memory. I want to write a rule that says if the number
of cars is greater than the number of drivers, then do something.

What I have done is to reserve a couple of slots on the policy to
store the number of cars and drivers, and use a couple of rules to
count the car facts and drivers facts and populate those slots. I have
another rule to "do something" if number of cars > number of drivers.

But I can only get those counting rules to fire once. They won't fire
again as I assert or retract car facts and driver facts.

I suspect there must be a "best practice" to deal with this sort of
thing. Any advice would be much appreciated. (By the way, thanks
Ernest for your answer to my previous question. Much appreciated!)

Felix

------------------------
Here is the script:

(deftemplate policy (slot policyId) (slot numOfCars) (slot numOfDrivers))
(deftemplate car (slot carId) (slot policyId) (slot make) (slot model)
(slot year))
(deftemplate driver (slot driverId) (slot policyId) (slot name) (slot age))

(defquery cars
    (declare (variables ?pid))
    (car (policyId ?pid))
)
(defquery drivers
    (declare (variables ?pid))
    (driver (policyId ?pid))
)

(defrule getNumOfCars
    ?p <- (policy (policyId ?pid))
    (exists (car (policyId ?pid)))
    =>
    (modify ?p (numOfCars (count-query-results cars ?pid)))
)
(defrule getNumOfDrivers
    ?p <- (policy (policyId ?pid) (numOfDrivers nil))
    (exists (driver (policyId ?pid)))
    =>
    (modify ?p (numOfDrivers (count-query-results drivers ?pid)))
)

(defrule moreCarsThanDrivers
    (policy (numOfCars ?nc&~nil) (numOfDrivers ?nd&~nil&:(> ?nc ?nd)))
    =>
    (printout t "More cars than drivers!" crlf)
)

(reset)

(assert (policy (policyId 1)))
(assert (car (carId 1) (policyId 1) (make Honda) (model civic) (year 1990)))
(assert (driver (driverId 1) (policyId 1) (name John) (age 35)))
(run)
(facts)
-- numOfCars and numOfDrivers populated as expected

(assert (car (carId 2) (policyId 1) (make Toyota) (model camry) (year 1995)))
(run)
(facts)
--- numOfCars did not get updated

----- Results
f-0   (MAIN::initial-fact)
f-1   (MAIN::policy (policyId 1) (numOfCars 1) (numOfDrivers 1))
f-2   (MAIN::car (carId 1) (policyId 1) (make Honda) (model civic) (year 1990))
f-3   (MAIN::driver (driverId 1) (policyId 1) (name John) (age 35))
For a total of 4 facts in module MAIN.
f-0   (MAIN::initial-fact)
f-1   (MAIN::policy (policyId 1) (numOfCars 1) (numOfDrivers 1))
f-2   (MAIN::car (carId 1) (policyId 1) (make Honda) (model civic) (year 1990))
f-3   (MAIN::driver (driverId 1) (policyId 1) (name John) (age 35))
f-7   (MAIN::car (carId 2) (policyId 1) (make Toyota) (model camry) (year 1995))
For a total of 5 facts in module MAIN.


--------------------------------------------------------------------
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: question about writing rule that is based on comparing the number of one kind of facts and that of another

Wolfgang Laun-2
On 7 July 2011 08:25, Felix Chan <[hidden email]> wrote:
Hi,

I am trying to find a way to write a rule that is based on comparing
the number of one kind of facts and the number of another kind. I am
sure experienced JESS users

Actually, Ernest has seen it a long time ago, and therefore we have...
 
must have seen this requirement before and
likely have a "standard", perhaps elegant way of dealing with it. But
I am sorry to say that I am still struggling with it after some time.

... the CE accumulate!

(defrule getNumOfCars
   ?p <- (policy (policyId ?pid))
   (car (policyId ?pid))
   ?c <- (accumulate (bind ?count 0)
                     (bind ?count (+ ?count 1))
                     ?count
                     (car (policyId ?pid)))
   =>
   (modify ?p (numOfCars ?c))
)
(defrule getNumOfDrivers
   ?p <- (policy (policyId ?pid))
   ?c <- (accumulate (bind ?count 0)
                     (bind ?count (+ ?count 1))
                     ?count
                     (driver (policyId ?pid)))
   =>
   (modify ?p (numOfDrivers ?c))
)

You can remove the queries.
-W
Reply | Threaded
Open this post in threaded view
|

Re: JESS: question about writing rule that is based on comparing the number of one kind of facts and that of another

Wolfgang Laun-2
In reply to this post by Felix Chan-2
On 7 July 2011 08:25, Felix Chan <[hidden email]> wrote:
Hi,

I am trying to find a way to write a rule that is based on comparing
the number of one kind of facts and the number of another kind. I am
sure experienced JESS users

Actually, Ernest has seen it a long time ago, and therefore we have...
 
must have seen this requirement before and
likely have a "standard", perhaps elegant way of dealing with it. But
I am sorry to say that I am still struggling with it after some time.

... the CE accumulate!

(defrule getNumOfCars
   ?p <- (policy (policyId ?pid))
   (car (policyId ?pid))
   ?c <- (accumulate (bind ?count 0)
                     (bind ?count (+ ?count 1))
                     ?count
                     (car (policyId ?pid)))
   =>
   (modify ?p (numOfCars ?c))
)
(defrule getNumOfDrivers
   ?p <- (policy (policyId ?pid))
   ?c <- (accumulate (bind ?count 0)
                     (bind ?count (+ ?count 1))
                     ?count
                     (driver (policyId ?pid)))
   =>
   (modify ?p (numOfDrivers ?c))
)

You can remove the queries.
-W
Reply | Threaded
Open this post in threaded view
|

Re: JESS: question about writing rule that is based on comparing the number of one kind of facts and that of another

Felix Chan-2
In reply to this post by Wolfgang Laun-2
Thanks Wolfgang. This is great.

On Jul 7, 2011, at 5:54 AM, "Wolfgang Laun" <[hidden email]> wrote:

On 7 July 2011 08:25, Felix Chan <[hidden email]> wrote:
Hi,

I am trying to find a way to write a rule that is based on comparing
the number of one kind of facts and the number of another kind. I am
sure experienced JESS users

Actually, Ernest has seen it a long time ago, and therefore we have...
 
must have seen this requirement before and
likely have a "standard", perhaps elegant way of dealing with it. But
I am sorry to say that I am still struggling with it after some time.

... the CE accumulate!

(defrule getNumOfCars
   ?p <- (policy (policyId ?pid))
   (car (policyId ?pid))
   ?c <- (accumulate (bind ?count 0)
                     (bind ?count (+ ?count 1))
                     ?count
                     (car (policyId ?pid)))
   =>
   (modify ?p (numOfCars ?c))
)
(defrule getNumOfDrivers
   ?p <- (policy (policyId ?pid))
   ?c <- (accumulate (bind ?count 0)
                     (bind ?count (+ ?count 1))
                     ?count
                     (driver (policyId ?pid)))
   =>
   (modify ?p (numOfDrivers ?c))
)

You can remove the queries.
-W