This will not improve efficiency but here's a single rule doing the job, at
the cost of one additional fact.

(deftemplate driver (slot driverId) (slot score) (slot rank))
(deftemplate rover  (slot rank))

(defrule rank-drivers
   ?d <- (driver (score ?s1) (rank nil))
   (not (driver (score ?s2&:(> ?s2 ?s1)) (rank nil)))
   ?r <- (rover (rank ?x))
=>
   (modify ?d (rank ?x))
   (modify ?r (rank (++ ?x)))
)

(reset)
..
(assert (rover (rank 1)))

Cheers
Wolfgang

On 6 March 2012 16:55, Friedman-Hill, Ernest <ejfr...@sandia.gov> wrote:

>  That's about the best you can do purely with rules, I'm afraid. The only
> way to do better would be to query for all the facts, sort them using an
> explicit sort, and then run through the list, modifying them one at a time.
> That wouldn't be too hard to code up in Java.
>
>  Now that I'm saying this, it seems like it should be possible to write a
> generic Userfunction which sorted facts based on some given criteria. That
> would be an interesting addition to Jess's library.
>
>   From: Felix Chan <chanfe...@gmail.com>
> Reply-To: <jess-users@sandia.gov>
> Date: Mon, 5 Mar 2012 17:57:25 -0800
> To: <jess-users@sandia.gov>
> Subject: JESS: [EXTERNAL] question on sorting
>
>  Hi,
>
> I need to rank a set of facts based on a score. I came up with the idea
> that I first find the top ranked fact using one rule, followed by ranking
> the remaining facts using another rule.
>
> It works. But I suspect that this method will not be very efficient if I
> have to rank thousands of facts, rather than just 4 as in my example below.
> I also suspect that someone must have solved this sorting problem in a much
> better way.
>
> Any recommendation would be much appreciated. Many thanks.
>
> Felix
>
>
>
> /******************************************************************/
>
> (deftemplate driver (slot driverId) (slot score) (slot rank))
>
> (defrule rankFirstDriver
>     "find top ranked driver if none has been ranked"
>     (not (driver (rank ~nil)))               ; if no drivers have been
> ranked
>     ?d1 <- (driver (score ?s1))              ; if we can find a driver
> with score s1
>     (not (driver (score ?s2&:(> ?s2 ?s1))))  ; but no other drivers have a
> score higher than s1
>     =>
>     (modify ?d1 (rank 1))
>     )
>
> (defrule rankOtherDrivers
>     "rank other drivers after top ranked drivers have been found"
>     (driver (rank 1)) ; if top ranked driver has been found
>
>     ; find lowest ranked driver
>     (driver (rank ?r1&~nil))
>     (not (driver (rank ?r2&~nil&:(> ?r2 ?r1))))
>
>     ; find unranked driver with highest score
>     ?d <- (driver (score ?s1) (rank nil))
>     (not (driver (score ?s2&:(> ?s2 ?s1)) (rank nil)))
>
>     =>
>     (modify ?d (rank (+ ?r1 1)))
>     )
>
> (reset)
> (assert (driver (driverId 1) (score 100)))
> (assert (driver (driverId 2) (score 50)))
> (assert (driver (driverId 3) (score 200)))
> (assert (driver (driverId 4) (score 75)))
>
> (run)
> (facts)
>
>
>
> /*********************************/
>
> /***** OUTPUT **************/
>
>
> f-0   (MAIN::initial-fact)
> f-1   (MAIN::driver (driverId 1) (score 100) (rank 2))
> f-2   (MAIN::driver (driverId 2) (score 50) (rank 4))
> f-3   (MAIN::driver (driverId 3) (score 200) (rank 1))
> f-4   (MAIN::driver (driverId 4) (score 75) (rank 3))
> For a total of 5 facts in module MAIN.
>

Reply via email to