【问题标题】:CLIPS beginner: How CLIPS rules interpret the facts order?CLIPS 初学者:CLIPS 规则如何解释事实顺序?
【发布时间】:2021-05-17 10:34:27
【问题描述】:

我想知道我每天都做哪些活动,所以我构建了以下代码:

(deftemplate schedule
(slot activity)
(slot starthour)
(slot endhour)
)

(defrule r1
(schedule (activity ?a) (starthour ?start) (endhour ?end))
(not (busy ?start ?a))
=>
(assert (busy ?start ?a))
)

(defrule r2
(busy ?d ?a)
(schedule (activity ?a) (starthour ?start) (endhour ?end))
(test (< ?d ?end))
=>
(assert (busy ( + ?d 1) ?a))
)
CLIPS> (assert (schedule (activity reading) (starthour 3) (endhour 5)))
<Fact-1>
CLIPS> (assert (schedule (activity music) (starthour 4) (endhour 7)))
<Fact-2>

对于我插入的事实,我得到了一个不按日期排序的结果。 CLIPS如何解释事实的顺序? 有没有办法让我在一天内进行 1 次以上的活动?

非常感谢!

【问题讨论】:

    标签: clips


    【解决方案1】:

    默认情况下,CLIPS 使用深度优先策略来确定下一个要执行的规则,因此通常下一个执行的规则将被最后一个断言或撤回的事实激活。基本编程指南中的第 5.3 节,冲突解决策略更详细地描述了此过程。

    只要规则生成了正确的事实,您就不必特别关心它们在事实列表中的排列顺序,因为 1) 使用事实列表显示程序的输出和 2) 强制特定的放置顺序可能很困难且过于复杂。

    相反,要在程序输出中对事实进行排序,请使用事实查询函数之一收集所有相关事实,然后使用带有自定义比较器的排序函数在打印事实之前对其进行排序:

             CLIPS (6.4 2/9/21)
    CLIPS> 
    (deftemplate schedule
       (slot activity)
       (slot starthour)
       (slot endhour))
    CLIPS>    
    (deftemplate busy
       (slot activity)
       (slot hour))
    CLIPS> 
    (defrule r1
       (schedule (activity ?a) (starthour ?start) (endhour ?end))
       (not (busy (activity ?a) (hour ?start)))
       =>
       (assert (busy (activity ?a) (hour ?start))))
    CLIPS> 
    (defrule r2
       (busy (activity ?a) (hour ?d))
       (schedule (activity ?a) (starthour ?start) (endhour ?end))
       (test (< ?d ?end)) 
       =>
       (assert (busy (activity ?a) (hour (+ ?d 1)))))
    CLIPS>    
    (deffacts schedules
       (schedule (activity reading) (starthour 3) (endhour 5))
       (schedule (activity music) (starthour 4) (endhour 7)))
    CLIPS>    
    (deffunction busy-compare (?f1 ?f2)
        ;; Sort by hour
        (if (> (fact-slot-value ?f2 hour) (fact-slot-value ?f1 hour))
           then (return FALSE))
        (if (< (fact-slot-value ?f2 hour) (fact-slot-value ?f1 hour))
           then (return TRUE))
        ;; And then sort by activity
        (if (> (str-compare (fact-slot-value ?f2 activity) 
                            (fact-slot-value ?f1 activity)) 0)
           then (return FALSE)
           else (return TRUE)))
    CLIPS>            
     (defrule print
        (declare (salience -10))
        =>
        (bind ?schedule (find-all-facts ((?f busy)) TRUE))
        (bind ?schedule (sort busy-compare ?schedule))
        (foreach ?s ?schedule
           (format t "%2d %s%n" (fact-slot-value ?s hour) (fact-slot-value ?s activity))))
    CLIPS> (reset)
    CLIPS> (run)
     3 reading
     4 music
     4 reading
     5 music
     5 reading
     6 music
     7 music
    CLIPS> (facts)
    f-1     (schedule (activity reading) (starthour 3) (endhour 5))
    f-2     (schedule (activity music) (starthour 4) (endhour 7))
    f-3     (busy (activity music) (hour 4))
    f-4     (busy (activity music) (hour 5))
    f-5     (busy (activity music) (hour 6))
    f-6     (busy (activity music) (hour 7))
    f-7     (busy (activity reading) (hour 3))
    f-8     (busy (activity reading) (hour 4))
    f-9     (busy (activity reading) (hour 5))
    For a total of 9 facts.
    CLIPS> 
    

    这是在每个繁忙的事实中存储多个活动的另一种方法:

    CLIPS> (clear)
    CLIPS> 
    (deftemplate schedule
       (slot activity)
       (slot starthour)
       (slot endhour))
    CLIPS> 
    (deftemplate busy
       (multislot activity)
       (slot hour))
    CLIPS> 
    (defrule r1
       (schedule (activity ?a) (starthour ?start) (endhour ?end))
       =>
       (loop-for-count (?hour ?start ?end)
          (assert (busy (activity ?a) (hour ?hour)))))
    CLIPS> 
    (defrule combine
       ?b1 <- (busy (activity $?a) (hour ?d))
       ?b2 <- (busy (activity ?n&:(not (member$ ?n ?a))) (hour ?d))
       =>
       (modify ?b1 (activity ?a ?n))
       (retract ?b2))
    CLIPS> 
    (deffacts schedules
       (schedule (activity reading) (starthour 3) (endhour 5))
       (schedule (activity music) (starthour 4) (endhour 7)))
    CLIPS> 
    (deffunction busy-compare (?f1 ?f2)
        (if (> (fact-slot-value ?f2 hour) (fact-slot-value ?f1 hour))
           then (return FALSE))
        (if (< (fact-slot-value ?f2 hour) (fact-slot-value ?f1 hour))
           then (return TRUE))
        (return FALSE))
    CLIPS>     
     (defrule print
        (declare (salience -10))
        =>
        (bind ?schedule (find-all-facts ((?f busy)) TRUE))
        (bind ?schedule (sort busy-compare ?schedule))
        (foreach ?s ?schedule
           (format t "%2d %s%n" (fact-slot-value ?s hour) (implode$ (fact-slot-value ?s activity)))))
    CLIPS> (reset)
    CLIPS> (run)
     3 reading
     4 reading music
     5 reading music
     6 music
     7 music
    CLIPS> (facts)
    f-1     (schedule (activity reading) (starthour 3) (endhour 5))
    f-2     (schedule (activity music) (starthour 4) (endhour 7))
    f-5     (busy (activity music) (hour 6))
    f-6     (busy (activity music) (hour 7))
    f-7     (busy (activity reading) (hour 3))
    f-8     (busy (activity reading music) (hour 4))
    f-9     (busy (activity reading music) (hour 5))
    For a total of 7 facts.
    CLIPS> 
    

    【讨论】:

    • 非常感谢加里的帮助!有没有办法在相同的事实中显示相同的时间,两个活动。例如:get (busy (activity music reading) (hour 4))?
    • 添加了使用多槽进行活动的附加解决方案。
    • 完美!感谢您的帮助,加里。
    猜你喜欢
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2017-04-05
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多