我是CLIPS的新手。我想计算具有两个相同参数的断言的平均值。例如,如果我有以下模板:
(deftemplate quiz (slot id (type INTEGER)) (slot course(type STRING)) (slot quizname (type STRING)) (slot userid (type INTEGER)) (slot firstname (type STRING)) (slot average (type FLOAT)) )
以及这些断言:
(deffacts users (quiz (id 1) (course "Math") (quizname "Equations") (userid 1) (firstname "Mike") (average 70.00)) (quiz (id 2) (course "Math") (quizname "Exercise") (userid 1) (firstname "Mike") (average 20.00)) (quiz (id 3) (course "Math") (quizname "Sum") (userid 2) (firstname "Ronald") (average 90.00)) (quiz (id 4) (course "Math") (quizname "Equations") (userid 2) (firstname "Ronald") (average 60.00)) (quiz (id 9) (course "English") (quizname "Listening") (userid 5) (firstname "Lionel") (average 60.00)) )
我想构建一个规则来计算具有相同’userid’和’course’的断言的平均值,并将结果写入文件。我希望得到的答案是:
迈克在数学中的平均分为45.00;罗纳德在数学中的平均分为75.00;莱昂内尔在英语中的平均分为60.00
我尝试了这个规则。我知道它完全是错误的:
(defrule averageStudent=>(bind ?sum 0)(do-for-all-facts ((?f quiz)) TRUE(bind ?sum (+ ?sum ?f:average)))(bind ?sum (/ ?sum (length$ (find-all-facts ((?nFacts quiz)) (eq ?nFacts:userid) (eq ?nFacts:namequiz math)))))(printout t ?firstname " in math has " ?sum crlf))
回答:
你需要构建一些东西来保存你想要计算平均值的所有名字/课程组合。在规则的动作中,你需要遍历quiz事实并生成一个包含(“迈克” “罗纳德” “莱昂内尔”)的多字段变量和另一个包含(“数学” “数学” “英语”)的多字段变量。然后,你需要使用从1到列表长度的索引来迭代这些列表,然后使用nth$函数从每个列表中提取名字和课程。然后,你可以使用事实查询函数来提取每个名字/课程的平均值并计算总平均值。
与其做所有这些,你可以编写一个规则来确定需要计算平均值的所有名字/课程组合,并将这些作为事实断言:
(deftemplate compute (slot course (type STRING)) (slot firstname (type STRING))) (defrule determine-course-name (logical (compute-averages)) (quiz (course ?course) (firstname ?name)) (not (compute (course ?course) (firstname ?name))) => (assert (compute (course ?course) (firstname ?name))))
然后你可以编写一个规则,仅计算一个名字/课程的平均值:
(defrule compute-average (compute (course ?course) (firstname ?name)) => (bind ?sum 0) (bind ?count 0) (do-for-all-facts ((?f quiz)) (and (eq ?f:course ?course) (eq ?f:firstname ?name)) (bind ?sum (+ ?sum ?f:average)) (bind ?count (+ ?count 1))) (format t "%s in %s has %0.2f%n" ?name ?course (/ ?sum ?count)))
determine-course-name规则最初不会被激活:
CLIPS (6.4 2/9/21)CLIPS> (deftemplate quiz (slot id (type INTEGER)) (slot course (type STRING)) (slot quizname (type STRING)) (slot userid (type INTEGER)) (slot firstname (type STRING)) (slot average (type FLOAT)))CLIPS> (deffacts users (quiz (id 1) (course "Math") (quizname "Equations") (userid 1) (firstname "Mike") (average 70.00)) (quiz (id 2) (course "Math") (quizname "Exercise") (userid 1) (firstname "Mike") (average 20.00)) (quiz (id 3) (course "Math") (quizname "Sum") (userid 2) (firstname "Ronald") (average 90.00)) (quiz (id 4) (course "Math") (quizname "Equations") (userid 2) (firstname "Ronald") (average 60.00)) (quiz (id 9) (course "English") (quizname "Listening") (userid 5) (firstname "Lionel") (average 60.00)))CLIPS> (deftemplate compute (slot course (type STRING)) (slot firstname (type STRING)))CLIPS> (defrule determine-course-name (logical (compute-averages)) (quiz (course ?course) (firstname ?name)) (not (compute (course ?course) (firstname ?name))) => (assert (compute (course ?course) (firstname ?name))))CLIPS> (defrule compute-average (compute (course ?course) (firstname ?name)) => (bind ?sum 0) (bind ?count 0) (do-for-all-facts ((?f quiz)) (and (eq ?f:course ?course) (eq ?f:firstname ?name)) (bind ?sum (+ ?sum ?f:average)) (bind ?count (+ ?count 1))) (format t "%s in %s has %0.2f%n" ?name ?course (/ ?sum ?count)))CLIPS> (reset)CLIPS> (facts)f-1 (quiz (id 1) (course "Math") (quizname "Equations") (userid 1) (firstname "Mike") (average 70.0))f-2 (quiz (id 2) (course "Math") (quizname "Exercise") (userid 1) (firstname "Mike") (average 20.0))f-3 (quiz (id 3) (course "Math") (quizname "Sum") (userid 2) (firstname "Ronald") (average 90.0))f-4 (quiz (id 4) (course "Math") (quizname "Equations") (userid 2) (firstname "Ronald") (average 60.0))f-5 (quiz (id 9) (course "English") (quizname "Listening") (userid 5) (firstname "Lionel") (average 60.0))For a total of 5 facts.CLIPS> (agenda)CLIPS>
一旦你断言(compute-averages),规则就可以计算平均值:
CLIPS> (assert (compute-averages))<Fact-6>CLIPS> (agenda)0 determine-course-name: f-6,f-5,*0 determine-course-name: f-6,f-4,*0 determine-course-name: f-6,f-3,*0 determine-course-name: f-6,f-2,*0 determine-course-name: f-6,f-1,*For a total of 5 activations.CLIPS> (run)Lionel in English has 60.00Ronald in Math has 75.00Mike in Math has 45.00CLIPS>
中间的compute事实仍然存在,但由于这些事实逻辑上依赖于(compute-averages)事实,如果你需要清理它们,你可以通过撤回那个事实来删除它们:
CLIPS> (facts)f-1 (quiz (id 1) (course "Math") (quizname "Equations") (userid 1) (firstname "Mike") (average 70.0))f-2 (quiz (id 2) (course "Math") (quizname "Exercise") (userid 1) (firstname "Mike") (average 20.0))f-3 (quiz (id 3) (course "Math") (quizname "Sum") (userid 2) (firstname "Ronald") (average 90.0))f-4 (quiz (id 4) (course "Math") (quizname "Equations") (userid 2) (firstname "Ronald") (average 60.0))f-5 (quiz (id 9) (course "English") (quizname "Listening") (userid 5) (firstname "Lionel") (average 60.0))f-6 (compute-averages)f-7 (compute (course "English") (firstname "Lionel"))f-8 (compute (course "Math") (firstname "Ronald"))f-9 (compute (course "Math") (firstname "Mike"))For a total of 9 facts.CLIPS> (retract 6)CLIPS> (facts)f-1 (quiz (id 1) (course "Math") (quizname "Equations") (userid 1) (firstname "Mike") (average 70.0))f-2 (quiz (id 2) (course "Math") (quizname "Exercise") (userid 1) (firstname "Mike") (average 20.0))f-3 (quiz (id 3) (course "Math") (quizname "Sum") (userid 2) (firstname "Ronald") (average 90.0))f-4 (quiz (id 4) (course "Math") (quizname "Equations") (userid 2) (firstname "Ronald") (average 60.0))f-5 (quiz (id 9) (course "English") (quizname "Listening") (userid 5) (firstname "Lionel") (average 60.0))For a total of 5 facts.CLIPS>