CLIPS 初学者:CLIPS 规则如何解释事实顺序?

CLIPS beginner: How CLIPS rules interpret the facts order?

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

(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 如何解释事实的顺序? 有没有办法让我在一天内合并超过 1activity?

非常感谢!

默认情况下,CLIPS 使用深度优先策略来确定接下来要执行的规则,因此通常下一个执行的规则将由最后断言或撤回的事实激活。 Basic Programming Guide 中的第 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>