This is my solution:
; satisfying package/location/object combinations
(deftemplate fit (slot package-name)(slot location)(slot object))
; create the fits
(defrule sat1
(pkg (package-name ?p)(location ?l)(boxes $? ?b $?))
(box (id ?b) (objects $? ?o $?))
(satisfies-need (box ?b) (location ?l) (object ?o))
=>
(printout t "rule sat1 - package " ?p " location " ?l " object " ?o crlf)
(assert (fit (package-name ?p)(location ?l)(object ?o)))
)
; count the fits
(defrule sat2
(location (id ?l) (need ?n))
(pkg (package-name ?p)(location ?l))
?c <- (accumulate (bind ?count 0)
(bind ?count (+ ?count 1))
?count
(fit (package-name ?p)(location ?l) (object ?o)))
(test (>= ?c ?n))
=>
(printout t "rule sat2 fires - location " ?l " package " ?p " count " ?c
crlf)
(assert (satisfied-need-pkg (package-name $p) (location $l)))
)
And you'll need a third, low-salience rule to get rid of the fits.
It would probably better to avoid multislots.
-W
On Tue, Oct 6, 2009 at 1:55 AM, Neelakantan Kartha <[email protected]
> wrote:
> I am trying to write a rule to check whether a package (chosen by a user
> via a UI) is appropriate for a location. If the chosen
> package is not appropriate, we want to warn the user.
>
> Here is a simplified version of the domain
>
> (deftemplate box (slot id)(multislot objects)) ;boxes can contain multiple
> objects
> (deftemplate location (slot id) (slot need)) ;locations have needs, which
> are integers
> (deftemplate satisfies-need (slot box) (slot location) (slot object)) ;some
> objects in a box can satisfy a need of a location.
> (deftemplate pkg (slot package-name)(slot location) (multislot boxes)) ; a
> package for a location consists of multiple boxes.
> (deftemplate satisfies-need-pkg (slot package-name)(slot location))
>
> (assert (box (id b1) (objects o1 o2)))
> (assert (box (id b2) (objects o3 o4)))
> (assert (box (id b3) (objects o5 o6)))
> (assert (box (id b4) (objects o7 o8 o9)))
> (assert (box (id b5) (objects o10 o11 o12)))
>
> (assert (location (id l1) (need 3))) ;location l1 has 3 needs
>
> (assert (satisfies-need (box b1) (location l1) (object o1))); object o1
> satisfies a need of location l1
> (assert (satisfies-need (box b2) (location l1) (object o3))); object o3
> satisfies a need of location l1
> (assert (satisfies-need (box b3) (location l1) (object o6))); object o6
> satisfies a need of location l1
>
> ;The following might be asserted as a result of the user defining a package
> using the UI.
> (assert (pkg (package-name p1)(location l1) (boxes b1 b2))) ; user chooses
> a pakckage p1 consisting of boxes b1 and b2
> (assert (pkg (package-name p2)(location l1) (boxes b1 b2 b3))); user
> chooses a package p2 consisting of boxes b1, b2 and b3.
>
> To see whether a package satisfies the need at a location, we do the
> following. Initialize count to zero.
> (a) Look at each box (call it b) in the package and look at each object
> inside b. If that object
> satisfies the need at the location, we add 1 to count. Otherwise we
> do nothing.
> (b) If the count at the end is greater than or equal to the value of the
> need slot of the location, the package
> satisfies the need.
> Example: Package p1 does not satisfy the need of location 1, since the
> count is only 2 (due to o1 and o3)and the need is 3
> Package p2 does satisfy the need of location l (from o1, o3 and
> o6)
> Note that the satisfied-need facts are asserted as a result of other
> rule firings to determine whether
> an object does satisfy the need of a location (and thus are not directly
> asserted as in the example above).
>
> The question is how do I write a rule to determine whether a package
> satisfies a need for a location:
>
> (defrule satisfies-need-pkg
>
> ?????
> ==>
> (assert (satisfied-need-pkg (package-name $p) (location $l)))
> )
>
>
> It seems that I should be able to use accumulate CE, but I am having a
> hard-time making it work. Any suggestions on how to do this (with or without
> using the accumulate CE)
>
> Thanks,
>
> Kartha
>
>
>
>
> --------------------------------------------------------------------
> 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].
> --------------------------------------------------------------------
>
>