JESS: question about writing rule that is based on comparing the number of one kind of facts and that of another
"Felix Chan" <[email protected]> Wed, 6 Jul 2011 23:25:43 -0700
| Newsgroups | gmane.comp.java.jess |
|---|---|
| Message-ID | <13046_1310042537_p67CgGE6027227_CAEg6sM8R6YNN6uaaUfbL7KcCrkXHbzi811yGErjtQKZdFPxF1Q@mail.gmail.com> |
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 [email protected]'
in the BODY of a message to [email protected], NOT to the list
(use your own address!) List problems? Notify [email protected].
--------------------------------------------------------------------