【问题标题】:CLIPS: forcing a rule to re-evaluate the value of a global variable?CLIPS:强制规则重新评估全局变量的值?
【发布时间】:2015-05-03 18:25:39
【问题描述】:

是否有可能使 CLIPS 重新评估 defrule 中全局变量的值?我有这个:

(defrule encourage "Do we have a GPA higher than 3.7?"
    (test (> (gpa) 3.7))
    =>
    (printout t "Keep up the excellent work!" crlf))

gpa 是根据两个全局变量(学分和学分)计算并返回一个数字的函数。我在某处读到对全局变量的更改不会调用模式匹配。我该如何去强迫这个?只要 GPA 高于 3.7,我就想在每次执行(运行)时打印该字符串。

【问题讨论】:

    标签: clips


    【解决方案1】:

    不要尝试以这种方式使用全局变量或函数调用。首先,全局变量专门设计为不会触发模式匹配。其次,CLIPS 需要一点魔法才能知道何时需要重新评估函数调用,因为有许多更改可能导致函数返回不同的值,而不仅仅是对全局变量的更改。如果您想要一条特定的信息来触发模式匹配,那么将它粘贴到一个事实或实例中。如果您将函数调用参数化并绑定要用作规则条件中的参数的值,它将使您的代码更易于理解。

    CLIPS> (clear)
    CLIPS> 
    (deffunction gpa (?grade-points ?number-of-credits)
       (/ ?grade-points ?number-of-credits))
    CLIPS>    
    (defrule encourage "Do we have a GPA higher than 3.7?"
        (grade-points ?gp)
        (number-of-credits ?noc)
        (test (> (gpa ?gp ?noc) 3.7))
        =>
        (printout t "Keep up the excellent work!" crlf))
    CLIPS> (assert (grade-points 35) (number-of-credits 10))
    <Fact-2>
    CLIPS> (agenda)
    CLIPS> (facts)
    f-0     (initial-fact)
    f-1     (grade-points 35)
    f-2     (number-of-credits 10)
    For a total of 3 facts.
    CLIPS> (retract 1)
    CLIPS> (assert (grade-points 38))
    <Fact-3>
    CLIPS> (agenda)
    0      encourage: f-3,f-2
    For a total of 1 activation.
    CLIPS>
    

    或者,您可以使用事实查询函数对一组事实进行迭代,以根据事实而不是全局变量动态计算 gpa。每次修改这些事实之一(添加或删除)时,您还可以断言一个事实,表明需要重新检查 gpa 以触发鼓励规则。

    CLIPS> (clear)
    CLIPS> 
    (deftemplate grade
       (slot class)
       (slot grade-points)
       (slot credits))
    CLIPS> 
    (deffunction gpa ()
       (bind ?grade-points 0)
       (bind ?credits 0)
       (do-for-all-facts ((?g grade)) TRUE
          (bind ?grade-points (+ ?grade-points ?g:grade-points))
          (bind ?credits (+ ?credits ?g:credits)))
       (if (= ?credits 0)
          then 0
          else (/ ?grade-points ?credits)))
    CLIPS> 
    (defrule encourage
       ?f <- (check-gpa)
       =>
       (retract ?f)
       (if (> (gpa) 3.7)
          then
          (printout t "Keep up the excellent work!" crlf)))
    CLIPS> (gpa)
    0
    CLIPS> (assert (check-gpa))
    <Fact-1>
    CLIPS> (run)
    CLIPS>  (assert (grade (class Algebra) (grade-points 12) (credits 3)))
    <Fact-2>
    CLIPS> (gpa)
    4.0
    CLIPS> (assert (check-gpa))
    <Fact-3>
    CLIPS> (run)
    Keep up the excellent work!
    CLIPS> (assert (grade (class History) (grade-points 6) (credits 2)))
    <Fact-4>
    CLIPS> (gpa)
    3.6
    CLIPS> (assert (check-gpa))
    <Fact-5>
    CLIPS> (run)
    CLIPS> (assert (grade (class Science) (grade-points 12) (credits 3)))
    <Fact-6>
    CLIPS> (gpa)
    3.75
    CLIPS> (assert (check-gpa))
    <Fact-7>
    CLIPS> (run)
    Keep up the excellent work!
    CLIPS>
    

    【讨论】:

    • 谢谢,但是我如何将东西积累到这些事实中呢?我不想手动撤回并重新断言成绩点和学分事实。我有一个函数“take”,它接受一个班级代码和一个成绩并断言一个“成绩”记录(它还收回任何以前记录的这个班级代码的成绩)。我很难将成绩点和学分数重置为 0 ONCE,然后根据我的“成绩”记录使用 defrule 来累积成绩点和学分数。如何在 deffunction 中使用 "?fact
    • 或者,换句话说,我如何将我的“成绩”记录中的所有学分和学分相加,并将其反映在我的学分和学分事实中一直?
    • 更新了答案以包含不同的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    相关资源
    最近更新 更多