Re: JESS: [EXTERNAL] question on sorting

"Friedman-Hill, Ernest" <[email protected]> Tue, 6 Mar 2012 15:55:39 +0000
Newsgroups gmane.comp.java.jess
Message-ID <CB7B9C9C.9742%[email protected]>
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 <[email protected]<mailto:[email protected]>>
Reply-To: <[email protected]<mailto:[email protected]>>
Date: Mon, 5 Mar 2012 17:57:25 -0800
To: <[email protected]<mailto:[email protected]>>
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.