JESS: Ranking facts
Hi, Consider the following situation. I have asserted quite a number of facts, with various values for their slots. Now I want to select a limited number of facts that are most suitable, according to some user-defined criterion. My idea was to set up a defquery and then use Java sorting to order the QuertResult according to my criterion. However, there seems to be no way to transform a QueyResult into a Collection. Note that my problems would be simple if I had fixed limits on my slot values, but I haven't: if i woudl have slot values of 2, 4 and 6 and I would like to have the smallest two, a limit of 5 would do it, but this would not work when the values were 13, 15 and 29. My suspicion is that I am trying to solve the problem in the wrong manner, or even trying to solve the wrong problem. Any suggestions are appreciated. Regards, JW Lokin 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]
Re: JESS: Ranking facts
Maybe this is coming close to what you want. ; your fact template (deftemplate Fact (slot id)(slot a)(slot b)(slot c)) ; supposed to contain the rating functions for the slot values (deftemplate Func (slot fa)(slot fb)(slot fc)) ; the computed ranking for a fact (deftemplate Rank (slot r)(slot f)) ; the collected results (deftemplate Count (slot n)(multislot facts)) ; some facts (deffacts someT (Fact (id A)(a 42)(b 23)(c 17)) (Fact (id B)(a 21)(b 11)(c 7)) (Fact (id C)(a 15)(b 10)(c 12)) (Fact (id D)(a 33)(b 12)(c 9)) ) ; rating functions for the slots (deffacts aFunc (Func (fa (lambda (?a) (return (- ?a 10 (fb (lambda (?b) (return (/ ?b 3 (fc (lambda (?c) (return (* ?c 2) ) ; a rule computing the fact ranking as the sum of the slot rankings (defrule setRank ?fact - (Fact (a ?a) (b ?b) (c ?c)) (Func (fa ?fa)(fb ?fb)(fc ?fc)) = (bind ?rank (+ (call ?fa ?a)(call ?fb ?b)(call ?fc ?c))) (assert (Rank (r ?rank)(f ?fact))) ) (reset) (run) ; getting displaying the n best rankings (defrule getBest ?count - (Count (n ?n : ( ?n 0))(facts $?facts)) ?rank - (Rank (r ?r)(f ?fact)) (not ( Rank (r ?r1 : ( ?r1 ?r = (-- ?n) (modify ?count (n ?n)(facts (list $?facts ?fact))) (retract ?rank) ) (defrule showBest ?count - (Count (n 0)(facts $?facts)) = (retract ?count) (foreach ?f $?facts (printout t (fact-slot-value ?f id) crlf) ) ) ; top 3 (assert (Count (n 3))) (run) Notice that some Rank facts remain, but these can be easily retracted. Kind regards Wolfgang Jan Willem Lokin wrote: Hi, Consider the following situation. I have asserted quite a number of facts, with various values for their slots. Now I want to select a limited number of facts that are most suitable, according to some user-defined criterion. My idea was to set up a defquery and then use Java sorting to order the QuertResult according to my criterion. However, there seems to be no way to transform a QueyResult into a Collection. Note that my problems would be simple if I had fixed limits on my slot values, but I haven't: if i woudl have slot values of 2, 4 and 6 and I would like to have the smallest two, a limit of 5 would do it, but this would not work when the values were 13, 15 and 29. My suspicion is that I am trying to solve the problem in the wrong manner, or even trying to solve the wrong problem. Any suggestions are appreciated. Regards, JW Lokin 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] 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]
Re: JESS: Ranking facts
Hi Jan, Couldn't you simply write one or more rules that place matching fact bindings into an arbitrary collection class? I'm assuming that you are filtering only on one type of fact. For example: (clear) (import java.util.ArrayList) (watch all) (deftemplate somefact (slot x) (slot y) (slot z)) (deffacts init (somefact (x 2) (y 4) (z 6)) (somefact (x 13) (y 15) (z 29)) (somefact (x 5) (y 8) (z 11))) (deffunction update-fact-list-display (?conditionNumber ?colFacts) (printout t Facts that match condition ?conditionNumber : crlf) (printout t crlf) (foreach ?fact ?colFacts (printout t FactID: ?fact crlf))) (defrule find-all-somefacts-condition-1 Finds all somefacts having 1st set of arbitrary conditions ?factId -(somefact (x ?x:(= ?x 5)) (y ?y:(= ?y 5)) (z ?)) = (bind ?colFacts1 (fetch colFacts1)) (?colFacts1 add ?factId) (update-fact-list-display 1 ?colFacts1)) (defrule find-all-somefacts-condition-2 Finds all somefacts having 2nd set of arbitrary conditions ?factId -(somefact (x ?x:(= ?x 5)) (y ?y:(= ?y 4)) (z ?)) = (bind ?colFacts2 (fetch colFacts2)) (?colFacts2 add ?factId) (update-fact-list-display 2 ?colFacts2)) ;; Program (bind ?colFacts1 (new ArrayList)) (store colFacts1 ?colFacts1) (bind ?colFacts2 (new ArrayList)) (store colFacts2 ?colFacts2) (reset) (run) // OUTPUT == MAIN::find-all-somefacts-condition-1: +1+1+1+1+t MAIN::find-all-somefacts-condition-2: =1+1+1+1+t == Focus MAIN == f-0 (MAIN::initial-fact) == f-1 (MAIN::somefact (x 2) (y 4) (z 6)) == Activation: MAIN::find-all-somefacts-condition-1 : == f-2 (MAIN::somefact (x 13) (y 15) (z 29)) == Activation: MAIN::find-all-somefacts-condition-2 : == f-3 (MAIN::somefact (x 5) (y 8) (z 11)) == Activation: MAIN::find-all-somefacts-condition-2 : FIRE 1 MAIN::find-all-somefacts-condition-2 f-3 Facts that match condtion 2: FactID: Java-Object:jess.Fact FIRE 2 MAIN::find-all-somefacts-condition-2 f-2 Facts that match condtion 2: FactID: Java-Object:jess.Fact FactID: Java-Object:jess.Fact FIRE 3 MAIN::find-all-somefacts-condition-1 f-1 Facts that match condtion 1: FactID: Java-Object:jess.Fact == Focus MAIN // Cheers, Jason -- --- Jason Morris Morris Technical Solutions LLC http://www.morris-technical-solutions.com On Nov 27, 2007 7:43 AM, Jan Willem Lokin [EMAIL PROTECTED] wrote: Hi, Consider the following situation. I have asserted quite a number of facts, with various values for their slots. Now I want to select a limited number of facts that are most suitable, according to some user-defined criterion. My idea was to set up a defquery and then use Java sorting to order the QuertResult according to my criterion. However, there seems to be no way to transform a QueyResult into a Collection. Note that my problems would be simple if I had fixed limits on my slot values, but I haven't: if i woudl have slot values of 2, 4 and 6 and I would like to have the smallest two, a limit of 5 would do it, but this would not work when the values were 13, 15 and 29. My suspicion is that I am trying to solve the problem in the wrong manner, or even trying to solve the wrong problem. Any suggestions are appreciated. Regards, JW Lokin 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] 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]
Re: JESS: Ranking facts
Facts can be selected in rank order with a defquery and a Java collection. (deftemplate sample Sample facts to be ranked (declare (ordered FALSE)) (slot primary (type INTEGER) (default 0)) (slot secondary (type INTEGER)) (slot stuff) ) (defquery sample-query Query for well-formed samples with an exclusion (declare (variables ?exclude)) ?sample - (sample (primary ?primary~nil) (secondary ?secondary~nil) (stuff ~?exclude))) (deffunction top-samples (?threshold ?criterion) Print top N sample facts according to criterion (bind ?tree-set (new java.util.TreeSet ?criterion)) (bind ?samples (run-query* sample-query nil)) (while (?samples next) (call ?tree-set add (?samples get sample))) (close ?samples) (bind ?iterator (?tree-set iterator)) (while (and (?iterator hasNext) ( ?threshold 0)) (-- ?threshold) (bind ?sample (?iterator next)) (printout t Sample fact: (fact-slot-value ?sample primary) (fact-slot-value ?sample secondary) (fact-slot-value ?sample stuff) crlf))) (defglobal ?*compare-samples* = (implement java.util.Comparator using (lambda (?dummy ?first ?second) (bind ?name1 (fact-slot-value ?first primary)) (bind ?name2 (fact-slot-value ?second primary)) (if ( ?name1 ?name2) then (return -1)) (if ( ?name1 ?name2) then (return 1)) (bind ?name1 (fact-slot-value ?first secondary)) (bind ?name2 (fact-slot-value ?second secondary)) (if ( ?name1 ?name2) then (return -1)) (if ( ?name1 ?name2) then (return 1)) 0))) (deffacts sample-facts Sample fact examples to be ranked (sample (primary 1) (secondary 10) (stuff A)) (sample (primary 1) (secondary 11) (stuff B)) (sample (primary 2) (secondary 5) (stuff C)) (sample (primary 2) (secondary 6) (stuff D)) (sample (primary 2) (secondary 6) (stuff E)) (sample (primary 2) (secondary 7) (stuff F)) (sample (primary 3) (secondary 9) (stuff G)) (sample (primary 3) (stuff H)) (sample (primary 1) (stuff I)) ) Jess (reset) TRUE Jess (top-samples 3 ?*compare-samples*) Sample fact: 1 10 A Sample fact: 1 11 B Sample fact: 2 5 C FALSE Many variations are possible. - To avoid recalculating an expensive comparison function, the criteria could be pre-calculated as the key of a TreeMap instead of a TreeSet. - The java.util.Collections.sort method could sort any java.util.List collection instead of a TreeSet. - A rule could add items to a collection instead of a defquery. Bob Kirby At 04:43 AM 11/27/2007, Jan Willem Lokin wrote: Hi, Consider the following situation. I have asserted quite a number of facts, with various values for their slots. Now I want to select a limited number of facts that are most suitable, according to some user-defined criterion. My idea was to set up a defquery and then use Java sorting to order the QuertResult according to my criterion. However, there seems to be no way to transform a QueyResult into a Collection. Note that my problems would be simple if I had fixed limits on my slot values, but I haven't: if i woudl have slot values of 2, 4 and 6 and I would like to have the smallest two, a limit of 5 would do it, but this would not work when the values were 13, 15 and 29. My suspicion is that I am trying to solve the problem in the wrong manner, or even trying to solve the wrong problem. Any suggestions are appreciated. Regards, JW Lokin